From 0a0894e098da01f24737e30d9699348e2f4ba5dd Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Tue, 15 Oct 2024 23:21:32 +0100 Subject: [PATCH 1/6] Remove global network from useBalanceChanges Add transaction prop to SimulationDetails. --- .../base-transaction-info.tsx | 3 +-- .../simulation-details.test.tsx | 6 ++++-- .../simulation-details/simulation-details.tsx | 14 ++++++------- .../useBalanceChanges.test.ts | 21 +++++++++++++------ .../simulation-details/useBalanceChanges.ts | 13 +++++++----- .../confirm-transaction-base.component.js | 6 +----- .../smart-transaction-status-page.tsx | 5 +---- 7 files changed, 37 insertions(+), 31 deletions(-) diff --git a/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx b/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx index a1ed4a1e43dc..e4199935ba70 100644 --- a/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx +++ b/ui/pages/confirmations/components/confirm/info/base-transaction-info/base-transaction-info.tsx @@ -26,8 +26,7 @@ const BaseTransactionInfo = () => { <> diff --git a/ui/pages/confirmations/components/simulation-details/simulation-details.test.tsx b/ui/pages/confirmations/components/simulation-details/simulation-details.test.tsx index 5971e513e3a1..5bb182ac7e66 100644 --- a/ui/pages/confirmations/components/simulation-details/simulation-details.test.tsx +++ b/ui/pages/confirmations/components/simulation-details/simulation-details.test.tsx @@ -4,6 +4,7 @@ import { screen } from '@testing-library/react'; import { SimulationData, SimulationErrorCode, + TransactionMeta, } from '@metamask/transaction-controller'; import { BigNumber } from 'bignumber.js'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; @@ -28,8 +29,9 @@ jest.mock('./useSimulationMetrics'); const renderSimulationDetails = (simulationData?: Partial) => renderWithProvider( , store, ); diff --git a/ui/pages/confirmations/components/simulation-details/simulation-details.tsx b/ui/pages/confirmations/components/simulation-details/simulation-details.tsx index 79d5c2105a9c..498e34743184 100644 --- a/ui/pages/confirmations/components/simulation-details/simulation-details.tsx +++ b/ui/pages/confirmations/components/simulation-details/simulation-details.tsx @@ -2,6 +2,7 @@ import { SimulationData, SimulationError, SimulationErrorCode, + TransactionMeta, } from '@metamask/transaction-controller'; import React from 'react'; import { @@ -30,10 +31,10 @@ import { useBalanceChanges } from './useBalanceChanges'; import { useSimulationMetrics } from './useSimulationMetrics'; export type SimulationDetailsProps = { - simulationData?: SimulationData; - transactionId: string; enableMetrics?: boolean; isTransactionsRedesign?: boolean; + simulationData?: SimulationData; + transaction: TransactionMeta; }; /** @@ -172,20 +173,19 @@ const SimulationDetailsLayout: React.FC<{ * Preview of a transaction's effects using simulation data. * * @param props - * @param props.simulationData - The simulation data to display. - * @param props.transactionId - The ID of the transaction being simulated. + * @param props.transaction - Metadata of the transaction that was simulated. * @param props.enableMetrics - Whether to enable simulation metrics. * @param props.isTransactionsRedesign - Whether or not the component is being * used inside the transaction redesign flow. */ export const SimulationDetails: React.FC = ({ - simulationData, - transactionId, + transaction, enableMetrics = false, isTransactionsRedesign = false, }: SimulationDetailsProps) => { const t = useI18nContext(); - const balanceChangesResult = useBalanceChanges(simulationData); + const { chainId, id: transactionId, simulationData } = transaction; + const balanceChangesResult = useBalanceChanges({ chainId, simulationData }); const loading = !simulationData || balanceChangesResult.pending; useSimulationMetrics({ diff --git a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts index 10e4cca518b7..8101fa0b477c 100644 --- a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts +++ b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts @@ -57,6 +57,8 @@ const DIFFERENCE_1_MOCK: Hex = '0x11'; const DIFFERENCE_2_MOCK: Hex = '0x2'; const DIFFERENCE_ETH_MOCK: Hex = '0x1234567890123456789'; +const CHAIN_ID_MOCK = '0x123'; + const dummyBalanceChange = { previousBalance: '0xIGNORE' as Hex, newBalance: '0xIGNORE' as Hex, @@ -98,7 +100,10 @@ describe('useBalanceChanges', () => { describe('pending states', () => { it('returns pending=true if no simulation data', async () => { const { result, waitForNextUpdate } = renderHook(() => - useBalanceChanges(undefined), + useBalanceChanges({ + chainId: CHAIN_ID_MOCK, + simulationData: undefined, + }), ); expect(result.current).toEqual({ pending: true, value: [] }); await waitForNextUpdate(); @@ -119,7 +124,7 @@ describe('useBalanceChanges', () => { ], }; const { result, unmount, waitForNextUpdate } = renderHook(() => - useBalanceChanges(simulationData), + useBalanceChanges({ chainId: CHAIN_ID_MOCK, simulationData }), ); await waitForNextUpdate(); @@ -143,7 +148,7 @@ describe('useBalanceChanges', () => { ], }; const { result, unmount, waitForNextUpdate } = renderHook(() => - useBalanceChanges(simulationData), + useBalanceChanges({ chainId: CHAIN_ID_MOCK, simulationData }), ); await waitForNextUpdate(); @@ -161,7 +166,9 @@ describe('useBalanceChanges', () => { nativeBalanceChange: undefined, tokenBalanceChanges, }; - return renderHook(() => useBalanceChanges(simulationData)); + return renderHook(() => + useBalanceChanges({ chainId: CHAIN_ID_MOCK, simulationData }), + ); }; it('maps token balance changes correctly', async () => { @@ -307,7 +314,9 @@ describe('useBalanceChanges', () => { nativeBalanceChange, tokenBalanceChanges: [], }; - return renderHook(() => useBalanceChanges(simulationData)); + return renderHook(() => + useBalanceChanges({ chainId: CHAIN_ID_MOCK, simulationData }), + ); }; it('maps native balance change correctly', async () => { @@ -382,7 +391,7 @@ describe('useBalanceChanges', () => { ], }; const { result, waitForNextUpdate } = renderHook(() => - useBalanceChanges(simulationData), + useBalanceChanges({ chainId: CHAIN_ID_MOCK, simulationData }), ); await waitForNextUpdate(); diff --git a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts index 2a198d76ea36..1c3fa3702c31 100644 --- a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts +++ b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts @@ -11,7 +11,7 @@ import { ContractExchangeRates } from '@metamask/assets-controllers'; import { useAsyncResultOrThrow } from '../../../../hooks/useAsyncResult'; import { TokenStandard } from '../../../../../shared/constants/transaction'; import { getConversionRate } from '../../../../ducks/metamask/metamask'; -import { getCurrentChainId, getCurrentCurrency } from '../../../../selectors'; +import { getCurrentCurrency } from '../../../../selectors'; import { fetchTokenExchangeRates } from '../../../../helpers/utils/util'; import { ERC20_DEFAULT_DECIMALS, fetchErc20Decimals } from '../../utils/token'; @@ -140,10 +140,13 @@ function getTokenBalanceChanges( } // Compiles a list of balance changes from simulation data -export const useBalanceChanges = ( - simulationData: SimulationData | undefined, -): { pending: boolean; value: BalanceChange[] } => { - const chainId = useSelector(getCurrentChainId); +export const useBalanceChanges = ({ + chainId, + simulationData, +}: { + chainId: Hex; + simulationData?: SimulationData; +}): { pending: boolean; value: BalanceChange[] } => { const fiatCurrency = useSelector(getCurrentCurrency); const nativeFiatRate = useSelector(getConversionRate); diff --git a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js index 96fd5315e317..a808a67e2481 100644 --- a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js @@ -536,11 +536,7 @@ export default class ConfirmTransactionBase extends Component { const { simulationData } = txData; const simulationDetails = ( - + ); const showTotals = Boolean(simulationData?.error); diff --git a/ui/pages/smart-transactions/smart-transaction-status-page/smart-transaction-status-page.tsx b/ui/pages/smart-transactions/smart-transaction-status-page/smart-transaction-status-page.tsx index 4492ed4e4844..5e4ef2511a51 100644 --- a/ui/pages/smart-transactions/smart-transaction-status-page/smart-transaction-status-page.tsx +++ b/ui/pages/smart-transactions/smart-transaction-status-page/smart-transaction-status-page.tsx @@ -366,10 +366,7 @@ export const SmartTransactionStatusPage = ({ {canShowSimulationDetails && ( - + )} From 6440e4bd9e7964b43a117c147bb265ee428bb8ed Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Wed, 16 Oct 2024 11:39:10 +0100 Subject: [PATCH 2/6] Fix storybook --- .storybook/main.js | 3 + .../simulation-details.stories.tsx | 277 ++++++++++-------- 2 files changed, 151 insertions(+), 129 deletions(-) diff --git a/.storybook/main.js b/.storybook/main.js index d63d924aa2e2..e55c33612faf 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -48,6 +48,9 @@ module.exports = { config.resolve.alias['../../../../../../store/actions'] = require.resolve( '../ui/__mocks__/actions.js', ); + config.resolve.alias['../../../store/actions'] = require.resolve( + '../ui/__mocks__/actions.js', + ); // Import within controller-utils crashes storybook. config.resolve.alias['@ethereumjs/util'] = require.resolve( '../ui/__mocks__/ethereumjs-util.js', diff --git a/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx b/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx index 7c4fdc6e0d22..42596e505311 100644 --- a/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx +++ b/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx @@ -8,6 +8,7 @@ import { Hex } from '@metamask/utils'; import { SimulationErrorCode, SimulationTokenStandard, + TransactionMeta, } from '@metamask/transaction-controller'; import { NameType } from '@metamask/name-controller'; import { CHAIN_IDS } from '../../../../../shared/constants/network'; @@ -71,19 +72,11 @@ const storeMock = configureStore({ }, }); -const storeMockPolygon = configureStore({ - metamask: { - ...mockState.metamask, - ...mockNetworkState({ chainId: CHAIN_IDS.POLYGON }), - }, -}); - -const storeMockArbitrum = configureStore({ - metamask: { - ...mockState.metamask, - ...mockNetworkState({ chainId: CHAIN_IDS.ARBITRUM }), - }, -}); +function createTransactionMeta( + metadata: Partial, +): TransactionMeta { + return metadata as TransactionMeta; +} const meta: Meta = { title: 'Components/App/SimulationDetails', @@ -96,180 +89,206 @@ type Story = StoryObj; export const MultipleTokens: Story = { args: { - simulationData: { - nativeBalanceChange: { - ...DUMMY_BALANCE_CHANGE, - difference: '0x12345678912345678', - isDecrease: true, - }, - tokenBalanceChanges: [ - { - ...DUMMY_BALANCE_CHANGE, - address: ERC20_TOKEN_1_MOCK, - difference: '0x123456', - isDecrease: false, - standard: SimulationTokenStandard.erc20, - }, - { - ...DUMMY_BALANCE_CHANGE, - address: ERC20_TOKEN_2_MOCK, - difference: '0x123456901', - isDecrease: false, - standard: SimulationTokenStandard.erc20, - }, - { + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + nativeBalanceChange: { ...DUMMY_BALANCE_CHANGE, - address: ERC721_TOKEN_MOCK, - difference: '0x1', - isDecrease: false, - id: '0x721', - standard: SimulationTokenStandard.erc721, + difference: '0x12345678912345678', + isDecrease: true, }, - { - ...DUMMY_BALANCE_CHANGE, - address: ERC1155_TOKEN_MOCK, - difference: '0x13', - isDecrease: false, - id: '0x1155', - standard: SimulationTokenStandard.erc1155, - }, - ], - }, + tokenBalanceChanges: [ + { + ...DUMMY_BALANCE_CHANGE, + address: ERC20_TOKEN_1_MOCK, + difference: '0x123456', + isDecrease: false, + standard: SimulationTokenStandard.erc20, + }, + { + ...DUMMY_BALANCE_CHANGE, + address: ERC20_TOKEN_2_MOCK, + difference: '0x123456901', + isDecrease: false, + standard: SimulationTokenStandard.erc20, + }, + { + ...DUMMY_BALANCE_CHANGE, + address: ERC721_TOKEN_MOCK, + difference: '0x1', + isDecrease: false, + id: '0x721', + standard: SimulationTokenStandard.erc721, + }, + { + ...DUMMY_BALANCE_CHANGE, + address: ERC1155_TOKEN_MOCK, + difference: '0x13', + isDecrease: false, + id: '0x1155', + standard: SimulationTokenStandard.erc1155, + }, + ], + }, + }), }, }; export const SendSmallAmount: Story = { args: { - simulationData: { - nativeBalanceChange: { - ...DUMMY_BALANCE_CHANGE, - difference: '0x123', - isDecrease: true, + transaction: createTransactionMeta({ + simulationData: { + nativeBalanceChange: { + ...DUMMY_BALANCE_CHANGE, + difference: '0x123', + isDecrease: true, + }, + tokenBalanceChanges: [], }, - tokenBalanceChanges: [], - }, + }), }, }; export const LongValuesAndNames: Story = { args: { - simulationData: { - nativeBalanceChange: { - ...DUMMY_BALANCE_CHANGE, - difference: '0x12345678912345678', - isDecrease: true, - }, - tokenBalanceChanges: [ - { + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + nativeBalanceChange: { ...DUMMY_BALANCE_CHANGE, - address: ERC20_TOKEN_1_MOCK, - difference: '0x42345909', - isDecrease: false, - standard: SimulationTokenStandard.erc20, + difference: '0x12345678912345678', + isDecrease: true, }, - { - ...DUMMY_BALANCE_CHANGE, - address: ERC20_TOKEN_2_MOCK, - difference: '0x123456901', - isDecrease: false, - standard: SimulationTokenStandard.erc20, - }, - ], - }, + tokenBalanceChanges: [ + { + ...DUMMY_BALANCE_CHANGE, + address: ERC20_TOKEN_1_MOCK, + difference: '0x42345909', + isDecrease: false, + standard: SimulationTokenStandard.erc20, + }, + { + ...DUMMY_BALANCE_CHANGE, + address: ERC20_TOKEN_2_MOCK, + difference: '0x123456901', + isDecrease: false, + standard: SimulationTokenStandard.erc20, + }, + ], + }, + }), }, }; export const PolygonNativeAsset: Story = { args: { - simulationData: { - nativeBalanceChange: { - ...DUMMY_BALANCE_CHANGE, - difference: '0x9345678923456789', - isDecrease: true, + transaction: createTransactionMeta({ + chainId: CHAIN_IDS.POLYGON, + simulationData: { + nativeBalanceChange: { + ...DUMMY_BALANCE_CHANGE, + difference: '0x9345678923456789', + isDecrease: true, + }, + tokenBalanceChanges: [], }, - tokenBalanceChanges: [], - }, + }), }, - decorators: [ - (story) => {story()}, - ], }; export const ArbitrumNativeAsset: Story = { args: { - simulationData: { - nativeBalanceChange: { - ...DUMMY_BALANCE_CHANGE, - difference: '0x9345678923456789', - isDecrease: true, + transaction: createTransactionMeta({ + chainId: CHAIN_IDS.ARBITRUM, + simulationData: { + nativeBalanceChange: { + ...DUMMY_BALANCE_CHANGE, + difference: '0x9345678923456789', + isDecrease: true, + }, + tokenBalanceChanges: [], }, - tokenBalanceChanges: [], - }, + }), }, - decorators: [ - (story) => {story()}, - ], }; export const ReceiveOnly: Story = { args: { - simulationData: { - nativeBalanceChange: { - previousBalance: '0x2', - newBalance: '0x1', - difference: '0x12345678912345678', - isDecrease: false, + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + nativeBalanceChange: { + previousBalance: '0x2', + newBalance: '0x1', + difference: '0x12345678912345678', + isDecrease: false, + }, + tokenBalanceChanges: [], }, - tokenBalanceChanges: [], - }, + }), }, }; export const SendOnly: Story = { args: { - simulationData: { - nativeBalanceChange: { - previousBalance: '0x1', - newBalance: '0x2', - difference: '0x12345678912345678', - isDecrease: true, + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + nativeBalanceChange: { + previousBalance: '0x1', + newBalance: '0x2', + difference: '0x12345678912345678', + isDecrease: true, + }, + tokenBalanceChanges: [], }, - tokenBalanceChanges: [], - }, + }), }, }; export const NoBalanceChanges: Story = { args: { - simulationData: { - nativeBalanceChange: undefined, - tokenBalanceChanges: [], - }, + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + nativeBalanceChange: undefined, + tokenBalanceChanges: [], + }, + }), }, }; export const Loading: Story = { args: { - simulationData: undefined, + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: undefined, + }), }, }; export const TransactionReverted: Story = { args: { - simulationData: { - error: { code: SimulationErrorCode.Reverted }, - nativeBalanceChange: undefined, - tokenBalanceChanges: [], - }, + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + error: { code: SimulationErrorCode.Reverted }, + nativeBalanceChange: undefined, + tokenBalanceChanges: [], + }, + }), }, }; export const GenericError: Story = { args: { - simulationData: { - error: {}, - nativeBalanceChange: undefined, - tokenBalanceChanges: [], - }, + transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, + simulationData: { + error: {}, + nativeBalanceChange: undefined, + tokenBalanceChanges: [], + }, + }), }, }; From bc6e6e311bac002404cbc2f3a9331767d50320e3 Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Thu, 24 Oct 2024 16:14:03 +0100 Subject: [PATCH 3/6] Remove current chain selectors --- .../info/token-transfer/token-transfer.tsx | 3 +-- .../simulation-details/amount-pill.test.tsx | 15 +++++++++++++-- .../simulation-details/asset-pill.test.tsx | 15 ++++++++++----- .../simulation-details/asset-pill.tsx | 14 +++++--------- .../components/simulation-details/types.ts | 6 ++---- .../simulation-details/useBalanceChanges.ts | 17 +++++++++++++++-- .../simulation-details/useSimulationMetrics.ts | 7 +------ 7 files changed, 47 insertions(+), 30 deletions(-) diff --git a/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx b/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx index b89e87350a36..df1136ec5213 100644 --- a/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx +++ b/ui/pages/confirmations/components/confirm/info/token-transfer/token-transfer.tsx @@ -22,8 +22,7 @@ const TokenTransferInfo = () => { {!isWalletInitiated && ( diff --git a/ui/pages/confirmations/components/simulation-details/amount-pill.test.tsx b/ui/pages/confirmations/components/simulation-details/amount-pill.test.tsx index 044eca8d887c..d08f9d7d1c52 100644 --- a/ui/pages/confirmations/components/simulation-details/amount-pill.test.tsx +++ b/ui/pages/confirmations/components/simulation-details/amount-pill.test.tsx @@ -6,7 +6,7 @@ import Tooltip from '../../../../components/ui/tooltip'; import { AmountPill } from './amount-pill'; import { AssetIdentifier, - NATIVE_ASSET_IDENTIFIER, + NativeAssetIdentifier, TokenAssetIdentifier, } from './types'; @@ -24,17 +24,28 @@ jest.mock('../../../../components/ui/tooltip', () => ({ })); const TOKEN_ID_MOCK = '0xabc'; +const CHAIN_ID_MOCK = '0x1'; + +const NATIVE_ASSET_MOCK: NativeAssetIdentifier = { + chainId: CHAIN_ID_MOCK, + standard: TokenStandard.none, +}; const ERC20_ASSET_MOCK: TokenAssetIdentifier = { + chainId: CHAIN_ID_MOCK, standard: TokenStandard.ERC20, address: '0x456', }; + const ERC721_ASSET_MOCK: TokenAssetIdentifier = { + chainId: CHAIN_ID_MOCK, standard: TokenStandard.ERC721, address: '0x123', tokenId: TOKEN_ID_MOCK, }; + const ERC1155_ASSET_MOCK: TokenAssetIdentifier = { + chainId: CHAIN_ID_MOCK, standard: TokenStandard.ERC1155, address: '0x789', tokenId: TOKEN_ID_MOCK, @@ -114,7 +125,7 @@ describe('AmountPill', () => { amount: BigNumber; expected: { text: string; tooltip: string }; }) => { - renderAndExpect(NATIVE_ASSET_IDENTIFIER, amount, expected); + renderAndExpect(NATIVE_ASSET_MOCK, amount, expected); }, ); }); diff --git a/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx b/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx index 477119b02284..e41d49145195 100644 --- a/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx +++ b/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx @@ -10,7 +10,7 @@ import { AvatarNetwork } from '../../../../components/component-library/avatar-n import { mockNetworkState } from '../../../../../test/stub/networks'; import mockState from '../../../../../test/data/mock-state.json'; import { AssetPill } from './asset-pill'; -import { NATIVE_ASSET_IDENTIFIER, TokenAssetIdentifier } from './types'; +import { NativeAssetIdentifier, TokenAssetIdentifier } from './types'; jest.mock('../../../../components/component-library/avatar-network', () => ({ AvatarNetworkSize: { Sm: 'Sm' }, @@ -22,6 +22,8 @@ jest.mock('../../../../components/app/name', () => ({ default: jest.fn(() => null), })); +const CHAIN_ID_MOCK = '0x1'; + describe('AssetPill', () => { beforeEach(() => { jest.clearAllMocks(); @@ -61,10 +63,12 @@ describe('AssetPill', () => { }, }); - renderWithProvider( - , - store, - ); + const asset: NativeAssetIdentifier = { + chainId: CHAIN_ID_MOCK, + standard: TokenStandard.none, + }; + + renderWithProvider(, store); expect(screen.getByText(expected.ticker)).toBeInTheDocument(); @@ -81,6 +85,7 @@ describe('AssetPill', () => { it('renders Name component with correct props when asset standard is not none', () => { const asset: TokenAssetIdentifier = { + chainId: CHAIN_ID_MOCK, standard: TokenStandard.ERC20, address: '0x1234567890123456789012345678901234567890', }; diff --git a/ui/pages/confirmations/components/simulation-details/asset-pill.tsx b/ui/pages/confirmations/components/simulation-details/asset-pill.tsx index 1545c86e452c..bae092aaf399 100644 --- a/ui/pages/confirmations/components/simulation-details/asset-pill.tsx +++ b/ui/pages/confirmations/components/simulation-details/asset-pill.tsx @@ -18,10 +18,7 @@ import { } from '../../../../helpers/constants/design-system'; import Name from '../../../../components/app/name'; import { TokenStandard } from '../../../../../shared/constants/transaction'; -import { - getCurrentChainId, - getNativeCurrencyImage, -} from '../../../../selectors'; +import { getNativeCurrencyImage } from '../../../../selectors'; import { getNativeCurrency } from '../../../../ducks/metamask/metamask'; import { AssetIdentifier } from './types'; @@ -60,10 +57,9 @@ const NativeAssetPill: React.FC = () => { * @param props * @param props.asset */ -export const AssetPill: React.FC<{ asset: AssetIdentifier }> = ({ asset }) => { - // TODO: Temporary pending multi-chain support in simulations; - const chainId = useSelector(getCurrentChainId); - +export const AssetPill: React.FC<{ + asset: AssetIdentifier; +}> = ({ asset }) => { return ( = ({ asset }) => { preferContractSymbol type={NameType.ETHEREUM_ADDRESS} value={asset.address} - variation={chainId} + variation={asset.chainId} /> )} diff --git a/ui/pages/confirmations/components/simulation-details/types.ts b/ui/pages/confirmations/components/simulation-details/types.ts index 7db6a30357cd..c1a3290f6838 100644 --- a/ui/pages/confirmations/components/simulation-details/types.ts +++ b/ui/pages/confirmations/components/simulation-details/types.ts @@ -2,10 +2,6 @@ import { Hex } from '@metamask/utils'; import { BigNumber } from 'bignumber.js'; import { TokenStandard } from '../../../../../shared/constants/transaction'; -export const NATIVE_ASSET_IDENTIFIER: NativeAssetIdentifier = { - standard: TokenStandard.none, -}; - /** * Describes an amount of fiat. */ @@ -17,6 +13,7 @@ export type FiatAmount = FiatAmountAvailable | typeof FIAT_UNAVAILABLE; * Identifies the native asset of a chain. */ export type NativeAssetIdentifier = { + chainId: Hex; standard: TokenStandard.none; address?: undefined; tokenId?: undefined; @@ -26,6 +23,7 @@ export type NativeAssetIdentifier = { * Uniquely identifies a token asset on a chain. */ export type TokenAssetIdentifier = { + chainId: Hex; standard: Exclude; address: Hex; tokenId?: Hex; diff --git a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts index 1c3fa3702c31..1bbc9cb5eec8 100644 --- a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts +++ b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.ts @@ -18,7 +18,7 @@ import { ERC20_DEFAULT_DECIMALS, fetchErc20Decimals } from '../../utils/token'; import { BalanceChange, FIAT_UNAVAILABLE, - NATIVE_ASSET_IDENTIFIER, + NativeAssetIdentifier, TokenAssetIdentifier, } from './types'; @@ -94,17 +94,25 @@ async function fetchTokenFiatRates( function getNativeBalanceChange( nativeBalanceChange: SimulationBalanceChange | undefined, nativeFiatRate: number | undefined, + chainId: Hex, ): BalanceChange | undefined { if (!nativeBalanceChange) { return undefined; } - const asset = NATIVE_ASSET_IDENTIFIER; + + const asset: NativeAssetIdentifier = { + chainId, + standard: TokenStandard.none, + }; + const amount = getAssetAmount(nativeBalanceChange, NATIVE_DECIMALS); + const fiatAmount = nativeFiatRate ? amount .times(convertNumberToStringWithPrecisionWarning(nativeFiatRate)) .toNumber() : FIAT_UNAVAILABLE; + return { asset, amount, fiatAmount }; } @@ -113,9 +121,11 @@ function getTokenBalanceChanges( tokenBalanceChanges: SimulationTokenBalanceChange[], erc20Decimals: Record, erc20FiatRates: Partial>, + chainId: Hex, ): BalanceChange[] { return tokenBalanceChanges.map((tokenBc) => { const asset: TokenAssetIdentifier = { + chainId, standard: convertStandard(tokenBc.standard), address: tokenBc.address.toLowerCase() as Hex, tokenId: tokenBc.id, @@ -174,11 +184,14 @@ export const useBalanceChanges = ({ const nativeChange = getNativeBalanceChange( nativeBalanceChange, nativeFiatRate, + chainId, ); + const tokenChanges = getTokenBalanceChanges( tokenBalanceChanges, erc20Decimals.value, erc20FiatRates.value, + chainId, ); const balanceChanges: BalanceChange[] = [ diff --git a/ui/pages/confirmations/components/simulation-details/useSimulationMetrics.ts b/ui/pages/confirmations/components/simulation-details/useSimulationMetrics.ts index 1f5c349d0050..15e8327176ea 100644 --- a/ui/pages/confirmations/components/simulation-details/useSimulationMetrics.ts +++ b/ui/pages/confirmations/components/simulation-details/useSimulationMetrics.ts @@ -4,7 +4,6 @@ import { } from '@metamask/transaction-controller'; import { useContext, useEffect, useState } from 'react'; import { NameType } from '@metamask/name-controller'; -import { useSelector } from 'react-redux'; import { useTransactionEventFragment } from '../../hooks/useTransactionEventFragment'; import { UseDisplayNameRequest, @@ -17,7 +16,6 @@ import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../../shared/constants/metametrics'; -import { getCurrentChainId } from '../../../../selectors'; import { calculateTotalFiat } from './fiat-display'; import { BalanceChange } from './types'; import { useLoadingTime } from './useLoadingTime'; @@ -65,9 +63,6 @@ export function useSimulationMetrics({ }: UseSimulationMetricsProps) { const { loadingTime, setLoadingComplete } = useLoadingTime(); - // TODO: Temporary pending multi-chain support in simulations. - const chainId = useSelector(getCurrentChainId); - if (!loading) { setLoadingComplete(); } @@ -79,7 +74,7 @@ export function useSimulationMetrics({ value: asset.address as string, type: NameType.ETHEREUM_ADDRESS, preferContractSymbol: true, - variation: chainId, + variation: asset.chainId, })); const displayNames = useDisplayNames(displayNameRequests); From bf5dad56b23db4f79349f8d0ac19a558f1090e86 Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Thu, 24 Oct 2024 21:33:39 +0100 Subject: [PATCH 4/6] Fix unit tests --- .../components/simulation-details/useBalanceChanges.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts index 23e9afae6683..f77774c6ec4a 100644 --- a/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts +++ b/ui/pages/confirmations/components/simulation-details/useBalanceChanges.test.ts @@ -188,6 +188,7 @@ describe('useBalanceChanges', () => { expect(changes).toEqual([ { asset: { + chainId: CHAIN_ID_MOCK, address: ERC20_TOKEN_ADDRESS_1_MOCK, standard: TokenStandard.ERC20, tokenId: undefined, @@ -244,6 +245,7 @@ describe('useBalanceChanges', () => { expect(result.current.value).toEqual([ { asset: { + chainId: CHAIN_ID_MOCK, address: NFT_TOKEN_ADDRESS_MOCK, standard: TokenStandard.ERC721, tokenId: TOKEN_ID_1_MOCK, @@ -332,6 +334,7 @@ describe('useBalanceChanges', () => { expect(changes).toEqual([ { asset: { + chainId: CHAIN_ID_MOCK, standard: TokenStandard.none, }, amount: new BigNumber('-5373.003641998677469065'), @@ -399,6 +402,7 @@ describe('useBalanceChanges', () => { const changes = result.current.value; expect(changes).toHaveLength(2); expect(changes[0].asset).toEqual({ + chainId: CHAIN_ID_MOCK, standard: TokenStandard.none, }); expect(changes[0].amount).toEqual( @@ -406,6 +410,7 @@ describe('useBalanceChanges', () => { ); expect(changes[0].fiatAmount).toBe(Number('-16119.010925996032')); expect(changes[1].asset).toEqual({ + chainId: CHAIN_ID_MOCK, address: ERC20_TOKEN_ADDRESS_1_MOCK, standard: TokenStandard.ERC20, }); From 59fa0d09302921ff4596e7e00cf3af5997913952 Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Thu, 24 Oct 2024 22:11:34 +0100 Subject: [PATCH 5/6] Fix unit tests --- .../confirm/info/nft-token-transfer/nft-token-transfer.tsx | 3 +-- .../components/simulation-details/simulation-details.tsx | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx b/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx index a2e6a73b4353..b5d579994ef9 100644 --- a/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx +++ b/ui/pages/confirmations/components/confirm/info/nft-token-transfer/nft-token-transfer.tsx @@ -22,8 +22,7 @@ const NFTTokenTransferInfo = () => { {!isWalletInitiated && ( diff --git a/ui/pages/confirmations/components/simulation-details/simulation-details.tsx b/ui/pages/confirmations/components/simulation-details/simulation-details.tsx index 498e34743184..0ad01e921cff 100644 --- a/ui/pages/confirmations/components/simulation-details/simulation-details.tsx +++ b/ui/pages/confirmations/components/simulation-details/simulation-details.tsx @@ -1,5 +1,4 @@ import { - SimulationData, SimulationError, SimulationErrorCode, TransactionMeta, @@ -33,7 +32,6 @@ import { useSimulationMetrics } from './useSimulationMetrics'; export type SimulationDetailsProps = { enableMetrics?: boolean; isTransactionsRedesign?: boolean; - simulationData?: SimulationData; transaction: TransactionMeta; }; From 1706b891d6de64bd532162e72ea02004ffe8ba13 Mon Sep 17 00:00:00 2001 From: Matthew Walsh Date: Thu, 24 Oct 2024 23:11:38 +0100 Subject: [PATCH 6/6] Fix stories --- .../simulation-details/asset-pill.test.tsx | 2 +- .../simulation-details/asset-pill.tsx | 28 ++++++--- .../simulation-details.stories.tsx | 61 +++++++++++-------- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx b/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx index e41d49145195..4b11adf0e17b 100644 --- a/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx +++ b/ui/pages/confirmations/components/simulation-details/asset-pill.test.tsx @@ -64,7 +64,7 @@ describe('AssetPill', () => { }); const asset: NativeAssetIdentifier = { - chainId: CHAIN_ID_MOCK, + chainId, standard: TokenStandard.none, }; diff --git a/ui/pages/confirmations/components/simulation-details/asset-pill.tsx b/ui/pages/confirmations/components/simulation-details/asset-pill.tsx index bae092aaf399..99bd2b3af8ef 100644 --- a/ui/pages/confirmations/components/simulation-details/asset-pill.tsx +++ b/ui/pages/confirmations/components/simulation-details/asset-pill.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { NameType } from '@metamask/name-controller'; import { useSelector } from 'react-redux'; +import { Hex } from '@metamask/utils'; import { AvatarNetwork, AvatarNetworkSize, @@ -18,13 +19,20 @@ import { } from '../../../../helpers/constants/design-system'; import Name from '../../../../components/app/name'; import { TokenStandard } from '../../../../../shared/constants/transaction'; -import { getNativeCurrencyImage } from '../../../../selectors'; -import { getNativeCurrency } from '../../../../ducks/metamask/metamask'; +import { getNetworkConfigurationsByChainId } from '../../../../selectors'; +import { CHAIN_ID_TOKEN_IMAGE_MAP } from '../../../../../shared/constants/network'; import { AssetIdentifier } from './types'; -const NativeAssetPill: React.FC = () => { - const ticker = useSelector(getNativeCurrency); - const imgSrc = useSelector(getNativeCurrencyImage); +const NativeAssetPill: React.FC<{ chainId: Hex }> = ({ chainId }) => { + const imgSrc = + CHAIN_ID_TOKEN_IMAGE_MAP[chainId as keyof typeof CHAIN_ID_TOKEN_IMAGE_MAP]; + + const networkConfigurationsByChainId = useSelector( + getNetworkConfigurationsByChainId, + ); + + const network = networkConfigurationsByChainId?.[chainId]; + const { nativeCurrency } = network; return ( { }} > - {ticker} + {nativeCurrency} ); @@ -60,6 +68,8 @@ const NativeAssetPill: React.FC = () => { export const AssetPill: React.FC<{ asset: AssetIdentifier; }> = ({ asset }) => { + const { chainId } = asset; + return ( {asset.standard === TokenStandard.none ? ( - + ) : ( )} diff --git a/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx b/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx index 42596e505311..0d1d5cd6c6d5 100644 --- a/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx +++ b/ui/pages/confirmations/components/simulation-details/simulation-details.stories.tsx @@ -19,7 +19,7 @@ const DUMMY_BALANCE_CHANGE = { newBalance: '0xIGNORED' as Hex, }; -const CHAIN_ID_MOCK = '0x1'; +const CHAIN_ID_MOCK = CHAIN_IDS.MAINNET; const ERC20_TOKEN_1_MOCK = '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'; // WBTC const ERC20_TOKEN_2_MOCK = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; // USDC const ERC721_TOKEN_MOCK = '0x06012c8cf97bead5deae237070f9587f8e7a266d'; // CryptoKitties @@ -28,36 +28,44 @@ const ERC1155_TOKEN_MOCK = '0x60e4d786628fea6478f785a6d7e704777c86a7c6'; // MAYC const storeMock = configureStore({ metamask: { ...mockState.metamask, + ...mockNetworkState( + { chainId: CHAIN_IDS.MAINNET }, + { chainId: CHAIN_IDS.POLYGON }, + { chainId: CHAIN_IDS.ARBITRUM }, + ), preferences: { ...mockState.metamask.preferences, showNativeTokenAsMainBalance: false, }, - ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), useTokenDetection: true, - tokenList: { - [ERC20_TOKEN_1_MOCK]: { - address: ERC20_TOKEN_1_MOCK, - symbol: 'WBTC', - name: 'Wrapped Bitcoin', - iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC20_TOKEN_1_MOCK}.png`, - }, - [ERC20_TOKEN_2_MOCK]: { - address: ERC20_TOKEN_2_MOCK, - symbol: 'USDC', - name: 'USD Coin', - iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC20_TOKEN_2_MOCK}.png`, - }, - [ERC721_TOKEN_MOCK]: { - address: ERC721_TOKEN_MOCK, - symbol: 'CK', - name: 'CryptoKitties', - iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC721_TOKEN_MOCK}.png`, - }, - [ERC1155_TOKEN_MOCK]: { - address: ERC1155_TOKEN_MOCK, - symbol: 'MAYC', - name: 'Mutant Ape Yacht Club', - iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC1155_TOKEN_MOCK}.png `, + tokensChainsCache: { + [CHAIN_ID_MOCK]: { + data: { + [ERC20_TOKEN_1_MOCK]: { + address: ERC20_TOKEN_1_MOCK, + symbol: 'WBTC', + name: 'Wrapped Bitcoin', + iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC20_TOKEN_1_MOCK}.png`, + }, + [ERC20_TOKEN_2_MOCK]: { + address: ERC20_TOKEN_2_MOCK, + symbol: 'USDC', + name: 'USD Coin', + iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC20_TOKEN_2_MOCK}.png`, + }, + [ERC721_TOKEN_MOCK]: { + address: ERC721_TOKEN_MOCK, + symbol: 'CK', + name: 'CryptoKitties', + iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC721_TOKEN_MOCK}.png`, + }, + [ERC1155_TOKEN_MOCK]: { + address: ERC1155_TOKEN_MOCK, + symbol: 'MAYC', + name: 'Mutant Ape Yacht Club', + iconUrl: `https://static.cx.metamask.io/api/v1/tokenIcons/1/${ERC1155_TOKEN_MOCK}.png `, + }, + }, }, }, names: { @@ -137,6 +145,7 @@ export const MultipleTokens: Story = { export const SendSmallAmount: Story = { args: { transaction: createTransactionMeta({ + chainId: CHAIN_ID_MOCK, simulationData: { nativeBalanceChange: { ...DUMMY_BALANCE_CHANGE,