From 88ae10418bbbf4ff94ae7fe4167e704c33487474 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 2 May 2023 10:06:24 -0230 Subject: [PATCH] Expand usage of `getProviderConfig` selector (#18906) The `getProviderConfig` selector is now used anywhere the `provider` state was previously referenced directly. This was done to simplify renaming this state from `provider` to `providerConfig` in a later PR. Note that there are many opportunities left to use more-specific selectors (e.g. `getChainId()` over `getProviderConfig().chainId`), but that was intentionally omitted from this PR to reduce the size. I started going down this path and it quickly exploded in scope. Relates to #18902 --- .../app/dropdowns/network-dropdown.js | 3 ++- .../loading-network-screen.container.js | 12 ++++----- .../app/network-display/network-display.js | 8 +++--- .../signature-request-original.container.js | 3 ++- .../signature-request.container.js | 3 ++- ui/ducks/metamask/metamask.js | 18 +++++-------- ui/ducks/send/send.js | 10 ++++---- ui/hooks/experiences/useRamps.ts | 3 ++- ui/hooks/useTransactionInfo.js | 10 ++++---- ui/pages/confirm-signature-request/index.js | 3 ++- .../confirm-transaction-base.container.js | 3 ++- .../confirmation-network-switch.js | 15 +++++------ .../import-token/import-token.container.js | 3 ++- ui/pages/routes/routes.container.js | 3 ++- .../edit-contact/edit-contact.container.js | 3 ++- ui/pages/token-details/token-details-page.js | 9 ++----- ui/selectors/selectors.js | 14 ++++------- ui/selectors/selectors.test.js | 4 +-- ui/selectors/transactions.js | 7 +++--- ui/store/actions.ts | 25 ++++++++++++------- 20 files changed, 76 insertions(+), 83 deletions(-) diff --git a/ui/components/app/dropdowns/network-dropdown.js b/ui/components/app/dropdowns/network-dropdown.js index 8b44fed0e..6ac6ef543 100644 --- a/ui/components/app/dropdowns/network-dropdown.js +++ b/ui/components/app/dropdowns/network-dropdown.js @@ -7,6 +7,7 @@ import { pickBy } from 'lodash'; import Button from '../../ui/button'; import * as actions from '../../../store/actions'; import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network'; +import { getProviderConfig } from '../../../ducks/metamask/metamask'; import { BUILT_IN_NETWORKS, CHAIN_ID_TO_RPC_URL_MAP, @@ -55,7 +56,7 @@ const DROP_DOWN_MENU_ITEM_STYLE = { function mapStateToProps(state) { return { - provider: state.metamask.provider, + provider: getProviderConfig(state), shouldShowTestNetworks: getShowTestNetworks(state), networkConfigurations: state.metamask.networkConfigurations, networkDropdownOpen: state.appState.networkDropdownOpen, 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 bb5a5d138..c67db5119 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 @@ -2,25 +2,23 @@ import { connect } from 'react-redux'; import { NETWORK_TYPES } from '../../../../shared/constants/network'; import * as actions from '../../../store/actions'; import { getNetworkIdentifier, isNetworkLoading } from '../../../selectors'; +import { getProviderConfig } from '../../../ducks/metamask/metamask'; import LoadingNetworkScreen from './loading-network-screen.component'; const DEPRECATED_TEST_NET_CHAINIDS = ['0x3', '0x2a', '0x4']; const mapStateToProps = (state) => { const { loadingMessage } = state.appState; - const { provider } = state.metamask; + const provider = getProviderConfig(state); const { rpcUrl, chainId, ticker, nickname, type } = provider; const setProviderArgs = - type === NETWORK_TYPES.RPC - ? [rpcUrl, chainId, ticker, nickname] - : [provider.type]; + type === NETWORK_TYPES.RPC ? [rpcUrl, chainId, ticker, nickname] : [type]; - const providerChainId = provider?.chainId; + const providerChainId = chainId; const isDeprecatedNetwork = DEPRECATED_TEST_NET_CHAINIDS.includes(providerChainId); - const isInfuraRpcUrl = - provider?.rpcUrl && new URL(provider.rpcUrl).host.endsWith('.infura.io'); + const isInfuraRpcUrl = rpcUrl && new URL(rpcUrl).host.endsWith('.infura.io'); const showDeprecatedRpcUrlWarning = isDeprecatedNetwork && isInfuraRpcUrl; return { diff --git a/ui/components/app/network-display/network-display.js b/ui/components/app/network-display/network-display.js index 57670908a..2e07267c0 100644 --- a/ui/components/app/network-display/network-display.js +++ b/ui/components/app/network-display/network-display.js @@ -19,6 +19,7 @@ import Chip from '../../ui/chip/chip'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { isNetworkLoading } from '../../../selectors'; import { Icon, IconName, IconSize } from '../../component-library'; +import { getProviderConfig } from '../../../ducks/metamask/metamask'; export default function NetworkDisplay({ indicatorSize, @@ -28,13 +29,10 @@ export default function NetworkDisplay({ onClick, }) { const networkIsLoading = useSelector(isNetworkLoading); - const currentNetwork = useSelector((state) => ({ - nickname: state.metamask.provider.nickname, - type: state.metamask.provider.type, - })); + const providerConfig = useSelector(getProviderConfig); const t = useI18nContext(); - const { nickname, type: networkType } = targetNetwork ?? currentNetwork; + const { nickname, type: networkType } = targetNetwork ?? providerConfig; return ( state.metamask.alertEnabledness; * Get the provider configuration for the current selected network. * * @param {object} state - Redux state object. - * @returns {object} The provider configuration for the current selected network. + * @returns {import('../../../app/scripts/controllers/network/network-controller').NetworkControllerState['provider']} The provider configuration for the current selected network. */ export function getProviderConfig(state) { return state.metamask.provider; @@ -259,12 +259,9 @@ export function getNftsDropdownState(state) { export const getNfts = (state) => { const { - metamask: { - allNfts, - provider: { chainId }, - selectedAddress, - }, + metamask: { allNfts, selectedAddress }, } = state; + const { chainId } = getProviderConfig(state); const chainIdAsDecimal = hexToDecimal(chainId); @@ -273,12 +270,9 @@ export const getNfts = (state) => { export const getNftContracts = (state) => { const { - metamask: { - allNftContracts, - provider: { chainId }, - selectedAddress, - }, + metamask: { allNftContracts, selectedAddress }, } = state; + const { chainId } = getProviderConfig(state); const chainIdAsDecimal = hexToDecimal(chainId); @@ -297,7 +291,7 @@ export function getNativeCurrency(state) { const useCurrencyRateCheck = getUseCurrencyRateCheck(state); return useCurrencyRateCheck ? state.metamask.nativeCurrency - : state.metamask.provider.ticker; + : getProviderConfig(state).ticker; } export function getSendHexDataFeatureFlagState(state) { diff --git a/ui/ducks/send/send.js b/ui/ducks/send/send.js index 0aefd5382..97448b0dd 100644 --- a/ui/ducks/send/send.js +++ b/ui/ducks/send/send.js @@ -78,6 +78,7 @@ import { } from '../../helpers/utils/util'; import { getGasEstimateType, + getProviderConfig, getTokens, getUnapprovedTxs, } from '../metamask/metamask'; @@ -1967,7 +1968,7 @@ export function updateRecipientUserInput(userInput) { export function updateSendAmount(amount) { return async (dispatch, getState) => { const state = getState(); - const { metamask } = state; + const { ticker } = getProviderConfig(state); const draftTransaction = state[name].draftTransactions[state[name].currentTransactionUUID]; let logAmount = amount; @@ -1992,9 +1993,7 @@ export function updateSendAmount(amount) { toCurrency: EtherDenomination.ETH, numberOfDecimals: 8, }); - logAmount = `${ethValue} ${ - metamask?.provider?.ticker || EtherDenomination.ETH - }`; + logAmount = `${ethValue} ${ticker || EtherDenomination.ETH}`; } await dispatch( addHistoryEntry(`sendFlow - user set amount to ${logAmount}`), @@ -2024,6 +2023,7 @@ export function updateSendAsset( ) { return async (dispatch, getState) => { const state = getState(); + const { ticker } = getProviderConfig(state); const draftTransaction = state[name].draftTransactions[state[name].currentTransactionUUID]; const sendingAddress = @@ -2038,7 +2038,7 @@ export function updateSendAsset( await dispatch( addHistoryEntry( `sendFlow - user set asset of type ${AssetType.native} with symbol ${ - state.metamask.provider?.ticker ?? EtherDenomination.ETH + ticker ?? EtherDenomination.ETH }`, ), ); diff --git a/ui/hooks/experiences/useRamps.ts b/ui/hooks/experiences/useRamps.ts index 93ea6d47b..cfb09e4ab 100644 --- a/ui/hooks/experiences/useRamps.ts +++ b/ui/hooks/experiences/useRamps.ts @@ -1,5 +1,6 @@ import { useCallback } from 'react'; import { useSelector } from 'react-redux'; +import type { Hex } from '@metamask/utils'; import { ChainId, CHAIN_IDS } from '../../../shared/constants/network'; import { getCurrentChainId } from '../../selectors'; @@ -13,7 +14,7 @@ const portfolioUrl = process.env.PORTFOLIO_URL; const useRamps = (): IUseRamps => { const chainId = useSelector(getCurrentChainId); - const getBuyURI = useCallback((_chainId: ChainId) => { + const getBuyURI = useCallback((_chainId: Hex) => { switch (_chainId) { case CHAIN_IDS.SEPOLIA: return 'https://faucet.sepolia.dev/'; diff --git a/ui/hooks/useTransactionInfo.js b/ui/hooks/useTransactionInfo.js index 8312fe1bf..453116321 100644 --- a/ui/hooks/useTransactionInfo.js +++ b/ui/hooks/useTransactionInfo.js @@ -1,14 +1,14 @@ import { useSelector } from 'react-redux'; +import { getProviderConfig } from '../ducks/metamask/metamask'; import { hexToDecimal } from '../../shared/modules/conversion.utils'; import { isEqualCaseInsensitive } from '../../shared/modules/string-utils'; export const useTransactionInfo = (txData = {}) => { - const { - allNftContracts, - selectedAddress, - provider: { chainId }, - } = useSelector((state) => state.metamask); + const { allNftContracts, selectedAddress } = useSelector( + (state) => state.metamask, + ); + const { chainId } = useSelector(getProviderConfig); const isNftTransfer = Boolean( allNftContracts?.[selectedAddress]?.[hexToDecimal(chainId)]?.find( diff --git a/ui/pages/confirm-signature-request/index.js b/ui/pages/confirm-signature-request/index.js index 84af604ba..cb4c52464 100644 --- a/ui/pages/confirm-signature-request/index.js +++ b/ui/pages/confirm-signature-request/index.js @@ -19,6 +19,7 @@ import { import { MESSAGE_TYPE } from '../../../shared/constants/app'; import { TransactionStatus } from '../../../shared/constants/transaction'; import { getSendTo } from '../../ducks/send'; +import { getProviderConfig } from '../../ducks/metamask/metamask'; const SIGN_MESSAGE_TYPE = { MESSAGE: 'message', @@ -70,8 +71,8 @@ const ConfirmTxScreen = ({ match }) => { unapprovedTypedMessages, networkId, blockGasLimit, - provider: { chainId }, } = useSelector((state) => state.metamask); + const { chainId } = useSelector(getProviderConfig); const { txId: index } = useSelector((state) => state.appState); ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) diff --git a/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js index 38bb983f5..89e9e53e6 100644 --- a/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -46,6 +46,7 @@ import { getIsGasEstimatesLoading, getNativeCurrency, getSendToAccounts, + getProviderConfig, } from '../../ducks/metamask/metamask'; import { addHexPrefix } from '../../../app/scripts/lib/util'; @@ -104,8 +105,8 @@ const mapStateToProps = (state, ownProps) => { networkId, unapprovedTxs, nextNonce, - provider: { chainId }, } = metamask; + const { chainId } = getProviderConfig(state); const { tokenData, txData, tokenProps, nonce } = confirmTransaction; const { txParams = {}, id: transactionId, type } = txData; const txId = transactionId || Number(paramsTransactionId); diff --git a/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js b/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js index 3596a3be3..7f0775e38 100644 --- a/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js +++ b/ui/pages/confirmation/components/confirmation-network-switch/confirmation-network-switch.js @@ -18,13 +18,10 @@ import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP, NETWORK_TO_NAME_MAP, } from '../../../../../shared/constants/network'; +import { getProviderConfig } from '../../../../ducks/metamask/metamask'; export default function ConfirmationNetworkSwitch({ newNetwork }) { - const currentNetwork = useSelector((state) => ({ - nickname: state.metamask.provider.nickname, - type: state.metamask.provider.type, - chainId: state.metamask.provider.chainId, - })); + const { chainId, nickname, type } = useSelector(getProviderConfig); return ( - {currentNetwork.chainId in CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP ? ( + {chainId in CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP ? ( ) : ( @@ -59,7 +56,7 @@ export default function ConfirmationNetworkSwitch({ newNetwork }) { justifyContent: JustifyContent.center, }} > - {currentNetwork.nickname || NETWORK_TO_NAME_MAP[currentNetwork.type]} + {nickname || NETWORK_TO_NAME_MAP[type]} { identities, tokens, pendingTokens, - provider: { chainId }, useTokenDetection, selectedAddress, }, } = state; + const { chainId } = getProviderConfig(state); const isTokenDetectionInactiveOnMainnet = getIsTokenDetectionInactiveOnMainnet(state); diff --git a/ui/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js index 3f5c857ba..d5b08b6a4 100644 --- a/ui/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -24,6 +24,7 @@ import { import { pageChanged } from '../../ducks/history/history'; import { prepareToLeaveSwaps } from '../../ducks/swaps/swaps'; import { getSendStage } from '../../ducks/send'; +import { getProviderConfig } from '../../ducks/metamask/metamask'; import Routes from './routes.component'; function mapStateToProps(state) { @@ -46,7 +47,7 @@ function mapStateToProps(state) { browserEnvironmentOs: state.metamask.browserEnvironment?.os, browserEnvironmentContainter: state.metamask.browserEnvironment?.browser, providerId: getNetworkIdentifier(state), - providerType: state.metamask.provider?.type, + providerType: getProviderConfig(state).type, theme: getTheme(state), sendStage: getSendStage(state), isNetworkUsed: getIsNetworkUsed(state), 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 bf29852f4..72cb08479 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 @@ -2,6 +2,7 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { getAddressBookEntry } from '../../../../selectors'; +import { getProviderConfig } from '../../../../ducks/metamask/metamask'; import { CONTACT_VIEW_ROUTE, CONTACT_LIST_ROUTE, @@ -25,7 +26,7 @@ const mapStateToProps = (state, ownProps) => { getAddressBookEntry(state, address) || state.metamask.identities[address]; const { memo, name } = contact || {}; - const { chainId } = state.metamask.provider; + const { chainId } = getProviderConfig(state); return { address: contact ? address : null, diff --git a/ui/pages/token-details/token-details-page.js b/ui/pages/token-details/token-details-page.js index a6628017a..4b75b71a8 100644 --- a/ui/pages/token-details/token-details-page.js +++ b/ui/pages/token-details/token-details-page.js @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Redirect, useHistory, useParams } from 'react-router-dom'; -import { getTokens } from '../../ducks/metamask/metamask'; +import { getProviderConfig, getTokens } from '../../ducks/metamask/metamask'; import { getTokenList } from '../../selectors'; import { useCopyToClipboard } from '../../hooks/useCopyToClipboard'; import Identicon from '../../components/ui/identicon'; @@ -54,12 +54,7 @@ export default function TokenDetailsPage() { token?.symbol, ); - const currentNetwork = useSelector((state) => ({ - nickname: state.metamask.provider.nickname, - type: state.metamask.provider.type, - })); - - const { nickname, type: networkType } = currentNetwork; + const { nickname, type: networkType } = useSelector(getProviderConfig); const [copied, handleCopy] = useCopyToClipboard(); diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index aae98905f..053876e3c 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -101,22 +101,18 @@ export function isNetworkLoading(state) { } export function getNetworkIdentifier(state) { - const { - metamask: { - provider: { type, nickname, rpcUrl }, - }, - } = state; + const { type, nickname, rpcUrl } = getProviderConfig(state); return nickname || rpcUrl || type; } export function getMetricsNetworkIdentifier(state) { - const { provider } = state.metamask; + const provider = getProviderConfig(state); return provider.type === NETWORK_TYPES.RPC ? provider.rpcUrl : provider.type; } export function getCurrentChainId(state) { - const { chainId } = state.metamask.provider; + const { chainId } = getProviderConfig(state); return chainId; } @@ -658,8 +654,8 @@ export function getTargetSubjectMetadata(state, origin) { } export function getRpcPrefsForCurrentProvider(state) { - const { provider: { rpcPrefs = {} } = {} } = state.metamask; - return rpcPrefs; + const { rpcPrefs } = getProviderConfig(state); + return rpcPrefs || {}; } export function getKnownMethodData(state, data) { diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index a16bec7ec..81f31340d 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -35,9 +35,9 @@ describe('Selectors', () => { }); describe('#getRpcPrefsForCurrentProvider', () => { - it('returns an empty object if state.metamask.provider is undefined', () => { + it('returns an empty object if state.metamask.provider is empty', () => { expect( - selectors.getRpcPrefsForCurrentProvider({ metamask: {} }), + selectors.getRpcPrefsForCurrentProvider({ metamask: { provider: {} } }), ).toStrictEqual({}); }); it('returns rpcPrefs from the provider', () => { diff --git a/ui/selectors/transactions.js b/ui/selectors/transactions.js index 5e95e8d6f..b104e8572 100644 --- a/ui/selectors/transactions.js +++ b/ui/selectors/transactions.js @@ -11,6 +11,7 @@ import { } from '../../shared/constants/transaction'; import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils'; import { hexToDecimal } from '../../shared/modules/conversion.utils'; +import { getProviderConfig } from '../ducks/metamask/metamask'; import { getCurrentChainId, deprecatedGetCurrentNetworkId, @@ -28,10 +29,8 @@ export const incomingTxListSelector = (state) => { return []; } - const { - networkId, - provider: { chainId }, - } = state.metamask; + const { networkId } = state.metamask; + const { chainId } = getProviderConfig(state); const selectedAddress = getSelectedAddress(state); return Object.values(state.metamask.incomingTransactions).filter( (tx) => diff --git a/ui/store/actions.ts b/ui/store/actions.ts index 59f498158..6501b9ee6 100644 --- a/ui/store/actions.ts +++ b/ui/store/actions.ts @@ -43,7 +43,10 @@ import { DraftTransaction, } from '../ducks/send'; import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account'; -import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask'; +import { + getProviderConfig, + getUnconnectedAccountAlertEnabledness, +} from '../ducks/metamask/metamask'; import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import { HardwareDeviceNames, @@ -1765,13 +1768,15 @@ export function updateMetamaskState( newState: MetaMaskReduxState['metamask'], ): ThunkAction { return (dispatch, getState) => { - const { metamask: currentState } = getState(); + const state = getState(); + const providerConfig = getProviderConfig(state); + const { metamask: currentState } = state; - const { currentLocale, selectedAddress, provider } = currentState; + const { currentLocale, selectedAddress } = currentState; const { currentLocale: newLocale, selectedAddress: newSelectedAddress, - provider: newProvider, + provider: newProviderConfig, } = newState; if (currentLocale && newLocale && currentLocale !== newLocale) { @@ -1782,8 +1787,10 @@ export function updateMetamaskState( dispatch({ type: actionConstants.SELECTED_ADDRESS_CHANGED }); } - const newAddressBook = newState.addressBook?.[newProvider?.chainId] ?? {}; - const oldAddressBook = currentState.addressBook?.[provider?.chainId] ?? {}; + const newAddressBook = + newState.addressBook?.[newProviderConfig?.chainId] ?? {}; + const oldAddressBook = + currentState.addressBook?.[providerConfig?.chainId] ?? {}; const newAccounts: { [address: string]: Record } = getMetaMaskAccounts({ metamask: newState }); const oldAccounts: { [address: string]: Record } = @@ -1832,10 +1839,10 @@ export function updateMetamaskState( type: actionConstants.UPDATE_METAMASK_STATE, value: newState, }); - if (provider.chainId !== newProvider.chainId) { + if (providerConfig.chainId !== newProviderConfig.chainId) { dispatch({ type: actionConstants.CHAIN_CHANGED, - payload: newProvider.chainId, + payload: newProviderConfig.chainId, }); // We dispatch this action to ensure that the send state stays up to date // after the chain changes. This async thunk will fail gracefully in the @@ -2615,7 +2622,7 @@ export function addToAddressBook( log.debug(`background.addToAddressBook`); return async (dispatch, getState) => { - const { chainId } = getState().metamask.provider; + const { chainId } = getProviderConfig(getState()); let set; try {