From a358d8ea766fa51e06d6152c9bdcdaff5834f12a Mon Sep 17 00:00:00 2001 From: KD Date: Thu, 21 Mar 2024 19:28:01 +0100 Subject: [PATCH 01/19] feat: implement transactionDataListItemStructure component --- src/modules/components/index.ts | 1 + src/modules/components/transaction/index.ts | 1 + .../transactionDataListItem/index.ts | 1 + .../transactionDataListItemStructure/index.ts | 7 ++ .../transactionDataListItem.test.tsx | 45 ++++++++++ .../transactionDataListItemStructure.api.ts | 69 +++++++++++++++ ...ansactionDataListItemStructure.stories.tsx | 37 +++++++++ .../transactionDataListItemStructure.tsx | 83 +++++++++++++++++++ .../blockExplorerUtils/blockExplorerUtils.ts | 39 +++++++++ src/modules/utils/blockExplorerUtils/index.ts | 1 + src/modules/utils/timestampUtils/index.ts | 1 + .../utils/timestampUtils/timestampUtils.ts | 24 ++++++ 12 files changed, 309 insertions(+) create mode 100644 src/modules/components/transaction/index.ts create mode 100644 src/modules/components/transaction/transactionDataListItem/index.ts create mode 100644 src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts create mode 100644 src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx create mode 100644 src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts create mode 100644 src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx create mode 100644 src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx create mode 100644 src/modules/utils/blockExplorerUtils/blockExplorerUtils.ts create mode 100644 src/modules/utils/blockExplorerUtils/index.ts create mode 100644 src/modules/utils/timestampUtils/index.ts create mode 100644 src/modules/utils/timestampUtils/timestampUtils.ts diff --git a/src/modules/components/index.ts b/src/modules/components/index.ts index 0da2bb7ef..127a9b294 100644 --- a/src/modules/components/index.ts +++ b/src/modules/components/index.ts @@ -2,3 +2,4 @@ export * from './dao'; export * from './member'; export * from './odsModulesProvider'; export * from './proposal'; +export * from './transaction'; diff --git a/src/modules/components/transaction/index.ts b/src/modules/components/transaction/index.ts new file mode 100644 index 000000000..6e6c336a4 --- /dev/null +++ b/src/modules/components/transaction/index.ts @@ -0,0 +1 @@ +export * from './transactionDataListItem/transactionDataListItemStructure'; diff --git a/src/modules/components/transaction/transactionDataListItem/index.ts b/src/modules/components/transaction/transactionDataListItem/index.ts new file mode 100644 index 000000000..3d83b0485 --- /dev/null +++ b/src/modules/components/transaction/transactionDataListItem/index.ts @@ -0,0 +1 @@ +export * from './transactionDataListItemStructure'; diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts new file mode 100644 index 000000000..b176d77f3 --- /dev/null +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts @@ -0,0 +1,7 @@ +import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; + +export const TransactionDataListItem = { + Structure: TransactionDataListItemStructure, +}; + +export type { ITransactionDataListItemProps } from './transactionDataListItemStructure.api'; diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx new file mode 100644 index 000000000..31647c97c --- /dev/null +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -0,0 +1,45 @@ +import { render, screen } from '@testing-library/react'; +import { DataList } from '../../../../../core'; +import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; +import { TransactionType, type ITransactionDataListItemProps } from './transactionDataListItemStructure.api'; + +describe(' component', () => { + const createTestComponent = (props?: Partial) => { + return ( + + + + + + ); + }; + + it('renders the transaction type heading', () => { + const transactionType = TransactionType.ACTION; + render(createTestComponent({ transactionType })); + const transactionTypeHeading = screen.getByText('Smart contract action'); + expect(transactionTypeHeading).toBeInTheDocument(); + }); + + it('renders the formatted date', () => { + const unixTimestamp = 1628841600; + render(createTestComponent({ unixTimestamp })); + const formattedDate = screen.getByText('January 19, 1970 at 9:27 PM'); + expect(formattedDate).toBeInTheDocument(); + }); + + it('renders the token value and symbol', () => { + const tokenSymbol = 'ETH'; + const tokenValue = 10; + render(createTestComponent({ tokenSymbol, tokenValue })); + const tokenPrintout = screen.getByText('10 ETH'); + expect(tokenPrintout).toBeInTheDocument(); + }); + + it('renders the formatted USD estimate', () => { + const usdEstimate = 100; + render(createTestComponent({ usdEstimate })); + const formattedUsdEstimate = screen.getByText('$100.00'); + expect(formattedUsdEstimate).toBeInTheDocument(); + }); +}); diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts new file mode 100644 index 000000000..a1c76a1e7 --- /dev/null +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts @@ -0,0 +1,69 @@ +import { type Hash } from 'viem'; +import { IconType, type AvatarIconVariant, type IDataListItemProps } from '../../../../../core'; + +export enum TransactionType { + DEPOSIT = 'DEPOSIT', + WITHDRAW = 'WITHDRAW', + ACTION = 'ACTION', + FAILED = 'TRANSACTION', +} + +export const txHeadingStringList: Record = { + [TransactionType.DEPOSIT]: 'Deposit', + [TransactionType.WITHDRAW]: 'Withdraw', + [TransactionType.ACTION]: 'Smart contract action', + [TransactionType.FAILED]: 'Failed transaction', +}; + +export const txIconTypeList: Record = { + [TransactionType.DEPOSIT]: IconType.DEPOSIT, + [TransactionType.WITHDRAW]: IconType.WITHDRAW, + [TransactionType.ACTION]: IconType.BLOCKCHAIN_SMARTCONTRACT, + [TransactionType.FAILED]: IconType.CLOSE, +}; + +export const txVariantList: Record = { + [TransactionType.DEPOSIT]: 'success', + [TransactionType.WITHDRAW]: 'warning', + [TransactionType.ACTION]: 'info', + [TransactionType.FAILED]: 'critical', +}; + +export interface ITransactionDataListItemProps extends IDataListItemProps { + /** + * The chain ID of the transaction. + */ + chainId?: number; + /** + * The address of the token. + */ + tokenAddress?: string; + /** + * The symbol of the token, e.g. 'ETH' as a string + */ + tokenSymbol?: string; + /** + * The token value in the transaction. + */ + tokenValue?: number; + /** + * The type of transaction. + */ + transactionType?: TransactionType; + /** + * The Unix timestamp of the transaction. + */ + unixTimestamp?: number; + /** + * The estimated USD value of the transaction. + */ + usdEstimate?: number; + /** + * Whether the transaction is pending. + */ + isPending?: boolean; + /** + * The transaction hash. + */ + txHash?: Hash; +} diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx new file mode 100644 index 000000000..1356f5e84 --- /dev/null +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { DataList } from '../../../../../core'; +import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; + +const meta: Meta = { + title: 'Modules/Components/Transaction/TransactionDataListItem.Structure', + component: TransactionDataListItemStructure, + tags: ['autodocs'], + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/file/ISSDryshtEpB7SUSdNqAcw/branch/P0GeJKqILL7UXvaqu5Jj7V/Aragon-ODS?type=design&node-id=14385%3A30819&mode=dev', + }, + }, + argTypes: { + txHash: { + control: 'text', + }, + }, +}; + +type Story = StoryObj; + +/** + * Default usage example of the TransactionDataList module component. + */ +export const Default: Story = { + render: (args) => ( + + + + + + ), +}; + +export default meta; diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx new file mode 100644 index 000000000..b32203329 --- /dev/null +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -0,0 +1,83 @@ +import { AvatarIcon, DataList, Heading, NumberFormat, Spinner, formatterUtils } from '../../../../../core'; +import { QueryType, createBlockExplorerLink } from '../../../../utils/blockExplorerUtils/blockExplorerUtils'; +import { formatDate } from '../../../../utils/timestampUtils'; +import { + TransactionType, + txHeadingStringList, + txIconTypeList, + txVariantList, + type ITransactionDataListItemProps, +} from './transactionDataListItemStructure.api'; + +export const TransactionDataListItemStructure: React.FC = (props) => { + const { + chainId, + tokenAddress, + tokenSymbol, + tokenValue, + usdEstimate, + transactionType, + unixTimestamp, + txHash, + ...otherProps + } = props; + + const getTxIcon = () => { + if (transactionType) { + return ( + + ); + } + return ; + }; + + return ( + +
+
+
+
{getTxIcon()}
+
+
+ + {transactionType ? txHeadingStringList[transactionType] : 'Transfer Type'} + + + {formatDate(unixTimestamp)} + +
+
+ +
+ + {tokenValue && transactionType !== TransactionType.ACTION ? ( + <> + {formatterUtils.formatNumber(tokenValue, { format: NumberFormat.TOKEN_AMOUNT_SHORT })} + {` ${tokenSymbol}`} + + ) : ( + `-` + )} + + + {formatterUtils.formatNumber( + usdEstimate && transactionType !== TransactionType.ACTION ? usdEstimate : 0, + { + format: NumberFormat.FIAT_TOTAL_SHORT, + }, + )} + +
+
+
+ ); +}; diff --git a/src/modules/utils/blockExplorerUtils/blockExplorerUtils.ts b/src/modules/utils/blockExplorerUtils/blockExplorerUtils.ts new file mode 100644 index 000000000..7b258a767 --- /dev/null +++ b/src/modules/utils/blockExplorerUtils/blockExplorerUtils.ts @@ -0,0 +1,39 @@ +import { type Hash } from 'viem'; + +export enum QueryType { + TX = 'TX', + BLOCK = 'BLOCK', + ADDRESS = 'ADDRESS', +} + +type ExplorerLinkCriteria = { + chainId?: number; + queryType?: QueryType; + txHash?: Hash; +}; + +export function createBlockExplorerLink(criteria: ExplorerLinkCriteria): string | undefined { + const { chainId, queryType, txHash } = criteria; + + if (chainId === undefined || queryType === undefined || txHash === undefined) { + return undefined; + } + + const baseUrls: { [key: number]: string } = { + 1: 'https://etherscan.io/', + 11155111: 'https://sepolia.etherscan.io/', + 137: 'https://polygonscan.com/', + 42161: 'https://arbiscan.io/', + 8453: 'https://basescan.org/', + }; + const baseUrl = baseUrls[chainId]; + + const typePaths: { [key in NonNullable]?: string } = { + TX: 'tx/', + BLOCK: 'block/', + ADDRESS: 'address/', + }; + const path = typePaths[queryType]; + + return `${baseUrl}${path}${txHash}`; +} diff --git a/src/modules/utils/blockExplorerUtils/index.ts b/src/modules/utils/blockExplorerUtils/index.ts new file mode 100644 index 000000000..2858d9f80 --- /dev/null +++ b/src/modules/utils/blockExplorerUtils/index.ts @@ -0,0 +1 @@ +export * as blockExplorerUtils from './blockExplorerUtils'; diff --git a/src/modules/utils/timestampUtils/index.ts b/src/modules/utils/timestampUtils/index.ts new file mode 100644 index 000000000..2341cbefc --- /dev/null +++ b/src/modules/utils/timestampUtils/index.ts @@ -0,0 +1 @@ +export * from './timestampUtils'; diff --git a/src/modules/utils/timestampUtils/timestampUtils.ts b/src/modules/utils/timestampUtils/timestampUtils.ts new file mode 100644 index 000000000..98cd7cd8e --- /dev/null +++ b/src/modules/utils/timestampUtils/timestampUtils.ts @@ -0,0 +1,24 @@ +export const formatDate = (unixTimestamp?: number): string => { + if (!unixTimestamp) { + return '-'; + } + + const now = new Date(); + const date = new Date(unixTimestamp); + const diffDays = Math.floor((now.getTime() - date.getTime()) / (1000 * 3600 * 24)); + const isCurrentYear = now.getFullYear() === date.getFullYear(); + const timeOptions: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric', hour12: true }; + const dateTimeOptions: Intl.DateTimeFormatOptions = isCurrentYear + ? { month: 'long', day: 'numeric', ...timeOptions } + : { year: 'numeric', month: 'long', day: 'numeric', ...timeOptions }; + + if (diffDays < 1 && now.getDate() === date.getDate()) { + return `Today at ${new Intl.DateTimeFormat('en-US', timeOptions).format(date)}`; + } else if (diffDays < 2 && now.getDate() - date.getDate() === 1) { + return `Yesterday at ${new Intl.DateTimeFormat('en-US', timeOptions).format(date)}`; + } else if (diffDays < 7) { + return `${diffDays} days ago at ${new Intl.DateTimeFormat('en-US', timeOptions).format(date)}`; + } else { + return new Intl.DateTimeFormat('en-US', dateTimeOptions).format(date); + } +}; From 2919e216c9f6595bf3a0111347e769f22eebdc1d Mon Sep 17 00:00:00 2001 From: KD Date: Thu, 21 Mar 2024 19:28:47 +0100 Subject: [PATCH 02/19] chore: update index exports --- src/modules/components/transaction/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/components/transaction/index.ts b/src/modules/components/transaction/index.ts index 6e6c336a4..1c841b92e 100644 --- a/src/modules/components/transaction/index.ts +++ b/src/modules/components/transaction/index.ts @@ -1 +1 @@ -export * from './transactionDataListItem/transactionDataListItemStructure'; +export * from './transactionDataListItem'; From 57f4eeedfe30bccbdab889851994aa829f9eae59 Mon Sep 17 00:00:00 2001 From: KD Date: Thu, 21 Mar 2024 19:29:29 +0100 Subject: [PATCH 03/19] chore: update CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d355f2aeb..8fc1d32fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added -- Implement `DaoDataListItem`, `ProposalDataListItem.Structure`, and `MemberDataListItem.Structure` module components +- Implement `DaoDataListItem`, `ProposalDataListItem.Structure`, `TransactionDataListItem.Structure` and + `MemberDataListItem.Structure` module components - Implement `StatePingAnimation` core component ### Changed From 915d27deab9f81380479f812aea6cab596a09784 Mon Sep 17 00:00:00 2001 From: KD Date: Mon, 25 Mar 2024 11:40:57 +0100 Subject: [PATCH 04/19] feat: handle tx status and relationship with tx type --- .../transactionDataListItemStructure.api.ts | 14 ++++-- .../transactionDataListItemStructure.tsx | 44 ++++++++++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts index a1c76a1e7..9acecceee 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts @@ -1,32 +1,34 @@ import { type Hash } from 'viem'; import { IconType, type AvatarIconVariant, type IDataListItemProps } from '../../../../../core'; +export enum TxStatusCode { + PENDING = 'PENDING', + SUCCESS = 'SUCCESS', + FAILED = 'FAILED', +} + export enum TransactionType { DEPOSIT = 'DEPOSIT', WITHDRAW = 'WITHDRAW', ACTION = 'ACTION', - FAILED = 'TRANSACTION', } export const txHeadingStringList: Record = { [TransactionType.DEPOSIT]: 'Deposit', [TransactionType.WITHDRAW]: 'Withdraw', [TransactionType.ACTION]: 'Smart contract action', - [TransactionType.FAILED]: 'Failed transaction', }; export const txIconTypeList: Record = { [TransactionType.DEPOSIT]: IconType.DEPOSIT, [TransactionType.WITHDRAW]: IconType.WITHDRAW, [TransactionType.ACTION]: IconType.BLOCKCHAIN_SMARTCONTRACT, - [TransactionType.FAILED]: IconType.CLOSE, }; export const txVariantList: Record = { [TransactionType.DEPOSIT]: 'success', [TransactionType.WITHDRAW]: 'warning', [TransactionType.ACTION]: 'info', - [TransactionType.FAILED]: 'critical', }; export interface ITransactionDataListItemProps extends IDataListItemProps { @@ -50,6 +52,10 @@ export interface ITransactionDataListItemProps extends IDataListItemProps { * The type of transaction. */ transactionType?: TransactionType; + /** + * The network state of the transaction. + */ + status?: TxStatusCode; /** * The Unix timestamp of the transaction. */ diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index b32203329..9f728bd4a 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -1,8 +1,18 @@ -import { AvatarIcon, DataList, Heading, NumberFormat, Spinner, formatterUtils } from '../../../../../core'; +import { + AvatarIcon, + DataList, + Heading, + IconType, + NumberFormat, + Spinner, + formatterUtils, + type AvatarIconVariant, +} from '../../../../../core'; import { QueryType, createBlockExplorerLink } from '../../../../utils/blockExplorerUtils/blockExplorerUtils'; import { formatDate } from '../../../../utils/timestampUtils'; import { TransactionType, + TxStatusCode, txHeadingStringList, txIconTypeList, txVariantList, @@ -17,20 +27,34 @@ export const TransactionDataListItemStructure: React.FC { + const type = transactionType; + if (status === TxStatusCode.FAILED) { + return { + icon: IconType.CLOSE, + variant: 'critical' as AvatarIconVariant, + heading: 'Failed transaction', + }; + } + + return { + icon: type ? txIconTypeList[type] : IconType.HELP, + variant: type ? txVariantList[type] : ('neutral' as AvatarIconVariant), + heading: type ? txHeadingStringList[type] : 'Unknown transaction type', + }; + }; + + const { icon, variant, heading } = getEffectiveStatus(); + const getTxIcon = () => { - if (transactionType) { - return ( - - ); + if (status !== TxStatusCode.PENDING) { + return ; } return ; }; @@ -49,7 +73,7 @@ export const TransactionDataListItemStructure: React.FC
- {transactionType ? txHeadingStringList[transactionType] : 'Transfer Type'} + {heading} {formatDate(unixTimestamp)} From b50ea0c81fcf614589d071c9722239b90de83141 Mon Sep 17 00:00:00 2001 From: KD Date: Mon, 25 Mar 2024 12:17:32 +0100 Subject: [PATCH 05/19] chore: improve test coverage for failed cases --- .../transactionDataListItem.test.tsx | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index 31647c97c..4b920493f 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -1,7 +1,11 @@ import { render, screen } from '@testing-library/react'; import { DataList } from '../../../../../core'; import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; -import { TransactionType, type ITransactionDataListItemProps } from './transactionDataListItemStructure.api'; +import { + TransactionType, + TxStatusCode, + type ITransactionDataListItemProps, +} from './transactionDataListItemStructure.api'; describe(' component', () => { const createTestComponent = (props?: Partial) => { @@ -42,4 +46,18 @@ describe(' component', () => { const formattedUsdEstimate = screen.getByText('$100.00'); expect(formattedUsdEstimate).toBeInTheDocument(); }); + + it('renders "Unknown transaction type" for transactions with an undefined type', () => { + render(createTestComponent({})); + const unknownTransactionTypeHeading = screen.getByText('Unknown transaction type'); + expect(unknownTransactionTypeHeading).toBeInTheDocument(); + }); + + it('overrides the transaction type display with the transaction status', () => { + render(createTestComponent({ transactionType: TransactionType.DEPOSIT, status: TxStatusCode.FAILED })); + const failedTransactionText = screen.getByText('Failed transaction'); + expect(failedTransactionText).toBeInTheDocument(); + const closeIcon = screen.getByTestId('CLOSE'); + expect(closeIcon).toBeInTheDocument(); + }); }); From 64e58941c03a789a9526a74f98866c9c6c380b00 Mon Sep 17 00:00:00 2001 From: KD Date: Mon, 25 Mar 2024 13:10:54 +0100 Subject: [PATCH 06/19] fix: update test for unix timestamp to pass on remote CI timezone --- .../transactionDataListItem.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index 4b920493f..c1c3366ad 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -28,7 +28,7 @@ describe(' component', () => { it('renders the formatted date', () => { const unixTimestamp = 1628841600; render(createTestComponent({ unixTimestamp })); - const formattedDate = screen.getByText('January 19, 1970 at 9:27 PM'); + const formattedDate = screen.getByText('January 19, 1970 at 8:27 PM'); expect(formattedDate).toBeInTheDocument(); }); From b214cff7a3373ffc7700e735a00e350b90569d0d Mon Sep 17 00:00:00 2001 From: KD Date: Mon, 25 Mar 2024 16:37:18 +0100 Subject: [PATCH 07/19] fix: prevent layout shift with spinner wrapper, extra cleanup --- .../transactionDataListItem.test.tsx | 2 +- .../transactionDataListItemStructure.tsx | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index c1c3366ad..10deeaa17 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -49,7 +49,7 @@ describe(' component', () => { it('renders "Unknown transaction type" for transactions with an undefined type', () => { render(createTestComponent({})); - const unknownTransactionTypeHeading = screen.getByText('Unknown transaction type'); + const unknownTransactionTypeHeading = screen.getByText('Unknown'); expect(unknownTransactionTypeHeading).toBeInTheDocument(); }); diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 9f728bd4a..4b84273e8 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -46,7 +46,7 @@ export const TransactionDataListItemStructure: React.FC { if (status !== TxStatusCode.PENDING) { - return ; + return ; } - return ; + return ( +
+ +
+ ); }; return ( @@ -67,12 +71,10 @@ export const TransactionDataListItemStructure: React.FC
-
-
-
{getTxIcon()}
-
+
+ {getTxIcon()}
- + {heading} From 18c445d7ee36465174a51a7a157396092e482946 Mon Sep 17 00:00:00 2001 From: KD Date: Mon, 25 Mar 2024 17:02:26 +0100 Subject: [PATCH 08/19] chore: prop cleanup + naming --- .../transactionDataListItem.test.tsx | 6 +++--- .../transactionDataListItemStructure.api.ts | 8 ++------ .../transactionDataListItemStructure.tsx | 14 +++++++------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index 10deeaa17..7ffb09c50 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -19,8 +19,8 @@ describe(' component', () => { }; it('renders the transaction type heading', () => { - const transactionType = TransactionType.ACTION; - render(createTestComponent({ transactionType })); + const txType = TransactionType.ACTION; + render(createTestComponent({ txType })); const transactionTypeHeading = screen.getByText('Smart contract action'); expect(transactionTypeHeading).toBeInTheDocument(); }); @@ -54,7 +54,7 @@ describe(' component', () => { }); it('overrides the transaction type display with the transaction status', () => { - render(createTestComponent({ transactionType: TransactionType.DEPOSIT, status: TxStatusCode.FAILED })); + render(createTestComponent({ txType: TransactionType.DEPOSIT, txStatus: TxStatusCode.FAILED })); const failedTransactionText = screen.getByText('Failed transaction'); expect(failedTransactionText).toBeInTheDocument(); const closeIcon = screen.getByTestId('CLOSE'); diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts index 9acecceee..882c9cb46 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts @@ -51,11 +51,11 @@ export interface ITransactionDataListItemProps extends IDataListItemProps { /** * The type of transaction. */ - transactionType?: TransactionType; + txType?: TransactionType; /** * The network state of the transaction. */ - status?: TxStatusCode; + txStatus?: TxStatusCode; /** * The Unix timestamp of the transaction. */ @@ -64,10 +64,6 @@ export interface ITransactionDataListItemProps extends IDataListItemProps { * The estimated USD value of the transaction. */ usdEstimate?: number; - /** - * Whether the transaction is pending. - */ - isPending?: boolean; /** * The transaction hash. */ diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 4b84273e8..2cc8917d6 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -26,16 +26,16 @@ export const TransactionDataListItemStructure: React.FC { - const type = transactionType; - if (status === TxStatusCode.FAILED) { + const type = txType; + if (txStatus === TxStatusCode.FAILED) { return { icon: IconType.CLOSE, variant: 'critical' as AvatarIconVariant, @@ -53,7 +53,7 @@ export const TransactionDataListItemStructure: React.FC { - if (status !== TxStatusCode.PENDING) { + if (txStatus !== TxStatusCode.PENDING) { return ; } return ( @@ -85,7 +85,7 @@ export const TransactionDataListItemStructure: React.FC - {tokenValue && transactionType !== TransactionType.ACTION ? ( + {tokenValue && txType !== TransactionType.ACTION ? ( <> {formatterUtils.formatNumber(tokenValue, { format: NumberFormat.TOKEN_AMOUNT_SHORT })} {` ${tokenSymbol}`} @@ -96,7 +96,7 @@ export const TransactionDataListItemStructure: React.FC {formatterUtils.formatNumber( - usdEstimate && transactionType !== TransactionType.ACTION ? usdEstimate : 0, + usdEstimate && txType !== TransactionType.ACTION ? usdEstimate : 0, { format: NumberFormat.FIAT_TOTAL_SHORT, }, From a18eb168b808a274e8431960a5e861e40c38ea82 Mon Sep 17 00:00:00 2001 From: KD Date: Tue, 26 Mar 2024 09:47:16 +0100 Subject: [PATCH 09/19] chore: clean up tests --- .../transactionDataListItem.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index 7ffb09c50..754f61c70 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -25,6 +25,7 @@ describe(' component', () => { expect(transactionTypeHeading).toBeInTheDocument(); }); + // fails on the local run, but passes on the CI for relative unix timestamps (CI server location == UTC 0) it('renders the formatted date', () => { const unixTimestamp = 1628841600; render(createTestComponent({ unixTimestamp })); @@ -47,7 +48,7 @@ describe(' component', () => { expect(formattedUsdEstimate).toBeInTheDocument(); }); - it('renders "Unknown transaction type" for transactions with an undefined type', () => { + it('renders "Unknown" for transactions with an undefined type', () => { render(createTestComponent({})); const unknownTransactionTypeHeading = screen.getByText('Unknown'); expect(unknownTransactionTypeHeading).toBeInTheDocument(); From 5ed869c2cfac683b6f790356a5474ca6f5adeef3 Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 27 Mar 2024 13:30:49 +0100 Subject: [PATCH 10/19] index on feat/APP-2797: a18eb16 chore: clean up tests From a8962c0cd8866472c861b685909b98abdc7a2baa Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 27 Mar 2024 19:30:59 +0100 Subject: [PATCH 11/19] feat: implement PR fixes from convos -- logic cleanup, props, index barrelin, etc --- .../transactionDataListItem/index.ts | 11 ++- .../transactionDataListItemStructure/index.ts | 3 +- .../transactionDataListItemStructure.api.ts | 8 +- .../transactionDataListItemStructure.tsx | 75 ++++++++++++------- 4 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/index.ts b/src/modules/components/transaction/transactionDataListItem/index.ts index e423bebfd..3113ec6eb 100644 --- a/src/modules/components/transaction/transactionDataListItem/index.ts +++ b/src/modules/components/transaction/transactionDataListItem/index.ts @@ -1,7 +1,10 @@ -import { TransactionDataListItemStructure } from './transactionDataListItemStructure/transactionDataListItemStructure'; +import { TransactionDataListItemStructure as Structure } from './transactionDataListItemStructure/transactionDataListItemStructure'; export const TransactionDataListItem = { - Structure: TransactionDataListItemStructure, + Structure, }; - - +export { + ITransactionDataListItemProps, + TransactionType, + TxStatusCode, +} from './transactionDataListItemStructure/transactionDataListItemStructure.api'; diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts index d53e79bbf..26496a2e8 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts @@ -1 +1,2 @@ -export * from './transactionDataListItemStructure'; \ No newline at end of file +export { TransactionDataListItemStructure } from './transactionDataListItemStructure'; +export { ITransactionDataListItemProps, TransactionType, TxStatusCode } from './transactionDataListItemStructure.api'; diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts index bc4f1e3b9..6ade9cef6 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts @@ -11,35 +11,31 @@ export enum TransactionType { DEPOSIT = 'DEPOSIT', WITHDRAW = 'WITHDRAW', ACTION = 'ACTION', - FAILED = 'FAILED', } export const txHeadingStringList: Record = { [TransactionType.DEPOSIT]: 'Deposit', [TransactionType.WITHDRAW]: 'Withdraw', [TransactionType.ACTION]: 'Smart contract action', - [TransactionType.FAILED]: 'Failed transaction', }; export const txIconTypeList: Record = { [TransactionType.DEPOSIT]: IconType.DEPOSIT, [TransactionType.WITHDRAW]: IconType.WITHDRAW, [TransactionType.ACTION]: IconType.BLOCKCHAIN_SMARTCONTRACT, - [TransactionType.FAILED]: IconType.CLOSE, }; export const txVariantList: Record = { [TransactionType.DEPOSIT]: 'success', [TransactionType.WITHDRAW]: 'warning', [TransactionType.ACTION]: 'info', - [TransactionType.FAILED]: 'critical', }; export interface ITransactionDataListItemProps extends IDataListItemProps { /** * The chain ID of the transaction. */ - chainId?: number; + chainId: number; /** * The address of the token. */ @@ -63,7 +59,7 @@ export interface ITransactionDataListItemProps extends IDataListItemProps { /** * The Unix timestamp of the transaction. */ - unixTimestamp?: number; + formattedTimestamp?: string; /** * The estimated fiat value of the transaction. */ diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 00c35f7a7..467cfb137 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -1,6 +1,15 @@ -import { useEffect, useState } from 'react'; +import classNames from 'classnames'; import { useChains } from 'wagmi'; -import { AvatarIcon, DataList, Heading, NumberFormat, Spinner, formatterUtils } from '../../../../../core'; +import { + AvatarIcon, + DataList, + Heading, + IconType, + NumberFormat, + Spinner, + formatterUtils, + type AvatarIconVariant, +} from '../../../../../core'; import { TransactionType, TxStatusCode, @@ -20,33 +29,50 @@ export const TransactionDataListItemStructure: React.FC(); const chains = useChains(); - useEffect(() => { - if (chainId) { - const matchingChain = chains.find((chain) => chain.id === chainId); - const url = matchingChain?.blockExplorers?.default.url; - setBlockExplorerBaseUrl(url); + const blockExplorerBaseUrl = chainId + ? chains.find((chain) => chain.id === chainId)?.blockExplorers?.default?.url + : undefined; + const blockExplorerAssembledHref = + blockExplorerBaseUrl && txHash ? `${blockExplorerBaseUrl}/tx/${txHash}` : undefined; + + const parsedHref = blockExplorerAssembledHref ?? href; + + const getEffectiveStatus = () => { + const type = txType; + if (txStatus === TxStatusCode.FAILED) { + return { + icon: IconType.CLOSE, + variant: 'critical' as AvatarIconVariant, + heading: 'Failed transaction', + }; } - }, [chainId, chains]); - const effectiveType = txStatus === TxStatusCode.FAILED ? 'FAILED' : txType; + return { + icon: txIconTypeList[type], + variant: txVariantList[type], + heading: txHeadingStringList[type], + }; + }; - const icon = txIconTypeList[effectiveType]; - const variant = txVariantList[effectiveType]; - const heading = txHeadingStringList[effectiveType]; + const { icon, variant, heading } = getEffectiveStatus(); + const formattedTokenValue = formatterUtils.formatNumber(tokenValue && tokenValue > 0 ? tokenValue : null, { + format: NumberFormat.TOKEN_AMOUNT_SHORT, + }); return (
@@ -63,23 +89,16 @@ export const TransactionDataListItemStructure: React.FC - {unixTimestamp && unixTimestamp} - {!unixTimestamp && '-'} + {formattedTimestamp ? formattedTimestamp : '-'}
- {tokenValue && txType !== TransactionType.ACTION && ( - <> - {formatterUtils.formatNumber(tokenValue > 0 ? tokenValue : null, { - format: NumberFormat.TOKEN_AMOUNT_SHORT, - })} - {` ${tokenSymbol}`} - - )} - {(tokenValue === undefined || txType === TransactionType.ACTION) && `-`} + {txType === TransactionType.ACTION || tokenValue == null + ? '-' + : `${formattedTokenValue} ${tokenSymbol}`} {formatterUtils.formatNumber( From 680a2b9e90b6b737cabf7de30a8ecf27dfce51ee Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 27 Mar 2024 19:47:22 +0100 Subject: [PATCH 12/19] chore: clean up tests --- .../transactionDataListItem.test.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index b18bf0f49..c564c5a61 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -8,13 +8,18 @@ import { } from './transactionDataListItemStructure.api'; jest.mock('wagmi', () => ({ - ...jest.requireActual('wagmi'), - useChains: jest.fn(), + useChains: () => [ + { + id: '1', + blockExplorers: { default: { url: 'https://example.com' } }, + }, + ], })); describe(' component', () => { const createTestComponent = (props?: Partial) => { const defaultProps: ITransactionDataListItemProps = { + chainId: 1, txType: TransactionType.ACTION, txStatus: TxStatusCode.PENDING, txHash: '0x123', From f9c96de24c884f1c6a1b43d6ed14735628f5e40c Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 27 Mar 2024 19:51:29 +0100 Subject: [PATCH 13/19] chore: rename effective function --- .../transactionDataListItemStructure.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 467cfb137..79ee68eb4 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -45,7 +45,7 @@ export const TransactionDataListItemStructure: React.FC { + const getEffectiveTxType = () => { const type = txType; if (txStatus === TxStatusCode.FAILED) { return { @@ -62,7 +62,8 @@ export const TransactionDataListItemStructure: React.FC 0 ? tokenValue : null, { format: NumberFormat.TOKEN_AMOUNT_SHORT, }); From cb5edffbc935cb3b697ea6e2cddda9325d5860e0 Mon Sep 17 00:00:00 2001 From: KD Date: Sun, 31 Mar 2024 23:04:16 +0200 Subject: [PATCH 14/19] chore: resolve PR conversations - improved readability, block explorer link, new prop naming, etc --- .../transactionDataListItem.test.tsx | 46 +++++++---- .../transactionDataListItemStructure.api.ts | 22 +++--- ...ansactionDataListItemStructure.stories.tsx | 18 ++--- .../transactionDataListItemStructure.tsx | 78 +++++++++---------- src/modules/utils/timestampUtils/index.ts | 1 - .../utils/timestampUtils/timestampUtils.ts | 24 ------ 6 files changed, 87 insertions(+), 102 deletions(-) delete mode 100644 src/modules/utils/timestampUtils/index.ts delete mode 100644 src/modules/utils/timestampUtils/timestampUtils.ts diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index c564c5a61..6df7dab0e 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -1,9 +1,9 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import { DataList, NumberFormat, formatterUtils } from '../../../../../core'; import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; import { + TransactionStatus, TransactionType, - TxStatusCode, type ITransactionDataListItemProps, } from './transactionDataListItemStructure.api'; @@ -20,9 +20,9 @@ describe(' component', () => { const createTestComponent = (props?: Partial) => { const defaultProps: ITransactionDataListItemProps = { chainId: 1, - txType: TransactionType.ACTION, - txStatus: TxStatusCode.PENDING, - txHash: '0x123', + type: TransactionType.ACTION, + status: TransactionStatus.PENDING, + hash: '0x123', ...props, }; return ( @@ -35,37 +35,53 @@ describe(' component', () => { }; it('renders the transaction type heading', () => { - const txType = TransactionType.ACTION; - render(createTestComponent({ txType })); + const type = TransactionType.ACTION; + render(createTestComponent({ type })); const transactionTypeHeading = screen.getByText('Smart contract action'); expect(transactionTypeHeading).toBeInTheDocument(); }); it('renders the token value and symbol in a deposit', () => { const tokenSymbol = 'ETH'; - const tokenValue = 10; - const txType = TransactionType.DEPOSIT; - render(createTestComponent({ tokenSymbol, tokenValue, txType })); + const tokenAmount = 10; + const type = TransactionType.DEPOSIT; + render(createTestComponent({ tokenSymbol, tokenAmount, type })); const tokenPrintout = screen.getByText('10 ETH'); expect(tokenPrintout).toBeInTheDocument(); }); it('renders the formatted USD estimate', () => { - const fiatEstimate = 100; - const txType = TransactionType.DEPOSIT; - const formattedEstimate = formatterUtils.formatNumber(fiatEstimate, { + const tokenPrice = 100; + const tokenAmount = 10; + const type = TransactionType.DEPOSIT; + const formattedEstimate = formatterUtils.formatNumber(tokenPrice * tokenAmount, { format: NumberFormat.FIAT_TOTAL_SHORT, }); - render(createTestComponent({ fiatEstimate, txType })); + render(createTestComponent({ tokenPrice, tokenAmount, type })); const formattedUsdEstimate = screen.getByText(formattedEstimate as string); expect(formattedUsdEstimate).toBeInTheDocument(); }); it('overrides the transaction type display with the transaction status', () => { - render(createTestComponent({ txType: TransactionType.DEPOSIT, txStatus: TxStatusCode.FAILED })); + render(createTestComponent({ type: TransactionType.DEPOSIT, status: TransactionStatus.FAILED })); const failedTransactionText = screen.getByText('Failed transaction'); expect(failedTransactionText).toBeInTheDocument(); const closeIcon = screen.getByTestId('CLOSE'); expect(closeIcon).toBeInTheDocument(); }); + + it('renders the provided timestamp correctly', () => { + const timestamp = '2023-01-01T00:00:00Z'; + render(createTestComponent({ timestamp })); + expect(screen.getByText(timestamp)).toBeInTheDocument(); + }); + + it('renders with the correct block explorer URL', async () => { + render(createTestComponent()); + + await waitFor(() => { + const linkElement = screen.getByRole('link'); + expect(linkElement).toHaveAttribute('href', 'https://example.com/tx/0x123'); + }); + }); }); diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts index 6ade9cef6..9593952f6 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts @@ -1,7 +1,7 @@ import { type Hash } from 'viem'; import { IconType, type AvatarIconVariant, type IDataListItemProps } from '../../../../../core'; -export enum TxStatusCode { +export enum TransactionStatus { PENDING = 'PENDING', SUCCESS = 'SUCCESS', FAILED = 'FAILED', @@ -47,25 +47,25 @@ export interface ITransactionDataListItemProps extends IDataListItemProps { /** * The token value in the transaction. */ - tokenValue?: number; + tokenAmount?: number; /** - * The type of transaction. + * The estimated fiat value of the transaction. */ - txType: TransactionType; + tokenPrice?: number | string; /** - * The current status of a blockchain transaction on the network. + * The type of transaction. @default TransactionType.ACTION */ - txStatus: TxStatusCode; + type?: TransactionType; /** - * The Unix timestamp of the transaction. + * The current status of a blockchain transaction on the network. @default TransactionStatus.PENDING */ - formattedTimestamp?: string; + status?: TransactionStatus; /** - * The estimated fiat value of the transaction. + * The Unix timestamp of the transaction. */ - fiatEstimate?: number; + timestamp?: string; /** * The transaction hash. */ - txHash: Hash; + hash: Hash; } diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx index fb945ebaa..934261f78 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { DataList } from '../../../../../core'; import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; -import { TransactionType, TxStatusCode } from './transactionDataListItemStructure.api'; +import { TransactionStatus, TransactionType } from './transactionDataListItemStructure.api'; const meta: Meta = { title: 'Modules/Components/Transaction/TransactionDataListItem.Structure', @@ -14,7 +14,7 @@ const meta: Meta = { }, }, argTypes: { - txHash: { + hash: { control: 'text', }, }, @@ -37,9 +37,9 @@ export const Default: Story = { export const Withdraw: Story = { args: { - txStatus: TxStatusCode.SUCCESS, - txType: TransactionType.WITHDRAW, - tokenValue: 10, + status: TransactionStatus.SUCCESS, + type: TransactionType.WITHDRAW, + tokenAmount: 10, tokenSymbol: 'ETH', }, render: (args) => ( @@ -53,11 +53,11 @@ export const Withdraw: Story = { export const Failed: Story = { args: { - txStatus: TxStatusCode.FAILED, - txType: TransactionType.DEPOSIT, + status: TransactionStatus.FAILED, + type: TransactionType.DEPOSIT, tokenSymbol: 'ETH', - tokenValue: 10, - fiatEstimate: 100, + tokenAmount: 10, + tokenPrice: 100, }, render: (args) => ( diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 79ee68eb4..abbb99469 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -1,18 +1,9 @@ import classNames from 'classnames'; import { useChains } from 'wagmi'; +import { AvatarIcon, DataList, Heading, IconType, NumberFormat, Spinner, formatterUtils } from '../../../../../core'; import { - AvatarIcon, - DataList, - Heading, - IconType, - NumberFormat, - Spinner, - formatterUtils, - type AvatarIconVariant, -} from '../../../../../core'; -import { + TransactionStatus, TransactionType, - TxStatusCode, txHeadingStringList, txIconTypeList, txVariantList, @@ -24,50 +15,60 @@ export const TransactionDataListItemStructure: React.FC chain.id === chainId)?.blockExplorers?.default?.url - : undefined; - const blockExplorerAssembledHref = - blockExplorerBaseUrl && txHash ? `${blockExplorerBaseUrl}/tx/${txHash}` : undefined; + const matchingChain = chains.find((chain) => chain.id.toString() === chainId.toString()); + const blockExplorerBaseUrl = matchingChain?.blockExplorers?.default?.url; + const blockExplorerAssembledHref = blockExplorerBaseUrl && hash ? `${blockExplorerBaseUrl}/tx/${hash}` : undefined; const parsedHref = blockExplorerAssembledHref ?? href; const getEffectiveTxType = () => { - const type = txType; - if (txStatus === TxStatusCode.FAILED) { + const e = type; + if (status === TransactionStatus.FAILED) { return { icon: IconType.CLOSE, - variant: 'critical' as AvatarIconVariant, + variant: 'critical' as const, heading: 'Failed transaction', }; } return { - icon: txIconTypeList[type], - variant: txVariantList[type], - heading: txHeadingStringList[type], + icon: txIconTypeList[e], + variant: txVariantList[e], + heading: txHeadingStringList[e], }; }; const { icon, variant, heading } = getEffectiveTxType(); - const formattedTokenValue = formatterUtils.formatNumber(tokenValue && tokenValue > 0 ? tokenValue : null, { + const formattedTokenValue = formatterUtils.formatNumber(tokenAmount && tokenAmount > 0 ? tokenAmount : null, { format: NumberFormat.TOKEN_AMOUNT_SHORT, }); + const fiatValue = Number(tokenAmount ?? 0) * Number(tokenPrice ?? 0); + + const formattedTokenPrice = formatterUtils.formatNumber( + fiatValue && type !== TransactionType.ACTION ? fiatValue : 0, + { + format: NumberFormat.FIAT_TOTAL_SHORT, + }, + ); + + const formattedTokenAmount = + type === TransactionType.ACTION || tokenAmount == null ? '-' : `${formattedTokenValue} ${tokenSymbol}`; + return (
- {txStatus !== TxStatusCode.PENDING && ( + {status !== TransactionStatus.PENDING && ( )} - {txStatus === TxStatusCode.PENDING && ( + {status === TransactionStatus.PENDING && (
@@ -90,24 +91,17 @@ export const TransactionDataListItemStructure: React.FC - {formattedTimestamp ? formattedTimestamp : '-'} + {timestamp ? timestamp : '-'}
- {txType === TransactionType.ACTION || tokenValue == null - ? '-' - : `${formattedTokenValue} ${tokenSymbol}`} + {formattedTokenAmount} - {formatterUtils.formatNumber( - fiatEstimate && txType !== TransactionType.ACTION ? fiatEstimate : 0, - { - format: NumberFormat.FIAT_TOTAL_SHORT, - }, - )} + {formattedTokenPrice}
diff --git a/src/modules/utils/timestampUtils/index.ts b/src/modules/utils/timestampUtils/index.ts deleted file mode 100644 index 2341cbefc..000000000 --- a/src/modules/utils/timestampUtils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './timestampUtils'; diff --git a/src/modules/utils/timestampUtils/timestampUtils.ts b/src/modules/utils/timestampUtils/timestampUtils.ts deleted file mode 100644 index 98cd7cd8e..000000000 --- a/src/modules/utils/timestampUtils/timestampUtils.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const formatDate = (unixTimestamp?: number): string => { - if (!unixTimestamp) { - return '-'; - } - - const now = new Date(); - const date = new Date(unixTimestamp); - const diffDays = Math.floor((now.getTime() - date.getTime()) / (1000 * 3600 * 24)); - const isCurrentYear = now.getFullYear() === date.getFullYear(); - const timeOptions: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric', hour12: true }; - const dateTimeOptions: Intl.DateTimeFormatOptions = isCurrentYear - ? { month: 'long', day: 'numeric', ...timeOptions } - : { year: 'numeric', month: 'long', day: 'numeric', ...timeOptions }; - - if (diffDays < 1 && now.getDate() === date.getDate()) { - return `Today at ${new Intl.DateTimeFormat('en-US', timeOptions).format(date)}`; - } else if (diffDays < 2 && now.getDate() - date.getDate() === 1) { - return `Yesterday at ${new Intl.DateTimeFormat('en-US', timeOptions).format(date)}`; - } else if (diffDays < 7) { - return `${diffDays} days ago at ${new Intl.DateTimeFormat('en-US', timeOptions).format(date)}`; - } else { - return new Intl.DateTimeFormat('en-US', dateTimeOptions).format(date); - } -}; From 6d1979ecfe8a17e1bb95eaa8b186c6a3083190ea Mon Sep 17 00:00:00 2001 From: KD Date: Mon, 1 Apr 2024 08:32:10 +0200 Subject: [PATCH 15/19] fix: TransactionStatus export --- .../components/transaction/transactionDataListItem/index.ts | 2 +- .../transactionDataListItemStructure/index.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/index.ts b/src/modules/components/transaction/transactionDataListItem/index.ts index 3113ec6eb..03b613d59 100644 --- a/src/modules/components/transaction/transactionDataListItem/index.ts +++ b/src/modules/components/transaction/transactionDataListItem/index.ts @@ -5,6 +5,6 @@ export const TransactionDataListItem = { }; export { ITransactionDataListItemProps, + TransactionStatus, TransactionType, - TxStatusCode, } from './transactionDataListItemStructure/transactionDataListItemStructure.api'; diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts index 26496a2e8..28cf62e9a 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts @@ -1,2 +1,6 @@ export { TransactionDataListItemStructure } from './transactionDataListItemStructure'; -export { ITransactionDataListItemProps, TransactionType, TxStatusCode } from './transactionDataListItemStructure.api'; +export { + ITransactionDataListItemProps, + TransactionStatus, + TransactionType, +} from './transactionDataListItemStructure.api'; From b02ab99ea7f4257761a0db34895ccdd204f2bc2f Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 3 Apr 2024 10:14:51 +0200 Subject: [PATCH 16/19] chore: update failed state, revise tests --- .../transactionDataListItem.test.tsx | 10 +++-- .../transactionDataListItemStructure.tsx | 43 ++++++++----------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index 6df7dab0e..e43599b19 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -10,7 +10,7 @@ import { jest.mock('wagmi', () => ({ useChains: () => [ { - id: '1', + id: 1, blockExplorers: { default: { url: 'https://example.com' } }, }, ], @@ -62,9 +62,9 @@ describe(' component', () => { expect(formattedUsdEstimate).toBeInTheDocument(); }); - it('overrides the transaction type display with the transaction status', () => { + it('renders a failed transaction indicator alongside the transaction type', () => { render(createTestComponent({ type: TransactionType.DEPOSIT, status: TransactionStatus.FAILED })); - const failedTransactionText = screen.getByText('Failed transaction'); + const failedTransactionText = screen.getByText('Deposit failed'); expect(failedTransactionText).toBeInTheDocument(); const closeIcon = screen.getByTestId('CLOSE'); expect(closeIcon).toBeInTheDocument(); @@ -77,7 +77,9 @@ describe(' component', () => { }); it('renders with the correct block explorer URL', async () => { - render(createTestComponent()); + const chainId = 1; + const hash = '0x123'; + render(createTestComponent({ chainId, hash })); await waitFor(() => { const linkElement = screen.getByRole('link'); diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index abbb99469..130939404 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -6,7 +6,6 @@ import { TransactionType, txHeadingStringList, txIconTypeList, - txVariantList, type ITransactionDataListItemProps, } from './transactionDataListItemStructure.api'; @@ -27,32 +26,12 @@ export const TransactionDataListItemStructure: React.FC chain.id.toString() === chainId.toString()); + const matchingChain = chains?.find((chain) => chain.id === chainId); const blockExplorerBaseUrl = matchingChain?.blockExplorers?.default?.url; const blockExplorerAssembledHref = blockExplorerBaseUrl && hash ? `${blockExplorerBaseUrl}/tx/${hash}` : undefined; const parsedHref = blockExplorerAssembledHref ?? href; - const getEffectiveTxType = () => { - const e = type; - if (status === TransactionStatus.FAILED) { - return { - icon: IconType.CLOSE, - variant: 'critical' as const, - heading: 'Failed transaction', - }; - } - - return { - icon: txIconTypeList[e], - variant: txVariantList[e], - heading: txHeadingStringList[e], - }; - }; - - const { icon, variant, heading } = getEffectiveTxType(); - const formattedTokenValue = formatterUtils.formatNumber(tokenAmount && tokenAmount > 0 ? tokenAmount : null, { format: NumberFormat.TOKEN_AMOUNT_SHORT, }); @@ -78,8 +57,21 @@ export const TransactionDataListItemStructure: React.FC
- {status !== TransactionStatus.PENDING && ( - + {status === TransactionStatus.SUCCESS && ( + + )} + {status === TransactionStatus.FAILED && ( + )} {status === TransactionStatus.PENDING && (
@@ -88,7 +80,8 @@ export const TransactionDataListItemStructure: React.FC - {heading} + {txHeadingStringList[type]} + {status === TransactionStatus.FAILED && ' failed'} {timestamp ? timestamp : '-'} From 8e1993ec4fe325f228e8d32ecec4315c86e31b7e Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 3 Apr 2024 11:02:28 +0200 Subject: [PATCH 17/19] fix: resolve PR convos - spy test, move consts, remove unnecessary checks and styles --- .../transactionDataListItem.test.tsx | 47 ++++++++----- .../transactionDataListItemStructure.api.ts | 30 ++------ .../transactionDataListItemStructure.tsx | 68 ++++++++++++------- 3 files changed, 81 insertions(+), 64 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx index e43599b19..235e96be5 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx @@ -1,4 +1,5 @@ import { render, screen, waitFor } from '@testing-library/react'; +import * as wagmi from 'wagmi'; import { DataList, NumberFormat, formatterUtils } from '../../../../../core'; import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; import { @@ -7,22 +8,36 @@ import { type ITransactionDataListItemProps, } from './transactionDataListItemStructure.api'; -jest.mock('wagmi', () => ({ - useChains: () => [ - { - id: 1, - blockExplorers: { default: { url: 'https://example.com' } }, - }, - ], -})); +describe(' component', () => { + const useChainsMock = jest.spyOn(wagmi, 'useChains'); + + beforeEach(() => { + useChainsMock.mockReturnValue([ + { + id: 1, + blockExplorers: { + default: { name: 'Etherscan', url: 'https://etherscan.io', apiUrl: 'https://api.etherscan.io/api' }, + }, + name: 'Chain Name', + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + rpcUrls: { default: { http: ['https://cloudflare-eth.com'] } }, + }, + ]); + }); + + afterEach(() => { + useChainsMock.mockReset(); + }); -describe(' component', () => { const createTestComponent = (props?: Partial) => { const defaultProps: ITransactionDataListItemProps = { chainId: 1, - type: TransactionType.ACTION, - status: TransactionStatus.PENDING, hash: '0x123', + date: '2023-01-01T00:00:00Z', ...props, }; return ( @@ -64,16 +79,16 @@ describe(' component', () => { it('renders a failed transaction indicator alongside the transaction type', () => { render(createTestComponent({ type: TransactionType.DEPOSIT, status: TransactionStatus.FAILED })); - const failedTransactionText = screen.getByText('Deposit failed'); + const failedTransactionText = screen.getByText('Deposit'); expect(failedTransactionText).toBeInTheDocument(); const closeIcon = screen.getByTestId('CLOSE'); expect(closeIcon).toBeInTheDocument(); }); it('renders the provided timestamp correctly', () => { - const timestamp = '2023-01-01T00:00:00Z'; - render(createTestComponent({ timestamp })); - expect(screen.getByText(timestamp)).toBeInTheDocument(); + const date = '2000-01-01T00:00:00Z'; + render(createTestComponent({ date })); + expect(screen.getByText(date)).toBeInTheDocument(); }); it('renders with the correct block explorer URL', async () => { @@ -83,7 +98,7 @@ describe(' component', () => { await waitFor(() => { const linkElement = screen.getByRole('link'); - expect(linkElement).toHaveAttribute('href', 'https://example.com/tx/0x123'); + expect(linkElement).toHaveAttribute('href', 'https://etherscan.io/tx/0x123'); }); }); }); diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts index 9593952f6..baf8f889f 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts @@ -1,5 +1,5 @@ import { type Hash } from 'viem'; -import { IconType, type AvatarIconVariant, type IDataListItemProps } from '../../../../../core'; +import { type IDataListItemProps } from '../../../../../core'; export enum TransactionStatus { PENDING = 'PENDING', @@ -13,24 +13,6 @@ export enum TransactionType { ACTION = 'ACTION', } -export const txHeadingStringList: Record = { - [TransactionType.DEPOSIT]: 'Deposit', - [TransactionType.WITHDRAW]: 'Withdraw', - [TransactionType.ACTION]: 'Smart contract action', -}; - -export const txIconTypeList: Record = { - [TransactionType.DEPOSIT]: IconType.DEPOSIT, - [TransactionType.WITHDRAW]: IconType.WITHDRAW, - [TransactionType.ACTION]: IconType.BLOCKCHAIN_SMARTCONTRACT, -}; - -export const txVariantList: Record = { - [TransactionType.DEPOSIT]: 'success', - [TransactionType.WITHDRAW]: 'warning', - [TransactionType.ACTION]: 'info', -}; - export interface ITransactionDataListItemProps extends IDataListItemProps { /** * The chain ID of the transaction. @@ -47,23 +29,25 @@ export interface ITransactionDataListItemProps extends IDataListItemProps { /** * The token value in the transaction. */ - tokenAmount?: number; + tokenAmount?: number | string; /** * The estimated fiat value of the transaction. */ tokenPrice?: number | string; /** - * The type of transaction. @default TransactionType.ACTION + * The type of transaction. + * @default TransactionType.ACTION */ type?: TransactionType; /** - * The current status of a blockchain transaction on the network. @default TransactionStatus.PENDING + * The current status of a blockchain transaction on the network. + * @default TransactionStatus.PENDING */ status?: TransactionStatus; /** * The Unix timestamp of the transaction. */ - timestamp?: string; + date: string; /** * The transaction hash. */ diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 130939404..187ce77df 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -1,14 +1,38 @@ import classNames from 'classnames'; import { useChains } from 'wagmi'; -import { AvatarIcon, DataList, Heading, IconType, NumberFormat, Spinner, formatterUtils } from '../../../../../core'; +import { + AvatarIcon, + DataList, + IconType, + NumberFormat, + Spinner, + formatterUtils, + type AvatarIconVariant, +} from '../../../../../core'; import { TransactionStatus, TransactionType, - txHeadingStringList, - txIconTypeList, type ITransactionDataListItemProps, } from './transactionDataListItemStructure.api'; +const txHeadingStringList: Record = { + [TransactionType.DEPOSIT]: 'Deposit', + [TransactionType.WITHDRAW]: 'Withdraw', + [TransactionType.ACTION]: 'Smart contract action', +}; + +const txIconTypeList: Record = { + [TransactionType.DEPOSIT]: IconType.DEPOSIT, + [TransactionType.WITHDRAW]: IconType.WITHDRAW, + [TransactionType.ACTION]: IconType.BLOCKCHAIN_SMARTCONTRACT, +}; + +const txVariantList: Record = { + [TransactionType.DEPOSIT]: 'success', + [TransactionType.WITHDRAW]: 'warning', + [TransactionType.ACTION]: 'info', +}; + export const TransactionDataListItemStructure: React.FC = (props) => { const { chainId, @@ -19,38 +43,35 @@ export const TransactionDataListItemStructure: React.FC chain.id === chainId); const blockExplorerBaseUrl = matchingChain?.blockExplorers?.default?.url; - const blockExplorerAssembledHref = blockExplorerBaseUrl && hash ? `${blockExplorerBaseUrl}/tx/${hash}` : undefined; + const blockExplorerAssembledHref = blockExplorerBaseUrl ? `${blockExplorerBaseUrl}/tx/${hash}` : undefined; const parsedHref = blockExplorerAssembledHref ?? href; - const formattedTokenValue = formatterUtils.formatNumber(tokenAmount && tokenAmount > 0 ? tokenAmount : null, { + const formattedTokenValue = formatterUtils.formatNumber(tokenAmount, { format: NumberFormat.TOKEN_AMOUNT_SHORT, }); const fiatValue = Number(tokenAmount ?? 0) * Number(tokenPrice ?? 0); - - const formattedTokenPrice = formatterUtils.formatNumber( - fiatValue && type !== TransactionType.ACTION ? fiatValue : 0, - { - format: NumberFormat.FIAT_TOTAL_SHORT, - }, - ); + const formattedTokenPrice = formatterUtils.formatNumber(fiatValue, { + format: NumberFormat.FIAT_TOTAL_SHORT, + }); const formattedTokenAmount = type === TransactionType.ACTION || tokenAmount == null ? '-' : `${formattedTokenValue} ${tokenSymbol}`; return ( @@ -79,23 +100,20 @@ export const TransactionDataListItemStructure: React.FC )}
- +

{txHeadingStringList[type]} - {status === TransactionStatus.FAILED && ' failed'} - - - {timestamp ? timestamp : '-'} - +

+

{date}

- +

{formattedTokenAmount} - - +

+

{formattedTokenPrice} - +

From 2582f01f4643e3443c8b3be48f42626562a9aac0 Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 3 Apr 2024 11:15:09 +0200 Subject: [PATCH 18/19] fix: remove console.log --- .../transactionDataListItemStructure.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 187ce77df..7de308898 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -50,7 +50,7 @@ export const TransactionDataListItemStructure: React.FC chain.id === chainId); const blockExplorerBaseUrl = matchingChain?.blockExplorers?.default?.url; const blockExplorerAssembledHref = blockExplorerBaseUrl ? `${blockExplorerBaseUrl}/tx/${hash}` : undefined; From d27d8ea8acf8c16ef95b1201d16a41c6f7b77639 Mon Sep 17 00:00:00 2001 From: KD Date: Wed, 3 Apr 2024 13:21:23 +0200 Subject: [PATCH 19/19] fix: swap out for additonal span tags --- .../transactionDataListItemStructure.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx index 7de308898..9292f9b5a 100644 --- a/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx +++ b/src/modules/components/transaction/transactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx @@ -100,20 +100,20 @@ export const TransactionDataListItemStructure: React.FC )}
-

+ {txHeadingStringList[type]} -

+

{date}

-

+ {formattedTokenAmount} -

-

+ + {formattedTokenPrice} -

+