From c782bcd407481bded585125d6f1374f29c78d372 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:00:06 +0200 Subject: [PATCH 01/20] test(multichain): deep clone evm/non-evm state for each tests --- ui/selectors/multichain.test.ts | 94 +++++++++++++++++---------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts index 2b01bf105e82..95465f6faa84 100644 --- a/ui/selectors/multichain.test.ts +++ b/ui/selectors/multichain.test.ts @@ -35,38 +35,42 @@ type TestState = AccountsState & { }; }; -const MOCK_EVM_STATE: TestState = { - metamask: { - preferences: { - showFiatInTestnets: false, - }, - providerConfig: { - ticker: 'ETH', - chainId: '0x1', - }, - currentCurrency: 'ETH', - currencyRates: { - ETH: { - conversionRate: 'usd', +function getEvmState(): TestState { + return { + metamask: { + preferences: { + showFiatInTestnets: false, + }, + providerConfig: { + ticker: 'ETH', + chainId: '0x1', + }, + currentCurrency: 'ETH', + currencyRates: { + ETH: { + conversionRate: 'usd', + }, + }, + completedOnboarding: true, + internalAccounts: { + selectedAccount: MOCK_ACCOUNT_EOA.id, + accounts: MOCK_ACCOUNTS, }, }, - completedOnboarding: true, - internalAccounts: { - selectedAccount: MOCK_ACCOUNT_EOA.id, - accounts: MOCK_ACCOUNTS, - }, - }, -}; + }; +} -const MOCK_NON_EVM_STATE: AccountsState = { - metamask: { - ...MOCK_EVM_STATE.metamask, - internalAccounts: { - selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id, - accounts: MOCK_ACCOUNTS, +function getNonEvmState(): TestState { + return { + metamask: { + ...getEvmState().metamask, + internalAccounts: { + selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id, + accounts: MOCK_ACCOUNTS, + }, }, - }, -}; + }; +} function getBip122ProviderConfig(): MultichainProviderConfig { // For now, we only have Bitcoin non-EVM network, so we are expecting to have @@ -77,7 +81,7 @@ function getBip122ProviderConfig(): MultichainProviderConfig { describe('Multichain Selectors', () => { describe('getMultichainNetworkProviders', () => { it('has some providers', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); const networkProviders = getMultichainNetworkProviders(state); expect(Array.isArray(networkProviders)).toBe(true); @@ -87,21 +91,21 @@ describe('Multichain Selectors', () => { describe('getMultichainNetwork', () => { it('returns an EVM network provider if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); const network = getMultichainNetwork(state); expect(network.isEvmNetwork).toBe(true); }); it('returns an non-EVM network provider if account is non-EVM', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const network = getMultichainNetwork(state); expect(network.isEvmNetwork).toBe(false); }); it('returns an EVM network provider if user is not onboarded', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); state.metamask.completedOnboarding = false; state.metamask.internalAccounts.selectedAccount = ''; @@ -112,13 +116,13 @@ describe('Multichain Selectors', () => { describe('getMultichainIsEvm', () => { it('returns true if selected account is EVM compatible', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainIsEvm(state)).toBe(true); }); it('returns false if selected account is not EVM compatible', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); expect(getMultichainIsEvm(state)).toBe(false); }); @@ -126,13 +130,13 @@ describe('Multichain Selectors', () => { describe('getMultichain{ProviderConfig,CurrentNetwork}', () => { it('returns a ProviderConfig if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainProviderConfig(state)).toBe(getProviderConfig(state)); }); it('returns a MultichainProviderConfig if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const bip122ProviderConfig = getBip122ProviderConfig(); expect(getMultichainProviderConfig(state)).toBe(bip122ProviderConfig); @@ -141,13 +145,13 @@ describe('Multichain Selectors', () => { describe('getMultichainNativeCurrency', () => { it('returns same native currency if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainNativeCurrency(state)).toBe(getNativeCurrency(state)); }); it('returns MultichainProviderConfig.ticker if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const bip122ProviderConfig = getBip122ProviderConfig(); expect(getMultichainNativeCurrency(state)).toBe( @@ -158,7 +162,7 @@ describe('Multichain Selectors', () => { describe('getMultichainCurrentCurrency', () => { it('returns same currency currency if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainCurrentCurrency(state)).toBe( getCurrentCurrency(state), @@ -169,7 +173,7 @@ describe('Multichain Selectors', () => { it.each(['usd', 'ETH'])( "returns current currency '%s' if account is EVM", (currency: string) => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); state.metamask.currentCurrency = currency; expect(getCurrentCurrency(state)).toBe(currency); @@ -178,7 +182,7 @@ describe('Multichain Selectors', () => { ); it('fallbacks to ticker as currency if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; // .currentCurrency = 'ETH' + const state = getNonEvmState(); // .currentCurrency = 'ETH' const bip122ProviderConfig = getBip122ProviderConfig(); expect(getCurrentCurrency(state).toLowerCase()).not.toBe('usd'); @@ -190,13 +194,13 @@ describe('Multichain Selectors', () => { describe('getMultichainShouldShowFiat', () => { it('returns same value as getShouldShowFiat if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainShouldShowFiat(state)).toBe(getShouldShowFiat(state)); }); it('returns true if account is non-EVM', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); expect(getMultichainShouldShowFiat(state)).toBe(true); }); @@ -204,7 +208,7 @@ describe('Multichain Selectors', () => { describe('getMultichainDefaultToken', () => { it('returns ETH if account is EVM', () => { - const state = MOCK_EVM_STATE; + const state = getEvmState(); expect(getMultichainDefaultToken(state)).toEqual({ symbol: 'ETH', @@ -212,7 +216,7 @@ describe('Multichain Selectors', () => { }); it('returns true if account is non-EVM (bip122:*)', () => { - const state = MOCK_NON_EVM_STATE; + const state = getNonEvmState(); const bip122ProviderConfig = getBip122ProviderConfig(); expect(getMultichainDefaultToken(state)).toEqual({ From 00dbae1a6202572a4fc30b04cc52a6ed3b74d1a2 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:04:04 +0200 Subject: [PATCH 02/20] feat(multichain): better typing + onboarding checks in selectors --- ui/selectors/multichain.test.ts | 15 ++++---- ui/selectors/multichain.ts | 62 ++++++++++++++++++++------------- ui/selectors/selectors.js | 7 ++++ 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts index 95465f6faa84..d539177dcab8 100644 --- a/ui/selectors/multichain.test.ts +++ b/ui/selectors/multichain.test.ts @@ -1,7 +1,4 @@ -import { - getNativeCurrency, - getProviderConfig, -} from '../ducks/metamask/metamask'; +import { getNativeCurrency } from '../ducks/metamask/metamask'; import { MULTICHAIN_PROVIDER_CONFIGS, MultichainNetworks, @@ -23,12 +20,12 @@ import { getMultichainProviderConfig, getMultichainShouldShowFiat, } from './multichain'; -import { getCurrentCurrency, getShouldShowFiat } from '.'; +import { getCurrentCurrency, getCurrentNetwork, getShouldShowFiat } from '.'; type TestState = AccountsState & { metamask: { preferences: { showFiatInTestnets: boolean }; - providerConfig: { ticker: string; chainId: string }; + providerConfig: { type: string; ticker: string; chainId: string }; currentCurrency: string; currencyRates: Record; completedOnboarding: boolean; @@ -42,6 +39,7 @@ function getEvmState(): TestState { showFiatInTestnets: false, }, providerConfig: { + type: 'mainnet', ticker: 'ETH', chainId: '0x1', }, @@ -132,7 +130,10 @@ describe('Multichain Selectors', () => { it('returns a ProviderConfig if account is EVM', () => { const state = getEvmState(); - expect(getMultichainProviderConfig(state)).toBe(getProviderConfig(state)); + // NOTE: We do fallback to `getCurrentNetwork` (using the "original" list + // of network) when using EVM context, so check against this value here + const evmMainnetNetwork = getCurrentNetwork(state); + expect(getMultichainProviderConfig(state)).toBe(evmMainnetNetwork); }); it('returns a MultichainProviderConfig if account is non-EVM (bip122:*)', () => { diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 87598561c406..55e95cafd6ea 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -5,6 +5,7 @@ import { KnownCaipNamespace, parseCaipChainId, } from '@metamask/utils'; +import { ChainId } from '@metamask/controller-utils'; import { MultichainProviderConfig, MULTICHAIN_PROVIDER_CONFIGS, @@ -18,6 +19,7 @@ import { AccountsState } from './accounts'; import { getAllNetworks, getCurrentCurrency, + getMaybeSelectedInternalAccount, getNativeCurrencyImage, getSelectedInternalAccount, getShouldShowFiat, @@ -33,7 +35,7 @@ export type MultichainNetwork = { nickname: string; isEvmNetwork: boolean; chainId?: CaipChainId; - network?: ProviderConfig | MultichainProviderConfig; + network: ProviderConfig | MultichainProviderConfig; }; export function getMultichainNetworkProviders( @@ -46,41 +48,48 @@ export function getMultichainNetworkProviders( export function getMultichainNetwork( state: MultichainState, ): MultichainNetwork { - const isOnboarded = getCompletedOnboarding(state); - // Selected account is not available during onboarding - // This is used in the app header - const selectedAccount = getSelectedInternalAccount(state); - const isEvm = isEvmAccountType(selectedAccount?.type); + const isEvm = getMultichainIsEvm(state); // EVM networks const evmNetworks: ProviderConfig[] = getAllNetworks(state); - const evmProvider: ProviderConfig = getProviderConfig(state); + const evmChainId: ChainId = getCurrentChainId(state); - if (!isOnboarded || isEvm) { - const evmChainId = - `${KnownCaipNamespace.Eip155}:${evmProvider.chainId}` as CaipChainId; - const evmNetwork = evmNetworks.find( - (network) => network.chainId === evmProvider.chainId, - ); + if (isEvm) { + const evmNetwork: ProviderConfig = + evmNetworks.find((provider) => provider.chainId === evmChainId) ?? + getProviderConfig(state); // We fallback to the original selector otherwise return { nickname: 'Ethereum', isEvmNetwork: true, - chainId: evmChainId, + // We assume the chain ID is `string` or `number`, so we convert it to a + // `Number` to be compliant with EIP155 CAIP chain ID + chainId: `${KnownCaipNamespace.Eip155}:${Number( + evmChainId, + )}` as CaipChainId, network: evmNetwork, }; } - // Non-EVM networks + // Non-EVM networks: // (Hardcoded for testing) // HACK: For now, we rely on the account type being "sort-of" CAIP compliant, so use // this as a CAIP-2 namespace and apply our filter with it + // For non-EVM, we know we have a selected account, since the logic `isEvm` is based + // on having a non-EVM account being selected! + const selectedAccount = getSelectedInternalAccount(state); const nonEvmNetworks = getMultichainNetworkProviders(state); const nonEvmNetwork = nonEvmNetworks.find((provider) => { const { namespace } = parseCaipChainId(provider.chainId); return selectedAccount.type.startsWith(namespace); }); + if (!nonEvmNetwork) { + throw new Error( + 'Could not find non-EVM provider for current config (THIS SHOULD NEVER HAPPEN)', + ); + } + return { // TODO: Adapt this for other non-EVM networks // TODO: We need to have a way of setting nicknames of other non-EVM networks @@ -97,18 +106,21 @@ export function getMultichainNetwork( // currency will be BTC.. export function getMultichainIsEvm(state: MultichainState) { - const selectedAccount = getSelectedInternalAccount(state); - - // There are no selected account during onboarding. we default to the current EVM provider. - return !selectedAccount || isEvmAccountType(selectedAccount.type); + const isOnboarded = getCompletedOnboarding(state); + // Selected account is not available during onboarding (this is used in + // the AppHeader) + const selectedAccount = getMaybeSelectedInternalAccount(state); + + // There are no selected account during onboarding. we default to the original EVM behavior. + return ( + !isOnboarded || !selectedAccount || isEvmAccountType(selectedAccount.type) + ); } -export function getMultichainProviderConfig( - state: MultichainState, -): ProviderConfig | MultichainProviderConfig { - return getMultichainIsEvm(state) - ? getProviderConfig(state) - : getMultichainNetwork(state).network; +export function getMultichainProviderConfig(state: MultichainState) { + // Naming is a bit confusing here, but we do use the `network` field that is actually + // a `{Multichain,}ProviderConfig` + return getMultichainNetwork(state).network; } export function getMultichainCurrentNetwork(state: MultichainState) { diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index e0fd002d17a1..a13494399bb0 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -327,6 +327,13 @@ export function getInternalAccountByAddress(state, address) { ); } +export function getMaybeSelectedInternalAccount(state) { + // Same as `getSelectedInternalAccount`, but might potentially be `undefined`: + // - This might happen during the onboarding + const accountId = state.metamask.internalAccounts?.selectedAccount; + return accountId && state.metamask.internalAccounts?.accounts[accountId]; +} + export function getSelectedInternalAccount(state) { const accountId = state.metamask.internalAccounts.selectedAccount; return state.metamask.internalAccounts.accounts[accountId]; From 491bcf2d7e67af12152ca10800277687e5813aa6 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:05:29 +0200 Subject: [PATCH 03/20] fix(multichain): fix getMultichain{CurrentCurrency,DefaultToken} --- ui/selectors/multichain.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 55e95cafd6ea..18a7f1f89a09 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -134,11 +134,16 @@ export function getMultichainNativeCurrency(state: MultichainState) { } export function getMultichainCurrentCurrency(state: MultichainState) { - const currentCurrency = getCurrentCurrency(state).toLowerCase(); + const currentCurrency = getCurrentCurrency(state); + if (getMultichainIsEvm(state)) { + return currentCurrency; + } + + // For non-EVM: // To mimic `getCurrentCurrency` we only consider fiat values, otherwise we // fallback to the current ticker symbol value - return currentCurrency === 'usd' + return currentCurrency && currentCurrency.toLowerCase() === 'usd' ? 'usd' : getMultichainProviderConfig(state).ticker; } @@ -163,7 +168,8 @@ export function getMultichainShouldShowFiat(state: MultichainState) { export function getMultichainDefaultToken(state: MultichainState) { const symbol = getMultichainIsEvm(state) - ? getProviderConfig(state).ticker + ? // We fallback to 'ETH' to keep original behavior of `getSwapsDefaultToken` + getProviderConfig(state).ticker ?? 'ETH' : getMultichainProviderConfig(state).ticker; return { symbol }; From 94621da7578a1230e34258c54658c33b2abd7c9b Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:06:03 +0200 Subject: [PATCH 04/20] feat(multichain): add getMultichain{IsMainnet,CurrentChainId} selectors --- ui/selectors/multichain.test.ts | 51 +++++++++++++++++++++++++++++++++ ui/selectors/multichain.ts | 17 +++++++++++ 2 files changed, 68 insertions(+) diff --git a/ui/selectors/multichain.test.ts b/ui/selectors/multichain.test.ts index d539177dcab8..d811f57798c3 100644 --- a/ui/selectors/multichain.test.ts +++ b/ui/selectors/multichain.test.ts @@ -9,11 +9,14 @@ import { MOCK_ACCOUNT_EOA, MOCK_ACCOUNT_BIP122_P2WPKH, } from '../../test/data/mock-accounts'; +import { CHAIN_IDS } from '../../shared/constants/network'; import { AccountsState } from './accounts'; import { + getMultichainCurrentChainId, getMultichainCurrentCurrency, getMultichainDefaultToken, getMultichainIsEvm, + getMultichainIsMainnet, getMultichainNativeCurrency, getMultichainNetwork, getMultichainNetworkProviders, @@ -225,4 +228,52 @@ describe('Multichain Selectors', () => { }); }); }); + + describe('getMultichainCurrentChainId', () => { + it('returns current chain ID if account is EVM (mainnet)', () => { + const state = getEvmState(); + + expect(getMultichainCurrentChainId(state)).toEqual(CHAIN_IDS.MAINNET); + }); + + it('returns current chain ID if account is EVM (other)', () => { + const state = getEvmState(); + + state.metamask.providerConfig.chainId = CHAIN_IDS.SEPOLIA; + expect(getMultichainCurrentChainId(state)).toEqual(CHAIN_IDS.SEPOLIA); + }); + + it('returns current chain ID if account is non-EVM (bip122:)', () => { + const state = getNonEvmState(); + + expect(getMultichainCurrentChainId(state)).toEqual( + MultichainNetworks.BITCOIN, + ); + }); + + // No test for testnet with non-EVM for now, as we only support mainnet network providers! + }); + + describe('getMultichainIsMainnet', () => { + it('returns true if account is EVM (mainnet)', () => { + const state = getEvmState(); + + expect(getMultichainIsMainnet(state)).toBe(true); + }); + + it('returns false if account is EVM (testnet)', () => { + const state = getEvmState(); + + state.metamask.providerConfig.chainId = CHAIN_IDS.SEPOLIA; + expect(getMultichainIsMainnet(state)).toBe(false); + }); + + it('returns current chain ID if account is non-EVM (bip122:)', () => { + const state = getNonEvmState(); + + expect(getMultichainIsMainnet(state)).toBe(true); + }); + + // No test for testnet with non-EVM for now, as we only support mainnet network providers! + }); }); diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 18a7f1f89a09..83fabac7bd7c 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -9,6 +9,7 @@ import { ChainId } from '@metamask/controller-utils'; import { MultichainProviderConfig, MULTICHAIN_PROVIDER_CONFIGS, + MultichainNetworks, } from '../../shared/constants/multichain/networks'; import { getCompletedOnboarding, @@ -18,7 +19,9 @@ import { import { AccountsState } from './accounts'; import { getAllNetworks, + getCurrentChainId, getCurrentCurrency, + getIsMainnet, getMaybeSelectedInternalAccount, getNativeCurrencyImage, getSelectedInternalAccount, @@ -174,3 +177,17 @@ export function getMultichainDefaultToken(state: MultichainState) { return { symbol }; } + +export function getMultichainCurrentChainId(state: MultichainState) { + const { chainId } = getMultichainProviderConfig(state); + return chainId; +} + +export function getMultichainIsMainnet(state: MultichainState) { + const chainId = getMultichainCurrentChainId(state); + return getMultichainIsEvm(state) + ? getIsMainnet(state) + : // TODO: For now we only check for bitcoin mainnet, but we will need to + // update this for other non-EVM networks later! + chainId === MultichainNetworks.BITCOIN; +} From 68c1239897f2a9ddfd879b1c698c4b99f6829e6e Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:10:23 +0200 Subject: [PATCH 05/20] refactor(ui): use multichain selectors in AssetList --- ui/components/app/asset-list/asset-list.js | 31 ++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/ui/components/app/asset-list/asset-list.js b/ui/components/app/asset-list/asset-list.js index a4e30cad81fc..2dff1f4f9715 100644 --- a/ui/components/app/asset-list/asset-list.js +++ b/ui/components/app/asset-list/asset-list.js @@ -6,23 +6,23 @@ import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'; import { getSelectedAccountCachedBalance, - getShouldShowFiat, - getNativeCurrencyImage, getDetectedTokensInCurrentNetwork, getIstokenDetectionInactiveOnNonMainnetSupportedNetwork, getShouldHideZeroBalanceTokens, ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) getIsBuyableChain, ///: END:ONLY_INCLUDE_IF - getCurrentNetwork, getSelectedAccount, getPreferences, - getIsMainnet, } from '../../../selectors'; import { - getNativeCurrency, - getProviderConfig, -} from '../../../ducks/metamask/metamask'; + getMultichainCurrentNetwork, + getMultichainNativeCurrency, + getMultichainIsEvm, + getMultichainShouldShowFiat, + getMultichainCurrencyImage, + getMultichainIsMainnet, +} from '../../../selectors/multichain'; import { useCurrencyDisplay } from '../../../hooks/useCurrencyDisplay'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { @@ -53,12 +53,13 @@ import { const AssetList = ({ onClickAsset }) => { const [showDetectedTokens, setShowDetectedTokens] = useState(false); const selectedAccountBalance = useSelector(getSelectedAccountCachedBalance); - const nativeCurrency = useSelector(getNativeCurrency); - const showFiat = useSelector(getShouldShowFiat); - const { chainId } = useSelector(getCurrentNetwork); - const isMainnet = useSelector(getIsMainnet); + const nativeCurrency = useSelector(getMultichainNativeCurrency); + const showFiat = useSelector(getMultichainShouldShowFiat); + const isMainnet = useSelector(getMultichainIsMainnet); const { useNativeCurrencyAsPrimaryCurrency } = useSelector(getPreferences); - const { ticker, type, rpcUrl } = useSelector(getProviderConfig); + const { chainId, ticker, type, rpcUrl } = useSelector( + getMultichainCurrentNetwork, + ); const isOriginalNativeSymbol = useIsOriginalNativeTokenSymbol( chainId, ticker, @@ -94,7 +95,7 @@ const AssetList = ({ onClickAsset }) => { currency: secondaryCurrency, }); - const primaryTokenImage = useSelector(getNativeCurrencyImage); + const primaryTokenImage = useSelector(getMultichainCurrencyImage); const detectedTokens = useSelector(getDetectedTokensInCurrentNetwork) || []; const isTokenDetectionInactiveOnNonMainnetSupportedNetwork = useSelector( getIstokenDetectionInactiveOnNonMainnetSupportedNetwork, @@ -112,7 +113,9 @@ const AssetList = ({ onClickAsset }) => { const shouldShowBuy = isBuyableChain && balanceIsZero; ///: END:ONLY_INCLUDE_IF - let isStakeable = isMainnet; + const isEvm = useSelector(getMultichainIsEvm); + + let isStakeable = isMainnet && isEvm; ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) isStakeable = false; ///: END:ONLY_INCLUDE_IF From 66703092affb20cbb58e772d2dc320afea9a8737 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:11:16 +0200 Subject: [PATCH 06/20] refactor(ui): use multichain selectors in UserPreferencedCurrencyDisplay --- .../user-preferenced-currency-display.component.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js index bfe1e8e09033..89a282db9ae4 100644 --- a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -1,13 +1,15 @@ import React, { useMemo } from 'react'; -import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; import { EtherDenomination } from '../../../../shared/constants/common'; import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'; import CurrencyDisplay from '../../ui/currency-display'; import { useUserPreferencedCurrency } from '../../../hooks/useUserPreferencedCurrency'; import { AvatarNetwork, AvatarNetworkSize } from '../../component-library'; -import { getCurrentNetwork } from '../../../selectors'; -import { getNativeCurrency } from '../../../ducks/metamask/metamask'; +import { + getMultichainNativeCurrency, + getMultichainCurrentNetwork, +} from '../../../selectors/multichain'; /* eslint-disable jsdoc/require-param-name */ // eslint-disable-next-line jsdoc/require-param @@ -24,9 +26,11 @@ export default function UserPreferencedCurrencyDisplay({ showCurrencySuffix, ...restProps }) { - const currentNetwork = useSelector(getCurrentNetwork); - const nativeCurrency = useSelector(getNativeCurrency); + const currentNetwork = useSelector(getMultichainCurrentNetwork); + const nativeCurrency = useSelector(getMultichainNativeCurrency); const { currency, numberOfDecimals } = useUserPreferencedCurrency(type, { + // FIXME: Do we need to pass this even for EVM currencies? + currency: nativeCurrency, ethNumberOfDecimals, fiatNumberOfDecimals, numberOfDecimals: propsNumberOfDecimals, From 0ff7cbb312c236d49b87854bf95c3b31c324afbf Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:12:03 +0200 Subject: [PATCH 07/20] fix(ui): fix AvatarNetwork alt --- .../component-library/avatar-network/avatar-network.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/components/component-library/avatar-network/avatar-network.tsx b/ui/components/component-library/avatar-network/avatar-network.tsx index 676b674aaad7..487f2ad7ee05 100644 --- a/ui/components/component-library/avatar-network/avatar-network.tsx +++ b/ui/components/component-library/avatar-network/avatar-network.tsx @@ -80,7 +80,7 @@ export const AvatarNetwork: AvatarNetworkComponent = React.forwardRef( } onError={handleOnError} src={src} - alt={`${name} logo` || 'network logo'} + alt={(name && `${name} logo`) || 'network logo'} /> )} From 7eb1846e2b8a18ce4cc8949dcc0d7403406c4817 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:13:04 +0200 Subject: [PATCH 08/20] refactor(ui): use multichain selectors in RampsCard --- ui/components/multichain/ramps-card/ramps-card.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ui/components/multichain/ramps-card/ramps-card.js b/ui/components/multichain/ramps-card/ramps-card.js index 9b1956ac6b7d..29edbe68a14c 100644 --- a/ui/components/multichain/ramps-card/ramps-card.js +++ b/ui/components/multichain/ramps-card/ramps-card.js @@ -10,7 +10,10 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { getCurrentNetwork, getSwapsDefaultToken } from '../../../selectors'; +import { + getMultichainDefaultToken, + getMultichainCurrentNetwork, +} from '../../../selectors/multichain'; import { MetaMetricsEventCategory, MetaMetricsEventName, @@ -68,14 +71,15 @@ export const RampsCard = ({ variant }) => { const { openBuyCryptoInPdapp } = useRamps(metamaskEntryMap[variant]); const trackEvent = useContext(MetaMetricsContext); const currentLocale = useSelector(getCurrentLocale); - const { chainId, nickname } = useSelector(getCurrentNetwork); - const { symbol = 'ETH' } = useSelector(getSwapsDefaultToken); + const { chainId, nickname } = useSelector(getMultichainCurrentNetwork); + const { symbol } = useSelector(getMultichainDefaultToken); useEffect(() => { trackEvent({ event: MetaMetricsEventName.EmptyBuyBannerDisplayed, category: MetaMetricsEventCategory.Navigation, properties: { + // FIXME: This might not be a number for non-EVM networks chain_id: chainId, locale: currentLocale, network: nickname, @@ -85,13 +89,14 @@ export const RampsCard = ({ variant }) => { }, [currentLocale, chainId, nickname, trackEvent]); const onClick = useCallback(() => { - openBuyCryptoInPdapp(); + openBuyCryptoInPdapp(chainId); trackEvent({ event: MetaMetricsEventName.NavBuyButtonClicked, category: MetaMetricsEventCategory.Navigation, properties: { location: `${variant} tab`, text: `Buy ${symbol}`, + // FIXME: This might not be a number for non-EVM networks chain_id: chainId, token_symbol: symbol, }, From fa3c43a75e1ccf9cc7467d3efcb24e78d1988ea1 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:13:37 +0200 Subject: [PATCH 09/20] refactor(ui): use multichain selectors in TokenListItem --- ui/components/multichain/token-list-item/token-list-item.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/components/multichain/token-list-item/token-list-item.js b/ui/components/multichain/token-list-item/token-list-item.js index 7f01753dfa7f..08e3debea079 100644 --- a/ui/components/multichain/token-list-item/token-list-item.js +++ b/ui/components/multichain/token-list-item/token-list-item.js @@ -36,12 +36,12 @@ import { ModalContent } from '../../component-library/modal-content/deprecated'; import { ModalHeader } from '../../component-library/modal-header/deprecated'; import { getCurrentChainId, - getCurrentNetwork, getMetaMetricsId, getNativeCurrencyImage, getPreferences, getTestNetworkBackgroundColor, } from '../../../selectors'; +import { getMultichainCurrentNetwork } from '../../../selectors/multichain'; import Tooltip from '../../ui/tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../contexts/metametrics'; @@ -132,7 +132,7 @@ export const TokenListItem = ({ ); // Used for badge icon - const currentNetwork = useSelector(getCurrentNetwork); + const currentNetwork = useSelector(getMultichainCurrentNetwork); const testNetworkBackgroundColor = useSelector(getTestNetworkBackgroundColor); return ( From a3288920fce431ac688974d062e8a9d0552cafcd Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:14:22 +0200 Subject: [PATCH 10/20] refactor(hooks): use multichain selectors in useCurrencyDisplay --- ui/hooks/useCurrencyDisplay.js | 72 +++++++++++++++++------------ ui/hooks/useCurrencyDisplay.test.js | 17 ++++++- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/ui/hooks/useCurrencyDisplay.js b/ui/hooks/useCurrencyDisplay.js index 7ff8d48e17e1..5f24f467f37c 100644 --- a/ui/hooks/useCurrencyDisplay.js +++ b/ui/hooks/useCurrencyDisplay.js @@ -2,11 +2,12 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import BigNumber from 'bignumber.js'; import { formatCurrency } from '../helpers/utils/confirm-tx.util'; -import { getCurrentCurrency } from '../selectors'; import { - getConversionRate, - getNativeCurrency, -} from '../ducks/metamask/metamask'; + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, +} from '../selectors/multichain'; +import { getConversionRate } from '../ducks/metamask/metamask'; import { getValueFromWeiHex } from '../../shared/modules/conversion.utils'; import { TEST_NETWORK_TICKER_MAP } from '../../shared/constants/network'; @@ -60,8 +61,9 @@ export function useCurrencyDisplay( inputValue, { displayValue, prefix, numberOfDecimals, denomination, currency, ...opts }, ) { - const currentCurrency = useSelector(getCurrentCurrency); - const nativeCurrency = useSelector(getNativeCurrency); + const isEvm = useSelector(getMultichainIsEvm); + const currentCurrency = useSelector(getMultichainCurrentCurrency); + const nativeCurrency = useSelector(getMultichainNativeCurrency); const conversionRate = useSelector(getConversionRate); const isUserPreferredCurrency = currency === currentCurrency; @@ -69,31 +71,41 @@ export function useCurrencyDisplay( if (displayValue) { return displayValue; } - if ( - currency === nativeCurrency || - (!isUserPreferredCurrency && !nativeCurrency) - ) { - const ethDisplayValue = new Numeric(inputValue, 16, EtherDenomination.WEI) - .toDenomination(denomination || EtherDenomination.ETH) - .round(numberOfDecimals || DEFAULT_PRECISION) - .toBase(10) - .toString(); - return ethDisplayValue === '0' && inputValue && Number(inputValue) !== 0 - ? MIN_AMOUNT_DISPLAY - : ethDisplayValue; - } else if (isUserPreferredCurrency && conversionRate) { - return formatCurrency( - getValueFromWeiHex({ - value: inputValue, - fromCurrency: nativeCurrency, - toCurrency: currency, - conversionRate, - numberOfDecimals: numberOfDecimals || 2, - toDenomination: denomination, - }), - currency, - ); + if (isEvm) { + if ( + currency === nativeCurrency || + (!isUserPreferredCurrency && !nativeCurrency) + ) { + const ethDisplayValue = new Numeric( + inputValue, + 16, + EtherDenomination.WEI, + ) + .toDenomination(denomination || EtherDenomination.ETH) + .round(numberOfDecimals || DEFAULT_PRECISION) + .toBase(10) + .toString(); + + return ethDisplayValue === '0' && inputValue && Number(inputValue) !== 0 + ? MIN_AMOUNT_DISPLAY + : ethDisplayValue; + } else if (isUserPreferredCurrency && conversionRate) { + return formatCurrency( + getValueFromWeiHex({ + value: inputValue, + fromCurrency: nativeCurrency, + toCurrency: currency, + conversionRate, + numberOfDecimals: numberOfDecimals || 2, + toDenomination: denomination, + }), + currency, + ); + } + } else { + // TODO: For non-EVM we assume the input value can be formatted "as-is" + return formatCurrency(inputValue, currency); } return null; }, [ diff --git a/ui/hooks/useCurrencyDisplay.test.js b/ui/hooks/useCurrencyDisplay.test.js index d3863d0247aa..b97064121593 100644 --- a/ui/hooks/useCurrencyDisplay.test.js +++ b/ui/hooks/useCurrencyDisplay.test.js @@ -2,6 +2,11 @@ import { renderHook } from '@testing-library/react-hooks'; import * as reactRedux from 'react-redux'; import sinon from 'sinon'; import { getCurrentCurrency } from '../selectors'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, +} from '../selectors/multichain'; import { getConversionRate, getNativeCurrency, @@ -128,9 +133,17 @@ describe('useCurrencyDisplay', () => { describe(`when input is { value: ${value}, decimals: ${restProps.numberOfDecimals}, denomation: ${restProps.denomination} }`, () => { const stub = sinon.stub(reactRedux, 'useSelector'); stub.callsFake((selector) => { - if (selector === getCurrentCurrency) { + if (selector === getMultichainIsEvm) { + return true; + } else if ( + selector === getCurrentCurrency || + selector === getMultichainCurrentCurrency + ) { return 'usd'; - } else if (selector === getNativeCurrency) { + } else if ( + selector === getNativeCurrency || + selector === getMultichainNativeCurrency + ) { return 'ETH'; } else if (selector === getConversionRate) { return 280.45; From 82bf9376c6c6a8813699a2ac4be3c84de3c75484 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:15:54 +0200 Subject: [PATCH 11/20] refactor(hooks): use multichain selectors in useUserPreferencedCurrency --- ui/hooks/useTransactionDisplayData.test.js | 25 +++++++++++++++++---- ui/hooks/useUserPreferencedCurrency.js | 17 +++++++------- ui/hooks/useUserPreferencedCurrency.test.js | 17 ++++++++++++-- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/ui/hooks/useTransactionDisplayData.test.js b/ui/hooks/useTransactionDisplayData.test.js index 6a8838fdbd61..60de4dccd295 100644 --- a/ui/hooks/useTransactionDisplayData.test.js +++ b/ui/hooks/useTransactionDisplayData.test.js @@ -25,6 +25,12 @@ import { CHAIN_IDS } from '../../shared/constants/network'; import { TransactionGroupCategory } from '../../shared/constants/transaction'; import { formatDateWithYearContext } from '../helpers/utils/util'; import { getMessage } from '../helpers/utils/i18n-helper'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, + getMultichainShouldShowFiat, +} from '../selectors/multichain'; import * as i18nhooks from './useI18nContext'; import * as useTokenFiatAmountHooks from './useTokenFiatAmount'; import { useTransactionDisplayData } from './useTransactionDisplayData'; @@ -201,7 +207,9 @@ describe('useTransactionDisplayData', () => { getMessage('en', messages, key, variables), ); useSelector.callsFake((selector) => { - if (selector === getTokens) { + if (selector === getMultichainIsEvm) { + return true; + } else if (selector === getTokens) { return [ { address: '0xabca64466f257793eaa52fcfff5066894b76a149', @@ -213,11 +221,20 @@ describe('useTransactionDisplayData', () => { return { useNativeCurrencyAsPrimaryCurrency: true, }; - } else if (selector === getShouldShowFiat) { + } else if ( + selector === getShouldShowFiat || + selector === getMultichainShouldShowFiat + ) { return false; - } else if (selector === getNativeCurrency) { + } else if ( + selector === getNativeCurrency || + selector === getMultichainNativeCurrency + ) { return 'ETH'; - } else if (selector === getCurrentCurrency) { + } else if ( + selector === getCurrentCurrency || + selector === getMultichainCurrentCurrency + ) { return 'ETH'; } else if (selector === getCurrentChainId) { return CHAIN_IDS.MAINNET; diff --git a/ui/hooks/useUserPreferencedCurrency.js b/ui/hooks/useUserPreferencedCurrency.js index 92b9f2e54e32..dbf5671f38c7 100644 --- a/ui/hooks/useUserPreferencedCurrency.js +++ b/ui/hooks/useUserPreferencedCurrency.js @@ -1,10 +1,10 @@ import { shallowEqual, useSelector } from 'react-redux'; +import { getPreferences } from '../selectors'; import { - getPreferences, - getShouldShowFiat, - getCurrentCurrency, -} from '../selectors'; -import { getNativeCurrency } from '../ducks/metamask/metamask'; + getMultichainNativeCurrency, + getMultichainCurrentCurrency, + getMultichainShouldShowFiat, +} from '../selectors/multichain'; import { PRIMARY, SECONDARY } from '../helpers/constants/common'; import { EtherDenomination } from '../../shared/constants/common'; @@ -41,13 +41,14 @@ import { ETH_DEFAULT_DECIMALS } from '../constants'; * @returns {UserPreferredCurrency} */ export function useUserPreferencedCurrency(type, opts = {}) { - const nativeCurrency = useSelector(getNativeCurrency); + const nativeCurrency = useSelector(getMultichainNativeCurrency); + const { useNativeCurrencyAsPrimaryCurrency } = useSelector( getPreferences, shallowEqual, ); - const showFiat = useSelector(getShouldShowFiat); - const currentCurrency = useSelector(getCurrentCurrency); + const showFiat = useSelector(getMultichainShouldShowFiat); + const currentCurrency = useSelector(getMultichainCurrentCurrency); const fiatReturn = { currency: currentCurrency, diff --git a/ui/hooks/useUserPreferencedCurrency.test.js b/ui/hooks/useUserPreferencedCurrency.test.js index 0b83fad77eba..814178068988 100644 --- a/ui/hooks/useUserPreferencedCurrency.test.js +++ b/ui/hooks/useUserPreferencedCurrency.test.js @@ -6,6 +6,11 @@ import { getPreferences, getShouldShowFiat, } from '../selectors'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainShouldShowFiat, +} from '../selectors/multichain'; import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; const tests = [ @@ -120,9 +125,17 @@ function getFakeUseSelector(state) { return (selector) => { if (selector === getPreferences) { return state; - } else if (selector === getShouldShowFiat) { + } else if (selector === getMultichainIsEvm) { + return state.nativeCurrency === 'ETH'; + } else if ( + selector === getShouldShowFiat || + selector === getMultichainShouldShowFiat + ) { return state.showFiat; - } else if (selector === getCurrentCurrency) { + } else if ( + selector === getCurrentCurrency || + selector === getMultichainCurrentCurrency + ) { return state.currentCurrency; } return state.nativeCurrency; From cefc849a927e47f697087f88d97f8425f4c9138a Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:16:46 +0200 Subject: [PATCH 12/20] test(hooks): fix missing multichain stubs/mocks --- ui/pages/confirmations/hooks/test-utils.js | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ui/pages/confirmations/hooks/test-utils.js b/ui/pages/confirmations/hooks/test-utils.js index 5805c56c8f93..fea126d1e50c 100644 --- a/ui/pages/confirmations/hooks/test-utils.js +++ b/ui/pages/confirmations/hooks/test-utils.js @@ -21,6 +21,12 @@ import { import { Numeric } from '../../../../shared/modules/Numeric'; import { EtherDenomination } from '../../../../shared/constants/common'; import { useGasFeeEstimates } from '../../../hooks/useGasFeeEstimates'; +import { + getMultichainCurrentCurrency, + getMultichainIsEvm, + getMultichainNativeCurrency, + getMultichainShouldShowFiat, +} from '../../../selectors/multichain'; // Why this number? // 20 gwei * 21000 gasLimit = 420,000 gwei @@ -96,10 +102,16 @@ export const generateUseSelectorRouter = shouldShowFiat = true, } = {}) => (selector) => { + if (selector === getMultichainIsEvm) { + return true; + } if (selector === getConversionRate) { return MOCK_ETH_USD_CONVERSION_RATE; } - if (selector === getNativeCurrency) { + if ( + selector === getMultichainNativeCurrency || + selector === getNativeCurrency + ) { return EtherDenomination.ETH; } if (selector === getPreferences) { @@ -107,10 +119,16 @@ export const generateUseSelectorRouter = useNativeCurrencyAsPrimaryCurrency: true, }; } - if (selector === getCurrentCurrency) { + if ( + selector === getMultichainCurrentCurrency || + selector === getCurrentCurrency + ) { return 'USD'; } - if (selector === getShouldShowFiat) { + if ( + selector === getMultichainShouldShowFiat || + selector === getShouldShowFiat + ) { return shouldShowFiat; } if (selector === txDataSelector) { From 93150875c6bebc12aba8371a7ed3019ba2a09af0 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 11:17:31 +0200 Subject: [PATCH 13/20] test: re-generate AssetPage snapshot --- .../asset/components/__snapshots__/asset-page.test.tsx.snap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap b/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap index 9b9b8d0a7fdd..dd027ab5608d 100644 --- a/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap +++ b/ui/pages/asset/components/__snapshots__/asset-page.test.tsx.snap @@ -192,7 +192,7 @@ exports[`AssetPage should render a native asset 1`] = ` class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-border-muted box--border-style-solid box--border-width-1" > undefined logo @@ -476,7 +476,7 @@ exports[`AssetPage should render an ERC20 asset without prices 1`] = ` class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-border-muted box--border-style-solid box--border-width-1" > undefined logo @@ -951,7 +951,7 @@ exports[`AssetPage should render an ERC20 token with prices 1`] = ` class="mm-box mm-text mm-avatar-base mm-avatar-base--size-xs mm-avatar-network mm-text--body-xs mm-text--text-transform-uppercase mm-box--display-flex mm-box--justify-content-center mm-box--align-items-center mm-box--color-text-default mm-box--background-color-background-alternative mm-box--rounded-full mm-box--border-color-border-muted box--border-style-solid box--border-width-1" > undefined logo From d54864a2ea1fff32c1185ff3ef17e17a42a765a9 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 13:09:49 +0200 Subject: [PATCH 14/20] refactor(ui): remove some TODO/FIXME --- .../user-preferenced-currency-display.component.js | 3 +-- ui/hooks/useCurrencyDisplay.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js index 89a282db9ae4..823aeb7a8124 100644 --- a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -29,8 +29,7 @@ export default function UserPreferencedCurrencyDisplay({ const currentNetwork = useSelector(getMultichainCurrentNetwork); const nativeCurrency = useSelector(getMultichainNativeCurrency); const { currency, numberOfDecimals } = useUserPreferencedCurrency(type, { - // FIXME: Do we need to pass this even for EVM currencies? - currency: nativeCurrency, + currency: nativeCurrency, // Required for non-EVM support for now ethNumberOfDecimals, fiatNumberOfDecimals, numberOfDecimals: propsNumberOfDecimals, diff --git a/ui/hooks/useCurrencyDisplay.js b/ui/hooks/useCurrencyDisplay.js index 5f24f467f37c..bd60566bbf88 100644 --- a/ui/hooks/useCurrencyDisplay.js +++ b/ui/hooks/useCurrencyDisplay.js @@ -104,7 +104,7 @@ export function useCurrencyDisplay( ); } } else { - // TODO: For non-EVM we assume the input value can be formatted "as-is" + // For non-EVM we assume the input value can be formatted "as-is" return formatCurrency(inputValue, currency); } return null; From b9e6353691000e7374da3fc0ef7b5bc109c95ccd Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 14:04:10 +0200 Subject: [PATCH 15/20] refactor(ui): remove changes related to bitcoin account overview support --- .../user-preferenced-currency-display.component.js | 1 - ui/components/multichain/ramps-card/ramps-card.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js index 823aeb7a8124..6611fbcd68c1 100644 --- a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -29,7 +29,6 @@ export default function UserPreferencedCurrencyDisplay({ const currentNetwork = useSelector(getMultichainCurrentNetwork); const nativeCurrency = useSelector(getMultichainNativeCurrency); const { currency, numberOfDecimals } = useUserPreferencedCurrency(type, { - currency: nativeCurrency, // Required for non-EVM support for now ethNumberOfDecimals, fiatNumberOfDecimals, numberOfDecimals: propsNumberOfDecimals, diff --git a/ui/components/multichain/ramps-card/ramps-card.js b/ui/components/multichain/ramps-card/ramps-card.js index 29edbe68a14c..e1c61f2a35c1 100644 --- a/ui/components/multichain/ramps-card/ramps-card.js +++ b/ui/components/multichain/ramps-card/ramps-card.js @@ -89,7 +89,7 @@ export const RampsCard = ({ variant }) => { }, [currentLocale, chainId, nickname, trackEvent]); const onClick = useCallback(() => { - openBuyCryptoInPdapp(chainId); + openBuyCryptoInPdapp(); trackEvent({ event: MetaMetricsEventName.NavBuyButtonClicked, category: MetaMetricsEventCategory.Navigation, From 11cd32c1e67783786beef04b994e27f9a1898d44 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 16:57:16 +0200 Subject: [PATCH 16/20] refactor(multichain): use ternary in getMaybeSelectedInternalAccount Co-authored-by: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> --- ui/selectors/selectors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index a13494399bb0..edd34fcfd1d0 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -331,7 +331,7 @@ export function getMaybeSelectedInternalAccount(state) { // Same as `getSelectedInternalAccount`, but might potentially be `undefined`: // - This might happen during the onboarding const accountId = state.metamask.internalAccounts?.selectedAccount; - return accountId && state.metamask.internalAccounts?.accounts[accountId]; + return accountId ? state.metamask.internalAccounts?.accounts[accountId] : undefined; } export function getSelectedInternalAccount(state) { From 6be29737e82d006b5e26edb30eee54c7ae8b8d13 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 16:57:51 +0200 Subject: [PATCH 17/20] refactor(multichain): better error message Co-authored-by: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> --- ui/selectors/multichain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 83fabac7bd7c..27afb9d9a8c3 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -89,7 +89,7 @@ export function getMultichainNetwork( if (!nonEvmNetwork) { throw new Error( - 'Could not find non-EVM provider for current config (THIS SHOULD NEVER HAPPEN)', + 'Could not find non-EVM provider for the current configuration. This should never happen.', ); } From cf24e63722c49a19d65bf1e50adfcb6933408101 Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 16:58:51 +0200 Subject: [PATCH 18/20] docs(multichain): add jsdoc for getMultichainProviderConfig Co-authored-by: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com> --- ui/selectors/multichain.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index 27afb9d9a8c3..d31ba8a852ce 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -120,9 +120,15 @@ export function getMultichainIsEvm(state: MultichainState) { ); } +/** + * Retrieves the provider configuration for a multichain network. + * + * This function extracts the `network` field from the result of `getMultichainNetwork(state)`, + * which is expected to be a `MultichainProviderConfig` object. The naming might suggest that + * it returns a network, but it actually returns a provider configuration specific to a multichain setup. + * + */ export function getMultichainProviderConfig(state: MultichainState) { - // Naming is a bit confusing here, but we do use the `network` field that is actually - // a `{Multichain,}ProviderConfig` return getMultichainNetwork(state).network; } From c2f7a53c610dec332b8e7ed20af629dc84532fba Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 17:14:15 +0200 Subject: [PATCH 19/20] chore: lint --- ui/selectors/selectors.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index edd34fcfd1d0..110a16f86f79 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -331,7 +331,9 @@ export function getMaybeSelectedInternalAccount(state) { // Same as `getSelectedInternalAccount`, but might potentially be `undefined`: // - This might happen during the onboarding const accountId = state.metamask.internalAccounts?.selectedAccount; - return accountId ? state.metamask.internalAccounts?.accounts[accountId] : undefined; + return accountId + ? state.metamask.internalAccounts?.accounts[accountId] + : undefined; } export function getSelectedInternalAccount(state) { From be53a20516c5916271a25c86b1ee8b01ddaa9bff Mon Sep 17 00:00:00 2001 From: Charly Chevalier Date: Thu, 13 Jun 2024 17:14:58 +0200 Subject: [PATCH 20/20] docs(multichain): fix doc for getMultichainProviderConfig --- ui/selectors/multichain.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index d31ba8a852ce..3e9070b1a3ab 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -122,11 +122,13 @@ export function getMultichainIsEvm(state: MultichainState) { /** * Retrieves the provider configuration for a multichain network. - * + * * This function extracts the `network` field from the result of `getMultichainNetwork(state)`, * which is expected to be a `MultichainProviderConfig` object. The naming might suggest that * it returns a network, but it actually returns a provider configuration specific to a multichain setup. * + * @param state - The redux state. + * @returns The current multichain provider configuration. */ export function getMultichainProviderConfig(state: MultichainState) { return getMultichainNetwork(state).network;