From 1970754ec76709d026529d1f531d7ead933a5169 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 13:36:21 -0800 Subject: [PATCH 01/13] multichain currency rate polling --- app/components/Views/Root/index.js | 9 +++-- .../NetworksSettings/NetworkSettings/index.js | 2 +- .../Views/Settings/NetworksSettings/index.js | 2 +- .../AssetPolling/AssetPollingProvider.tsx | 11 ++++++ .../AssetPolling/useCurrencyRatePolling.ts | 39 +++++++++++++++++++ app/core/Engine.ts | 10 +---- app/selectors/currencyRateController.ts | 7 ++++ 7 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 app/components/hooks/AssetPolling/AssetPollingProvider.tsx create mode 100644 app/components/hooks/AssetPolling/useCurrencyRatePolling.ts diff --git a/app/components/Views/Root/index.js b/app/components/Views/Root/index.js index 7ffa81485d3..05a52cb033b 100644 --- a/app/components/Views/Root/index.js +++ b/app/components/Views/Root/index.js @@ -12,6 +12,7 @@ import { useAppTheme, ThemeContext } from '../../../util/theme'; import { ToastContextWrapper } from '../../../component-library/components/Toast'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { isTest } from '../../../util/test/utils'; +import { AssetPollingProvider } from '../../hooks/AssetPolling/AssetPollingProvider'; /** * Top level of the component hierarchy @@ -85,9 +86,11 @@ const ConnectedRoot = () => { - - - + + + + + diff --git a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js index 44873cd9344..419aea0ba54 100644 --- a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js @@ -1538,7 +1538,7 @@ export class NetworkSettings extends PureComponent { networkConfigurations.defaultRpcEndpointIndex ] ?? {}; - CurrencyRateController.updateExchangeRate(NetworksTicker.mainnet); + CurrencyRateController.updateExchangeRate([NetworksTicker.mainnet]); NetworkController.setActiveNetwork(networkClientId); setTimeout(async () => { diff --git a/app/components/Views/Settings/NetworksSettings/index.js b/app/components/Views/Settings/NetworksSettings/index.js index b96e2bb7e4e..518e958c7ca 100644 --- a/app/components/Views/Settings/NetworksSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/index.js @@ -188,7 +188,7 @@ class NetworksSettings extends PureComponent { switchToMainnet = () => { const { NetworkController, CurrencyRateController } = Engine.context; - CurrencyRateController.updateExchangeRate(NetworksTicker.mainnet); + CurrencyRateController.updateExchangeRate([NetworksTicker.mainnet]); NetworkController.setProviderType(MAINNET); setTimeout(async () => { diff --git a/app/components/hooks/AssetPolling/AssetPollingProvider.tsx b/app/components/hooks/AssetPolling/AssetPollingProvider.tsx new file mode 100644 index 00000000000..7c7c3eda5fa --- /dev/null +++ b/app/components/hooks/AssetPolling/AssetPollingProvider.tsx @@ -0,0 +1,11 @@ +import React, { ReactNode } from 'react'; +import useCurrencyRatePolling from './useCurrencyRatePolling'; + +// This provider is a step towards making controller polling fully UI based. +// Eventually, individual UI components will call the use*Polling hooks to +// poll and return particular data. This polls globally in the meantime. +export const AssetPollingProvider = ({ children }: { children: ReactNode }) => { + useCurrencyRatePolling(); + + return <>{children}; +}; diff --git a/app/components/hooks/AssetPolling/useCurrencyRatePolling.ts b/app/components/hooks/AssetPolling/useCurrencyRatePolling.ts new file mode 100644 index 00000000000..7663c1e5dcb --- /dev/null +++ b/app/components/hooks/AssetPolling/useCurrencyRatePolling.ts @@ -0,0 +1,39 @@ +import { useSelector } from 'react-redux'; +import usePolling from '../usePolling'; +import { selectNetworkConfigurations } from '../../../selectors/networkController'; +import Engine from '../../../core/Engine'; +import { selectConversionRate, selectCurrencyRates } from '../../../selectors/currencyRateController'; + +// Polls native currency prices across networks. +const useCurrencyRatePolling = () => { + + // Selectors to determine polling input + const networkConfigurations = useSelector(selectNetworkConfigurations); + + // Selectors returning state updated by the polling + const conversionRate = useSelector(selectConversionRate); + const currencyRates = useSelector(selectCurrencyRates); + + const nativeCurrencies = [ + ...new Set( + Object.values(networkConfigurations).map((n) => n.nativeCurrency), + ), + ]; + + const { CurrencyRateController } = Engine.context; + + usePolling({ + startPolling: + CurrencyRateController.startPolling.bind(CurrencyRateController), + stopPollingByPollingToken: + CurrencyRateController.stopPollingByPollingToken.bind(CurrencyRateController), + input: [{nativeCurrencies}], + }); + + return { + conversionRate, + currencyRates, + }; +}; + +export default useCurrencyRatePolling; diff --git a/app/core/Engine.ts b/app/core/Engine.ts index 976ecc5a198..ed5efca70fb 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -706,15 +706,7 @@ export class Engine { }), state: initialState.CurrencyRateController, }); - const currentNetworkConfig = - networkController.getNetworkConfigurationByNetworkClientId( - networkController?.state.selectedNetworkClientId, - ); - currencyRateController.startPolling({ - nativeCurrencies: currentNetworkConfig?.nativeCurrency - ? [currentNetworkConfig?.nativeCurrency] - : [], - }); + const gasFeeController = new GasFeeController({ // @ts-expect-error TODO: Resolve mismatch between base-controller versions. messenger: this.controllerMessenger.getRestricted({ diff --git a/app/selectors/currencyRateController.ts b/app/selectors/currencyRateController.ts index fa58efe5106..9617d02710d 100644 --- a/app/selectors/currencyRateController.ts +++ b/app/selectors/currencyRateController.ts @@ -34,3 +34,10 @@ export const selectCurrentCurrency = createSelector( (currencyRateControllerState: CurrencyRateState) => currencyRateControllerState?.currentCurrency, ); + +export const selectCurrencyRates = createSelector( + selectCurrencyRateControllerState, + ( + currencyRateControllerState: CurrencyRateState, + ) => currencyRateControllerState?.currencyRates, +); From e23a19c52591930cf0636282e56a4d699aa4967a Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 13:58:57 -0800 Subject: [PATCH 02/13] remove unused places --- .../Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx | 4 +--- .../Views/NetworkSelector/NetworkSelector.tsx | 13 ------------- app/core/RPCMethods/lib/ethereum-chain-utils.js | 2 -- app/util/networks/handleNetworkSwitch.ts | 5 ----- 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx index 5178c067e10..9894e7e5d13 100644 --- a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx +++ b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx @@ -153,14 +153,13 @@ function NetworkSwitcher() { const switchNetwork = useCallback( (networkConfiguration) => { - const { CurrencyRateController, NetworkController } = Engine.context; + const { NetworkController } = Engine.context; const config = Object.values(networkConfigurations).find( ({ chainId }) => chainId === networkConfiguration.chainId, ); if (config) { const { - nativeCurrency: ticker, rpcEndpoints, defaultRpcEndpointIndex, } = config; @@ -168,7 +167,6 @@ function NetworkSwitcher() { const { networkClientId } = rpcEndpoints?.[defaultRpcEndpointIndex] ?? {}; - CurrencyRateController.updateExchangeRate([ticker]); NetworkController.setActiveNetwork(networkClientId); navigateToGetStarted(); } diff --git a/app/components/Views/NetworkSelector/NetworkSelector.tsx b/app/components/Views/NetworkSelector/NetworkSelector.tsx index ea36deab166..a82fb3e7397 100644 --- a/app/components/Views/NetworkSelector/NetworkSelector.tsx +++ b/app/components/Views/NetworkSelector/NetworkSelector.tsx @@ -37,9 +37,7 @@ import Networks, { } from '../../../util/networks'; import { LINEA_MAINNET, - LINEA_SEPOLIA, MAINNET, - SEPOLIA, } from '../../../constants/network'; import Button from '../../../component-library/components/Buttons/Button/Button'; import { @@ -65,7 +63,6 @@ import createStyles from './NetworkSelector.styles'; import { BUILT_IN_NETWORKS, InfuraNetworkType, - TESTNET_TICKER_SYMBOLS, } from '@metamask/controller-utils'; import InfoModal from '../../../../app/components/UI/Swaps/components/InfoModal'; import hideKeyFromUrl from '../../../util/hideKeyFromUrl'; @@ -268,8 +265,6 @@ const NetworkSelector = () => { networkConfigurationId, ); } else { - CurrencyRateController.updateExchangeRate([ticker]); - const { networkClientId } = rpcEndpoints[defaultRpcEndpointIndex]; await NetworkController.setActiveNetwork(networkClientId); @@ -378,13 +373,6 @@ const NetworkSelector = () => { if (domainIsConnectedDapp && process.env.MULTICHAIN_V1) { SelectedNetworkController.setNetworkClientIdForDomain(origin, type); } else { - let ticker = type; - if (type === LINEA_SEPOLIA) { - ticker = TESTNET_TICKER_SYMBOLS.LINEA_SEPOLIA as InfuraNetworkType; - } - if (type === SEPOLIA) { - ticker = TESTNET_TICKER_SYMBOLS.SEPOLIA as InfuraNetworkType; - } const networkConfiguration = networkConfigurations[BUILT_IN_NETWORKS[type].chainId]; @@ -394,7 +382,6 @@ const NetworkSelector = () => { networkConfiguration.defaultRpcEndpointIndex ].networkClientId ?? type; - CurrencyRateController.updateExchangeRate([ticker]); NetworkController.setActiveNetwork(clientId); closeRpcModal(); AccountTrackerController.refresh(); diff --git a/app/core/RPCMethods/lib/ethereum-chain-utils.js b/app/core/RPCMethods/lib/ethereum-chain-utils.js index cb71659205f..dc3575ad718 100644 --- a/app/core/RPCMethods/lib/ethereum-chain-utils.js +++ b/app/core/RPCMethods/lib/ethereum-chain-utils.js @@ -207,7 +207,6 @@ export async function switchToNetwork({ isAddNetworkFlow = false, }) { const { - CurrencyRateController, NetworkController, PermissionController, SelectedNetworkController, @@ -300,7 +299,6 @@ export async function switchToNetwork({ networkConfigurationId || networkConfiguration.networkType, ); } else { - CurrencyRateController.updateExchangeRate(requestData.ticker); NetworkController.setActiveNetwork( networkConfigurationId || networkConfiguration.networkType, ); diff --git a/app/util/networks/handleNetworkSwitch.ts b/app/util/networks/handleNetworkSwitch.ts index b05ad5df60c..60fddb9012f 100644 --- a/app/util/networks/handleNetworkSwitch.ts +++ b/app/util/networks/handleNetworkSwitch.ts @@ -1,4 +1,3 @@ -import { CurrencyRateController } from '@metamask/assets-controllers'; import { toHex } from '@metamask/controller-utils'; import { NetworkController } from '@metamask/network-controller'; import Engine from '../../core/Engine'; @@ -22,8 +21,6 @@ const handleNetworkSwitch = (switchToChainId: string): string | undefined => { return; } - const currencyRateController = Engine.context - .CurrencyRateController as CurrencyRateController; const networkController = Engine.context .NetworkController as NetworkController; const chainId = selectChainId(store.getState()); @@ -44,13 +41,11 @@ const handleNetworkSwitch = (switchToChainId: string): string | undefined => { , { name: nickname, - nativeCurrency: ticker, rpcEndpoints, defaultRpcEndpointIndex, }, ] = entry; - currencyRateController.updateExchangeRate([ticker]); const { networkClientId } = rpcEndpoints[defaultRpcEndpointIndex]; networkController.setActiveNetwork(networkClientId); From 9a2342c1c50b9377855da5d480ca2e3d54c461a6 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 14:03:05 -0800 Subject: [PATCH 03/13] lint --- app/components/Views/NetworkSelector/NetworkSelector.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/components/Views/NetworkSelector/NetworkSelector.tsx b/app/components/Views/NetworkSelector/NetworkSelector.tsx index a82fb3e7397..21bf02d1b71 100644 --- a/app/components/Views/NetworkSelector/NetworkSelector.tsx +++ b/app/components/Views/NetworkSelector/NetworkSelector.tsx @@ -238,7 +238,6 @@ const NetworkSelector = () => { const onSetRpcTarget = async (networkConfiguration: NetworkConfiguration) => { const { - CurrencyRateController, NetworkController, SelectedNetworkController, } = Engine.context; @@ -251,7 +250,6 @@ const NetworkSelector = () => { const { name: nickname, chainId, - nativeCurrency: ticker, rpcEndpoints, defaultRpcEndpointIndex, } = networkConfiguration; @@ -365,7 +363,6 @@ const NetworkSelector = () => { }); const { NetworkController, - CurrencyRateController, AccountTrackerController, SelectedNetworkController, } = Engine.context; From 910395e2919c2eeda704fb49956ce1ed1523517f Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 14:37:59 -0800 Subject: [PATCH 04/13] add unit test --- .../useCurrencyRatePolling.test.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 app/components/hooks/AssetPolling/useCurrencyRatePolling.test.ts diff --git a/app/components/hooks/AssetPolling/useCurrencyRatePolling.test.ts b/app/components/hooks/AssetPolling/useCurrencyRatePolling.test.ts new file mode 100644 index 00000000000..fbf94e9d316 --- /dev/null +++ b/app/components/hooks/AssetPolling/useCurrencyRatePolling.test.ts @@ -0,0 +1,42 @@ +import useCurrencyRatePolling from './useCurrencyRatePolling'; +import { renderHookWithProvider } from '../../../util/test/renderWithProvider'; +import Engine from '../../../core/Engine'; + +jest.mock('../../../core/Engine', () => ({ + context: { + CurrencyRateController: { + startPolling: jest.fn(), + stopPollingByPollingToken: jest.fn(), + }, + }, +})); + +describe('useCurrencyRatePolling', () => { + + it('Should poll by the native currencies in network state', async () => { + + const state = { + engine: { + backgroundState: { + NetworkController: { + networkConfigurationsByChainId: { + '0x1': { + nativeCurrency: 'ETH', + }, + '0x89': { + nativeCurrency: 'POL', + }, + }, + }, + }, + }, + }; + + renderHookWithProvider(() => useCurrencyRatePolling(), {state}); + + expect( + jest.mocked(Engine.context.CurrencyRateController.startPolling) + ).toHaveBeenCalledWith({nativeCurrencies: ['ETH', 'POL']}); + + }); +}); From 1492b4c10c9299d88a7d937d59b205c0a8861960 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 14:50:10 -0800 Subject: [PATCH 05/13] update unit tests --- app/core/RPCMethods/wallet_addEthereumChain.test.js | 2 -- app/util/networks/handleNetworkSwitch.test.ts | 7 ------- 2 files changed, 9 deletions(-) diff --git a/app/core/RPCMethods/wallet_addEthereumChain.test.js b/app/core/RPCMethods/wallet_addEthereumChain.test.js index f84e2ebcd29..dc434b43cc4 100644 --- a/app/core/RPCMethods/wallet_addEthereumChain.test.js +++ b/app/core/RPCMethods/wallet_addEthereumChain.test.js @@ -393,7 +393,6 @@ describe('RPC Method - wallet_addEthereumChain', () => { }), ); expect(spyOnSetActiveNetwork).toHaveBeenCalledTimes(1); - expect(spyOnUpdateExchangeRate).toHaveBeenCalledTimes(1); }); it('should not add a networkConfiguration that has a chainId that already exists in wallet state, and should switch to the existing network', async () => { @@ -432,7 +431,6 @@ describe('RPC Method - wallet_addEthereumChain', () => { expect(spyOnAddNetwork).not.toHaveBeenCalled(); expect(spyOnSetActiveNetwork).toHaveBeenCalledTimes(1); - expect(spyOnUpdateExchangeRate).toHaveBeenCalledTimes(1); }); describe('MM_CHAIN_PERMISSIONS is enabled', () => { diff --git a/app/util/networks/handleNetworkSwitch.test.ts b/app/util/networks/handleNetworkSwitch.test.ts index 9084fb3c89e..776891fd60b 100644 --- a/app/util/networks/handleNetworkSwitch.test.ts +++ b/app/util/networks/handleNetworkSwitch.test.ts @@ -136,9 +136,6 @@ describe('useHandleNetworkSwitch', () => { const nickname = handleNetworkSwitch('1338'); - expect( - mockEngine.context.CurrencyRateController.updateExchangeRate, - ).toBeCalledWith(['TEST']); expect( mockEngine.context.NetworkController.setActiveNetwork, ).toBeCalledWith('networkId1'); @@ -153,10 +150,6 @@ describe('useHandleNetworkSwitch', () => { const networkType = handleNetworkSwitch('11155111'); - // TODO: This is a bug, it should be set to SepoliaETH - expect( - mockEngine.context.CurrencyRateController.updateExchangeRate, - ).toBeCalledWith(['ETH']); expect( mockEngine.context.NetworkController.setProviderType, ).not.toBeCalledWith(); From ae15f4582b475bac6e2951724cffb1d76a210b9c Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 14:57:29 -0800 Subject: [PATCH 06/13] update unit test --- .../Views/NetworkSwitcher/NetworkSwitcher.test.tsx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx index 49eab63ff75..f9921440bd4 100644 --- a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx +++ b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx @@ -303,18 +303,6 @@ describe('NetworkSwitcher View', () => { ], ] `); - expect( - (Engine.context.CurrencyRateController.updateExchangeRate as jest.Mock) - .mock.calls, - ).toMatchInlineSnapshot(` - [ - [ - [ - "POL", - ], - ], - ] - `); }); it('renders correctly with errors', async () => { From 3b6c675271ecd0c61007c258bb457bd52e1e6188 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 15:07:59 -0800 Subject: [PATCH 07/13] remove other network updates --- .../Settings/NetworksSettings/NetworkSettings/index.js | 6 ++---- app/components/Views/Settings/NetworksSettings/index.js | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js index 419aea0ba54..2833c06f795 100644 --- a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.js @@ -822,14 +822,13 @@ export class NetworkSettings extends PureComponent { shouldNetworkSwitchPopToWallet, navigation, }) => { - const { NetworkController, CurrencyRateController } = Engine.context; + const { NetworkController } = Engine.context; const url = new URL(rpcUrl); if (!isPrivateConnection(url.hostname)) { url.set('protocol', 'https:'); } - CurrencyRateController.updateExchangeRate([ticker]); const existingNetwork = this.props.networkConfigurations[chainId]; const indexRpc = rpcUrls.findIndex(({ url }) => url === rpcUrl); @@ -1530,7 +1529,7 @@ export class NetworkSettings extends PureComponent { }; switchToMainnet = () => { - const { NetworkController, CurrencyRateController } = Engine.context; + const { NetworkController } = Engine.context; const { networkConfigurations } = this.props; const { networkClientId } = @@ -1538,7 +1537,6 @@ export class NetworkSettings extends PureComponent { networkConfigurations.defaultRpcEndpointIndex ] ?? {}; - CurrencyRateController.updateExchangeRate([NetworksTicker.mainnet]); NetworkController.setActiveNetwork(networkClientId); setTimeout(async () => { diff --git a/app/components/Views/Settings/NetworksSettings/index.js b/app/components/Views/Settings/NetworksSettings/index.js index 518e958c7ca..56a1b062165 100644 --- a/app/components/Views/Settings/NetworksSettings/index.js +++ b/app/components/Views/Settings/NetworksSettings/index.js @@ -186,9 +186,8 @@ class NetworksSettings extends PureComponent { }; switchToMainnet = () => { - const { NetworkController, CurrencyRateController } = Engine.context; + const { NetworkController } = Engine.context; - CurrencyRateController.updateExchangeRate([NetworksTicker.mainnet]); NetworkController.setProviderType(MAINNET); setTimeout(async () => { From 2e9dff399579b626704431fa29478494febde8f6 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 15:12:08 -0800 Subject: [PATCH 08/13] remove additional call --- app/components/UI/NetworkModal/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/components/UI/NetworkModal/index.tsx b/app/components/UI/NetworkModal/index.tsx index d62f026fc21..3c58495c9f5 100644 --- a/app/components/UI/NetworkModal/index.tsx +++ b/app/components/UI/NetworkModal/index.tsx @@ -317,12 +317,10 @@ const NetworkModals = (props: NetworkProps) => { }; const switchNetwork = async () => { - const { NetworkController, CurrencyRateController } = Engine.context; + const { NetworkController } = Engine.context; const url = new URLPARSE(rpcUrl); const existingNetwork = networkConfigurationByChainId[chainId]; - CurrencyRateController.updateExchangeRate([ticker]); - if (!isPrivateConnection(url.hostname)) { url.set('protocol', 'https:'); } From 9a5935ecc69eb0835a22cb46b2810849cab10888 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Tue, 12 Nov 2024 17:47:53 -0800 Subject: [PATCH 09/13] bump asset controller, and poll tokens across chains --- app/components/UI/Tokens/index.test.tsx | 4 +- app/components/UI/Tokens/index.tsx | 6 +- .../AssetPolling/AssetPollingProvider.tsx | 2 + .../AssetPolling/useTokenRatesPolling.test.ts | 63 +++++++ .../AssetPolling/useTokenRatesPolling.ts | 33 ++++ app/core/Engine.ts | 10 +- app/selectors/tokenRatesController.ts | 6 + package.json | 2 +- ...@metamask+assets-controllers+42.0.0.patch} | 178 ++---------------- yarn.lock | 8 +- 10 files changed, 137 insertions(+), 175 deletions(-) create mode 100644 app/components/hooks/AssetPolling/useTokenRatesPolling.test.ts create mode 100644 app/components/hooks/AssetPolling/useTokenRatesPolling.ts rename patches/{@metamask+assets-controllers+41.0.0.patch => @metamask+assets-controllers+42.0.0.patch} (89%) diff --git a/app/components/UI/Tokens/index.test.tsx b/app/components/UI/Tokens/index.test.tsx index 401c3c8ed9d..12cef311341 100644 --- a/app/components/UI/Tokens/index.test.tsx +++ b/app/components/UI/Tokens/index.test.tsx @@ -40,7 +40,7 @@ jest.mock('../../../core/Engine', () => ({ updateExchangeRate: jest.fn(() => Promise.resolve()), }, TokenRatesController: { - updateExchangeRates: jest.fn(() => Promise.resolve()), + updateExchangeRatesByChainId: jest.fn(() => Promise.resolve()), }, NetworkController: { getNetworkClientById: () => ({ @@ -359,7 +359,7 @@ describe('Tokens', () => { Engine.context.CurrencyRateController.updateExchangeRate, ).toHaveBeenCalled(); expect( - Engine.context.TokenRatesController.updateExchangeRates, + Engine.context.TokenRatesController.updateExchangeRatesByChainId, ).toHaveBeenCalled(); }); }); diff --git a/app/components/UI/Tokens/index.tsx b/app/components/UI/Tokens/index.tsx index a19a8cbaa92..7248812d461 100644 --- a/app/components/UI/Tokens/index.tsx +++ b/app/components/UI/Tokens/index.tsx @@ -183,7 +183,11 @@ const Tokens: React.FC = ({ tokens }) => { TokenDetectionController.detectTokens(), AccountTrackerController.refresh(), CurrencyRateController.updateExchangeRate(nativeCurrencies), - TokenRatesController.updateExchangeRates(), + ...Object.values(networkConfigurationsByChainId).map((network) => + TokenRatesController.updateExchangeRatesByChainId( + { chainId: network.chainId, nativeCurrency: network.nativeCurrency } + ), + ), ]; await Promise.all(actions).catch((error) => { Logger.error(error, 'Error while refreshing tokens'); diff --git a/app/components/hooks/AssetPolling/AssetPollingProvider.tsx b/app/components/hooks/AssetPolling/AssetPollingProvider.tsx index 7c7c3eda5fa..005d60f02c9 100644 --- a/app/components/hooks/AssetPolling/AssetPollingProvider.tsx +++ b/app/components/hooks/AssetPolling/AssetPollingProvider.tsx @@ -1,11 +1,13 @@ import React, { ReactNode } from 'react'; import useCurrencyRatePolling from './useCurrencyRatePolling'; +import useTokenRatesPolling from './useTokenRatesPolling'; // This provider is a step towards making controller polling fully UI based. // Eventually, individual UI components will call the use*Polling hooks to // poll and return particular data. This polls globally in the meantime. export const AssetPollingProvider = ({ children }: { children: ReactNode }) => { useCurrencyRatePolling(); + useTokenRatesPolling(); return <>{children}; }; diff --git a/app/components/hooks/AssetPolling/useTokenRatesPolling.test.ts b/app/components/hooks/AssetPolling/useTokenRatesPolling.test.ts new file mode 100644 index 00000000000..d4182f16518 --- /dev/null +++ b/app/components/hooks/AssetPolling/useTokenRatesPolling.test.ts @@ -0,0 +1,63 @@ +import useTokenRatesPolling from './useTokenRatesPolling'; +import { renderHookWithProvider } from '../../../util/test/renderWithProvider'; +import Engine from '../../../core/Engine'; + +jest.mock('../../../core/Engine', () => ({ + context: { + TokenRatesController: { + startPolling: jest.fn(), + stopPollingByPollingToken: jest.fn(), + }, + }, +})); + +describe('useTokenRatesPolling', () => { + + beforeEach(() => { + jest.resetAllMocks(); + }); + + const state = { + engine: { + backgroundState: { + TokenRatesController: { + marketData: {}, + }, + NetworkController: { + networkConfigurationsByChainId: { + '0x1': {}, + '0x89': {}, + }, + }, + }, + }, + }; + + it('Should poll by provided chain ids', async () => { + + renderHookWithProvider(() => useTokenRatesPolling({chainIds: ['0x1']}), {state}); + + const mockedTokenRatesController = jest.mocked(Engine.context.TokenRatesController); + + expect(mockedTokenRatesController.startPolling).toHaveBeenCalledTimes(1); + expect( + mockedTokenRatesController.startPolling + ).toHaveBeenCalledWith({chainId: '0x1'}); + + }); + + it('Should poll by all chain ids in network state, if no chain ids are explicitly provided', async () => { + + renderHookWithProvider(() => useTokenRatesPolling(), {state}); + + const mockedTokenRatesController = jest.mocked(Engine.context.TokenRatesController); + + expect(mockedTokenRatesController.startPolling).toHaveBeenCalledTimes(2); + expect( + mockedTokenRatesController.startPolling + ).toHaveBeenCalledWith({chainId: '0x1'}); + expect( + mockedTokenRatesController.startPolling + ).toHaveBeenCalledWith({chainId: '0x89'}); + }); +}); diff --git a/app/components/hooks/AssetPolling/useTokenRatesPolling.ts b/app/components/hooks/AssetPolling/useTokenRatesPolling.ts new file mode 100644 index 00000000000..dfc3240aa4f --- /dev/null +++ b/app/components/hooks/AssetPolling/useTokenRatesPolling.ts @@ -0,0 +1,33 @@ +import { useSelector } from 'react-redux'; +import usePolling from '../usePolling'; +import Engine from '../../../core/Engine'; +import { selectNetworkConfigurations } from '../../../selectors/networkController'; +import { Hex } from '@metamask/utils'; +import { selectContractExchangeRates, selectTokenMarketData } from '../../../selectors/tokenRatesController'; + +const useTokenRatesPolling = ({ chainIds }: { chainIds?: Hex[] } = {}) => { + + // Selectors to determine polling input + const networkConfigurations = useSelector(selectNetworkConfigurations); + + // Selectors returning state updated by the polling + const contractExchangeRates = useSelector(selectContractExchangeRates); + const tokenMarketData = useSelector(selectTokenMarketData); + + const { TokenRatesController } = Engine.context; + + usePolling({ + startPolling: + TokenRatesController.startPolling.bind(TokenRatesController), + stopPollingByPollingToken: + TokenRatesController.stopPollingByPollingToken.bind(TokenRatesController), + input: (chainIds ?? Object.keys(networkConfigurations)).map((chainId) => ({chainId: chainId as Hex})), + }); + + return { + contractExchangeRates, + tokenMarketData + }; +}; + +export default useTokenRatesPolling; diff --git a/app/core/Engine.ts b/app/core/Engine.ts index ed5efca70fb..1f17e36d09e 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -1907,14 +1907,12 @@ export class Engine { TokenDetectionController, TokenListController, TransactionController, - TokenRatesController, } = this.context; TokenListController.start(); TokenDetectionController.start(); // leaving the reference of TransactionController here, rather than importing it from utils to avoid circular dependency TransactionController.startIncomingTransactionPolling(); - TokenRatesController.start(); } configureControllersOnNetworkChange() { @@ -2157,11 +2155,11 @@ export class Engine { // SelectedNetworkController.unsetAllDomains() //Clear assets info - TokensController.reset(); - NftController.reset(); + TokensController.resetState(); + NftController.resetState(); - TokenBalancesController.reset(); - TokenRatesController.reset(); + TokenBalancesController.resetState(); + TokenRatesController.resetState(); // eslint-disable-next-line @typescript-eslint/no-explicit-any (TransactionController as any).update(() => ({ diff --git a/app/selectors/tokenRatesController.ts b/app/selectors/tokenRatesController.ts index e41d78a0dd3..995e5988fd4 100644 --- a/app/selectors/tokenRatesController.ts +++ b/app/selectors/tokenRatesController.ts @@ -14,3 +14,9 @@ export const selectContractExchangeRates = createSelector( (chainId: Hex, tokenRatesControllerState: TokenRatesControllerState) => tokenRatesControllerState.marketData[chainId], ); + +export const selectTokenMarketData = createSelector( + selectTokenRatesControllerState, + (tokenRatesControllerState: TokenRatesControllerState) => + tokenRatesControllerState.marketData, +); diff --git a/package.json b/package.json index 8ac2ebb7606..31538d8217f 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ "@metamask/accounts-controller": "^18.2.1", "@metamask/address-book-controller": "^6.0.1", "@metamask/approval-controller": "^7.1.0", - "@metamask/assets-controllers": "^41.0.0", + "@metamask/assets-controllers": "^42.0.0", "@metamask/base-controller": "^7.0.1", "@metamask/composable-controller": "^3.0.0", "@metamask/contract-metadata": "^2.1.0", diff --git a/patches/@metamask+assets-controllers+41.0.0.patch b/patches/@metamask+assets-controllers+42.0.0.patch similarity index 89% rename from patches/@metamask+assets-controllers+41.0.0.patch rename to patches/@metamask+assets-controllers+42.0.0.patch index 30bedc1ce68..9d224a2b50e 100644 --- a/patches/@metamask+assets-controllers+41.0.0.patch +++ b/patches/@metamask+assets-controllers+42.0.0.patch @@ -610,7 +610,7 @@ index 15a0e56..deeb1eb 100644 _AssetsContractController_provider = new WeakMap(), _AssetsContractController_ipfsGateway = new WeakMap(), _AssetsContractController_chainId = new WeakMap(), _AssetsContractController_instances = new WeakSet(), _AssetsContractController_registerActionHandlers = function _AssetsContractController_registerActionHandlers() { const methodsExcludedFromMessenger = [ diff --git a/node_modules/@metamask/assets-controllers/dist/NftController.cjs b/node_modules/@metamask/assets-controllers/dist/NftController.cjs -index 82613cf..f7fd41e 100644 +index 6ccbe9c..49270d6 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftController.cjs +++ b/node_modules/@metamask/assets-controllers/dist/NftController.cjs @@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function ( @@ -657,27 +657,7 @@ index 82613cf..f7fd41e 100644 __classPrivateFieldSet(this, _NftController_useIpfsSubdomains, useIpfsSubdomains, "f"); __classPrivateFieldSet(this, _NftController_isIpfsGatewayEnabled, isIpfsGatewayEnabled, "f"); __classPrivateFieldSet(this, _NftController_onNftAdded, onNftAdded, "f"); -@@ -97,6 +97,19 @@ class NftController extends base_controller_1.BaseController { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_onSelectedAccountChange).bind(this)); - } -+ -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset() { -+ this.update((state) => { -+ state.allNftContracts = {}; -+ state.allNfts = {}; -+ state.ignoredNfts = []; -+ }); -+ } -+ - getNftApi() { - // TODO: Either fix this lint violation or explain why it's necessary to ignore. - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -@@ -581,7 +594,7 @@ class NftController extends base_controller_1.BaseController { +@@ -589,7 +589,7 @@ class NftController extends base_controller_1.BaseController { } } exports.NftController = NftController; @@ -686,7 +666,7 @@ index 82613cf..f7fd41e 100644 const { configuration: { chainId }, } = this.messagingSystem.call('NetworkController:getNetworkClientById', selectedNetworkClientId); __classPrivateFieldSet(this, _NftController_chainId, chainId, "f"); }, _NftController_onPreferencesControllerStateChange = -@@ -589,16 +602,16 @@ _NftController_mutex = new WeakMap(), _NftController_selectedAccountId = new Wea +@@ -597,16 +597,16 @@ _NftController_mutex = new WeakMap(), _NftController_selectedAccountId = new Wea * Handles the state change of the preference controller. * @param preferencesState - The new state of the preference controller. * @param preferencesState.ipfsGateway - The configured IPFS gateway. @@ -707,7 +687,7 @@ index 82613cf..f7fd41e 100644 if (needsUpdateNftMetadata && selectedAccount) { await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_updateNftUpdateForAccount).call(this, selectedAccount); } -@@ -611,7 +624,7 @@ async function _NftController_onSelectedAccountChange(internalAccount) { +@@ -619,7 +619,7 @@ async function _NftController_onSelectedAccountChange(internalAccount) { const oldSelectedAccountId = __classPrivateFieldGet(this, _NftController_selectedAccountId, "f"); __classPrivateFieldSet(this, _NftController_selectedAccountId, internalAccount.id, "f"); const needsUpdateNftMetadata = ((__classPrivateFieldGet(this, _NftController_isIpfsGatewayEnabled, "f") && __classPrivateFieldGet(this, _NftController_ipfsGateway, "f") !== '') || @@ -716,7 +696,7 @@ index 82613cf..f7fd41e 100644 oldSelectedAccountId !== internalAccount.id; if (needsUpdateNftMetadata) { await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_updateNftUpdateForAccount).call(this, internalAccount); -@@ -686,6 +699,7 @@ async function _NftController_getNftInformationFromApi(contractAddress, tokenId) +@@ -694,6 +694,7 @@ async function _NftController_getNftInformationFromApi(contractAddress, tokenId) description: null, image: null, standard: null, @@ -724,7 +704,7 @@ index 82613cf..f7fd41e 100644 }; } // if we've reached this point, we have successfully fetched some data for nftInformation -@@ -730,7 +744,7 @@ async function _NftController_getNftInformationFromTokenURI(contractAddress, tok +@@ -738,7 +739,7 @@ async function _NftController_getNftInformationFromTokenURI(contractAddress, tok tokenURI: tokenURI ?? null, }; } @@ -733,7 +713,7 @@ index 82613cf..f7fd41e 100644 if (!hasIpfsTokenURI && !isDisplayNFTMediaToggleEnabled) { return { image: null, -@@ -739,6 +753,7 @@ async function _NftController_getNftInformationFromTokenURI(contractAddress, tok +@@ -747,6 +748,7 @@ async function _NftController_getNftInformationFromTokenURI(contractAddress, tok standard: standard || null, favorite: false, tokenURI: tokenURI ?? null, @@ -741,7 +721,7 @@ index 82613cf..f7fd41e 100644 }; } if (hasIpfsTokenURI) { -@@ -777,6 +792,7 @@ async function _NftController_getNftInformationFromTokenURI(contractAddress, tok +@@ -785,6 +787,7 @@ async function _NftController_getNftInformationFromTokenURI(contractAddress, tok standard: standard || null, favorite: false, tokenURI: tokenURI ?? null, @@ -749,7 +729,7 @@ index 82613cf..f7fd41e 100644 }; } }, _NftController_getNftURIAndStandard = -@@ -832,10 +848,21 @@ async function _NftController_getNftInformation(contractAddress, tokenId, networ +@@ -840,10 +843,21 @@ async function _NftController_getNftInformation(contractAddress, tokenId, networ }); const [blockchainMetadata, nftApiMetadata] = await Promise.all([ (0, controller_utils_1.safelyExecute)(() => __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_getNftInformationFromTokenURI).call(this, contractAddress, tokenId, networkClientId)), @@ -772,7 +752,7 @@ index 82613cf..f7fd41e 100644 return { ...nftApiMetadata, name: blockchainMetadata?.name ?? nftApiMetadata?.name ?? null, -@@ -977,6 +1004,7 @@ async function _NftController_addIndividualNft(tokenAddress, tokenId, nftMetadat +@@ -985,6 +999,7 @@ async function _NftController_addIndividualNft(tokenAddress, tokenId, nftMetadat tokenId: tokenId.toString(), standard: nftMetadata.standard, source, @@ -781,7 +761,7 @@ index 82613cf..f7fd41e 100644 } } diff --git a/node_modules/@metamask/assets-controllers/dist/NftController.d.cts b/node_modules/@metamask/assets-controllers/dist/NftController.d.cts -index 6306bb6..7e9bfec 100644 +index a34725f..21e9d20 100644 --- a/node_modules/@metamask/assets-controllers/dist/NftController.d.cts +++ b/node_modules/@metamask/assets-controllers/dist/NftController.d.cts @@ -108,6 +108,7 @@ export type NftMetadata = { @@ -792,21 +772,8 @@ index 6306bb6..7e9bfec 100644 collection?: Collection; address?: string; attributes?: Attributes[]; -@@ -419,6 +420,11 @@ export declare class NftController extends BaseController; - _requestApproval(suggestedNftMeta: SuggestedNftMeta): Promise; -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset(): void; - } - export default NftController; - //# sourceMappingURL=NftController.d.cts.map -\ No newline at end of file diff --git a/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.cjs b/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.cjs -index f7b75d7..bae1292 100644 +index 6f48d64..f9dc513 100644 --- a/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.cjs +++ b/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.cjs @@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function ( @@ -830,26 +797,7 @@ index f7b75d7..bae1292 100644 this.messagingSystem.subscribe('TokensController:stateChange', ({ tokens: newTokens, detectedTokens }) => { __classPrivateFieldSet(this, _TokenBalancesController_tokens, [...newTokens, ...detectedTokens], "f"); // TODO: Either fix this lint violation or explain why it's necessary to ignore. -@@ -73,6 +75,18 @@ class TokenBalancesController extends base_controller_1.BaseController { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.poll(); - } -+ -+ -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset() { -+ this.update((state) => { -+ state.contractBalances = {}; -+ }); -+ } -+ - /** - * Allows controller to update tracked tokens contract balances. - */ -@@ -113,24 +127,31 @@ class TokenBalancesController extends base_controller_1.BaseController { +@@ -113,21 +115,28 @@ class TokenBalancesController extends base_controller_1.BaseController { } const selectedInternalAccount = this.messagingSystem.call('AccountsController:getSelectedAccount'); const newContractBalances = {}; @@ -885,6 +833,10 @@ index f7b75d7..bae1292 100644 }); + __classPrivateFieldSet(this, _TokenBalancesController_updateInProgress, updateInProgress, "f"); } + /** + * Reset the controller state to the default state. +@@ -139,6 +148,6 @@ class TokenBalancesController extends base_controller_1.BaseController { + } } exports.TokenBalancesController = TokenBalancesController; -_TokenBalancesController_handle = new WeakMap(), _TokenBalancesController_interval = new WeakMap(), _TokenBalancesController_tokens = new WeakMap(), _TokenBalancesController_disabled = new WeakMap(); @@ -892,102 +844,6 @@ index f7b75d7..bae1292 100644 exports.default = TokenBalancesController; //# sourceMappingURL=TokenBalancesController.cjs.map \ No newline at end of file -diff --git a/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.d.cts b/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.d.cts -index d252cab..ccc3d82 100644 ---- a/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.d.cts -+++ b/node_modules/@metamask/assets-controllers/dist/TokenBalancesController.d.cts -@@ -77,6 +77,11 @@ export declare class TokenBalancesController extends BaseController; -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset(): void; - } - export default TokenBalancesController; - //# sourceMappingURL=TokenBalancesController.d.cts.map -\ No newline at end of file -diff --git a/node_modules/@metamask/assets-controllers/dist/TokenRatesController.cjs b/node_modules/@metamask/assets-controllers/dist/TokenRatesController.cjs -index beb4f95..6aab19a 100644 ---- a/node_modules/@metamask/assets-controllers/dist/TokenRatesController.cjs -+++ b/node_modules/@metamask/assets-controllers/dist/TokenRatesController.cjs -@@ -117,6 +117,16 @@ class TokenRatesController extends (0, polling_controller_1.StaticIntervalPollin - __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_subscribeToTokensStateChange).call(this); - __classPrivateFieldGet(this, _TokenRatesController_instances, "m", _TokenRatesController_subscribeToNetworkStateChange).call(this); - } -+ -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset() { -+ this.update((state) => { -+ state.marketData = {}; -+ }); -+ } - /** - * Allows controller to make active and passive polling requests - */ -diff --git a/node_modules/@metamask/assets-controllers/dist/TokenRatesController.d.cts b/node_modules/@metamask/assets-controllers/dist/TokenRatesController.d.cts -index a5d6404..0d3d017 100644 ---- a/node_modules/@metamask/assets-controllers/dist/TokenRatesController.d.cts -+++ b/node_modules/@metamask/assets-controllers/dist/TokenRatesController.d.cts -@@ -183,6 +183,11 @@ export declare class TokenRatesController extends TokenRatesController_base; -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset(): void; - } - export default TokenRatesController; - //# sourceMappingURL=TokenRatesController.d.cts.map -\ No newline at end of file -diff --git a/node_modules/@metamask/assets-controllers/dist/TokensController.cjs b/node_modules/@metamask/assets-controllers/dist/TokensController.cjs -index 742de5b..651d1dd 100644 ---- a/node_modules/@metamask/assets-controllers/dist/TokensController.cjs -+++ b/node_modules/@metamask/assets-controllers/dist/TokensController.cjs -@@ -109,6 +109,19 @@ class TokensController extends base_controller_1.BaseController { - } - }); - } -+ -+ /** -+ * THIS FUNCTIONS IS CURRENTLY PATCHED AND STILL NEEDS TO BE IMPLEMENTED ON THE CORE REPO -+ * Resets to the default state -+ */ -+ reset() { -+ this.update((state) => { -+ state.allTokens = {}; -+ state.allIgnoredTokens = {}; -+ state.ignoredTokens = []; -+ state.tokens = []; -+ }); -+ } - /** - * Adds a token to the stored token list. - * -diff --git a/node_modules/@metamask/assets-controllers/dist/TokensController.d.cts b/node_modules/@metamask/assets-controllers/dist/TokensController.d.cts -index 3fbbc66..4f99591 100644 ---- a/node_modules/@metamask/assets-controllers/dist/TokensController.d.cts -+++ b/node_modules/@metamask/assets-controllers/dist/TokensController.d.cts -@@ -160,6 +160,11 @@ export declare class TokensController extends BaseController Date: Tue, 12 Nov 2024 18:02:38 -0800 Subject: [PATCH 10/13] add platform argument to token detection controller --- app/core/Engine.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/core/Engine.ts b/app/core/Engine.ts index 1f17e36d09e..e7ed4c11611 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -1540,6 +1540,8 @@ export class Engine { assetsContractController.getBalancesInSingleCall.bind( assetsContractController, ), + platform: 'mobile', + useAccountsAPI: true, }), new NftDetectionController({ From 4095e64c169229b1464fea71f04032809264a905 Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Thu, 14 Nov 2024 15:14:09 -0800 Subject: [PATCH 11/13] use feature flag --- app/components/UI/Tokens/index.tsx | 6 ++---- .../hooks/AssetPolling/useTokenRatesPolling.ts | 10 ++++++++-- app/util/networks/index.js | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/components/UI/Tokens/index.tsx b/app/components/UI/Tokens/index.tsx index 7248812d461..c87c8b843ce 100644 --- a/app/components/UI/Tokens/index.tsx +++ b/app/components/UI/Tokens/index.tsx @@ -13,7 +13,7 @@ import { selectChainId, selectNetworkConfigurations, } from '../../../selectors/networkController'; -import { getDecimalChainId } from '../../../util/networks'; +import { getDecimalChainId, isPortfolioViewEnabled } from '../../../util/networks'; import { isZero } from '../../../util/lodash'; import createStyles from './styles'; import { TokenList } from './TokenList'; @@ -243,15 +243,13 @@ const Tokens: React.FC = ({ tokens }) => { const onActionSheetPress = (index: number) => index === 0 ? removeToken() : null; - const isTokenFilterEnabled = process.env.PORTFOLIO_VIEW === 'true'; - return ( - {isTokenFilterEnabled ? ( + {isPortfolioViewEnabled ? ( { // Selectors to determine polling input const networkConfigurations = useSelector(selectNetworkConfigurations); + const currentChainId = useSelector(selectChainId); // Selectors returning state updated by the polling const contractExchangeRates = useSelector(selectContractExchangeRates); const tokenMarketData = useSelector(selectTokenMarketData); + const chainIdsToPoll = isPortfolioViewEnabled + ? [currentChainId] + : (chainIds ?? Object.keys(networkConfigurations)); + const { TokenRatesController } = Engine.context; usePolling({ @@ -21,7 +27,7 @@ const useTokenRatesPolling = ({ chainIds }: { chainIds?: Hex[] } = {}) => { TokenRatesController.startPolling.bind(TokenRatesController), stopPollingByPollingToken: TokenRatesController.stopPollingByPollingToken.bind(TokenRatesController), - input: (chainIds ?? Object.keys(networkConfigurations)).map((chainId) => ({chainId: chainId as Hex})), + input: chainIdsToPoll.map((chainId) => ({chainId: chainId as Hex})), }); return { diff --git a/app/util/networks/index.js b/app/util/networks/index.js index 62491502031..b05627467d4 100644 --- a/app/util/networks/index.js +++ b/app/util/networks/index.js @@ -592,3 +592,6 @@ export const isChainPermissionsFeatureEnabled = export const isPermissionsSettingsV1Enabled = process.env.MM_PERMISSIONS_SETTINGS_V1_ENABLED === '1'; + +export const isPortfolioViewEnabled = + process.env.PORTFOLIO_VIEW === 'true'; From df6273fcced16aa3d618e0eb47a128d5b17c52bb Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Fri, 15 Nov 2024 08:23:45 -0800 Subject: [PATCH 12/13] use feature flag in token page refresh --- app/components/UI/Tokens/index.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/app/components/UI/Tokens/index.tsx b/app/components/UI/Tokens/index.tsx index c87c8b843ce..2643d147e25 100644 --- a/app/components/UI/Tokens/index.tsx +++ b/app/components/UI/Tokens/index.tsx @@ -183,11 +183,16 @@ const Tokens: React.FC = ({ tokens }) => { TokenDetectionController.detectTokens(), AccountTrackerController.refresh(), CurrencyRateController.updateExchangeRate(nativeCurrencies), - ...Object.values(networkConfigurationsByChainId).map((network) => - TokenRatesController.updateExchangeRatesByChainId( - { chainId: network.chainId, nativeCurrency: network.nativeCurrency } - ), - ), + ...(isPortfolioViewEnabled + ? Object.values(networkConfigurationsByChainId).map((network) => + TokenRatesController.updateExchangeRatesByChainId( + { + chainId: network.chainId, + nativeCurrency: network.nativeCurrency, + }, + ), + ) : [TokenRatesController.updateExchangeRates()] + ) ]; await Promise.all(actions).catch((error) => { Logger.error(error, 'Error while refreshing tokens'); From eaeb2c73d461bc86bda13b8d2490c5c31e4393ac Mon Sep 17 00:00:00 2001 From: Brian Bergeron Date: Fri, 15 Nov 2024 08:41:57 -0800 Subject: [PATCH 13/13] fix unit test --- app/components/UI/Tokens/index.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/UI/Tokens/index.test.tsx b/app/components/UI/Tokens/index.test.tsx index 12cef311341..401c3c8ed9d 100644 --- a/app/components/UI/Tokens/index.test.tsx +++ b/app/components/UI/Tokens/index.test.tsx @@ -40,7 +40,7 @@ jest.mock('../../../core/Engine', () => ({ updateExchangeRate: jest.fn(() => Promise.resolve()), }, TokenRatesController: { - updateExchangeRatesByChainId: jest.fn(() => Promise.resolve()), + updateExchangeRates: jest.fn(() => Promise.resolve()), }, NetworkController: { getNetworkClientById: () => ({ @@ -359,7 +359,7 @@ describe('Tokens', () => { Engine.context.CurrencyRateController.updateExchangeRate, ).toHaveBeenCalled(); expect( - Engine.context.TokenRatesController.updateExchangeRatesByChainId, + Engine.context.TokenRatesController.updateExchangeRates, ).toHaveBeenCalled(); }); });