From 5116c3249876a8098d8b96cbed8369500805b2b7 Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:01:48 -0500 Subject: [PATCH] refactor: move `getProviderConfig` out of `ducks/metamask.js` to `shared/selectors/networks.ts` (#27646) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts some from functions from JS to TS. Also updates some functions to match the actual expect return values. Why only these functions? I'm trying to solve circular dependency issues. `getProviderConfig` is so widely used in the codebase, and makes use of multiple selectors itself, it makes it very complicated to untangle. I've put it in a new file (`seelctors/networks.ts`) just to, hopefully temporarily, simplify untangling other circular dependency issues. --- app/scripts/lib/ppom/ppom-middleware.ts | 3 +- app/scripts/lib/ppom/ppom-util.ts | 2 +- app/scripts/metamask-controller.js | 6 +- shared/constants/bridge.ts | 2 + shared/constants/multichain/networks.ts | 2 + shared/constants/network.ts | 2 + shared/modules/selectors/networks.ts | 114 ++++++++++++++++ .../modules/selectors/smart-transactions.ts | 9 +- {ui => shared/modules}/selectors/util.js | 0 test/data/mock-state.json | 8 +- .../asset-list-control-bar.tsx | 7 +- .../app/assets/asset-list/asset-list.tsx | 2 +- .../network-filter/network-filter.tsx | 2 +- .../app/currency-input/currency-input.js | 6 +- .../detected-token-selection-popover.js | 2 +- .../app/detected-token/detected-token.js | 6 +- .../loading-network-screen.container.js | 6 +- .../confirm-delete-network.container.js | 2 +- .../hide-token-confirmation-modal.js | 6 +- .../transaction-already-confirmed.tsx | 9 +- .../multi-rpc-edit-modal.tsx | 2 +- .../selected-account-component.test.js | 7 - .../selected-account.container.js | 2 +- ...-percentage-overview-cross-chains.test.tsx | 7 +- .../wrong-network-notification.tsx | 9 +- .../address-copy-button.js | 2 +- .../asset-picker-modal-network.tsx | 6 +- .../asset-picker/asset-picker.tsx | 6 +- .../detected-token-banner.js | 2 +- .../import-tokens-modal.js | 2 +- .../network-list-menu/network-list-menu.tsx | 2 +- ...ification-detail-block-explorer-button.tsx | 2 +- .../review-permissions-page.tsx | 2 +- .../components/recipient-content.test.tsx | 2 +- .../deprecated-networks.js | 6 +- .../ui/new-network-info/new-network-info.js | 2 +- ui/ducks/bridge/selectors.ts | 18 +-- ui/ducks/metamask/metamask.js | 43 +----- ui/ducks/send/helpers.test.js | 1 - ui/ducks/send/send.js | 6 +- ui/hooks/bridge/useBridging.ts | 2 +- ...eAccountTotalCrossChainFiatBalance.test.ts | 7 +- .../useAccountTotalCrossChainFiatBalance.ts | 2 +- ui/hooks/useAccountTrackerPolling.ts | 6 +- ui/hooks/useCurrencyRatePolling.ts | 6 +- ui/hooks/useGasFeeEstimates.js | 2 +- ui/hooks/useGasFeeEstimates.test.js | 9 +- ui/hooks/useMMICustodySendTransaction.ts | 2 +- ui/hooks/useMultichainSelector.test.ts | 2 +- ui/hooks/useTokenBalances.ts | 2 +- ui/hooks/useTokenDetectionPolling.ts | 7 +- ui/hooks/useTokenFiatAmount.js | 2 +- ui/hooks/useTokenListPolling.ts | 2 +- ui/hooks/useTokenRatesPolling.ts | 2 +- ui/hooks/useTokenTracker.js | 2 +- .../asset/components/chart/asset-chart.tsx | 3 +- ui/pages/asset/components/native-asset.tsx | 2 +- ui/pages/asset/components/token-asset.tsx | 2 +- ui/pages/asset/useHistoricalPrices.ts | 3 +- ui/pages/asset/util.ts | 3 +- ui/pages/bridge/hooks/useAddToken.ts | 6 +- .../hooks/useSubmitBridgeTransaction.test.tsx | 23 +++- ui/pages/bridge/index.tsx | 2 +- .../bridge/prepare/prepare-bridge-page.tsx | 2 +- .../confirm/info/hooks/useSupportsEIP1559.ts | 6 +- .../nft-send-heading/nft-send-heading.tsx | 2 +- .../token-transfer/token-details-section.tsx | 2 +- .../simulation-details/asset-pill.tsx | 2 +- .../confirm-transaction-base.container.js | 2 +- .../confirm-transaction.component.js | 2 +- .../confirmation/confirmation.js | 2 +- ui/pages/confirmations/selectors/confirm.ts | 2 +- ui/pages/home/home.container.js | 3 +- .../privacy-settings/privacy-settings.js | 2 +- .../connect-page/connect-page.tsx | 2 +- ui/pages/routes/routes.container.js | 10 +- .../edit-contact/edit-contact.container.js | 2 +- .../networks-form/networks-form.tsx | 2 +- .../security-tab/security-tab.container.js | 2 +- .../settings-tab/settings-tab.container.js | 2 +- ui/pages/settings/settings.container.js | 2 +- ui/pages/swaps/hooks/useUpdateSwapsState.ts | 3 +- ui/selectors/approvals.ts | 2 +- ui/selectors/confirm-transaction.js | 2 +- ui/selectors/institutional/selectors.test.ts | 17 ++- ui/selectors/institutional/selectors.ts | 9 +- .../metamask-notifications.ts | 2 +- ui/selectors/multichain.test.ts | 6 +- ui/selectors/multichain.ts | 12 +- ui/selectors/networks.test.ts | 129 ++++++++++++++++++ ui/selectors/permissions.js | 2 +- ui/selectors/selectors.js | 46 +------ ui/selectors/selectors.test.js | 59 +------- ui/selectors/signatures.ts | 2 +- ui/selectors/snaps/accounts.ts | 2 +- ui/selectors/snaps/address-book.ts | 2 +- ui/selectors/transactions.js | 10 +- ui/store/actions.ts | 10 +- 98 files changed, 462 insertions(+), 326 deletions(-) create mode 100644 shared/modules/selectors/networks.ts rename {ui => shared/modules}/selectors/util.js (100%) create mode 100644 ui/selectors/networks.test.ts diff --git a/app/scripts/lib/ppom/ppom-middleware.ts b/app/scripts/lib/ppom/ppom-middleware.ts index 44c7a8a965c4..f99cf675f534 100644 --- a/app/scripts/lib/ppom/ppom-middleware.ts +++ b/app/scripts/lib/ppom/ppom-middleware.ts @@ -14,8 +14,7 @@ import { SIGNING_METHODS } from '../../../../shared/constants/transaction'; import { PreferencesController } from '../../controllers/preferences-controller'; import { AppStateController } from '../../controllers/app-state-controller'; import { SECURITY_ALERT_RESPONSE_CHECKING_CHAIN } from '../../../../shared/constants/security-provider'; -// eslint-disable-next-line import/no-restricted-paths -import { getProviderConfig } from '../../../../ui/ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import { trace, TraceContext, TraceName } from '../../../../shared/lib/trace'; import { generateSecurityAlertId, diff --git a/app/scripts/lib/ppom/ppom-util.ts b/app/scripts/lib/ppom/ppom-util.ts index b0bf6b03b4d9..d27ec6c8e505 100644 --- a/app/scripts/lib/ppom/ppom-util.ts +++ b/app/scripts/lib/ppom/ppom-util.ts @@ -158,7 +158,7 @@ export async function isChainSupported(chainId: Hex): Promise { `Error fetching supported chains from security alerts API`, ); } - return supportedChainIds.includes(chainId); + return supportedChainIds.includes(chainId as Hex); } function normalizePPOMRequest( diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ac633bbc8e5d..548b2f9d940c 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -239,10 +239,8 @@ import { } from '../../shared/lib/transactions-controller-utils'; // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths -import { getCurrentChainId } from '../../ui/selectors'; -// TODO: Remove restricted import -// eslint-disable-next-line import/no-restricted-paths -import { getProviderConfig } from '../../ui/ducks/metamask/metamask'; +import { getCurrentChainId } from '../../ui/selectors/selectors'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; import { endTrace, trace } from '../../shared/lib/trace'; // eslint-disable-next-line import/no-restricted-paths import { isSnapId } from '../../ui/helpers/utils/snaps'; diff --git a/shared/constants/bridge.ts b/shared/constants/bridge.ts index ed3b21c6a581..10f2587d3fbd 100644 --- a/shared/constants/bridge.ts +++ b/shared/constants/bridge.ts @@ -13,6 +13,8 @@ export const ALLOWED_BRIDGE_CHAIN_IDS = [ CHAIN_IDS.BASE, ]; +export type AllowedBridgeChainIds = (typeof ALLOWED_BRIDGE_CHAIN_IDS)[number]; + export const BRIDGE_DEV_API_BASE_URL = 'https://bridge.dev-api.cx.metamask.io'; export const BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io'; export const BRIDGE_API_BASE_URL = process.env.BRIDGE_USE_DEV_APIS diff --git a/shared/constants/multichain/networks.ts b/shared/constants/multichain/networks.ts index 04ee1134c0b6..f5a45138d88a 100644 --- a/shared/constants/multichain/networks.ts +++ b/shared/constants/multichain/networks.ts @@ -22,6 +22,8 @@ export type MultichainProviderConfig = ProviderConfigWithImageUrl & { isAddressCompatible: (address: string) => boolean; }; +export type MultichainNetworkIds = `${MultichainNetworks}`; + export enum MultichainNetworks { BITCOIN = 'bip122:000000000019d6689c085ae165831e93', BITCOIN_TESTNET = 'bip122:000000000933ea01ad0ee984209779ba', diff --git a/shared/constants/network.ts b/shared/constants/network.ts index aef122ea67bc..3fca971c338e 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -87,6 +87,8 @@ export const NETWORK_TYPES = { LINEA_MAINNET: 'linea-mainnet', } as const; +export type NetworkTypes = (typeof NETWORK_TYPES)[keyof typeof NETWORK_TYPES]; + /** * An object containing shortcut names for any non-builtin network. We need * this to be able to differentiate between networks that require custom diff --git a/shared/modules/selectors/networks.ts b/shared/modules/selectors/networks.ts new file mode 100644 index 000000000000..41aad6da6948 --- /dev/null +++ b/shared/modules/selectors/networks.ts @@ -0,0 +1,114 @@ +import { + RpcEndpointType, + type NetworkConfiguration, + type NetworkState as _NetworkState, +} from '@metamask/network-controller'; +import { createSelector } from 'reselect'; +import { NetworkStatus } from '../../constants/network'; +import { createDeepEqualSelector } from './util'; + +export type NetworkState = { metamask: _NetworkState }; + +export type NetworkConfigurationsState = { + metamask: { + networkConfigurations: Record< + string, + MetaMaskExtensionNetworkConfiguration + >; + }; +}; + +export type SelectedNetworkClientIdState = { + metamask: { + selectedNetworkClientId: string; + }; +}; + +export type MetaMaskExtensionNetworkConfiguration = NetworkConfiguration; + +export type NetworkConfigurationsByChainIdState = { + metamask: Pick<_NetworkState, 'networkConfigurationsByChainId'>; +}; + +export type ProviderConfigState = NetworkConfigurationsByChainIdState & + SelectedNetworkClientIdState; + +export const getNetworkConfigurationsByChainId = createDeepEqualSelector( + (state: NetworkConfigurationsByChainIdState) => + state.metamask.networkConfigurationsByChainId, + (networkConfigurationsByChainId) => networkConfigurationsByChainId, +); + +export function getSelectedNetworkClientId( + state: SelectedNetworkClientIdState, +) { + return state.metamask.selectedNetworkClientId; +} + +/** + * Get the provider configuration for the current selected network. + * + * @param state - Redux state object. + */ +export const getProviderConfig = createSelector( + (state: ProviderConfigState) => getNetworkConfigurationsByChainId(state), + getSelectedNetworkClientId, + (networkConfigurationsByChainId, selectedNetworkClientId) => { + for (const network of Object.values(networkConfigurationsByChainId)) { + for (const rpcEndpoint of network.rpcEndpoints) { + if (rpcEndpoint.networkClientId === selectedNetworkClientId) { + const blockExplorerUrl = + network.defaultBlockExplorerUrlIndex === undefined + ? undefined + : network.blockExplorerUrls?.[ + network.defaultBlockExplorerUrlIndex + ]; + + return { + chainId: network.chainId, + ticker: network.nativeCurrency, + rpcPrefs: { ...(blockExplorerUrl && { blockExplorerUrl }) }, + type: + rpcEndpoint.type === RpcEndpointType.Custom + ? 'rpc' + : rpcEndpoint.networkClientId, + ...(rpcEndpoint.type === RpcEndpointType.Custom && { + id: rpcEndpoint.networkClientId, + nickname: network.name, + rpcUrl: rpcEndpoint.url, + }), + }; + } + } + } + return undefined; // should not be reachable + }, +); + +export function getNetworkConfigurations( + state: NetworkConfigurationsState, +): Record { + return state.metamask.networkConfigurations; +} + +/** + * Returns true if the currently selected network is inaccessible or whether no + * provider has been set yet for the currently selected network. + * + * @param state - Redux state object. + */ +export function isNetworkLoading(state: NetworkState) { + const selectedNetworkClientId = getSelectedNetworkClientId(state); + return ( + selectedNetworkClientId && + state.metamask.networksMetadata[selectedNetworkClientId].status !== + NetworkStatus.Available + ); +} + +export function getInfuraBlocked(state: NetworkState) { + return ( + state.metamask.networksMetadata[getSelectedNetworkClientId(state)] + .status === NetworkStatus.Blocked + ); +} diff --git a/shared/modules/selectors/smart-transactions.ts b/shared/modules/selectors/smart-transactions.ts index 4fb6d56fc87d..b88d5f7c029b 100644 --- a/shared/modules/selectors/smart-transactions.ts +++ b/shared/modules/selectors/smart-transactions.ts @@ -12,6 +12,7 @@ import { // eslint-disable-next-line import/no-restricted-paths } from '../../../ui/selectors/selectors'; // TODO: Migrate shared selectors to this file. import { isProduction } from '../environment'; +import { NetworkState } from './networks'; type SmartTransactionsMetaMaskState = { metamask: { @@ -113,9 +114,7 @@ export const getCurrentChainSupportsSmartTransactions = ( return getAllowedSmartTransactionsChainIds().includes(chainId); }; -const getIsAllowedRpcUrlForSmartTransactions = ( - state: SmartTransactionsMetaMaskState, -) => { +const getIsAllowedRpcUrlForSmartTransactions = (state: NetworkState) => { const chainId = getCurrentChainId(state); if (!isProduction() || SKIP_STX_RPC_URL_CHECK_CHAIN_IDS.includes(chainId)) { // Allow any STX RPC URL in development and testing environments or for specific chain IDs. @@ -131,7 +130,7 @@ const getIsAllowedRpcUrlForSmartTransactions = ( }; export const getSmartTransactionsEnabled = ( - state: SmartTransactionsMetaMaskState, + state: SmartTransactionsMetaMaskState & NetworkState, ): boolean => { const supportedAccount = accountSupportsSmartTx(state); // TODO: Create a new proxy service only for MM feature flags. @@ -150,7 +149,7 @@ export const getSmartTransactionsEnabled = ( }; export const getIsSmartTransaction = ( - state: SmartTransactionsMetaMaskState, + state: SmartTransactionsMetaMaskState & NetworkState, ): boolean => { const smartTransactionsPreferenceEnabled = getSmartTransactionsPreferenceEnabled(state); diff --git a/ui/selectors/util.js b/shared/modules/selectors/util.js similarity index 100% rename from ui/selectors/util.js rename to shared/modules/selectors/util.js diff --git a/test/data/mock-state.json b/test/data/mock-state.json index d2b66cee3108..734845f0ca9a 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -402,26 +402,30 @@ "name": "Custom Mainnet RPC", "nativeCurrency": "ETH", "defaultRpcEndpointIndex": 0, + "ticker": "ETH", "rpcEndpoints": [ { "type": "custom", "url": "https://testrpc.com", "networkClientId": "testNetworkConfigurationId" } - ] + ], + "blockExplorerUrls": [] }, "0x5": { "chainId": "0x5", "name": "Goerli", "nativeCurrency": "ETH", "defaultRpcEndpointIndex": 0, + "ticker": "ETH", "rpcEndpoints": [ { "type": "custom", "url": "https://goerli.com", "networkClientId": "goerli" } - ] + ], + "blockExplorerUrls": [] } }, "internalAccounts": { diff --git a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx index a09b5128396a..dede9004d29e 100644 --- a/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx +++ b/ui/components/app/assets/asset-list/asset-list-control-bar/asset-list-control-bar.tsx @@ -1,10 +1,7 @@ import React, { useEffect, useRef, useState, useContext, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { - getCurrentNetwork, - getNetworkConfigurationsByChainId, - getPreferences, -} from '../../../../../selectors'; +import { getCurrentNetwork, getPreferences } from '../../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../../shared/modules/selectors/networks'; import { Box, ButtonBase, diff --git a/ui/components/app/assets/asset-list/asset-list.tsx b/ui/components/app/assets/asset-list/asset-list.tsx index 114ced0496ca..6a3036f88764 100644 --- a/ui/components/app/assets/asset-list/asset-list.tsx +++ b/ui/components/app/assets/asset-list/asset-list.tsx @@ -7,10 +7,10 @@ import { getAllDetectedTokensForSelectedAddress, getDetectedTokensInCurrentNetwork, getIstokenDetectionInactiveOnNonMainnetSupportedNetwork, - getNetworkConfigurationsByChainId, getPreferences, getSelectedAccount, } from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; import { getMultichainIsEvm, getMultichainSelectedAccountCachedBalance, diff --git a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx index 29e4c97e2c82..4e9aa14eea25 100644 --- a/ui/components/app/assets/asset-list/network-filter/network-filter.tsx +++ b/ui/components/app/assets/asset-list/network-filter/network-filter.tsx @@ -5,11 +5,11 @@ import { getCurrentChainId, getCurrentNetwork, getPreferences, - getNetworkConfigurationsByChainId, getChainIdsToPoll, getShouldHideZeroBalanceTokens, getSelectedAccount, } from '../../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../../shared/modules/selectors/networks'; import { useI18nContext } from '../../../../../hooks/useI18nContext'; import { SelectableListItem } from '../sort-control/sort-control'; import { Text } from '../../../../component-library/text/text'; diff --git a/ui/components/app/currency-input/currency-input.js b/ui/components/app/currency-input/currency-input.js index 43da00ad3ab0..3efcecb35150 100644 --- a/ui/components/app/currency-input/currency-input.js +++ b/ui/components/app/currency-input/currency-input.js @@ -5,10 +5,8 @@ import { Box } from '../../component-library'; import { BlockSize } from '../../../helpers/constants/design-system'; import UnitInput from '../../ui/unit-input'; import CurrencyDisplay from '../../ui/currency-display'; -import { - getNativeCurrency, - getProviderConfig, -} from '../../../ducks/metamask/metamask'; +import { getNativeCurrency } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import { getCurrentChainId, getCurrentCurrency, diff --git a/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js b/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js index 5974d8ba71b6..ff205f7844f0 100644 --- a/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js +++ b/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js @@ -14,9 +14,9 @@ import { getCurrentChainId, getCurrentNetwork, getDetectedTokensInCurrentNetwork, - getNetworkConfigurationsByChainId, getPreferences, } from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; import Popover from '../../../ui/popover'; import Box from '../../../ui/box'; diff --git a/ui/components/app/detected-token/detected-token.js b/ui/components/app/detected-token/detected-token.js index 31e100547e12..bb215b4f7301 100644 --- a/ui/components/app/detected-token/detected-token.js +++ b/ui/components/app/detected-token/detected-token.js @@ -12,10 +12,12 @@ import { getAllDetectedTokensForSelectedAddress, getCurrentChainId, getDetectedTokensInCurrentNetwork, - getNetworkConfigurationsByChainId, getPreferences, - getSelectedNetworkClientId, } from '../../../selectors'; +import { + getSelectedNetworkClientId, + getNetworkConfigurationsByChainId, +} from '../../../../shared/modules/selectors/networks'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { diff --git a/ui/components/app/loading-network-screen/loading-network-screen.container.js b/ui/components/app/loading-network-screen/loading-network-screen.container.js index 34a626bc1b5e..77920ad68032 100644 --- a/ui/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/components/app/loading-network-screen/loading-network-screen.container.js @@ -4,9 +4,11 @@ import * as actions from '../../../store/actions'; import { getAllEnabledNetworks, getNetworkIdentifier, - isNetworkLoading, } from '../../../selectors'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { + getProviderConfig, + isNetworkLoading, +} from '../../../../shared/modules/selectors/networks'; import LoadingNetworkScreen from './loading-network-screen.component'; const DEPRECATED_TEST_NET_CHAINIDS = ['0x3', '0x2a', '0x4']; diff --git a/ui/components/app/modals/confirm-delete-network/confirm-delete-network.container.js b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.container.js index ac4c444692d2..ccca2935bf4d 100644 --- a/ui/components/app/modals/confirm-delete-network/confirm-delete-network.container.js +++ b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; import { removeNetwork } from '../../../../store/actions'; -import { getNetworkConfigurationsByChainId } from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; import ConfirmDeleteNetwork from './confirm-delete-network.component'; const mapStateToProps = (state, ownProps) => { diff --git a/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js b/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js index e1662a641ae7..c34e4897d50a 100644 --- a/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js +++ b/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js @@ -9,10 +9,8 @@ import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../../shared/constants/metametrics'; -import { - getCurrentChainId, - getNetworkConfigurationsByChainId, -} from '../../../../selectors'; +import { getCurrentChainId } from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; function mapStateToProps(state) { return { diff --git a/ui/components/app/modals/transaction-already-confirmed/transaction-already-confirmed.tsx b/ui/components/app/modals/transaction-already-confirmed/transaction-already-confirmed.tsx index 1bd2afc75926..031ffcf175c8 100644 --- a/ui/components/app/modals/transaction-already-confirmed/transaction-already-confirmed.tsx +++ b/ui/components/app/modals/transaction-already-confirmed/transaction-already-confirmed.tsx @@ -2,7 +2,6 @@ import React, { useContext } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { getBlockExplorerLink } from '@metamask/etherscan-link'; import { type TransactionMeta } from '@metamask/transaction-controller'; -import { type NetworkClientConfiguration } from '@metamask/network-controller'; import { getRpcPrefsForCurrentProvider, getTransaction, @@ -38,9 +37,7 @@ export default function TransactionAlreadyConfirmed() { // eslint-disable-next-line @typescript-eslint/no-explicit-any (getTransaction as any)(state, originalTransactionId), ); - const rpcPrefs: NetworkClientConfiguration = useSelector( - getRpcPrefsForCurrentProvider, - ); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const viewTransaction = () => { // TODO: Fix getBlockExplorerLink arguments compatible with the actual controller types @@ -48,9 +45,7 @@ export default function TransactionAlreadyConfirmed() { // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any transaction as any, - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - rpcPrefs as any, + rpcPrefs, ); global.platform.openTab({ url: blockExplorerLink, diff --git a/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx b/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx index 0d6985dbfb4d..3136c92993dd 100644 --- a/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx +++ b/ui/components/app/multi-rpc-edit-modal/multi-rpc-edit-modal.tsx @@ -24,7 +24,7 @@ import { setShowMultiRpcModal } from '../../../store/actions'; // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { getNetworkConfigurationsByChainId } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import NetworkListItem from './network-list-item/network-list-item'; diff --git a/ui/components/app/selected-account/selected-account-component.test.js b/ui/components/app/selected-account/selected-account-component.test.js index 9545580bebbb..257ee44aa46a 100644 --- a/ui/components/app/selected-account/selected-account-component.test.js +++ b/ui/components/app/selected-account/selected-account-component.test.js @@ -52,13 +52,6 @@ jest.mock('../../../selectors', () => { getAccountType: mockGetAccountType, getSelectedInternalAccount: mockGetSelectedAccount, getCurrentChainId: jest.fn(() => '0x5'), - getSelectedNetworkClientId: jest.fn(() => 'goerli'), - getNetworkConfigurationsByChainId: jest.fn(() => ({ - '0x5': { - chainId: '0x5', - rpcEndpoints: [{ networkClientId: 'goerli' }], - }, - })), }; }); diff --git a/ui/components/app/selected-account/selected-account.container.js b/ui/components/app/selected-account/selected-account.container.js index a6e0c03a347a..2ba78fa4c2de 100644 --- a/ui/components/app/selected-account/selected-account.container.js +++ b/ui/components/app/selected-account/selected-account.container.js @@ -10,7 +10,7 @@ import { getCustodyAccountDetails, getIsCustodianSupportedChain, } from '../../../selectors/institutional/selectors'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; ///: END:ONLY_INCLUDE_IF import SelectedAccount from './selected-account.component'; diff --git a/ui/components/app/wallet-overview/aggregated-percentage-overview-cross-chains.test.tsx b/ui/components/app/wallet-overview/aggregated-percentage-overview-cross-chains.test.tsx index 1a335de9c14b..72b2e89e49c6 100644 --- a/ui/components/app/wallet-overview/aggregated-percentage-overview-cross-chains.test.tsx +++ b/ui/components/app/wallet-overview/aggregated-percentage-overview-cross-chains.test.tsx @@ -8,11 +8,11 @@ import { getShouldHideZeroBalanceTokens, getPreferences, getMarketData, - getNetworkConfigurationsByChainId, getAllTokens, getChainIdsToPoll, } from '../../../selectors'; import { useAccountTotalCrossChainFiatBalance } from '../../../hooks/useAccountTotalCrossChainFiatBalance'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { AggregatedPercentageOverviewCrossChains } from './aggregated-percentage-overview-cross-chains'; jest.mock('react-redux', () => ({ @@ -36,11 +36,14 @@ jest.mock('../../../selectors', () => ({ getPreferences: jest.fn(), getShouldHideZeroBalanceTokens: jest.fn(), getMarketData: jest.fn(), - getNetworkConfigurationsByChainId: jest.fn(), getAllTokens: jest.fn(), getChainIdsToPoll: jest.fn(), })); +jest.mock('../../../../shared/modules/selectors/networks', () => ({ + getNetworkConfigurationsByChainId: jest.fn(), +})); + jest.mock('../../../hooks/useAccountTotalCrossChainFiatBalance', () => ({ useAccountTotalCrossChainFiatBalance: jest.fn(), })); diff --git a/ui/components/institutional/wrong-network-notification/wrong-network-notification.tsx b/ui/components/institutional/wrong-network-notification/wrong-network-notification.tsx index 217ce2e575c0..f5c412260bb2 100644 --- a/ui/components/institutional/wrong-network-notification/wrong-network-notification.tsx +++ b/ui/components/institutional/wrong-network-notification/wrong-network-notification.tsx @@ -11,16 +11,13 @@ import { import { getSelectedAccountCachedBalance } from '../../../selectors'; import { getIsCustodianSupportedChain } from '../../../selectors/institutional/selectors'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import { Icon, IconName, IconSize, Box, Text } from '../../component-library'; const WrongNetworkNotification: React.FC = () => { const t = useI18nContext(); - const providerConfig = useSelector< - object, - { nickname?: string; type: string } | undefined - >(getProviderConfig); - const balance = useSelector(getSelectedAccountCachedBalance); + const providerConfig = useSelector(getProviderConfig); + const balance = useSelector(getSelectedAccountCachedBalance); const isCustodianSupportedChain = useSelector(getIsCustodianSupportedChain); diff --git a/ui/components/multichain/address-copy-button/address-copy-button.js b/ui/components/multichain/address-copy-button/address-copy-button.js index fa8b0803ee0b..8fb73c299fd2 100644 --- a/ui/components/multichain/address-copy-button/address-copy-button.js +++ b/ui/components/multichain/address-copy-button/address-copy-button.js @@ -8,7 +8,7 @@ import { getIsCustodianSupportedChain, getCustodianIconForAddress, } from '../../../selectors/institutional/selectors'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; ///: END:ONLY_INCLUDE_IF import { ButtonBase, IconName, Box } from '../../component-library'; import { diff --git a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx index d674fbef528e..f64209543557 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx @@ -19,8 +19,10 @@ import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../shared/constan import { useI18nContext } from '../../../../hooks/useI18nContext'; ///: END:ONLY_INCLUDE_IF import { NetworkListItem } from '../../network-list-item'; -import { getNetworkConfigurationsByChainId } from '../../../../selectors'; -import { getProviderConfig } from '../../../../ducks/metamask/metamask'; +import { + getNetworkConfigurationsByChainId, + getProviderConfig, +} from '../../../../../shared/modules/selectors/networks'; /** * AssetPickerModalNetwork component displays a modal for selecting a network in the asset picker. diff --git a/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx b/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx index ff665ce0f8f8..cf87ee3ba7f1 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx @@ -24,10 +24,8 @@ import { } from '../../../../helpers/constants/design-system'; import { AssetType } from '../../../../../shared/constants/transaction'; import { AssetPickerModal } from '../asset-picker-modal/asset-picker-modal'; -import { - getCurrentNetwork, - getNetworkConfigurationsByChainId, -} from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; +import { getCurrentNetwork } from '../../../../selectors'; import Tooltip from '../../../ui/tooltip'; import { LARGE_SYMBOL_LENGTH } from '../constants'; ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) diff --git a/ui/components/multichain/detected-token-banner/detected-token-banner.js b/ui/components/multichain/detected-token-banner/detected-token-banner.js index 59db889d11ce..4f76fa22fb35 100644 --- a/ui/components/multichain/detected-token-banner/detected-token-banner.js +++ b/ui/components/multichain/detected-token-banner/detected-token-banner.js @@ -9,8 +9,8 @@ import { getDetectedTokensInCurrentNetwork, getAllDetectedTokensForSelectedAddress, getPreferences, - getNetworkConfigurationsByChainId, } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsEventCategory, diff --git a/ui/components/multichain/import-tokens-modal/import-tokens-modal.js b/ui/components/multichain/import-tokens-modal/import-tokens-modal.js index b9ef596b8f07..a1194f2285f2 100644 --- a/ui/components/multichain/import-tokens-modal/import-tokens-modal.js +++ b/ui/components/multichain/import-tokens-modal/import-tokens-modal.js @@ -21,13 +21,13 @@ import { getIstokenDetectionInactiveOnNonMainnetSupportedNetwork, getRpcPrefsForCurrentProvider, getSelectedInternalAccount, - getSelectedNetworkClientId, getTokenDetectionSupportNetworkByChainId, getTokenList, getCurrentNetwork, getTestNetworkBackgroundColor, getTokenExchangeRates, } from '../../../selectors'; +import { getSelectedNetworkClientId } from '../../../../shared/modules/selectors/networks'; import { addImportedTokens, clearPendingTokens, diff --git a/ui/components/multichain/network-list-menu/network-list-menu.tsx b/ui/components/multichain/network-list-menu/network-list-menu.tsx index 9c99b3048a95..8b18170adc6c 100644 --- a/ui/components/multichain/network-list-menu/network-list-menu.tsx +++ b/ui/components/multichain/network-list-menu/network-list-menu.tsx @@ -36,6 +36,7 @@ import { FEATURED_RPCS, TEST_CHAINS, } from '../../../../shared/constants/network'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { getCurrentChainId, getShowTestNetworks, @@ -44,7 +45,6 @@ import { getOriginOfCurrentTab, getUseRequestQueue, getEditedNetwork, - getNetworkConfigurationsByChainId, getOrderedNetworksList, getIsAddingNewNetwork, getIsMultiRpcOnboarding, diff --git a/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx b/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx index 6ca6e27c491f..8f0395abf230 100644 --- a/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx +++ b/ui/components/multichain/notification-detail-block-explorer-button/notification-detail-block-explorer-button.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useSelector } from 'react-redux'; import type { NotificationServicesController } from '@metamask/notification-services-controller'; import { toHex } from '@metamask/controller-utils'; -import { getNetworkConfigurationsByChainId } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { CHAIN_IDS } from '../../../../shared/constants/network'; import { ButtonVariant } from '../../component-library'; import { useI18nContext } from '../../../hooks/useI18nContext'; diff --git a/ui/components/multichain/pages/review-permissions-page/review-permissions-page.tsx b/ui/components/multichain/pages/review-permissions-page/review-permissions-page.tsx index 66e7cadd7546..f65dd7a662cf 100644 --- a/ui/components/multichain/pages/review-permissions-page/review-permissions-page.tsx +++ b/ui/components/multichain/pages/review-permissions-page/review-permissions-page.tsx @@ -11,10 +11,10 @@ import { FlexDirection, } from '../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../hooks/useI18nContext'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; import { getConnectedSitesList, getInternalAccounts, - getNetworkConfigurationsByChainId, getPermissionSubjects, getPermittedAccountsForSelectedTab, getPermittedChainsForSelectedTab, diff --git a/ui/components/multichain/pages/send/components/recipient-content.test.tsx b/ui/components/multichain/pages/send/components/recipient-content.test.tsx index d738aee3cb8a..fe3f1b539ea3 100644 --- a/ui/components/multichain/pages/send/components/recipient-content.test.tsx +++ b/ui/components/multichain/pages/send/components/recipient-content.test.tsx @@ -21,7 +21,7 @@ jest.mock('reselect', () => ({ createSelector: jest.fn(), })); -jest.mock('../../../../../selectors/util', () => ({ +jest.mock('../../../../../../shared/modules/selectors/util', () => ({ createDeepEqualSelector: jest.fn(), })); diff --git a/ui/components/ui/deprecated-networks/deprecated-networks.js b/ui/components/ui/deprecated-networks/deprecated-networks.js index 736b5badb6a0..de7bbec1fd28 100644 --- a/ui/components/ui/deprecated-networks/deprecated-networks.js +++ b/ui/components/ui/deprecated-networks/deprecated-networks.js @@ -7,10 +7,8 @@ import { Severity, } from '../../../helpers/constants/design-system'; -import { - getCurrentNetwork, - getNetworkConfigurationsByChainId, -} from '../../../selectors'; +import { getCurrentNetwork } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { getCompletedOnboarding } from '../../../ducks/metamask/metamask'; import { BannerAlert, Box } from '../../component-library'; import { diff --git a/ui/components/ui/new-network-info/new-network-info.js b/ui/components/ui/new-network-info/new-network-info.js index 51b96bdc5b36..15a11918afc1 100644 --- a/ui/components/ui/new-network-info/new-network-info.js +++ b/ui/components/ui/new-network-info/new-network-info.js @@ -3,7 +3,7 @@ import { useSelector } from 'react-redux'; import { TOKEN_API_METASWAP_CODEFI_URL } from '../../../../shared/constants/tokens'; import fetchWithCache from '../../../../shared/lib/fetch-with-cache'; import { I18nContext } from '../../../contexts/i18n'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import { AlignItems, BackgroundColor, diff --git a/ui/ducks/bridge/selectors.ts b/ui/ducks/bridge/selectors.ts index 5624a0ec5569..86f4c8155b17 100644 --- a/ui/ducks/bridge/selectors.ts +++ b/ui/ducks/bridge/selectors.ts @@ -1,11 +1,7 @@ -import { - NetworkConfiguration, - NetworkState, -} from '@metamask/network-controller'; +import { NetworkConfiguration } from '@metamask/network-controller'; import { uniqBy } from 'lodash'; import { createSelector } from 'reselect'; import { - getNetworkConfigurationsByChainId, getIsBridgeEnabled, getSwapsDefaultToken, SwapsEthToken, @@ -17,8 +13,12 @@ import { // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths } from '../../../app/scripts/controllers/bridge/types'; -import { createDeepEqualSelector } from '../../selectors/util'; -import { getProviderConfig } from '../metamask/metamask'; +import { createDeepEqualSelector } from '../../../shared/modules/selectors/util'; +import { + NetworkState, + getProviderConfig, + getNetworkConfigurationsByChainId, +} from '../../../shared/modules/selectors/networks'; import { SwapsTokenObject } from '../../../shared/constants/swaps'; import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils'; // TODO: Remove restricted import @@ -26,8 +26,8 @@ import { calcTokenAmount } from '../../../shared/lib/transactions-controller-uti import { RequestStatus } from '../../../app/scripts/controllers/bridge/constants'; import { BridgeState } from './bridge'; -export type BridgeAppState = { - metamask: NetworkState & { bridgeState: BridgeControllerState } & { +type BridgeAppState = NetworkState & { + metamask: { bridgeState: BridgeControllerState } & { useExternalServices: boolean; }; bridge: BridgeState; diff --git a/ui/ducks/metamask/metamask.js b/ui/ducks/metamask/metamask.js index af456e29acbc..93550d45fc10 100644 --- a/ui/ducks/metamask/metamask.js +++ b/ui/ducks/metamask/metamask.js @@ -1,7 +1,6 @@ import { addHexPrefix, isHexString } from 'ethereumjs-util'; import { createSelector } from 'reselect'; import { mergeGasFeeEstimates } from '@metamask/transaction-controller'; -import { RpcEndpointType } from '@metamask/network-controller'; import { AlertTypes } from '../../../shared/constants/alerts'; import { GasEstimateTypes, @@ -16,9 +15,11 @@ import { accountsWithSendEtherInfoSelector, checkNetworkAndAccountSupports1559, getAddressBook, - getSelectedNetworkClientId, - getNetworkConfigurationsByChainId, } from '../../selectors/selectors'; +import { + getProviderConfig, + getSelectedNetworkClientId, +} from '../../../shared/modules/selectors/networks'; import { getSelectedInternalAccount } from '../../selectors/accounts'; import * as actionConstants from '../../store/actionConstants'; import { updateTransactionGasFees } from '../../store/actions'; @@ -274,42 +275,6 @@ export function updateGasFees({ export const getAlertEnabledness = (state) => state.metamask.alertEnabledness; -/** - * Get the provider configuration for the current selected network. - * - * @param {object} state - Redux state object. - */ -export const getProviderConfig = createSelector( - (state) => getNetworkConfigurationsByChainId(state), - (state) => getSelectedNetworkClientId(state), - (networkConfigurationsByChainId, selectedNetworkClientId) => { - for (const network of Object.values(networkConfigurationsByChainId)) { - for (const rpcEndpoint of network.rpcEndpoints) { - if (rpcEndpoint.networkClientId === selectedNetworkClientId) { - const blockExplorerUrl = - network.blockExplorerUrls?.[network.defaultBlockExplorerUrlIndex]; - - return { - chainId: network.chainId, - ticker: network.nativeCurrency, - rpcPrefs: { ...(blockExplorerUrl && { blockExplorerUrl }) }, - type: - rpcEndpoint.type === RpcEndpointType.Custom - ? 'rpc' - : rpcEndpoint.networkClientId, - ...(rpcEndpoint.type === RpcEndpointType.Custom && { - id: rpcEndpoint.networkClientId, - nickname: network.name, - rpcUrl: rpcEndpoint.url, - }), - }; - } - } - } - return undefined; // should not be reachable - }, -); - export const getUnconnectedAccountAlertEnabledness = (state) => getAlertEnabledness(state)[AlertTypes.unconnectedAccount]; diff --git a/ui/ducks/send/helpers.test.js b/ui/ducks/send/helpers.test.js index 74f660991cd7..7129ffca8194 100644 --- a/ui/ducks/send/helpers.test.js +++ b/ui/ducks/send/helpers.test.js @@ -64,7 +64,6 @@ jest.mock('../metamask/metamask', () => ({ ...jest.requireActual('../metamask/metamask'), getGasFeeEstimates: jest.fn(), getNativeCurrency: jest.fn(), - getProviderConfig: jest.fn(), })); jest.mock('../swaps/swaps', () => ({ diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index 30cbc6eeb5dd..15acc3355d8f 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -53,10 +53,13 @@ import { getSelectedInternalAccount, getSelectedInternalAccountWithBalance, getUnapprovedTransactions, - getSelectedNetworkClientId, getIsSwapsChain, getUseExternalServices, } from '../../selectors'; +import { + getSelectedNetworkClientId, + getProviderConfig, +} from '../../../shared/modules/selectors/networks'; import { displayWarning, hideLoadingIndication, @@ -101,7 +104,6 @@ import { import { getGasEstimateType, getNativeCurrency, - getProviderConfig, getTokens, } from '../metamask/metamask'; diff --git a/ui/hooks/bridge/useBridging.ts b/ui/hooks/bridge/useBridging.ts index fe7a21e2206f..c4ae1cca57a3 100644 --- a/ui/hooks/bridge/useBridging.ts +++ b/ui/hooks/bridge/useBridging.ts @@ -30,7 +30,7 @@ import { isHardwareKeyring } from '../../helpers/utils/hardware'; import { getPortfolioUrl } from '../../helpers/utils/portfolio'; import { setSwapsFromToken } from '../../ducks/swaps/swaps'; import { SwapsTokenObject } from '../../../shared/constants/swaps'; -import { getProviderConfig } from '../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../shared/modules/selectors/networks'; ///: END:ONLY_INCLUDE_IF const useBridging = () => { diff --git a/ui/hooks/useAccountTotalCrossChainFiatBalance.test.ts b/ui/hooks/useAccountTotalCrossChainFiatBalance.test.ts index 9fe819d92171..dd5b8aaab579 100644 --- a/ui/hooks/useAccountTotalCrossChainFiatBalance.test.ts +++ b/ui/hooks/useAccountTotalCrossChainFiatBalance.test.ts @@ -3,11 +3,11 @@ import { renderHook } from '@testing-library/react-hooks'; import { act } from 'react-dom/test-utils'; import { getCurrentCurrency, - getNetworkConfigurationsByChainId, getCrossChainTokenExchangeRates, getCrossChainMetaMaskCachedBalances, } from '../selectors'; import { getCurrencyRates } from '../ducks/metamask/metamask'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import { FormattedTokensWithBalances, useAccountTotalCrossChainFiatBalance, @@ -19,13 +19,16 @@ jest.mock('react-redux', () => ({ jest.mock('../selectors', () => ({ getCurrentCurrency: jest.fn(), - getNetworkConfigurationsByChainId: jest.fn(), getCrossChainTokenExchangeRates: jest.fn(), getCrossChainMetaMaskCachedBalances: jest.fn(), })); jest.mock('../ducks/metamask/metamask', () => ({ getCurrencyRates: jest.fn(), })); +jest.mock('../../shared/modules/selectors/networks', () => ({ + getSelectedNetworkClientId: jest.fn(), + getNetworkConfigurationsByChainId: jest.fn(), +})); const mockGetCurrencyRates = getCurrencyRates as jest.Mock; const mockGetCurrentCurrency = getCurrentCurrency as jest.Mock; diff --git a/ui/hooks/useAccountTotalCrossChainFiatBalance.ts b/ui/hooks/useAccountTotalCrossChainFiatBalance.ts index d63328e4fbcf..ac5658278946 100644 --- a/ui/hooks/useAccountTotalCrossChainFiatBalance.ts +++ b/ui/hooks/useAccountTotalCrossChainFiatBalance.ts @@ -2,7 +2,6 @@ import { shallowEqual, useSelector } from 'react-redux'; import { toChecksumAddress } from 'ethereumjs-util'; import { getCurrentCurrency, - getNetworkConfigurationsByChainId, getCrossChainTokenExchangeRates, getCrossChainMetaMaskCachedBalances, } from '../selectors'; @@ -13,6 +12,7 @@ import { import { getCurrencyRates } from '../ducks/metamask/metamask'; import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { TokenWithBalance } from '../components/app/assets/asset-list/asset-list'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; type AddressBalances = { [address: string]: number; diff --git a/ui/hooks/useAccountTrackerPolling.ts b/ui/hooks/useAccountTrackerPolling.ts index cc7f9aee3818..5dffe5dfc852 100644 --- a/ui/hooks/useAccountTrackerPolling.ts +++ b/ui/hooks/useAccountTrackerPolling.ts @@ -1,8 +1,5 @@ import { useSelector } from 'react-redux'; -import { - getCurrentChainId, - getNetworkConfigurationsByChainId, -} from '../selectors'; +import { getCurrentChainId } from '../selectors'; import { accountTrackerStartPolling, accountTrackerStopPollingByPollingToken, @@ -11,6 +8,7 @@ import { getCompletedOnboarding, getIsUnlocked, } from '../ducks/metamask/metamask'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import useMultiPolling from './useMultiPolling'; const useAccountTrackerPolling = () => { diff --git a/ui/hooks/useCurrencyRatePolling.ts b/ui/hooks/useCurrencyRatePolling.ts index 34772a94a501..cd8c616cd4b9 100644 --- a/ui/hooks/useCurrencyRatePolling.ts +++ b/ui/hooks/useCurrencyRatePolling.ts @@ -1,8 +1,6 @@ import { useSelector } from 'react-redux'; -import { - getNetworkConfigurationsByChainId, - getUseCurrencyRateCheck, -} from '../selectors'; +import { getUseCurrencyRateCheck } from '../selectors'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import { currencyRateStartPolling, currencyRateStopPollingByPollingToken, diff --git a/ui/hooks/useGasFeeEstimates.js b/ui/hooks/useGasFeeEstimates.js index abbaf0db0bb9..b1b686256059 100644 --- a/ui/hooks/useGasFeeEstimates.js +++ b/ui/hooks/useGasFeeEstimates.js @@ -12,7 +12,7 @@ import { gasFeeStopPollingByPollingToken, getNetworkConfigurationByNetworkClientId, } from '../store/actions'; -import { getSelectedNetworkClientId } from '../selectors'; +import { getSelectedNetworkClientId } from '../../shared/modules/selectors/networks'; import usePolling from './usePolling'; /** diff --git a/ui/hooks/useGasFeeEstimates.test.js b/ui/hooks/useGasFeeEstimates.test.js index dd63e10581d0..c09785ac36ab 100644 --- a/ui/hooks/useGasFeeEstimates.test.js +++ b/ui/hooks/useGasFeeEstimates.test.js @@ -36,13 +36,16 @@ jest.mock('../ducks/metamask/metamask', () => ({ .mockReturnValue('getIsNetworkBusyByChainId'), })); +jest.mock('../../shared/modules/selectors/networks', () => ({ + getSelectedNetworkClientId: jest + .fn() + .mockReturnValue('getSelectedNetworkClientId'), +})); + jest.mock('../selectors', () => ({ checkNetworkAndAccountSupports1559: jest .fn() .mockReturnValue('checkNetworkAndAccountSupports1559'), - getSelectedNetworkClientId: jest - .fn() - .mockReturnValue('getSelectedNetworkClientId'), })); jest.mock('react-redux', () => { diff --git a/ui/hooks/useMMICustodySendTransaction.ts b/ui/hooks/useMMICustodySendTransaction.ts index 49634fbf0174..ac434bb5d8db 100644 --- a/ui/hooks/useMMICustodySendTransaction.ts +++ b/ui/hooks/useMMICustodySendTransaction.ts @@ -19,7 +19,7 @@ import { getConfirmationSender } from '../pages/confirmations/components/confirm import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import { getSmartTransactionsEnabled } from '../../shared/modules/selectors'; import { CHAIN_ID_TO_RPC_URL_MAP } from '../../shared/constants/network'; -import { getProviderConfig } from '../ducks/metamask/metamask'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; type MMITransactionMeta = TransactionMeta & { txParams: { from: string }; diff --git a/ui/hooks/useMultichainSelector.test.ts b/ui/hooks/useMultichainSelector.test.ts index 35ed5cf7b155..e5d7f197ffcb 100644 --- a/ui/hooks/useMultichainSelector.test.ts +++ b/ui/hooks/useMultichainSelector.test.ts @@ -1,7 +1,7 @@ import { InternalAccount } from '@metamask/keyring-api'; import { createMockInternalAccount } from '../../test/jest/mocks'; import { renderHookWithProvider } from '../../test/lib/render-helpers'; -import { getSelectedNetworkClientId } from '../selectors'; +import { getSelectedNetworkClientId } from '../../shared/modules/selectors/networks'; import { MultichainState, getMultichainIsEvm } from '../selectors/multichain'; import { CHAIN_IDS } from '../../shared/constants/network'; import { mockNetworkState } from '../../test/stub/networks'; diff --git a/ui/hooks/useTokenBalances.ts b/ui/hooks/useTokenBalances.ts index 8d3a078f8d07..52add5a99592 100644 --- a/ui/hooks/useTokenBalances.ts +++ b/ui/hooks/useTokenBalances.ts @@ -2,7 +2,7 @@ import { useSelector } from 'react-redux'; import BN from 'bn.js'; import { Token } from '@metamask/assets-controllers'; import { Hex } from '@metamask/utils'; -import { getNetworkConfigurationsByChainId } from '../selectors'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import { tokenBalancesStartPolling, tokenBalancesStopPollingByPollingToken, diff --git a/ui/hooks/useTokenDetectionPolling.ts b/ui/hooks/useTokenDetectionPolling.ts index d2e08d01892d..66e027b5af6b 100644 --- a/ui/hooks/useTokenDetectionPolling.ts +++ b/ui/hooks/useTokenDetectionPolling.ts @@ -1,9 +1,6 @@ import { useSelector } from 'react-redux'; -import { - getCurrentChainId, - getNetworkConfigurationsByChainId, - getUseTokenDetection, -} from '../selectors'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; +import { getCurrentChainId, getUseTokenDetection } from '../selectors'; import { tokenDetectionStartPolling, tokenDetectionStopPollingByPollingToken, diff --git a/ui/hooks/useTokenFiatAmount.js b/ui/hooks/useTokenFiatAmount.js index 5abbbc608de0..2728b2994781 100644 --- a/ui/hooks/useTokenFiatAmount.js +++ b/ui/hooks/useTokenFiatAmount.js @@ -7,8 +7,8 @@ import { getConfirmationExchangeRates, getMarketData, getCurrencyRates, - getNetworkConfigurationsByChainId, } from '../selectors'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { getConversionRate } from '../ducks/metamask/metamask'; import { isEqualCaseInsensitive } from '../../shared/modules/string-utils'; diff --git a/ui/hooks/useTokenListPolling.ts b/ui/hooks/useTokenListPolling.ts index 7f7de517c304..98ea0c324da4 100644 --- a/ui/hooks/useTokenListPolling.ts +++ b/ui/hooks/useTokenListPolling.ts @@ -1,12 +1,12 @@ import { useSelector } from 'react-redux'; import { getCurrentChainId, - getNetworkConfigurationsByChainId, getPetnamesEnabled, getUseExternalServices, getUseTokenDetection, getUseTransactionSimulations, } from '../selectors'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import { tokenListStartPolling, tokenListStopPollingByPollingToken, diff --git a/ui/hooks/useTokenRatesPolling.ts b/ui/hooks/useTokenRatesPolling.ts index 37864ec89b82..bd57da835a99 100644 --- a/ui/hooks/useTokenRatesPolling.ts +++ b/ui/hooks/useTokenRatesPolling.ts @@ -2,11 +2,11 @@ import { useSelector } from 'react-redux'; import { getCurrentChainId, getMarketData, - getNetworkConfigurationsByChainId, getTokenExchangeRates, getTokensMarketData, getUseCurrencyRateCheck, } from '../selectors'; +import { getNetworkConfigurationsByChainId } from '../../shared/modules/selectors/networks'; import { tokenRatesStartPolling, tokenRatesStopPollingByPollingToken, diff --git a/ui/hooks/useTokenTracker.js b/ui/hooks/useTokenTracker.js index 0ce2c9cbcac2..c38b3c295f58 100644 --- a/ui/hooks/useTokenTracker.js +++ b/ui/hooks/useTokenTracker.js @@ -2,9 +2,9 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import TokenTracker from '@metamask/eth-token-tracker'; import { shallowEqual, useSelector } from 'react-redux'; import { getSelectedInternalAccount } from '../selectors'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; import { SECOND } from '../../shared/constants/time'; import { isEqualCaseInsensitive } from '../../shared/modules/string-utils'; -import { getProviderConfig } from '../ducks/metamask/metamask'; import { useEqualityCheck } from './useEqualityCheck'; export function useTokenTracker({ diff --git a/ui/pages/asset/components/chart/asset-chart.tsx b/ui/pages/asset/components/chart/asset-chart.tsx index efa7adad03ad..b49eaf7ced90 100644 --- a/ui/pages/asset/components/chart/asset-chart.tsx +++ b/ui/pages/asset/components/chart/asset-chart.tsx @@ -14,6 +14,7 @@ import { import { Line } from 'react-chartjs-2'; import classnames from 'classnames'; import { brandColor } from '@metamask/design-tokens'; +import { Hex } from '@metamask/utils'; import { useTheme } from '../../../../hooks/useTheme'; import { BackgroundColor, @@ -80,7 +81,7 @@ const AssetChart = ({ currentPrice, currency, }: { - chainId: `0x${string}`; + chainId: Hex; address: string; currentPrice?: number; currency: string; diff --git a/ui/pages/asset/components/native-asset.tsx b/ui/pages/asset/components/native-asset.tsx index abd571b231a7..38f24f8d5bea 100644 --- a/ui/pages/asset/components/native-asset.tsx +++ b/ui/pages/asset/components/native-asset.tsx @@ -8,7 +8,7 @@ import { getSelectedInternalAccount, getNativeCurrencyForChain, } from '../../../selectors'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import { AssetType } from '../../../../shared/constants/transaction'; import { useIsOriginalNativeTokenSymbol } from '../../../hooks/useIsOriginalNativeTokenSymbol'; import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics'; diff --git a/ui/pages/asset/components/token-asset.tsx b/ui/pages/asset/components/token-asset.tsx index ef91b92aae5d..80ff721a216c 100644 --- a/ui/pages/asset/components/token-asset.tsx +++ b/ui/pages/asset/components/token-asset.tsx @@ -6,7 +6,6 @@ import { useHistory } from 'react-router-dom'; import { Hex } from '@metamask/utils'; import { NetworkConfiguration } from '@metamask/network-controller'; import { - getNetworkConfigurationsByChainId, getSelectedInternalAccount, getTokenList, selectERC20TokensByChain, @@ -22,6 +21,7 @@ import { import { MetaMetricsContext } from '../../../contexts/metametrics'; import { showModal } from '../../../store/actions'; import { MetaMetricsEventCategory } from '../../../../shared/constants/metametrics'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import AssetOptions from './asset-options'; import AssetPage from './asset-page'; diff --git a/ui/pages/asset/useHistoricalPrices.ts b/ui/pages/asset/useHistoricalPrices.ts index febf99a9daed..38c76fcf9de1 100644 --- a/ui/pages/asset/useHistoricalPrices.ts +++ b/ui/pages/asset/useHistoricalPrices.ts @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; // @ts-expect-error suppress CommonJS vs ECMAScript error import { Point } from 'chart.js'; import { useSelector } from 'react-redux'; +import { Hex } from '@metamask/utils'; import fetchWithCache from '../../../shared/lib/fetch-with-cache'; import { MINUTE } from '../../../shared/constants/time'; import { getShouldShowFiat } from '../../selectors'; @@ -20,7 +21,7 @@ export const useHistoricalPrices = ({ currency, timeRange, }: { - chainId: `0x${string}`; + chainId: Hex; address: string; currency: string; timeRange: TimeRange; diff --git a/ui/pages/asset/util.ts b/ui/pages/asset/util.ts index c18d6e92dcfa..2f4a41df6cc9 100644 --- a/ui/pages/asset/util.ts +++ b/ui/pages/asset/util.ts @@ -1,4 +1,5 @@ import { SUPPORTED_CHAIN_IDS, Token } from '@metamask/assets-controllers'; +import { Hex } from '@metamask/utils'; /** Formats a datetime in a short human readable format like 'Feb 8, 12:11 PM' */ export const getShortDateFormatter = () => @@ -59,7 +60,7 @@ export const getPricePrecision = (price: number) => { * * @param chainId - The hexadecimal chain id. */ -export const chainSupportsPricing = (chainId: `0x${string}`) => +export const chainSupportsPricing = (chainId: Hex) => (SUPPORTED_CHAIN_IDS as readonly string[]).includes(chainId); /** The opacity components should set during transition */ diff --git a/ui/pages/bridge/hooks/useAddToken.ts b/ui/pages/bridge/hooks/useAddToken.ts index 597149b16e49..d0d29847bf57 100644 --- a/ui/pages/bridge/hooks/useAddToken.ts +++ b/ui/pages/bridge/hooks/useAddToken.ts @@ -2,12 +2,12 @@ import { useDispatch, useSelector } from 'react-redux'; import { NetworkConfiguration } from '@metamask/network-controller'; import { Numeric } from '../../../../shared/modules/Numeric'; import { QuoteResponse } from '../types'; +import { FEATURED_RPCS } from '../../../../shared/constants/network'; +import { addToken, addNetwork } from '../../../store/actions'; import { getNetworkConfigurationsByChainId, getSelectedNetworkClientId, -} from '../../../selectors'; -import { FEATURED_RPCS } from '../../../../shared/constants/network'; -import { addToken, addNetwork } from '../../../store/actions'; +} from '../../../../shared/modules/selectors/networks'; export default function useAddToken() { const dispatch = useDispatch(); diff --git a/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx b/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx index 20f471b1065b..54d7b9e96700 100644 --- a/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx +++ b/ui/pages/bridge/hooks/useSubmitBridgeTransaction.test.tsx @@ -7,7 +7,7 @@ import { Provider } from 'react-redux'; import { MemoryRouter, useHistory } from 'react-router-dom'; import { createBridgeMockStore } from '../../../../test/jest/mock-store'; import * as actions from '../../../store/actions'; -import * as selectors from '../../../selectors'; +import * as networks from '../../../../shared/modules/selectors/networks'; import { DummyQuotesNoApproval, DummyQuotesWithApproval, @@ -41,13 +41,12 @@ jest.mock('../../../store/actions', () => { }; }); -jest.mock('../../../selectors', () => { - const original = jest.requireActual('../../../selectors'); +jest.mock('../../../../shared/modules/selectors/networks', () => { + const original = jest.requireActual( + '../../../../shared/modules/selectors/networks', + ); return { ...original, - getIsBridgeEnabled: () => true, - getIsBridgeChain: () => true, - checkNetworkAndAccountSupports1559: () => true, getSelectedNetworkClientId: () => 'mainnet', getNetworkConfigurationsByChainId: jest.fn(() => ({ '0x1': { @@ -84,6 +83,16 @@ jest.mock('../../../selectors', () => { }; }); +jest.mock('../../../selectors', () => { + const original = jest.requireActual('../../../selectors'); + return { + ...original, + getIsBridgeEnabled: () => true, + getIsBridgeChain: () => true, + checkNetworkAndAccountSupports1559: () => true, + }; +}); + const middleware = [thunk]; const makeMockStore = () => { @@ -402,7 +411,7 @@ describe('ui/pages/bridge/hooks/useSubmitBridgeTransaction', () => { ); const mockedGetNetworkConfigurationsByChainId = // @ts-expect-error this is a jest mock - selectors.getNetworkConfigurationsByChainId as jest.Mock; + networks.getNetworkConfigurationsByChainId as jest.Mock; mockedGetNetworkConfigurationsByChainId.mockImplementationOnce(() => ({ '0x1': { blockExplorerUrls: ['https://etherscan.io'], diff --git a/ui/pages/bridge/index.tsx b/ui/pages/bridge/index.tsx index 2c9f082519e9..687057094005 100644 --- a/ui/pages/bridge/index.tsx +++ b/ui/pages/bridge/index.tsx @@ -17,13 +17,13 @@ import { IconName, } from '../../components/component-library'; import { getIsBridgeChain, getIsBridgeEnabled } from '../../selectors'; +import { getProviderConfig } from '../../../shared/modules/selectors/networks'; import useBridging from '../../hooks/bridge/useBridging'; import { Content, Footer, Header, } from '../../components/multichain/pages/page'; -import { getProviderConfig } from '../../ducks/metamask/metamask'; import { resetBridgeState, setFromChain } from '../../ducks/bridge/actions'; import { useSwapsFeatureFlags } from '../swaps/hooks/useSwapsFeatureFlags'; import PrepareBridgePage from './prepare/prepare-bridge-page'; diff --git a/ui/pages/bridge/prepare/prepare-bridge-page.tsx b/ui/pages/bridge/prepare/prepare-bridge-page.tsx index 46fbdd77786b..b0553407686d 100644 --- a/ui/pages/bridge/prepare/prepare-bridge-page.tsx +++ b/ui/pages/bridge/prepare/prepare-bridge-page.tsx @@ -41,7 +41,7 @@ import { QuoteRequest } from '../types'; import { calcTokenValue } from '../../../../shared/lib/swaps-utils'; import { BridgeQuoteCard } from '../quotes/bridge-quote-card'; import { isValidQuoteRequest } from '../utils/quote'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import { BridgeInputGroup } from './bridge-input-group'; const PrepareBridgePage = () => { diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useSupportsEIP1559.ts b/ui/pages/confirmations/components/confirm/info/hooks/useSupportsEIP1559.ts index 57fbd78de9fc..d492c5030354 100644 --- a/ui/pages/confirmations/components/confirm/info/hooks/useSupportsEIP1559.ts +++ b/ui/pages/confirmations/components/confirm/info/hooks/useSupportsEIP1559.ts @@ -4,10 +4,8 @@ import { } from '@metamask/transaction-controller'; import { useSelector } from 'react-redux'; import { isLegacyTransaction } from '../../../../../../helpers/utils/transactions.util'; -import { - checkNetworkAndAccountSupports1559, - getSelectedNetworkClientId, -} from '../../../../../../selectors'; +import { checkNetworkAndAccountSupports1559 } from '../../../../../../selectors'; +import { getSelectedNetworkClientId } from '../../../../../../../shared/modules/selectors/networks'; export function useSupportsEIP1559(transactionMeta: TransactionMeta) { const isLegacyTxn = diff --git a/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx b/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx index 405236fe66da..09c5ffa922c6 100644 --- a/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx +++ b/ui/pages/confirmations/components/confirm/info/shared/nft-send-heading/nft-send-heading.tsx @@ -17,9 +17,9 @@ import { TextVariant, } from '../../../../../../../helpers/constants/design-system'; import { getNftImageAlt } from '../../../../../../../helpers/utils/nfts'; -import { getNetworkConfigurationsByChainId } from '../../../../../../../selectors'; import { useConfirmContext } from '../../../../../context/confirm'; import { useAssetDetails } from '../../../../../hooks/useAssetDetails'; +import { getNetworkConfigurationsByChainId } from '../../../../../../../../shared/modules/selectors/networks'; const NFTSendHeading = () => { const { currentConfirmation: transactionMeta } = diff --git a/ui/pages/confirmations/components/confirm/info/token-transfer/token-details-section.tsx b/ui/pages/confirmations/components/confirm/info/token-transfer/token-details-section.tsx index b2ee988adde9..dc394fb1442b 100644 --- a/ui/pages/confirmations/components/confirm/info/token-transfer/token-details-section.tsx +++ b/ui/pages/confirmations/components/confirm/info/token-transfer/token-details-section.tsx @@ -26,7 +26,7 @@ import { TextVariant, } from '../../../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../../../hooks/useI18nContext'; -import { getNetworkConfigurationsByChainId } from '../../../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../../../shared/modules/selectors/networks'; import { useConfirmContext } from '../../../../context/confirm'; import { selectConfirmationAdvancedDetailsOpen } from '../../../../selectors/preferences'; import { useBalanceChanges } from '../../../simulation-details/useBalanceChanges'; diff --git a/ui/pages/confirmations/components/simulation-details/asset-pill.tsx b/ui/pages/confirmations/components/simulation-details/asset-pill.tsx index 99bd2b3af8ef..0b7efdf13282 100644 --- a/ui/pages/confirmations/components/simulation-details/asset-pill.tsx +++ b/ui/pages/confirmations/components/simulation-details/asset-pill.tsx @@ -19,7 +19,7 @@ import { } from '../../../../helpers/constants/design-system'; import Name from '../../../../components/app/name'; import { TokenStandard } from '../../../../../shared/constants/transaction'; -import { getNetworkConfigurationsByChainId } from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; import { CHAIN_ID_TOKEN_IMAGE_MAP } from '../../../../../shared/constants/network'; import { AssetIdentifier } from './types'; diff --git a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js index c34025e2f0c5..d9a04ace67a9 100644 --- a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.container.js @@ -54,7 +54,6 @@ import { getUnapprovedTransactions, getInternalAccountByAddress, getApprovedAndSignedTransactions, - getSelectedNetworkClientId, getPrioritizedUnapprovedTemplatedConfirmations, } from '../../../selectors'; import { @@ -72,6 +71,7 @@ import { getSendToAccounts, findKeyringForAddress, } from '../../../ducks/metamask/metamask'; +import { getSelectedNetworkClientId } from '../../../../shared/modules/selectors/networks'; import { addHexPrefix, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) diff --git a/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js b/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js index 12971f21a2af..ef08fb6bbba1 100644 --- a/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js +++ b/ui/pages/confirmations/confirm-transaction/confirm-transaction.component.js @@ -13,6 +13,7 @@ import { } from '../../../ducks/confirm-transaction/confirm-transaction.duck'; import { getMostRecentOverviewPage } from '../../../ducks/history/history'; import { getSendTo } from '../../../ducks/send'; +import { getSelectedNetworkClientId } from '../../../../shared/modules/selectors/networks'; import { CONFIRM_DEPLOY_CONTRACT_PATH, CONFIRM_SEND_ETHER_PATH, @@ -27,7 +28,6 @@ import { isTokenMethodAction } from '../../../helpers/utils/transactions.util'; import usePolling from '../../../hooks/usePolling'; import { usePrevious } from '../../../hooks/usePrevious'; import { - getSelectedNetworkClientId, unconfirmedTransactionsHashSelector, unconfirmedTransactionsListSelector, use4ByteResolutionSelector, diff --git a/ui/pages/confirmations/confirmation/confirmation.js b/ui/pages/confirmations/confirmation/confirmation.js index 30816acea1f2..c2d42be40e47 100644 --- a/ui/pages/confirmations/confirmation/confirmation.js +++ b/ui/pages/confirmations/confirmation/confirmation.js @@ -32,9 +32,9 @@ import { getTotalUnapprovedCount, useSafeChainsListValidationSelector, getSnapsMetadata, - getNetworkConfigurationsByChainId, getHideSnapBranding, } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import Callout from '../../../components/ui/callout'; import { Box, Icon, IconName } from '../../../components/component-library'; import Loading from '../../../components/ui/loading-screen'; diff --git a/ui/pages/confirmations/selectors/confirm.ts b/ui/pages/confirmations/selectors/confirm.ts index 57107bdf3021..e1a3282532d6 100644 --- a/ui/pages/confirmations/selectors/confirm.ts +++ b/ui/pages/confirmations/selectors/confirm.ts @@ -3,7 +3,7 @@ import { ApprovalType } from '@metamask/controller-utils'; import { createSelector } from 'reselect'; import { getPendingApprovals } from '../../../selectors/approvals'; import { getPreferences } from '../../../selectors/selectors'; -import { createDeepEqualSelector } from '../../../selectors/util'; +import { createDeepEqualSelector } from '../../../../shared/modules/selectors/util'; import { ConfirmMetamaskState } from '../types/confirm'; const ConfirmationApprovalTypes = [ diff --git a/ui/pages/home/home.container.js b/ui/pages/home/home.container.js index 9d4511021529..da4677111e63 100644 --- a/ui/pages/home/home.container.js +++ b/ui/pages/home/home.container.js @@ -26,7 +26,6 @@ import { getTotalUnapprovedCount, getUnapprovedTemplatedConfirmations, getWeb3ShimUsageStateForOrigin, - getInfuraBlocked, getShowWhatsNewPopup, getSortedAnnouncementsToShow, getShowRecoveryPhraseReminder, @@ -51,7 +50,7 @@ import { getAccountType, ///: END:ONLY_INCLUDE_IF } from '../../selectors'; - +import { getInfuraBlocked } from '../../../shared/modules/selectors/networks'; import { closeNotificationPopup, setConnectedStatusPopoverHasBeenShown, diff --git a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js index aed08f196957..3e0d2e19de48 100644 --- a/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js +++ b/ui/pages/onboarding-flow/privacy-settings/privacy-settings.js @@ -51,8 +51,8 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import { getPetnamesEnabled, getExternalServicesOnboardingToggleState, - getNetworkConfigurationsByChainId, } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { selectIsProfileSyncingEnabled } from '../../../selectors/metamask-notifications/profile-syncing'; import { setIpfsGateway, diff --git a/ui/pages/permissions-connect/connect-page/connect-page.tsx b/ui/pages/permissions-connect/connect-page/connect-page.tsx index e002e54ef34e..ba9bcc6bf674 100644 --- a/ui/pages/permissions-connect/connect-page/connect-page.tsx +++ b/ui/pages/permissions-connect/connect-page/connect-page.tsx @@ -5,10 +5,10 @@ import { NetworkConfiguration } from '@metamask/network-controller'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { getInternalAccounts, - getNetworkConfigurationsByChainId, getSelectedInternalAccount, getUpdatedAndSortedAccounts, } from '../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { Box, Button, diff --git a/ui/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js index e0fe5575e2c2..bb02e0ebaaa9 100644 --- a/ui/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -6,7 +6,6 @@ import { getIsNetworkUsed, getNetworkIdentifier, getPreferences, - isNetworkLoading, getTheme, getIsTestnet, getCurrentChainId, @@ -26,6 +25,10 @@ import { getUnapprovedTransactions, getPendingApprovals, } from '../../selectors'; +import { + isNetworkLoading, + getProviderConfig, +} from '../../../shared/modules/selectors/networks'; import { lockMetamask, hideImportNftsModal, @@ -47,10 +50,7 @@ import { import { pageChanged } from '../../ducks/history/history'; import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps'; import { getSendStage } from '../../ducks/send'; -import { - getIsUnlocked, - getProviderConfig, -} from '../../ducks/metamask/metamask'; +import { getIsUnlocked } from '../../ducks/metamask/metamask'; import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../shared/constants/preferences'; import { selectSwitchedNetworkNeverShowMessage } from '../../components/app/toast-master/selectors'; import Routes from './routes.component'; diff --git a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js index ff10d850345e..259c503ef5eb 100644 --- a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js +++ b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js @@ -7,7 +7,7 @@ import { getInternalAccountByAddress, getInternalAccounts, } from '../../../../selectors'; -import { getProviderConfig } from '../../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../../shared/modules/selectors/networks'; import { CONTACT_VIEW_ROUTE, CONTACT_LIST_ROUTE, diff --git a/ui/pages/settings/networks-tab/networks-form/networks-form.tsx b/ui/pages/settings/networks-tab/networks-form/networks-form.tsx index 6c5ecdad8c58..db3a86ce0ed4 100644 --- a/ui/pages/settings/networks-tab/networks-form/networks-form.tsx +++ b/ui/pages/settings/networks-tab/networks-form/networks-form.tsx @@ -28,7 +28,7 @@ import { import { jsonRpcRequest } from '../../../../../shared/modules/rpc.utils'; import { MetaMetricsContext } from '../../../../contexts/metametrics'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { getNetworkConfigurationsByChainId } from '../../../../selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../../shared/modules/selectors/networks'; import { addNetwork, setEditedNetwork, diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index 676a53097d4a..c70640c624e9 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -24,10 +24,10 @@ import { } from '../../../store/actions'; import { getIsSecurityAlertsEnabled, - getNetworkConfigurationsByChainId, getMetaMetricsDataDeletionId, getPetnamesEnabled, } from '../../../selectors/selectors'; +import { getNetworkConfigurationsByChainId } from '../../../../shared/modules/selectors/networks'; import { openBasicFunctionalityModal } from '../../../ducks/app/app'; import SecurityTab from './security-tab.component'; diff --git a/ui/pages/settings/settings-tab/settings-tab.container.js b/ui/pages/settings/settings-tab/settings-tab.container.js index e6ad25f0df92..ec46a2f3cd5b 100644 --- a/ui/pages/settings/settings-tab/settings-tab.container.js +++ b/ui/pages/settings/settings-tab/settings-tab.container.js @@ -14,7 +14,7 @@ import { getTheme, getSelectedInternalAccount, } from '../../../selectors'; -import { getProviderConfig } from '../../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../../shared/modules/selectors/networks'; import SettingsTab from './settings-tab.component'; const mapStateToProps = (state) => { diff --git a/ui/pages/settings/settings.container.js b/ui/pages/settings/settings.container.js index 58a35f37e616..db500f8b1d46 100644 --- a/ui/pages/settings/settings.container.js +++ b/ui/pages/settings/settings.container.js @@ -32,7 +32,7 @@ import { ADD_NETWORK_ROUTE, ADD_POPULAR_CUSTOM_NETWORK, } from '../../helpers/constants/routes'; -import { getProviderConfig } from '../../ducks/metamask/metamask'; +import { getProviderConfig } from '../../../shared/modules/selectors/networks'; import { toggleNetworkMenu } from '../../store/actions'; import Settings from './settings.component'; diff --git a/ui/pages/swaps/hooks/useUpdateSwapsState.ts b/ui/pages/swaps/hooks/useUpdateSwapsState.ts index ea72c8e273ab..dc44c51a8489 100644 --- a/ui/pages/swaps/hooks/useUpdateSwapsState.ts +++ b/ui/pages/swaps/hooks/useUpdateSwapsState.ts @@ -18,6 +18,7 @@ import { getIsSwapsChain, getUseExternalServices, } from '../../../selectors'; +import { SWAPS_CHAINID_DEFAULT_TOKEN_MAP } from '../../../../shared/constants/swaps'; export default function useUpdateSwapsState() { const dispatch = useDispatch(); @@ -35,7 +36,7 @@ export default function useUpdateSwapsState() { return undefined; } - fetchTokens(chainId) + fetchTokens(chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP) .then((tokens) => { dispatch(setSwapsTokens(tokens)); }) diff --git a/ui/selectors/approvals.ts b/ui/selectors/approvals.ts index 9ee42f769482..14e2362d0708 100644 --- a/ui/selectors/approvals.ts +++ b/ui/selectors/approvals.ts @@ -1,7 +1,7 @@ import { ApprovalControllerState } from '@metamask/approval-controller'; import { ApprovalType } from '@metamask/controller-utils'; import { createSelector } from 'reselect'; -import { createDeepEqualSelector } from './util'; +import { createDeepEqualSelector } from '../../shared/modules/selectors/util'; export type ApprovalsMetaMaskState = { metamask: { diff --git a/ui/selectors/confirm-transaction.js b/ui/selectors/confirm-transaction.js index 9a1457e2bc66..b68d598a0839 100644 --- a/ui/selectors/confirm-transaction.js +++ b/ui/selectors/confirm-transaction.js @@ -11,7 +11,6 @@ import { getGasEstimateType, getGasFeeEstimates, getNativeCurrency, - getProviderConfig, } from '../ducks/metamask/metamask'; import { GasEstimateTypes, @@ -29,6 +28,7 @@ import { subtractHexes, sumHexes, } from '../../shared/modules/conversion.utils'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; import { getAveragePriceEstimateInHexWEI } from './custom-gas'; import { checkNetworkAndAccountSupports1559, diff --git a/ui/selectors/institutional/selectors.test.ts b/ui/selectors/institutional/selectors.test.ts index 52b27bb8871f..4c398b6fab0b 100644 --- a/ui/selectors/institutional/selectors.test.ts +++ b/ui/selectors/institutional/selectors.test.ts @@ -4,7 +4,11 @@ import { Hex } from '@metamask/utils'; import { toHex } from '@metamask/controller-utils'; import { ETH_EOA_METHODS } from '../../../shared/constants/eth-methods'; import { mockNetworkState } from '../../../test/stub/networks'; -import { CHAIN_IDS } from '../../../shared/constants/network'; +import { + CHAIN_IDS, + CURRENCY_SYMBOLS, + NETWORK_TO_NAME_MAP, +} from '../../../shared/constants/network'; import { getConfiguredCustodians, getCustodianIconForAddress, @@ -71,10 +75,15 @@ const custodianMock = { function buildState(overrides = {}) { const defaultState = { metamask: { + selectedNetworkClientId: '0x1', networkConfigurationsByChainId: { - [toHex(1)]: { - chainId: toHex(1), - rpcEndpoints: [{}], + [CHAIN_IDS.MAINNET]: { + chainId: CHAIN_IDS.MAINNET, + blockExplorerUrls: [], + defaultRpcEndpointIndex: 0, + name: NETWORK_TO_NAME_MAP[CHAIN_IDS.MAINNET], + nativeCurrency: CURRENCY_SYMBOLS.ETH, + rpcEndpoints: [], }, }, internalAccounts: { diff --git a/ui/selectors/institutional/selectors.ts b/ui/selectors/institutional/selectors.ts index 05bd13b52509..eb70e0fcd72c 100644 --- a/ui/selectors/institutional/selectors.ts +++ b/ui/selectors/institutional/selectors.ts @@ -1,7 +1,10 @@ import { toChecksumAddress } from 'ethereumjs-util'; import { getAccountType } from '../selectors'; import { getSelectedInternalAccount } from '../accounts'; -import { getProviderConfig } from '../../ducks/metamask/metamask'; +import { + ProviderConfigState, + getProviderConfig, +} from '../../../shared/modules/selectors/networks'; import { hexToDecimal } from '../../../shared/modules/conversion.utils'; // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths @@ -165,7 +168,9 @@ export function getCustodianIconForAddress(state: State, address: string) { return custodianIcon; } -export function getIsCustodianSupportedChain(state: State) { +export function getIsCustodianSupportedChain( + state: State & ProviderConfigState, +) { try { // @ts-expect-error state types don't match const selectedAccount = getSelectedInternalAccount(state); diff --git a/ui/selectors/metamask-notifications/metamask-notifications.ts b/ui/selectors/metamask-notifications/metamask-notifications.ts index ae71adaa8d36..10f4f337eabf 100644 --- a/ui/selectors/metamask-notifications/metamask-notifications.ts +++ b/ui/selectors/metamask-notifications/metamask-notifications.ts @@ -1,6 +1,6 @@ import { createSelector } from 'reselect'; import { NotificationServicesController } from '@metamask/notification-services-controller'; -import { createDeepEqualSelector } from '../util'; +import { createDeepEqualSelector } from '../../../shared/modules/selectors/util'; const { TRIGGER_TYPES } = NotificationServicesController.Constants; diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts index 3097d61f9549..2fa47a8db9e8 100644 --- a/ui/selectors/multichain.test.ts +++ b/ui/selectors/multichain.test.ts @@ -2,10 +2,7 @@ import { Cryptocurrency } from '@metamask/assets-controllers'; import { InternalAccount } from '@metamask/keyring-api'; import { Hex } from '@metamask/utils'; import { NetworkConfiguration } from '@metamask/network-controller'; -import { - getNativeCurrency, - getProviderConfig, -} from '../ducks/metamask/metamask'; +import { getNativeCurrency } from '../ducks/metamask/metamask'; import { MULTICHAIN_PROVIDER_CONFIGS, MultichainNetworks, @@ -24,6 +21,7 @@ import { } from '../../shared/constants/network'; import { MultichainNativeAssets } from '../../shared/constants/multichain/assets'; import { mockNetworkState } from '../../test/stub/networks'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; import { AccountsState } from './accounts'; import { MultichainState, diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 08078be52f03..1914dbce2dd8 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -14,7 +14,6 @@ import { getCompletedOnboarding, getConversionRate, getNativeCurrency, - getProviderConfig, } from '../ducks/metamask/metamask'; // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths @@ -25,6 +24,11 @@ import { TEST_NETWORK_IDS, CHAIN_IDS, } from '../../shared/constants/network'; +import { + getProviderConfig, + NetworkState, + getNetworkConfigurationsByChainId, +} from '../../shared/modules/selectors/networks'; import { AccountsState, getSelectedInternalAccount } from './accounts'; import { getCurrentChainId, @@ -32,7 +36,6 @@ import { getIsMainnet, getMaybeSelectedInternalAccount, getNativeCurrencyImage, - getNetworkConfigurationsByChainId, getSelectedAccountCachedBalance, getShouldShowFiat, getShowFiatInTestnets, @@ -46,7 +49,10 @@ export type BalancesState = { metamask: BalancesControllerState; }; -export type MultichainState = AccountsState & RatesState & BalancesState; +export type MultichainState = AccountsState & + RatesState & + BalancesState & + NetworkState; // TODO: Remove after updating to @metamask/network-controller 20.0.0 export type ProviderConfigWithImageUrlAndExplorerUrl = { diff --git a/ui/selectors/networks.test.ts b/ui/selectors/networks.test.ts new file mode 100644 index 000000000000..2df8a23f302c --- /dev/null +++ b/ui/selectors/networks.test.ts @@ -0,0 +1,129 @@ +import { NetworkStatus, RpcEndpointType } from '@metamask/network-controller'; +import mockState from '../../test/data/mock-state.json'; +import { mockNetworkState } from '../../test/stub/networks'; +import { CHAIN_IDS } from '../../shared/constants/network'; +import * as networks from '../../shared/modules/selectors/networks'; + +describe('Network Selectors', () => { + describe('#getNetworkConfigurationsByChainId', () => { + it('returns networkConfigurationsByChainId', () => { + const networkConfigurationsByChainId = { + '0x1351': { + name: 'TEST', + chainId: '0x1351' as const, + nativeCurrency: 'TEST', + defaultRpcEndpointUrl: 'https://mock-rpc-url-1', + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + type: RpcEndpointType.Custom as const, + networkClientId: 'testNetworkConfigurationId1', + url: 'https://mock-rpc-url-1', + }, + ], + blockExplorerUrls: [], + }, + '0x1337': { + name: 'RPC', + chainId: '0x1337' as const, + nativeCurrency: 'RPC', + defaultRpcEndpointUrl: 'https://mock-rpc-url-2', + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + type: RpcEndpointType.Custom as const, + networkClientId: 'testNetworkConfigurationId2', + url: 'https://mock-rpc-url-2', + }, + ], + blockExplorerUrls: [], + }, + }; + + expect( + networks.getNetworkConfigurationsByChainId({ + metamask: { + networkConfigurationsByChainId, + }, + }), + ).toStrictEqual(networkConfigurationsByChainId); + }); + }); + + describe('#getNetworkConfigurations', () => { + it('returns undefined if state.metamask.networkConfigurations is undefined', () => { + expect( + networks.getNetworkConfigurations({ + metamask: { + // @ts-expect-error the types forbid `undefined`. this is a strange test. + networkConfigurations: undefined, + }, + }), + ).toBeUndefined(); + }); + + it('returns networkConfigurations', () => { + const networkConfigurations = { + '0x1351': { + name: 'TEST', + chainId: '0x1351' as const, + nativeCurrency: 'TEST', + defaultRpcEndpointUrl: 'https://mock-rpc-url-1', + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + type: RpcEndpointType.Custom as const, + networkClientId: 'testNetworkConfigurationId1', + url: 'https://mock-rpc-url-1', + }, + ], + blockExplorerUrls: [], + }, + '0x1337': { + name: 'RPC', + chainId: '0x1337' as const, + nativeCurrency: 'RPC', + defaultRpcEndpointUrl: 'https://mock-rpc-url-2', + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + type: RpcEndpointType.Custom as const, + networkClientId: 'testNetworkConfigurationId2', + url: 'https://mock-rpc-url-2', + }, + ], + blockExplorerUrls: [], + }, + }; + expect( + networks.getNetworkConfigurations({ + metamask: { + networkConfigurations, + }, + }), + ).toStrictEqual(networkConfigurations); + }); + }); + + describe('#getInfuraBlocked', () => { + it('returns getInfuraBlocked', () => { + let isInfuraBlocked = networks.getInfuraBlocked( + mockState as networks.NetworkState, + ); + expect(isInfuraBlocked).toBe(false); + + const modifiedMockState = { + ...mockState, + metamask: { + ...mockState.metamask, + ...mockNetworkState({ + chainId: CHAIN_IDS.GOERLI, + metadata: { status: NetworkStatus.Blocked, EIPS: {} }, + }), + }, + }; + isInfuraBlocked = networks.getInfuraBlocked(modifiedMockState); + expect(isInfuraBlocked).toBe(true); + }); + }); +}); diff --git a/ui/selectors/permissions.js b/ui/selectors/permissions.js index 00468f2f948d..a0d69b7dc75e 100644 --- a/ui/selectors/permissions.js +++ b/ui/selectors/permissions.js @@ -4,8 +4,8 @@ import { isEvmAccountType } from '@metamask/keyring-api'; import { CaveatTypes } from '../../shared/constants/permissions'; // eslint-disable-next-line import/no-restricted-paths import { PermissionNames } from '../../app/scripts/controllers/permissions'; +import { createDeepEqualSelector } from '../../shared/modules/selectors/util'; import { getApprovalRequestsByType } from './approvals'; -import { createDeepEqualSelector } from './util'; import { getInternalAccount, getMetaMaskAccountsOrdered, diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 27b3a878042b..e4e9c7e27fa7 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -24,7 +24,6 @@ import { CHAIN_ID_TO_RPC_URL_MAP, CHAIN_IDS, NETWORK_TYPES, - NetworkStatus, SEPOLIA_DISPLAY_NAME, GOERLI_DISPLAY_NAME, LINEA_GOERLI_DISPLAY_NAME, @@ -79,7 +78,6 @@ import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens'; import { DAY } from '../../shared/constants/time'; import { TERMS_OF_USE_LAST_UPDATED } from '../../shared/constants/terms'; import { - getProviderConfig, getConversionRate, isNotEIP1559Network, isEIP1559Network, @@ -106,6 +104,12 @@ import { MultichainNativeAssets } from '../../shared/constants/multichain/assets import { BridgeFeatureFlagsKey } from '../../app/scripts/controllers/bridge/types'; import { hasTransactionData } from '../../shared/modules/transaction.utils'; import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; +import { + getProviderConfig, + getSelectedNetworkClientId, + getNetworkConfigurationsByChainId, +} from '../../shared/modules/selectors/networks'; +import { createDeepEqualSelector } from '../../shared/modules/selectors/util'; import { getAllUnapprovedTransactions, getCurrentNetworkTransactions, @@ -120,28 +124,8 @@ import { getSubjectMetadata, } from './permissions'; import { getSelectedInternalAccount, getInternalAccounts } from './accounts'; -import { createDeepEqualSelector } from './util'; import { getMultichainBalances, getMultichainNetwork } from './multichain'; -/** - * Returns true if the currently selected network is inaccessible or whether no - * provider has been set yet for the currently selected network. - * - * @param {object} state - Redux state object. - */ -export function isNetworkLoading(state) { - const selectedNetworkClientId = getSelectedNetworkClientId(state); - return ( - selectedNetworkClientId && - state.metamask.networksMetadata[selectedNetworkClientId].status !== - NetworkStatus.Available - ); -} - -export function getSelectedNetworkClientId(state) { - return state.metamask.selectedNetworkClientId; -} - export function getNetworkIdentifier(state) { const { type, nickname, rpcUrl } = getProviderConfig(state); @@ -838,15 +822,6 @@ export function getGasIsLoading(state) { return state.appState.gasIsLoading; } -export const getNetworkConfigurationsByChainId = createDeepEqualSelector( - (state) => state.metamask.networkConfigurationsByChainId, - /** - * @param networkConfigurationsByChainId - * @returns { import('@metamask/network-controller').NetworkState['networkConfigurationsByChainId']} - */ - (networkConfigurationsByChainId) => networkConfigurationsByChainId, -); - export const getNetworkConfigurationIdByChainId = createDeepEqualSelector( (state) => state.metamask.networkConfigurationsByChainId, (networkConfigurationsByChainId) => @@ -1437,7 +1412,7 @@ export const getMultipleTargetsSubjectMetadata = createDeepEqualSelector( export function getRpcPrefsForCurrentProvider(state) { const { rpcPrefs } = getProviderConfig(state); - return rpcPrefs || {}; + return rpcPrefs; } export function getKnownMethodData(state, data) { @@ -1477,13 +1452,6 @@ export function getUseExternalServices(state) { return state.metamask.useExternalServices; } -export function getInfuraBlocked(state) { - return ( - state.metamask.networksMetadata[getSelectedNetworkClientId(state)] - .status === NetworkStatus.Blocked - ); -} - export function getUSDConversionRate(state) { return state.metamask.currencyRates[getProviderConfig(state).ticker] ?.usdConversionRate; diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index d3799885eaf6..e70e9cd7ff29 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -10,10 +10,10 @@ import { KeyringType } from '../../shared/constants/keyring'; import mockState from '../../test/data/mock-state.json'; import { CHAIN_IDS, NETWORK_TYPES } from '../../shared/constants/network'; import { createMockInternalAccount } from '../../test/jest/mocks'; -import { getProviderConfig } from '../ducks/metamask/metamask'; import { mockNetworkState } from '../../test/stub/networks'; import { DeleteRegulationStatus } from '../../shared/constants/metametrics'; import { selectSwitchedNetworkNeverShowMessage } from '../components/app/toast-master/selectors'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; import * as selectors from './selectors'; jest.mock('../../app/scripts/lib/util', () => ({ @@ -646,45 +646,6 @@ describe('Selectors', () => { }); }); - describe('#getNetworkConfigurationsByChainId', () => { - it('returns networkConfigurationsByChainId', () => { - const networkConfigurationsByChainId = { - '0xtest': { - chainId: '0xtest', - nativeCurrency: 'TEST', - defaultRpcEndpointUrl: 'https://mock-rpc-url-1', - defaultRpcEndpointIndex: 0, - rpcEndpoints: [ - { - networkClientId: 'testNetworkConfigurationId1', - url: 'https://mock-rpc-url-1', - }, - ], - }, - '0x1337': { - chainId: '0x1337', - nativeCurrency: 'RPC', - defaultRpcEndpointUrl: 'https://mock-rpc-url-2', - defaultRpcEndpointIndex: 0, - rpcEndpoints: [ - { - networkClientId: 'testNetworkConfigurationId2', - url: 'https://mock-rpc-url-2', - }, - ], - }, - }; - - expect( - selectors.getNetworkConfigurationsByChainId({ - metamask: { - networkConfigurationsByChainId, - }, - }), - ).toStrictEqual(networkConfigurationsByChainId); - }); - }); - describe('#getCurrentNetwork', () => { it('returns built-in network configuration', () => { const modifiedMockState = { @@ -1317,24 +1278,6 @@ describe('Selectors', () => { expect(selectors.getSnapsInstallPrivacyWarningShown(mockState)).toBe(false); }); - it('#getInfuraBlocked', () => { - let isInfuraBlocked = selectors.getInfuraBlocked(mockState); - expect(isInfuraBlocked).toBe(false); - - const modifiedMockState = { - ...mockState, - metamask: { - ...mockState.metamask, - ...mockNetworkState({ - chainId: CHAIN_IDS.GOERLI, - metadata: { status: 'blocked' }, - }), - }, - }; - isInfuraBlocked = selectors.getInfuraBlocked(modifiedMockState); - expect(isInfuraBlocked).toBe(true); - }); - it('#getSnapRegistryData', () => { const mockSnapId = 'npm:@metamask/test-snap-bip44'; expect(selectors.getSnapRegistryData(mockState, mockSnapId)).toStrictEqual( diff --git a/ui/selectors/signatures.ts b/ui/selectors/signatures.ts index 7325e5c038c0..0fd99eb4361a 100644 --- a/ui/selectors/signatures.ts +++ b/ui/selectors/signatures.ts @@ -1,10 +1,10 @@ import { createSelector } from 'reselect'; import { DefaultRootState } from 'react-redux'; +import { createDeepEqualSelector } from '../../shared/modules/selectors/util'; import { unapprovedPersonalMsgsSelector, unapprovedTypedMessagesSelector, } from './transactions'; -import { createDeepEqualSelector } from './util'; export const selectUnapprovedMessages = createSelector( unapprovedPersonalMsgsSelector, diff --git a/ui/selectors/snaps/accounts.ts b/ui/selectors/snaps/accounts.ts index 55a30f0c72eb..0b0559b7d1dd 100644 --- a/ui/selectors/snaps/accounts.ts +++ b/ui/selectors/snaps/accounts.ts @@ -2,7 +2,7 @@ import { createSelector } from 'reselect'; import { AccountsControllerState } from '@metamask/accounts-controller'; import { getAccountName } from '../selectors'; import { getInternalAccounts } from '../accounts'; -import { createDeepEqualSelector } from '../util'; +import { createDeepEqualSelector } from '../../../shared/modules/selectors/util'; /** * The Metamask state for the accounts controller. diff --git a/ui/selectors/snaps/address-book.ts b/ui/selectors/snaps/address-book.ts index e002153d9e61..da2e4ac802c9 100644 --- a/ui/selectors/snaps/address-book.ts +++ b/ui/selectors/snaps/address-book.ts @@ -1,5 +1,5 @@ import { AddressBookController } from '@metamask/address-book-controller'; -import { createDeepEqualSelector } from '../util'; +import { createDeepEqualSelector } from '../../../shared/modules/selectors/util'; import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils'; /** diff --git a/ui/selectors/transactions.js b/ui/selectors/transactions.js index 3074fd4bfde4..9428a6fbd8c3 100644 --- a/ui/selectors/transactions.js +++ b/ui/selectors/transactions.js @@ -12,14 +12,14 @@ import { import txHelper from '../helpers/utils/tx-helper'; import { SmartTransactionStatus } from '../../shared/constants/transaction'; import { hexToDecimal } from '../../shared/modules/conversion.utils'; -import { getProviderConfig } from '../ducks/metamask/metamask'; -import { getCurrentChainId } from './selectors'; -import { getSelectedInternalAccount } from './accounts'; -import { hasPendingApprovals, getApprovalRequestsByType } from './approvals'; +import { getProviderConfig } from '../../shared/modules/selectors/networks'; import { createDeepEqualSelector, filterAndShapeUnapprovedTransactions, -} from './util'; +} from '../../shared/modules/selectors/util'; +import { getCurrentChainId } from './selectors'; +import { getSelectedInternalAccount } from './accounts'; +import { hasPendingApprovals, getApprovalRequestsByType } from './approvals'; const INVALID_INITIAL_TRANSACTION_TYPES = [ TransactionType.cancel, diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 66962d46161d..f3f4e712acf5 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -69,8 +69,11 @@ import { getInternalAccountByAddress, getSelectedInternalAccount, getInternalAccounts, - getSelectedNetworkClientId, } from '../selectors'; +import { + getSelectedNetworkClientId, + getProviderConfig, +} from '../../shared/modules/selectors/networks'; import { computeEstimatedGasLimit, initializeSendState, @@ -82,10 +85,7 @@ import { SEND_STAGES, } from '../ducks/send'; import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account'; -import { - getProviderConfig, - getUnconnectedAccountAlertEnabledness, -} from '../ducks/metamask/metamask'; +import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask'; import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import { HardwareDeviceNames,