diff --git a/test/data/confirmations/personal_sign.ts b/test/data/confirmations/personal_sign.ts index b0f135efa53d..69c3ff9f75bc 100644 --- a/test/data/confirmations/personal_sign.ts +++ b/test/data/confirmations/personal_sign.ts @@ -1,3 +1,4 @@ +import { CHAIN_IDS } from '@metamask/transaction-controller'; import { SignatureRequestType } from '../../../ui/pages/confirmations/types/confirm'; export const PERSONAL_SIGN_SENDER_ADDRESS = @@ -5,6 +6,7 @@ export const PERSONAL_SIGN_SENDER_ADDRESS = export const unapprovedPersonalSignMsg = { id: '0050d5b0-c023-11ee-a0cb-3390a510a0ab', + chainId: CHAIN_IDS.GOERLI, status: 'unapproved', time: new Date().getTime(), type: 'personal_sign', @@ -20,6 +22,7 @@ export const unapprovedPersonalSignMsg = { export const signatureRequestSIWE = { id: '210ca3b0-1ccb-11ef-b096-89c4d726ebb5', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', @@ -57,6 +60,7 @@ export const signatureRequestSIWE = { export const SignatureRequestSIWEWithResources = { id: '210ca3b0-1ccb-11ef-b096-89c4d726ebb5', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', diff --git a/test/data/confirmations/typed_sign.ts b/test/data/confirmations/typed_sign.ts index 7be24a1389c6..831d561f0cb2 100644 --- a/test/data/confirmations/typed_sign.ts +++ b/test/data/confirmations/typed_sign.ts @@ -1,9 +1,10 @@ -import { TransactionType } from '@metamask/transaction-controller'; +import { CHAIN_IDS, TransactionType } from '@metamask/transaction-controller'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; import { SignatureRequestType } from '../../../ui/pages/confirmations/types/confirm'; export const unapprovedTypedSignMsgV1 = { id: '82ab2400-e2c6-11ee-9627-73cc88f00492', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', @@ -60,6 +61,7 @@ const rawMessageV3 = { export const unapprovedTypedSignMsgV3 = { id: '17e41af0-e073-11ee-9eec-5fd284826685', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', @@ -129,6 +131,7 @@ export const rawMessageV4 = { export const unapprovedTypedSignMsgV4 = { id: '0050d5b0-c023-11ee-a0cb-3390a510a0ab', + chainId: CHAIN_IDS.GOERLI, status: 'unapproved', time: new Date().getTime(), chainid: '0x5', @@ -145,6 +148,7 @@ export const unapprovedTypedSignMsgV4 = { export const orderSignatureMsg = { id: 'e5249ae0-4b6b-11ef-831f-65b48eb489ec', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { result_type: 'loading', reason: 'validation_in_progress', @@ -165,6 +169,7 @@ export const orderSignatureMsg = { export const permitSignatureMsg = { id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', @@ -185,6 +190,7 @@ export const permitSignatureMsg = { export const permitNFTSignatureMsg = { id: 'c5067710-87cf-11ef-916c-71f266571322', + chainId: CHAIN_IDS.GOERLI, status: 'unapproved', time: 1728651190529, type: 'eth_signTypedData', @@ -200,6 +206,7 @@ export const permitNFTSignatureMsg = { export const permitSignatureMsgWithNoDeadline = { id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', @@ -219,6 +226,7 @@ export const permitSignatureMsgWithNoDeadline = { export const permitBatchSignatureMsg = { id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', @@ -239,6 +247,7 @@ export const permitBatchSignatureMsg = { export const permitSingleSignatureMsg = { id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659', + chainId: CHAIN_IDS.GOERLI, securityAlertResponse: { reason: 'loading', result_type: 'validation_in_progress', diff --git a/test/integration/confirmations/signatures/permit.test.tsx b/test/integration/confirmations/signatures/permit.test.tsx index 8e9c979562f2..5ff87bf7c533 100644 --- a/test/integration/confirmations/signatures/permit.test.tsx +++ b/test/integration/confirmations/signatures/permit.test.tsx @@ -1,6 +1,7 @@ import { ApprovalType } from '@metamask/controller-utils'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import nock from 'nock'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import { MESSAGE_TYPE } from '../../../../shared/constants/app'; import { MetaMetricsEventCategory, @@ -42,6 +43,7 @@ const getMetaMaskStateWithUnapprovedPermitSign = (accountAddress: string) => { unapprovedTypedMessages: { [pendingPermitId]: { id: pendingPermitId, + chainId: CHAIN_IDS.SEPOLIA, status: 'unapproved', time: pendingPermitTime, type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA, diff --git a/test/integration/confirmations/signatures/personalSign.test.tsx b/test/integration/confirmations/signatures/personalSign.test.tsx index 690446caa533..5a9c311c9abd 100644 --- a/test/integration/confirmations/signatures/personalSign.test.tsx +++ b/test/integration/confirmations/signatures/personalSign.test.tsx @@ -1,5 +1,6 @@ import { ApprovalType } from '@metamask/controller-utils'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import { MESSAGE_TYPE } from '../../../../shared/constants/app'; import { MetaMetricsEventCategory, @@ -34,6 +35,7 @@ const getMetaMaskStateWithUnapprovedPersonalSign = (accountAddress: string) => { unapprovedPersonalMsgs: { [pendingPersonalSignId]: { id: pendingPersonalSignId, + chainId: CHAIN_IDS.SEPOLIA, status: 'unapproved', time: pendingPersonalSignTime, type: MESSAGE_TYPE.PERSONAL_SIGN, diff --git a/ui/hooks/useName.test.ts b/ui/hooks/useName.test.ts index f746c4bb6267..b102e9dce7a0 100644 --- a/ui/hooks/useName.test.ts +++ b/ui/hooks/useName.test.ts @@ -15,7 +15,6 @@ jest.mock('react-redux', () => ({ })); jest.mock('../selectors', () => ({ - getCurrentChainId: jest.fn(), getNames: jest.fn(), })); diff --git a/ui/hooks/useNftCollectionsMetadata.test.ts b/ui/hooks/useNftCollectionsMetadata.test.ts index e1e2b6745ad1..cf7997cb518b 100644 --- a/ui/hooks/useNftCollectionsMetadata.test.ts +++ b/ui/hooks/useNftCollectionsMetadata.test.ts @@ -16,10 +16,6 @@ jest.mock('react-redux', () => ({ useSelector: (selector: any) => selector(), })); -jest.mock('../selectors', () => ({ - getCurrentChainId: jest.fn(), -})); - jest.mock('../store/actions', () => ({ getNFTContractInfo: jest.fn(), getTokenStandardAndDetails: jest.fn(), diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx index fa0c911d5eae..c7a9eae6a496 100644 --- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx +++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx @@ -59,6 +59,7 @@ const PermitSimulationValueDisplay: React.FC< const tokenDetails = useGetTokenStandardAndDetails(tokenContract); useTrackERC20WithoutDecimalInformation( + chainId, tokenContract, tokenDetails as TokenDetailsERC20, MetaMetricsEventLocation.SignatureConfirmation, diff --git a/ui/pages/confirmations/components/confirm/network-change-toast/network-change-toast-legacy.tsx b/ui/pages/confirmations/components/confirm/network-change-toast/network-change-toast-legacy.tsx index fca355a9b063..f8d6b87e50db 100644 --- a/ui/pages/confirmations/components/confirm/network-change-toast/network-change-toast-legacy.tsx +++ b/ui/pages/confirmations/components/confirm/network-change-toast/network-change-toast-legacy.tsx @@ -1,18 +1,14 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; -import { Hex } from '@metamask/utils'; import { Box } from '../../../../../components/component-library'; import { Toast } from '../../../../../components/multichain'; import { getLastInteractedConfirmationInfo, setLastInteractedConfirmationInfo, } from '../../../../../store/actions'; -import { - getCurrentChainId, - getNetworkConfigurationsByChainId, -} from '../../../../../selectors'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; +import { selectNetworkConfigurationByChainId } from '../../../../../selectors'; const CHAIN_CHANGE_THRESHOLD_MILLISECONDS = 60 * 1000; // 1 Minute const TOAST_TIMEOUT_MILLISECONDS = 5 * 1000; // 5 Seconds @@ -22,12 +18,13 @@ const NetworkChangeToastLegacy = ({ }: { confirmation: { id: string; chainId: string }; }) => { - const chainId = useSelector(getCurrentChainId); - const newChainId = confirmation?.chainId ?? chainId; + const newChainId = confirmation?.chainId; const [toastVisible, setToastVisible] = useState(false); const t = useI18nContext(); - const networkConfigurations = useSelector(getNetworkConfigurationsByChainId); - const network = networkConfigurations[newChainId as Hex]; + + const network = useSelector((state) => + selectNetworkConfigurationByChainId(state, newChainId), + ); const hideToast = useCallback(() => { setToastVisible(false); @@ -35,9 +32,11 @@ const NetworkChangeToastLegacy = ({ useEffect(() => { let isMounted = true; + if (!confirmation) { return undefined; } + (async () => { const lastInteractedConfirmationInfo = await getLastInteractedConfirmationInfo(); @@ -71,7 +70,7 @@ const NetworkChangeToastLegacy = ({ return () => { isMounted = false; }; - }, [confirmation?.id, chainId]); + }, [confirmation?.id]); if (!toastVisible) { return null; diff --git a/ui/pages/confirmations/components/contract-details-modal/contract-details-modal.js b/ui/pages/confirmations/components/contract-details-modal/contract-details-modal.js index a0a16cc838c3..795401673691 100644 --- a/ui/pages/confirmations/components/contract-details-modal/contract-details-modal.js +++ b/ui/pages/confirmations/components/contract-details-modal/contract-details-modal.js @@ -39,7 +39,7 @@ export default function ContractDetailsModal({ tokenAddress, toAddress, chainId, - rpcPrefs, + blockExplorerUrl, tokenId, assetName, assetStandard, @@ -178,7 +178,7 @@ export default function ContractDetailsModal({ tokenAddress, chainId, { - blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null, + blockExplorerUrl: blockExplorerUrl ?? null, }, null, ); @@ -287,7 +287,7 @@ export default function ContractDetailsModal({ toAddress, chainId, { - blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null, + blockExplorerUrl: blockExplorerUrl ?? null, }, null, ); @@ -338,9 +338,9 @@ ContractDetailsModal.propTypes = { */ chainId: PropTypes.string, /** - * RPC prefs of the current network + * Block explorer URL of the current network */ - rpcPrefs: PropTypes.object, + blockExplorerUrl: PropTypes.string, /** * The token id of the NFT */ diff --git a/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js b/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js index 4115f06cd644..ff5adfea8b5d 100644 --- a/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js +++ b/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/blockaid-banner-alert.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import { captureException } from '@sentry/browser'; import BlockaidPackage from '@blockaid/ppom_release/package.json'; -import { useSelector } from 'react-redux'; import { NETWORK_TO_NAME_MAP } from '../../../../../../shared/constants/network'; import { OverflowWrap } from '../../../../../helpers/constants/design-system'; import { I18nContext } from '../../../../../contexts/i18n'; @@ -20,7 +19,6 @@ import { useTransactionEventFragment } from '../../../hooks/useTransactionEventF import SecurityProviderBannerAlert from '../security-provider-banner-alert'; import LoadingIndicator from '../../../../../components/ui/loading-indicator'; -import { getCurrentChainId } from '../../../../../selectors'; import { getReportUrl } from './blockaid-banner-utils'; const zlib = require('zlib'); @@ -59,8 +57,6 @@ function BlockaidBannerAlert({ txData, ...props }) { const { securityAlertResponse, origin, msgParams, type, txParams, chainId } = txData; - const selectorChainId = useSelector(getCurrentChainId); - const t = useContext(I18nContext); const { updateTransactionEventFragment } = useTransactionEventFragment(); @@ -131,7 +127,7 @@ function BlockaidBannerAlert({ txData, ...props }) { const reportData = { blockNumber: block, blockaidVersion: BlockaidPackage.version, - chain: NETWORK_TO_NAME_MAP[chainId ?? selectorChainId], + chain: NETWORK_TO_NAME_MAP[chainId], classification: isFailedResultType ? 'error' : reason, domain: origin ?? msgParams?.origin ?? txParams?.origin, jsonRpcMethod: type, diff --git a/ui/pages/confirmations/components/signature-request-header/signature-request-header.js b/ui/pages/confirmations/components/signature-request-header/signature-request-header.js index 9c91ca476ebb..61cbfe13e290 100644 --- a/ui/pages/confirmations/components/signature-request-header/signature-request-header.js +++ b/ui/pages/confirmations/components/signature-request-header/signature-request-header.js @@ -1,16 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; +import { RpcEndpointType } from '@metamask/network-controller'; +import { NetworkType } from '@metamask/controller-utils'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { - getNativeCurrency, - getProviderConfig, -} from '../../../../ducks/metamask/metamask'; import { accountsWithSendEtherInfoSelector, - getCurrentChainId, getCurrentCurrency, + selectDefaultRpcEndpointByChainId, + selectNetworkConfigurationByChainId, } from '../../../../selectors'; import { formatCurrency } from '../../../../helpers/utils/confirm-tx.util'; import { @@ -26,22 +25,33 @@ import NetworkAccountBalanceHeader from '../../../../components/app/network-acco const SignatureRequestHeader = ({ txData }) => { const t = useI18nContext(); const { + chainId, msgParams: { from }, } = txData; const allAccounts = useSelector(accountsWithSendEtherInfoSelector); const fromAccount = getAccountByAddress(allAccounts, from); - const nativeCurrency = useSelector(getNativeCurrency); const currentCurrency = useSelector(getCurrentCurrency); - const currentChainId = useSelector(getCurrentChainId); - const providerConfig = useSelector(getProviderConfig); - const networkName = getNetworkNameFromProviderType(providerConfig.type); + const { nativeCurrency, name: networkNickname } = useSelector((state) => + selectNetworkConfigurationByChainId(state, chainId), + ); + + const defaultRpcEndpoint = useSelector((state) => + selectDefaultRpcEndpointByChainId(state, chainId), + ); + + const networkType = + defaultRpcEndpoint.type === RpcEndpointType.Custom + ? NetworkType.rpc + : defaultRpcEndpoint.networkClientId; + + const networkName = getNetworkNameFromProviderType(networkType); const conversionRate = null; // setting conversion rate to null by default to display balance in native const currentNetwork = networkName === '' - ? providerConfig.nickname || t('unknownNetwork') + ? networkNickname || t('unknownNetwork') : t(networkName); const balanceInBaseAsset = conversionRate @@ -71,7 +81,7 @@ const SignatureRequestHeader = ({ txData }) => { conversionRate ? currentCurrency?.toUpperCase() : nativeCurrency } accountAddress={fromAccount.address} - chainId={currentChainId} + chainId={chainId} /> ); }; diff --git a/ui/pages/confirmations/components/signature-request-header/signature-request-header.stories.js b/ui/pages/confirmations/components/signature-request-header/signature-request-header.stories.js index 673b9a67e598..111be8932207 100644 --- a/ui/pages/confirmations/components/signature-request-header/signature-request-header.stories.js +++ b/ui/pages/confirmations/components/signature-request-header/signature-request-header.stories.js @@ -1,13 +1,30 @@ import React from 'react'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; +import { Provider } from 'react-redux'; +import configureStore from '../../../../store/store'; +import testData from '../../../../../.storybook/test-data'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import SignatureRequestHeader from './signature-request-header'; +const CHAIN_ID_MOCK = CHAIN_IDS.MAINNET; + +const store = configureStore({ + ...testData, + metamask: { + ...testData.metamask, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), + }, +}); + export default { title: 'Confirmations/Components/SignatureRequestHeader', + decorators: [(story) => {story()}], argTypes: { txData: { control: 'object' }, }, args: { txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', data: JSON.stringify({ diff --git a/ui/pages/confirmations/components/signature-request-header/signature-request-header.test.js b/ui/pages/confirmations/components/signature-request-header/signature-request-header.test.js index a3ddd3136627..862339239643 100644 --- a/ui/pages/confirmations/components/signature-request-header/signature-request-header.test.js +++ b/ui/pages/confirmations/components/signature-request-header/signature-request-header.test.js @@ -1,12 +1,17 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import mockState from '../../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import SignatureRequestHeader from '.'; +const CHAIN_ID_MOCK = CHAIN_IDS.GOERLI; + const props = { txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', }, @@ -14,7 +19,10 @@ const props = { }; describe('SignatureRequestHeader', () => { - const store = configureMockStore()(mockState); + const store = configureMockStore()({ + ...mockState, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), + }); it('should match snapshot', () => { const { container } = renderWithProvider( diff --git a/ui/pages/confirmations/components/signature-request-original/signature-request-original.stories.js b/ui/pages/confirmations/components/signature-request-original/signature-request-original.stories.js index 297978bb5f04..7343d5c34140 100644 --- a/ui/pages/confirmations/components/signature-request-original/signature-request-original.stories.js +++ b/ui/pages/confirmations/components/signature-request-original/signature-request-original.stories.js @@ -1,10 +1,16 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; +import { Provider } from 'react-redux'; import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; import testData from '../../../../../.storybook/test-data'; +import configureStore from '../../../../store/store'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import README from './README.mdx'; import SignatureRequestOriginal from './signature-request-original.component'; +const CHAIN_ID_MOCK = CHAIN_IDS.MAINNET; + const [MOCK_PRIMARY_ACCOUNT, MOCK_SECONDARY_ACCOUNT] = Object.values( testData.metamask.internalAccounts.accounts, ); @@ -41,9 +47,17 @@ const MOCK_SIGN_DATA = JSON.stringify({ }, }); +const store = configureStore({ + ...testData, + metamask: { + ...testData.metamask, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), + }, +}); + export default { title: 'Confirmations/Components/SignatureRequestOriginal', - + decorators: [(story) => {story()}], component: SignatureRequestOriginal, parameters: { docs: { @@ -87,6 +101,7 @@ DefaultStory.storyName = 'personal_sign Type'; DefaultStory.args = { txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', data: MOCK_SIGN_DATA, @@ -102,6 +117,7 @@ ETHSignTypedStory.storyName = 'eth_signTypedData Type'; ETHSignTypedStory.args = { txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', data: [ @@ -128,6 +144,7 @@ AccountMismatchStory.storyName = 'Account Mismatch warning'; AccountMismatchStory.args = { txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4', data: MOCK_SIGN_DATA, diff --git a/ui/pages/confirmations/components/signature-request-original/signature-request-original.test.js b/ui/pages/confirmations/components/signature-request-original/signature-request-original.test.js index 11577f44e312..b8d1429751e6 100644 --- a/ui/pages/confirmations/components/signature-request-original/signature-request-original.test.js +++ b/ui/pages/confirmations/components/signature-request-original/signature-request-original.test.js @@ -3,6 +3,7 @@ import configureMockStore from 'redux-mock-store'; import { fireEvent, screen } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; import { EthAccountType } from '@metamask/keyring-api'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; import { SECURITY_PROVIDER_MESSAGE_SEVERITY } from '../../../../../shared/constants/security-provider'; import mockState from '../../../../../test/data/mock-state.json'; @@ -11,6 +12,7 @@ import configureStore from '../../../../store/store'; import { rejectPendingApproval } from '../../../../store/actions'; import { shortenAddress } from '../../../../helpers/utils/util'; import { ETH_EOA_METHODS } from '../../../../../shared/constants/eth-methods'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import SignatureRequestOriginal from '.'; jest.mock('../../../../store/actions', () => ({ @@ -21,12 +23,15 @@ jest.mock('../../../../store/actions', () => ({ setLastInteractedConfirmationInfo: jest.fn(), })); +const CHAIN_ID_MOCK = CHAIN_IDS.GOERLI; + const address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'; const props = { signMessage: jest.fn(), cancelMessage: jest.fn(), txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: address, data: [ @@ -76,6 +81,7 @@ const render = ({ txData = props.txData, selectedAccount } = {}) => { const store = configureStore({ metamask: { ...mockState.metamask, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), internalAccounts, }, }); @@ -120,6 +126,7 @@ describe('SignatureRequestOriginal', () => { it('should escape RTL character in label or value', () => { const txData = { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', data: [ diff --git a/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap b/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap index a524cbcc1caf..fcf0bb30d8a3 100644 --- a/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap +++ b/ui/pages/confirmations/components/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap @@ -169,7 +169,7 @@ exports[`SignatureRequestSIWE (Sign in with Ethereum) should match snapshot 1`] > 966.987986 - ETH + GoerliETH diff --git a/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.stories.js b/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.stories.js index de29680421c6..7900cfe1828d 100644 --- a/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.stories.js +++ b/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.stories.js @@ -1,18 +1,37 @@ import React from 'react'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; +import { Provider } from 'react-redux'; import testData from '../../../../../.storybook/test-data'; +import configureStore from '../../../../store/store'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import README from './README.mdx'; import SignatureRequestSIWE from './signature-request-siwe'; +const CHAIN_ID_MOCK = CHAIN_IDS.MAINNET; + +const TRANSACTION_DATA_MOCK = { + chainId: CHAIN_ID_MOCK, +}; + const { internalAccounts: { accounts, selectedAccount }, } = testData.metamask; + const otherAccount = Object.values(accounts)[1]; const { address: selectedAddress } = accounts[selectedAccount]; +const store = configureStore({ + ...testData, + metamask: { + ...testData.metamask, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), + }, +}); + export default { title: 'Confirmations/Components/SignatureRequestSIWE', - + decorators: [(story) => {story()}], component: SignatureRequestSIWE, parameters: { docs: { @@ -134,6 +153,7 @@ DefaultStory.storyName = 'Default'; DefaultStory.args = { txData: { + ...TRANSACTION_DATA_MOCK, msgParams, }, }; @@ -144,6 +164,7 @@ export const BadDomainStory = (args) => { BadDomainStory.args = { txData: { + ...TRANSACTION_DATA_MOCK, msgParams: badDomainParams, }, }; @@ -154,6 +175,7 @@ export const BadAddressStory = (args) => { BadAddressStory.args = { txData: { + ...TRANSACTION_DATA_MOCK, msgParams: badAddressParams, }, }; @@ -164,6 +186,7 @@ export const BadDomainAndAddressStory = (args) => { BadDomainAndAddressStory.args = { txData: { + ...TRANSACTION_DATA_MOCK, msgParams: badDomainAndAddressParams, }, }; diff --git a/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.test.js b/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.test.js index c97be33e45b0..f8f1a67b8cbc 100644 --- a/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.test.js +++ b/ui/pages/confirmations/components/signature-request-siwe/signature-request-siwe.test.js @@ -2,14 +2,16 @@ import React from 'react'; import { cloneDeep } from 'lodash'; import { fireEvent } from '@testing-library/react'; import { ApprovalType } from '@metamask/controller-utils'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import mockState from '../../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import configureStore from '../../../../store/store'; -import { getCurrentChainId } from '../../../../selectors'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import SignatureRequestSIWE from '.'; const MOCK_ORIGIN = 'https://example-dapp.website'; const MOCK_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'; +const CHAIN_ID_MOCK = CHAIN_IDS.GOERLI; const mockStoreInitialState = { metamask: { @@ -20,6 +22,7 @@ const mockStoreInitialState = { name: 'Example Test Dapp', }, }, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), }, }; @@ -37,6 +40,7 @@ const mockProps = { cancelPersonalMessage: jest.fn(), signPersonalMessage: jest.fn(), txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: MOCK_ADDRESS, data: '0x6c6f63616c686f73743a383038302077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078466232433135303034333433393034653566343038323537386334653865313131303563463765330a0a436c69636b20746f207369676e20696e20616e642061636365707420746865205465726d73206f6620536572766963653a2068747470733a2f2f636f6d6d756e6974792e6d6574616d61736b2e696f2f746f730a0a5552493a20687474703a2f2f6c6f63616c686f73743a383038300a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a2053544d74364b514d7777644f58453330360a4973737565642041743a20323032322d30332d31385432313a34303a34302e3832335a0a5265736f75726365733a0a2d20697066733a2f2f516d653773733341525667787636725871565069696b4d4a3875324e4c676d67737a673133705972444b456f69750a2d2068747470733a2f2f6578616d706c652e636f6d2f6d792d776562322d636c61696d2e6a736f6e', @@ -183,7 +187,7 @@ describe('SignatureRequestSIWE (Sign in with Ethereum)', () => { transactions: [ ...mockStoreInitialState.metamask.transactions, { - chainId: getCurrentChainId(mockStoreInitialState), + chainId: CHAIN_ID_MOCK, status: 'unapproved', }, ], diff --git a/ui/pages/confirmations/components/signature-request/__snapshots__/signature-request.test.js.snap b/ui/pages/confirmations/components/signature-request/__snapshots__/signature-request.test.js.snap index ba272fc26d89..943f8699b9aa 100644 --- a/ui/pages/confirmations/components/signature-request/__snapshots__/signature-request.test.js.snap +++ b/ui/pages/confirmations/components/signature-request/__snapshots__/signature-request.test.js.snap @@ -177,26 +177,6 @@ exports[`Signature Request Component render should match snapshot when we are us
-
- -
-

- To view and confirm your most recent request, you'll need to approve or reject existing requests first. -

-

-

-
@@ -962,7 +942,6 @@ exports[`Signature Request Component render should match snapshot when we want t > 0 - ETH
@@ -970,26 +949,6 @@ exports[`Signature Request Component render should match snapshot when we want t
-
- -
-

- To view and confirm your most recent request, you'll need to approve or reject existing requests first. -

-

-

-
diff --git a/ui/pages/confirmations/components/signature-request/signature-request.js b/ui/pages/confirmations/components/signature-request/signature-request.js index 3cf2a54327c9..2a7977da0c75 100644 --- a/ui/pages/confirmations/components/signature-request/signature-request.js +++ b/ui/pages/confirmations/components/signature-request/signature-request.js @@ -18,16 +18,14 @@ import { doesAddressRequireLedgerHidConnection, getSubjectMetadata, getTotalUnapprovedMessagesCount, + selectNetworkConfigurationByChainId, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) accountsWithSendEtherInfoSelector, getSelectedAccount, getAccountType, ///: END:ONLY_INCLUDE_IF } from '../../../../selectors'; -import { - getProviderConfig, - isAddressLedger, -} from '../../../../ducks/metamask/metamask'; +import { isAddressLedger } from '../../../../ducks/metamask/metamask'; import { sanitizeMessage, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) @@ -97,6 +95,7 @@ const SignatureRequest = ({ txData, warnings }) => { const { id, type, + chainId, msgParams: { from, data, origin, version }, } = txData; @@ -104,7 +103,12 @@ const SignatureRequest = ({ txData, warnings }) => { const hardwareWalletRequiresConnection = useSelector((state) => doesAddressRequireLedgerHidConnection(state, from), ); - const { chainId, rpcPrefs } = useSelector(getProviderConfig); + + const { blockExplorerUrls } = useSelector((state) => + selectNetworkConfigurationByChainId(state, chainId), + ); + + const blockExplorerUrl = blockExplorerUrls?.[0]; const unapprovedMessagesCount = useSelector(getTotalUnapprovedMessagesCount); const subjectMetadata = useSelector(getSubjectMetadata); const isLedgerWallet = useSelector((state) => isAddressLedger(state, from)); @@ -337,7 +341,7 @@ const SignatureRequest = ({ txData, warnings }) => { setShowContractDetails(false)} isContractRequestingSignature /> diff --git a/ui/pages/confirmations/components/signature-request/signature-request.stories.js b/ui/pages/confirmations/components/signature-request/signature-request.stories.js index b31032f8b1a7..cc5374e2becb 100644 --- a/ui/pages/confirmations/components/signature-request/signature-request.stories.js +++ b/ui/pages/confirmations/components/signature-request/signature-request.stories.js @@ -1,21 +1,25 @@ import React from 'react'; import { Provider } from 'react-redux'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import configureStore from '../../../../store/store'; import testData from '../../../../../.storybook/test-data'; +import { mockNetworkState } from '../../../../../test/stub/networks'; import README from './README.mdx'; import SignatureRequest from './signature-request'; +const CHAIN_ID_MOCK = CHAIN_IDS.MAINNET; + const store = configureStore({ ...testData, metamask: { ...testData.metamask, + ...mockNetworkState({ chainId: CHAIN_ID_MOCK }), }, }); export default { title: 'Confirmations/Components/SignatureRequest', decorators: [(story) => {story()}], - component: SignatureRequest, parameters: { docs: { @@ -35,6 +39,7 @@ DefaultStory.storyName = 'Default'; DefaultStory.args = { txData: { + chainId: CHAIN_ID_MOCK, msgParams: { from: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', data: JSON.stringify({ @@ -82,6 +87,7 @@ AccountMismatchStory.storyName = 'AccountMismatch'; AccountMismatchStory.args = { ...DefaultStory.args, txData: { + chainId: CHAIN_ID_MOCK, msgParams: { ...DefaultStory.args.txData.msgParams, from: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4', diff --git a/ui/pages/confirmations/components/signature-request/signature-request.test.js b/ui/pages/confirmations/components/signature-request/signature-request.test.js index 9851cdbef454..2e10381c40cb 100644 --- a/ui/pages/confirmations/components/signature-request/signature-request.test.js +++ b/ui/pages/confirmations/components/signature-request/signature-request.test.js @@ -1,35 +1,25 @@ import React from 'react'; -import { useSelector } from 'react-redux'; import { fireEvent } from '@testing-library/react'; import configureMockStore from 'redux-mock-store'; import { EthAccountType } from '@metamask/keyring-api'; import mockState from '../../../../../test/data/mock-state.json'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import { SECURITY_PROVIDER_MESSAGE_SEVERITY } from '../../../../../shared/constants/security-provider'; -import { - getNativeCurrency, - getProviderConfig, -} from '../../../../ducks/metamask/metamask'; -import { - accountsWithSendEtherInfoSelector, - conversionRateSelector, - getCurrentCurrency, - getMemoizedAddressBook, - getPreferences, - getSelectedAccount, - getTotalUnapprovedMessagesCount, - getInternalAccounts, - unconfirmedTransactionsHashSelector, - getAccountType, - getMemoizedMetaMaskInternalAccounts, - getSelectedInternalAccount, - pendingApprovalsSortedSelector, - getNetworkConfigurationsByChainId, -} from '../../../../selectors'; import { ETH_EOA_METHODS } from '../../../../../shared/constants/eth-methods'; import { mockNetworkState } from '../../../../../test/stub/networks'; import SignatureRequest from './signature-request'; +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: () => jest.fn(), +})); + +const CHAIN_ID_MOCK = '0x539'; + +const TRANSACTION_DATA_MOCK = { + chainId: CHAIN_ID_MOCK, +}; + const baseProps = { clearConfirmTransaction: () => jest.fn(), cancel: () => jest.fn(), @@ -37,8 +27,11 @@ const baseProps = { showRejectTransactionsConfirmationModal: () => jest.fn(), sign: () => jest.fn(), }; + const mockStore = { + ...mockState, metamask: { + ...mockState.metamask, ...mockNetworkState({ chainId: '0x539', nickname: 'Localhost 8545', @@ -61,12 +54,13 @@ const mockStore = { metadata: { name: 'John Doe', keyring: { - type: 'HD Key Tree', + type: 'Custody', }, }, options: {}, methods: ETH_EOA_METHODS, type: EthAccountType.Eoa, + balance: 0, }, }, selectedAccount: 'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3', @@ -94,15 +88,6 @@ const mockStore = { }, }, }; -jest.mock('react-redux', () => { - const actual = jest.requireActual('react-redux'); - - return { - ...actual, - useSelector: jest.fn(), - useDispatch: () => jest.fn(), - }; -}); const mockCustodySignFn = jest.fn(); @@ -114,62 +99,13 @@ jest.mock('../../../../hooks/useMMICustodySignMessage', () => ({ jest.mock('@metamask-institutional/extension'); -const generateUseSelectorRouter = (opts) => (selector) => { - const mockSelectedInternalAccount = getSelectedInternalAccount(opts); - - switch (selector) { - case getProviderConfig: - return getProviderConfig(opts); - case getCurrentCurrency: - return opts.metamask.currentCurrency; - case getNativeCurrency: - return getProviderConfig(opts).ticker; - case getTotalUnapprovedMessagesCount: - return opts.metamask.unapprovedTypedMessagesCount; - case getPreferences: - return opts.metamask.preferences; - case conversionRateSelector: - return opts.metamask.currencyRates[getProviderConfig(opts).ticker] - ?.conversionRate; - case getSelectedAccount: - return mockSelectedInternalAccount; - case getInternalAccounts: - return Object.values(opts.metamask.internalAccounts.accounts); - case getMemoizedMetaMaskInternalAccounts: - return Object.values(opts.metamask.internalAccounts.accounts); - case getMemoizedAddressBook: - return []; - case accountsWithSendEtherInfoSelector: - return Object.values(opts.metamask.internalAccounts.accounts).map( - (internalAccount) => { - return { - ...internalAccount, - ...(opts.metamask.accounts[internalAccount.address] ?? {}), - balance: - opts.metamask.accounts[internalAccount.address]?.balance ?? 0, - }; - }, - ); - case getAccountType: - return 'custody'; - case unconfirmedTransactionsHashSelector: - return {}; - case pendingApprovalsSortedSelector: - return Object.values(opts.metamask.pendingApprovals); - case getNetworkConfigurationsByChainId: - return opts.metamask.networkConfigurationsByChainId; - default: - return undefined; - } -}; describe('Signature Request Component', () => { - const store = configureMockStore()(mockState); + const store = configureMockStore()(mockStore); describe('render', () => { let messageData; beforeEach(() => { - useSelector.mockImplementation(generateUseSelectorRouter(mockStore)); messageData = { domain: { chainId: 97, @@ -219,35 +155,39 @@ describe('Signature Request Component', () => { }); it('should match snapshot when we want to switch to fiat', () => { - useSelector.mockImplementation( - generateUseSelectorRouter({ - ...mockStore, - metamask: { - ...mockStore.metamask, - currencyRates: { - ...mockStore.metamask.currencyRates, - ETH: { - ...(mockStore.metamask.currencyRates.ETH || {}), - conversionRate: 231.06, - }, + const storeOverride = configureMockStore()({ + ...mockStore, + metamask: { + ...mockStore.metamask, + ...mockNetworkState({ + chainId: CHAIN_ID_MOCK, + }), + currencyRates: { + ...mockStore.metamask.currencyRates, + ETH: { + ...(mockStore.metamask.currencyRates.ETH || {}), + conversionRate: 231.06, }, }, - }), - ); + }, + }); + const msgParams = { from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', }; + const { container } = renderWithProvider( , - store, + storeOverride, ); expect(container).toMatchSnapshot(); @@ -260,10 +200,12 @@ describe('Signature Request Component', () => { version: 'V4', origin: 'test', }; + const { container } = renderWithProvider( , @@ -280,10 +222,12 @@ describe('Signature Request Component', () => { version: 'V4', origin: 'test', }; + const { queryByTestId } = renderWithProvider( , @@ -308,6 +252,7 @@ describe('Signature Request Component', () => { , @@ -321,29 +266,30 @@ describe('Signature Request Component', () => { }); it('should not render a reject multiple requests link if there is not multiple requests', () => { - useSelector.mockImplementation( - generateUseSelectorRouter({ - ...mockStore, - metamask: { - ...mockStore.metamask, - unapprovedTypedMessagesCount: 0, - }, - }), - ); + const storeOverride = configureMockStore()({ + ...mockStore, + metamask: { + ...mockStore.metamask, + unapprovedTypedMessagesCount: 0, + }, + }); + const msgParams = { from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', data: JSON.stringify(messageData), version: 'V4', origin: 'test', }; + const { container } = renderWithProvider( , - store, + storeOverride, ); expect( @@ -358,10 +304,12 @@ describe('Signature Request Component', () => { version: 'V4', origin: 'test', }; + const { container } = renderWithProvider( , @@ -384,6 +332,7 @@ describe('Signature Request Component', () => { , @@ -408,6 +357,7 @@ describe('Signature Request Component', () => { , @@ -429,6 +379,7 @@ describe('Signature Request Component', () => { { { }); it('should render a warning when the selected account is not the one being used to sign', () => { - const msgParams = { - from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - data: JSON.stringify(messageData), - version: 'V4', - origin: 'test', - }; - - useSelector.mockImplementation( - generateUseSelectorRouter({ - ...mockStore, - metamask: { - ...mockStore.metamask, + const storeOverride = configureMockStore()({ + ...mockStore, + metamask: { + ...mockStore.metamask, + accounts: { + ...mockStore.metamask.accounts, + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + balance: '0x0', + name: 'Account 1', + }, + '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5': { + address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + balance: '0x0', + name: 'Account 2', + }, + }, + internalAccounts: { accounts: { - ...mockStore.metamask.accounts, - '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + 'b7e813d6-e31c-4bad-8615-8d4eff9f44f1': { address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - balance: '0x0', - name: 'Account 1', - }, - '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5': { - address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - balance: '0x0', - name: 'Account 2', - }, - }, - internalAccounts: { - accounts: { - 'b7e813d6-e31c-4bad-8615-8d4eff9f44f1': { - address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', - id: 'b7e813d6-e31c-4bad-8615-8d4eff9f44f1', - metadata: { - name: 'Account 1', - keyring: { - type: 'HD Key Tree', - }, + id: 'b7e813d6-e31c-4bad-8615-8d4eff9f44f1', + metadata: { + name: 'Account 1', + keyring: { + type: 'HD Key Tree', }, - options: {}, - methods: ETH_EOA_METHODS, - type: EthAccountType.Eoa, }, - 'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3': { - address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', - id: 'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3', - metadata: { - name: 'Account 2', - keyring: { - type: 'HD Key Tree', - }, + options: {}, + methods: ETH_EOA_METHODS, + type: EthAccountType.Eoa, + }, + 'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3': { + address: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + id: 'cf8dace4-9439-4bd4-b3a8-88c821c8fcb3', + metadata: { + name: 'Account 2', + keyring: { + type: 'HD Key Tree', }, - options: {}, - methods: ETH_EOA_METHODS, - type: EthAccountType.Eoa, }, + options: {}, + methods: ETH_EOA_METHODS, + type: EthAccountType.Eoa, }, - selectedAccount: 'b7e813d6-e31c-4bad-8615-8d4eff9f44f1', }, + selectedAccount: 'b7e813d6-e31c-4bad-8615-8d4eff9f44f1', }, - }), - ); + }, + }); + + const msgParams = { + from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', + data: JSON.stringify(messageData), + version: 'V4', + origin: 'test', + }; const { container } = renderWithProvider( , - store, + storeOverride, ); expect( @@ -571,6 +522,7 @@ describe('Signature Request Component', () => { {...baseProps} conversionRate={null} txData={{ + ...TRANSACTION_DATA_MOCK, msgParams, securityAlertResponse: { resultType: 'Malicious', @@ -602,6 +554,7 @@ describe('Signature Request Component', () => { , @@ -610,7 +563,9 @@ describe('Signature Request Component', () => { const rejectRequestsLink = getByTestId('page-container-footer-next'); fireEvent.click(rejectRequestsLink); - expect(mockCustodySignFn).toHaveBeenCalledWith({ msgParams }); + expect(mockCustodySignFn).toHaveBeenCalledWith( + expect.objectContaining({ msgParams }), + ); }); }); }); diff --git a/ui/pages/confirmations/confirm-signature-request/index.test.js b/ui/pages/confirmations/confirm-signature-request/index.test.js index e0c7c7c8bbeb..f634bf40845c 100644 --- a/ui/pages/confirmations/confirm-signature-request/index.test.js +++ b/ui/pages/confirmations/confirm-signature-request/index.test.js @@ -7,13 +7,21 @@ import { CHAIN_IDS } from '../../../../shared/constants/network'; import { mockNetworkState } from '../../../../test/stub/networks'; import ConfTx from '.'; +const CHAIN_ID_MOCK = CHAIN_IDS.GOERLI; + const mockState = { metamask: { + ...mockNetworkState({ + chainId: CHAIN_IDS.GOERLI, + nickname: 'Goerli test network', + ticker: undefined, + }), unapprovedPersonalMsgs: {}, unapprovedPersonalMsgCount: 0, unapprovedTypedMessages: { 267460284130106: { id: 267460284130106, + chainId: CHAIN_ID_MOCK, msgParams: { data: '{"domain":{"chainId":"5","name":"Ether Mail","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","version":"1"},"message":{"contents":"Hello, Bob!","from":{"name":"Cow","wallets":["0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826","0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF"]},"to":[{"name":"Bob","wallets":["0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB","0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57","0xB0B0b0b0b0b0B000000000000000000000000000"]}]},"primaryType":"Mail","types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Group":[{"name":"name","type":"string"},{"name":"members","type":"Person[]"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person[]"},{"name":"contents","type":"string"}],"Person":[{"name":"name","type":"string"},{"name":"wallets","type":"address[]"}]}}', from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', @@ -27,11 +35,6 @@ const mockState = { }, }, unapprovedTypedMessagesCount: 1, - ...mockNetworkState({ - chainId: CHAIN_IDS.GOERLI, - nickname: 'Goerli test network', - ticker: undefined, - }), currencyRates: {}, keyrings: [], subjectMetadata: {}, diff --git a/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts b/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts index 1b6412d66614..2f26fcefbee9 100644 --- a/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts +++ b/ui/pages/confirmations/hooks/alerts/useBlockaidAlerts.ts @@ -15,7 +15,6 @@ import { import { Alert } from '../../../../ducks/confirm-alerts/confirm-alerts'; import ZENDESK_URLS from '../../../../helpers/constants/zendesk-url'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { getCurrentChainId } from '../../../../selectors'; import { SIGNATURE_TRANSACTION_TYPES, REDESIGN_DEV_TRANSACTION_TYPES, @@ -51,7 +50,6 @@ type SecurityAlertResponsesState = { const useBlockaidAlerts = (): Alert[] => { const t = useI18nContext(); const { currentConfirmation } = useConfirmContext(); - const selectorChainId = useSelector(getCurrentChainId); const securityAlertId = ( currentConfirmation?.securityAlertResponse as SecurityAlertResponse @@ -99,9 +97,7 @@ const useBlockaidAlerts = (): Alert[] => { const reportData = { blockNumber: block, blockaidVersion: BlockaidPackage.version, - chain: (NETWORK_TO_NAME_MAP as Record)[ - chainId ?? selectorChainId - ], + chain: (NETWORK_TO_NAME_MAP as Record)[chainId], classification: isFailedResultType ? 'error' : reason, domain: origin ?? msgParams?.origin ?? origin, jsonRpcMethod: type, diff --git a/ui/pages/confirmations/hooks/useConfirmationNetworkInfo.ts b/ui/pages/confirmations/hooks/useConfirmationNetworkInfo.ts index 4c6dddfa7a5a..f0463287ef34 100644 --- a/ui/pages/confirmations/hooks/useConfirmationNetworkInfo.ts +++ b/ui/pages/confirmations/hooks/useConfirmationNetworkInfo.ts @@ -6,30 +6,23 @@ import { NETWORK_TO_NAME_MAP, } from '../../../../shared/constants/network'; -import { - getCurrentChainId, - getNetworkConfigurationsByChainId, -} from '../../../selectors'; - import { useI18nContext } from '../../../hooks/useI18nContext'; import { useConfirmContext } from '../context/confirm'; +import { selectNetworkConfigurationByChainId } from '../../../selectors'; function useConfirmationNetworkInfo() { const t = useI18nContext(); const { currentConfirmation } = useConfirmContext(); - const networkConfigurations = useSelector(getNetworkConfigurationsByChainId); - const currentChainId = useSelector(getCurrentChainId); + const chainId = currentConfirmation?.chainId as Hex; + + const networkConfiguration = useSelector((state) => + selectNetworkConfigurationByChainId(state, chainId), + ); let networkDisplayName = ''; let networkImageUrl = ''; if (currentConfirmation) { - // use the current confirmation chainId, else use the current network chainId - const chainId = - (currentConfirmation?.chainId as Hex | undefined) ?? currentChainId; - - const networkConfiguration = networkConfigurations[chainId]; - networkDisplayName = networkConfiguration?.name ?? NETWORK_TO_NAME_MAP[chainId as keyof typeof NETWORK_TO_NAME_MAP] ?? diff --git a/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.test.ts b/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.test.ts index dff0103fbe21..9c98432918e2 100644 --- a/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.test.ts +++ b/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.test.ts @@ -1,6 +1,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { useContext } from 'react'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; import { TokenStandard } from '../../../../shared/constants/transaction'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { TokenDetailsERC20 } from '../utils/token'; @@ -30,7 +31,7 @@ describe('useTrackERC20WithoutDecimalInformation', () => { }); renderHook(() => - useTrackERC20WithoutDecimalInformation('0x5', { + useTrackERC20WithoutDecimalInformation(CHAIN_IDS.MAINNET, '0x5', { standard: TokenStandard.ERC20, } as TokenDetailsERC20), ); diff --git a/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.ts b/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.ts index fa6a5e620fc4..266048e11134 100644 --- a/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.ts +++ b/ui/pages/confirmations/hooks/useTrackERC20WithoutDecimalInformation.ts @@ -1,4 +1,3 @@ -import { useSelector } from 'react-redux'; import { useContext, useEffect } from 'react'; import { Hex } from '@metamask/utils'; @@ -10,23 +9,23 @@ import { } from '../../../../shared/constants/metametrics'; import { TokenStandard } from '../../../../shared/constants/transaction'; import { MetaMetricsContext } from '../../../contexts/metametrics'; -import { getCurrentChainId } from '../../../selectors'; import { parseTokenDetailDecimals, TokenDetailsERC20 } from '../utils/token'; /** * Track event that number of decimals in ERC20 is not obtained * + * @param chainId * @param tokenAddress * @param tokenDetails * @param metricLocation */ const useTrackERC20WithoutDecimalInformation = ( + chainId: Hex, tokenAddress: Hex | string | undefined, tokenDetails?: TokenDetailsERC20, metricLocation = MetaMetricsEventLocation.SignatureConfirmation, ) => { const trackEvent = useContext(MetaMetricsContext); - const chainId = useSelector(getCurrentChainId); useEffect(() => { if (chainId === undefined || tokenDetails === undefined) { diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index ac8a6394bf6b..5f1557700bc0 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -704,6 +704,28 @@ export const getNetworkConfigurationsByChainId = createDeepEqualSelector( (networkConfigurationsByChainId) => networkConfigurationsByChainId, ); +/** + * @type (state: any, chainId: string) => import('@metamask/network-controller').NetworkConfiguration + */ +export const selectNetworkConfigurationByChainId = createSelector( + getNetworkConfigurationsByChainId, + (_state, chainId) => chainId, + (networkConfigurationsByChainId, chainId) => + networkConfigurationsByChainId[chainId], +); + +export const selectDefaultRpcEndpointByChainId = createSelector( + selectNetworkConfigurationByChainId, + (networkConfiguration) => { + if (!networkConfiguration) { + return undefined; + } + + const { defaultRpcEndpointIndex, rpcEndpoints } = networkConfiguration; + return rpcEndpoints[defaultRpcEndpointIndex]; + }, +); + export function getRequestingNetworkInfo(state, chainIds) { // If chainIds is undefined, set it to an empty array let processedChainIds = chainIds === undefined ? [] : chainIds;