From 7abf52fcd27c5eb67e0c3e96ff4eac20dea1835a Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Fri, 16 Feb 2024 01:05:11 -0500 Subject: [PATCH] stash --- .../src/TokenDetectionController.test.ts | 98 +++++---- .../src/TokenDetectionController.ts | 191 ++++++++++-------- 2 files changed, 170 insertions(+), 119 deletions(-) diff --git a/packages/assets-controllers/src/TokenDetectionController.test.ts b/packages/assets-controllers/src/TokenDetectionController.test.ts index 971bd3d49b2..64622793690 100644 --- a/packages/assets-controllers/src/TokenDetectionController.test.ts +++ b/packages/assets-controllers/src/TokenDetectionController.test.ts @@ -13,6 +13,7 @@ import { type NetworkState, type NetworkConfiguration, type NetworkController, + ProviderConfig, } from '@metamask/network-controller'; import { getDefaultPreferencesState, @@ -43,6 +44,7 @@ import { } from './TokenListController'; import type { TokensController, TokensState } from './TokensController'; import { getDefaultTokensState } from './TokensController'; +import { Chain } from '@ethereumjs/common'; const DEFAULT_INTERVAL = 180000; @@ -138,8 +140,11 @@ function buildTokenDetectionControllerMessenger( return controllerMessenger.getRestricted({ name: controllerName, allowedActions: [ + 'AccountsController:getSelectedAccount', 'KeyringController:getState', + 'NetworkController:findNetworkClientIdByChainId', 'NetworkController:getNetworkConfigurationByNetworkClientId', + 'NetworkController:getProviderConfig', 'TokensController:getState', 'TokensController:addDetectedTokens', 'TokenListController:getState', @@ -541,7 +546,7 @@ describe('TokenDetectionController', () => { clock.restore(); }); - describe('when "disabled" is false', () => { + describe('when "disableLegacyInterval" is false', () => { it('should detect new tokens after switching between accounts', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -553,7 +558,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -609,7 +614,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -664,7 +669,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -710,7 +715,7 @@ describe('TokenDetectionController', () => { }); }); - describe('when "disabled" is true', () => { + describe('when "disableLegacyInterval" is true', () => { it('should not detect new tokens after switching between accounts', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -722,7 +727,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: true, + disableLegacyInterval: true, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -777,7 +782,7 @@ describe('TokenDetectionController', () => { clock.restore(); }); - describe('when "disabled" is false', () => { + describe('when "disableLegacyInterval" is false', () => { it('should detect new tokens after switching between accounts', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -789,7 +794,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -847,7 +852,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -904,7 +909,7 @@ describe('TokenDetectionController', () => { ); }); - it('should not detect new tokens after switching between account if token detection is disabled', async () => { + it('should not detect new tokens after switching between account if token detection is disableLegacyInterval', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), }); @@ -915,7 +920,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -963,7 +968,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1015,7 +1020,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -1064,7 +1069,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1114,7 +1119,7 @@ describe('TokenDetectionController', () => { }); }); - describe('when "disabled" is true', () => { + describe('when "disableLegacyInterval" is true', () => { it('should not detect new tokens after switching between accounts', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -1126,7 +1131,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: true, + disableLegacyInterval: true, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress: firstSelectedAddress, @@ -1174,7 +1179,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: true, + disableLegacyInterval: true, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1233,7 +1238,7 @@ describe('TokenDetectionController', () => { clock.restore(); }); - describe('when "disabled" is false', () => { + describe('when "disableLegacyInterval" is false', () => { it('should detect new tokens after switching network client id', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -1242,7 +1247,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1299,7 +1304,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1351,7 +1356,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1399,7 +1404,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1441,7 +1446,7 @@ describe('TokenDetectionController', () => { }); }); - describe('when "disabled" is true', () => { + describe('when "disableLegacyInterval" is true', () => { it('should not detect new tokens after switching network client id', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -1450,7 +1455,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: true, + disableLegacyInterval: true, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1501,7 +1506,7 @@ describe('TokenDetectionController', () => { clock.restore(); }); - describe('when "disabled" is false', () => { + describe('when "disableLegacyInterval" is false', () => { it('should detect tokens if the token list is non-empty', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -1510,7 +1515,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1567,7 +1572,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1603,7 +1608,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1643,7 +1648,7 @@ describe('TokenDetectionController', () => { }); }); - describe('when "disabled" is true', () => { + describe('when "disableLegacyInterval" is true', () => { it('should not detect tokens', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), @@ -1652,7 +1657,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: true, + disableLegacyInterval: true, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1709,7 +1714,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1768,7 +1773,7 @@ describe('TokenDetectionController', () => { }); describe('detectTokens', () => { - it('should not detect tokens if token detection is disabled and current network is not mainnet', async () => { + it('should not detect tokens if token detection is disableLegacyInterval and current network is not mainnet', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue({ [sampleTokenA.address]: new BN(1), }); @@ -1776,7 +1781,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.goerli, selectedAddress, @@ -1802,7 +1807,7 @@ describe('TokenDetectionController', () => { ); }); - it('should detect and add tokens from the `@metamask/contract-metadata` legacy token list if token detection is disabled and current network is mainnet', async () => { + it('should detect and add tokens from the `@metamask/contract-metadata` legacy token list if token detection is disableLegacyInterval and current network is mainnet', async () => { const mockGetBalancesInSingleCall = jest.fn().mockResolvedValue( Object.keys(STATIC_MAINNET_TOKEN_LIST).reduce>( (acc, address) => { @@ -1816,7 +1821,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1840,14 +1845,14 @@ describe('TokenDetectionController', () => { Object.values(STATIC_MAINNET_TOKEN_LIST).map((token) => { const newToken = { ...token, - image: token.iconUrl, - isERC721: false, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any delete (newToken as any).erc20; // eslint-disable-next-line @typescript-eslint/no-explicit-any delete (newToken as any).erc721; delete newToken.iconUrl; + delete newToken.aggregators; + delete newToken.name; return newToken; }), { @@ -1867,7 +1872,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, networkClientId: NetworkType.mainnet, selectedAddress, @@ -1921,7 +1926,7 @@ describe('TokenDetectionController', () => { await withController( { options: { - disabled: false, + disableLegacyInterval: false, getBalancesInSingleCall: mockGetBalancesInSingleCall, trackMetaMetricsEvent: mockTrackMetaMetricsEvent, networkClientId: NetworkType.mainnet, @@ -1987,6 +1992,7 @@ type WithControllerCallback = ({ mockTokensGetState, mockTokenListGetState, mockPreferencesGetState, + mockGetProviderConfig, callActionSpy, triggerKeyringUnlock, triggerKeyringLock, @@ -2003,6 +2009,7 @@ type WithControllerCallback = ({ mockGetNetworkConfigurationByNetworkClientId: ( handler: (networkClientId: string) => NetworkConfiguration, ) => void; + mockGetProviderConfig: (chainId: Hex) => void; callActionSpy: jest.SpyInstance; triggerKeyringUnlock: () => void; triggerKeyringLock: () => void; @@ -2058,6 +2065,13 @@ async function withController( }, ), ); + const mockGetProviderConfig = jest.fn(); + controllerMessenger.registerActionHandler( + 'NetworkController:getProviderConfig', + mockGetProviderConfig.mockReturnValue({ + chainId: '0x1', + } as unknown as ProviderConfig), + ); const mockTokensState = jest.fn(); controllerMessenger.registerActionHandler( 'TokensController:getState', @@ -2108,6 +2122,9 @@ async function withController( mockTokenListGetState: (state: TokenListState) => { mockTokenListState.mockReturnValue(state); }, + mockFindNetworkClientIdByChainId: (chainId: Hex) => { + mockFindNetworkClientIdByChainId.mockReturnValue(); + }, mockGetNetworkConfigurationByNetworkClientId: ( handler: (networkClientId: string) => NetworkConfiguration, ) => { @@ -2115,6 +2132,9 @@ async function withController( handler, ); }, + mockGetProviderConfig: () => { + defaultNetworkState.providerConfig; + }, callActionSpy, triggerKeyringUnlock: () => { controllerMessenger.publish('KeyringController:unlock'); diff --git a/packages/assets-controllers/src/TokenDetectionController.ts b/packages/assets-controllers/src/TokenDetectionController.ts index 04664885776..eedec15e2f8 100644 --- a/packages/assets-controllers/src/TokenDetectionController.ts +++ b/packages/assets-controllers/src/TokenDetectionController.ts @@ -1,15 +1,14 @@ -import type { AccountsControllerSelectedAccountChangeEvent } from '@metamask/accounts-controller'; +import type { + AccountsControllerGetSelectedAccountAction, + AccountsControllerSelectedAccountChangeEvent, +} from '@metamask/accounts-controller'; import type { RestrictedControllerMessenger, ControllerGetStateAction, ControllerStateChangeEvent, } from '@metamask/base-controller'; import contractMap from '@metamask/contract-metadata'; -import { - ChainId, - safelyExecute, - toChecksumHexAddress, -} from '@metamask/controller-utils'; +import { ChainId, safelyExecute } from '@metamask/controller-utils'; import type { KeyringControllerGetStateAction, KeyringControllerLockEvent, @@ -19,6 +18,8 @@ import type { NetworkClientId, NetworkControllerNetworkDidChangeEvent, NetworkControllerGetNetworkConfigurationByNetworkClientId, + NetworkControllerGetProviderConfigAction, + NetworkControllerFindNetworkClientIdByChainIdAction, } from '@metamask/network-controller'; import { StaticIntervalPollingController } from '@metamask/polling-controller'; import type { @@ -43,13 +44,23 @@ import type { const DEFAULT_INTERVAL = 180000; /** - * Finds a case insensitive match in an array of strings - * @param source - An array of strings to search. - * @param target - The target string to search for. - * @returns The first match that is found. + * Compare 2 given strings and return boolean + * eg: "foo" and "FOO" => true + * eg: "foo" and "bar" => false + * eg: "foo" and 123 => false + * + * @param value1 - first string to compare + * @param value2 - first string to compare + * @returns true if 2 strings are identical when they are lowercase */ -function findCaseInsensitiveMatch(source: string[], target: string) { - return source.find((e: string) => e.toLowerCase() === target.toLowerCase()); +export function isEqualCaseInsensitive( + value1: string, + value2: string, +): boolean { + if (typeof value1 !== 'string' || typeof value2 !== 'string') { + return false; + } + return value1.toLowerCase() === value2.toLowerCase(); } type LegacyToken = Omit< @@ -95,7 +106,10 @@ export type TokenDetectionControllerActions = TokenDetectionControllerGetStateAction; export type AllowedActions = + | AccountsControllerGetSelectedAccountAction | NetworkControllerGetNetworkConfigurationByNetworkClientId + | NetworkControllerGetProviderConfigAction + | NetworkControllerFindNetworkClientIdByChainIdAction | GetTokenListState | KeyringControllerGetStateAction | PreferencesControllerGetStateAction @@ -130,7 +144,7 @@ export type TokenDetectionControllerMessenger = RestrictedControllerMessenger< * @property chainId - The chain ID of the current network * @property selectedAddress - Vault selected address * @property networkClientId - The network client ID of the current selected network - * @property disabled - Boolean to track if network requests are blocked + * @property disableLegacyInterval - Boolean to track if network requests are blocked * @property isUnlocked - Boolean to track if the keyring state is unlocked * @property isDetectionEnabledFromPreferences - Boolean to track if detection is enabled from PreferencesController * @property isDetectionEnabledForNetwork - Boolean to track if detected is enabled for current network @@ -148,7 +162,7 @@ export class TokenDetectionController extends StaticIntervalPollingController< #networkClientId: NetworkClientId; - #disabled: boolean; + #disableLegacyInterval: boolean; #isUnlocked: boolean; @@ -173,7 +187,7 @@ export class TokenDetectionController extends StaticIntervalPollingController< * * @param options - The controller options. * @param options.messenger - The controller messaging system. - * @param options.disabled - If set to true, all network requests are blocked. + * @param options.disableLegacyInterval - If set to true, all network requests are blocked. * @param options.interval - Polling interval used to fetch new token rates * @param options.networkClientId - The selected network client ID of the current network * @param options.selectedAddress - Vault selected address @@ -184,7 +198,7 @@ export class TokenDetectionController extends StaticIntervalPollingController< networkClientId, selectedAddress = '', interval = DEFAULT_INTERVAL, - disabled = true, + disableLegacyInterval = true, getBalancesInSingleCall, trackMetaMetricsEvent, messenger, @@ -192,7 +206,7 @@ export class TokenDetectionController extends StaticIntervalPollingController< networkClientId: NetworkClientId; selectedAddress?: string; interval?: number; - disabled?: boolean; + disableLegacyInterval?: boolean; getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall']; trackMetaMetricsEvent: (options: { event: string; @@ -212,12 +226,19 @@ export class TokenDetectionController extends StaticIntervalPollingController< metadata: {}, }); - this.#disabled = disabled; - this.setIntervalLength(interval); + this.#disableLegacyInterval = disableLegacyInterval; + if (!this.#disableLegacyInterval) { + this.setIntervalLength(interval); + } - this.#networkClientId = networkClientId; - this.#selectedAddress = selectedAddress; - this.#chainId = this.#getCorrectChainId(networkClientId); + this.#selectedAddress = + selectedAddress ?? + this.messagingSystem.call('AccountsController:getSelectedAccount') + .address; + const { chainId, networkClientId: newNetworkClientId } = + this.#getCorrectChainIdAndNetworkClientId(networkClientId); + this.#chainId = chainId; + this.#networkClientId = newNetworkClientId; const { useTokenDetection: defaultUseTokenDetection } = this.messagingSystem.call('PreferencesController:getState'); @@ -308,7 +329,8 @@ export class TokenDetectionController extends StaticIntervalPollingController< const isNetworkClientIdChanged = this.#networkClientId !== selectedNetworkClientId; - const newChainId = this.#getCorrectChainId(selectedNetworkClientId); + const { chainId: newChainId } = + this.#getCorrectChainIdAndNetworkClientId(selectedNetworkClientId); this.#isDetectionEnabledForNetwork = isTokenDetectionSupportedForNetwork(newChainId); @@ -326,14 +348,14 @@ export class TokenDetectionController extends StaticIntervalPollingController< * Allows controller to make active and passive polling requests */ enable() { - this.#disabled = false; + this.#disableLegacyInterval = false; } /** * Blocks controller from making network calls */ disable() { - this.#disabled = true; + this.#disableLegacyInterval = true; } /** @@ -342,7 +364,7 @@ export class TokenDetectionController extends StaticIntervalPollingController< * @type {object} */ get isActive() { - return !this.#disabled && this.#isUnlocked; + return !this.#disableLegacyInterval && this.#isUnlocked; } /** @@ -381,13 +403,32 @@ export class TokenDetectionController extends StaticIntervalPollingController< }, this.getIntervalLength()); } - #getCorrectChainId(networkClientId?: NetworkClientId) { - const { chainId } = - this.messagingSystem.call( + #getCorrectChainIdAndNetworkClientId(networkClientId?: NetworkClientId) { + if (networkClientId) { + const networkClient = this.messagingSystem.call( 'NetworkController:getNetworkConfigurationByNetworkClientId', - networkClientId ?? this.#networkClientId, - ) ?? {}; - return chainId ?? this.#chainId; + networkClientId, + ); + if (networkClient) { + this.#networkClientId = networkClientId; + this.#chainId = networkClient.chainId; + return { + chainId: this.#chainId, + networkClientId: this.#networkClientId, + }; + } + } + this.#chainId = this.messagingSystem.call( + 'NetworkController:getProviderConfig', + ).chainId; + this.#networkClientId = this.messagingSystem.call( + 'NetworkController:findNetworkClientIdByChainId', + this.#chainId, + ); + return { + chainId: this.#chainId, + networkClientId: this.#networkClientId, + }; } async _executePoll( @@ -398,8 +439,8 @@ export class TokenDetectionController extends StaticIntervalPollingController< return; } await this.detectTokens({ + ...options, networkClientId, - accountAddress: options.address, }); } @@ -441,20 +482,21 @@ export class TokenDetectionController extends StaticIntervalPollingController< return; } const selectedAddress = accountAddress ?? this.#selectedAddress; - const chainId = this.#getCorrectChainId(networkClientId); + this.#getCorrectChainIdAndNetworkClientId(networkClientId); if ( !this.#isDetectionEnabledFromPreferences && - chainId !== ChainId.mainnet + this.#chainId !== ChainId.mainnet ) { return; } const isTokenDetectionInactiveInMainnet = - !this.#isDetectionEnabledFromPreferences && chainId === ChainId.mainnet; + !this.#isDetectionEnabledFromPreferences && + this.#chainId === ChainId.mainnet; const { tokensChainsCache } = this.messagingSystem.call( 'TokenListController:getState', ); - const tokenList = tokensChainsCache[chainId]?.data || {}; + const tokenList = tokensChainsCache[this.#chainId]?.data ?? {}; const tokenListUsed = isTokenDetectionInactiveInMainnet ? STATIC_MAINNET_TOKEN_LIST @@ -462,20 +504,26 @@ export class TokenDetectionController extends StaticIntervalPollingController< const { allTokens, allDetectedTokens, allIgnoredTokens } = this.messagingSystem.call('TokensController:getState'); - const tokens = allTokens[chainId]?.[selectedAddress] || []; - const detectedTokens = allDetectedTokens[chainId]?.[selectedAddress] || []; - const ignoredTokens = allIgnoredTokens[chainId]?.[selectedAddress] || []; - + const [tokensAddresses, detectedTokensAddresses, ignoredTokensAddreses] = [ + allTokens, + allDetectedTokens, + allIgnoredTokens, + ].map((findAddressList) => + (findAddressList[this.#chainId]?.[selectedAddress] ?? []).map( + (tokenOrAddress) => + typeof tokenOrAddress === 'string' + ? tokenOrAddress + : tokenOrAddress.address, + ), + ); const tokensToDetect: string[] = []; for (const tokenAddress of Object.keys(tokenListUsed)) { if ( - !findCaseInsensitiveMatch( - tokens.map(({ address }) => address), - tokenAddress, - ) && - !findCaseInsensitiveMatch( - detectedTokens.map(({ address }) => address), - tokenAddress, + [tokensAddresses, detectedTokensAddresses, ignoredTokensAddreses].every( + (addressList) => + !addressList.find((address) => + isEqualCaseInsensitive(address, tokenAddress), + ), ) ) { tokensToDetect.push(tokenAddress); @@ -502,40 +550,23 @@ export class TokenDetectionController extends StaticIntervalPollingController< const balances = await this.#getBalancesInSingleCall( selectedAddress, tokensSlice, + this.#networkClientId, ); - const tokensToAdd: Token[] = []; + + const tokensWithBalance: Token[] = []; const eventTokensDetails: string[] = []; - let ignored; - for (const tokenAddress of Object.keys(balances)) { - if (ignoredTokens.length) { - ignored = ignoredTokens.find( - (ignoredTokenAddress) => - ignoredTokenAddress === toChecksumHexAddress(tokenAddress), - ); - } - const caseInsensitiveTokenKey = - findCaseInsensitiveMatch( - Object.keys(tokenListUsed), - tokenAddress, - ) ?? ''; - - if (ignored === undefined) { - const { decimals, symbol, aggregators, iconUrl, name } = - tokenListUsed[caseInsensitiveTokenKey]; - eventTokensDetails.push(`${symbol} - ${tokenAddress}`); - tokensToAdd.push({ - address: tokenAddress, - decimals, - symbol, - aggregators, - image: iconUrl, - isERC721: false, - name, - }); - } + for (const nonZeroTokenAddress of Object.keys(balances)) { + const { address, symbol, decimals } = + tokenListUsed[nonZeroTokenAddress]; + eventTokensDetails.push(`${symbol} - ${nonZeroTokenAddress}`); + tokensWithBalance.push({ + address, + symbol, + decimals, + }); } - if (tokensToAdd.length) { + if (tokensWithBalance.length) { this.#trackMetaMetricsEvent({ event: 'Token Detected', category: 'Wallet', @@ -547,10 +578,10 @@ export class TokenDetectionController extends StaticIntervalPollingController< }); await this.messagingSystem.call( 'TokensController:addDetectedTokens', - tokensToAdd, + tokensWithBalance, { selectedAddress, - chainId, + chainId: this.#chainId, }, ); }