@metamask-previews/assets-controllers 94.1.0-preview-a9886279 → 95.0.0-preview-cb897e9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +19 -3
  2. package/dist/AccountTrackerController.cjs +4 -0
  3. package/dist/AccountTrackerController.cjs.map +1 -1
  4. package/dist/AccountTrackerController.d.cts.map +1 -1
  5. package/dist/AccountTrackerController.d.mts.map +1 -1
  6. package/dist/AccountTrackerController.mjs +4 -0
  7. package/dist/AccountTrackerController.mjs.map +1 -1
  8. package/dist/TokenDetectionController.cjs +3 -6
  9. package/dist/TokenDetectionController.cjs.map +1 -1
  10. package/dist/TokenDetectionController.d.cts.map +1 -1
  11. package/dist/TokenDetectionController.d.mts.map +1 -1
  12. package/dist/TokenDetectionController.mjs +3 -6
  13. package/dist/TokenDetectionController.mjs.map +1 -1
  14. package/dist/TokenListController.cjs +3 -2
  15. package/dist/TokenListController.cjs.map +1 -1
  16. package/dist/TokenListController.d.cts +2 -12
  17. package/dist/TokenListController.d.cts.map +1 -1
  18. package/dist/TokenListController.d.mts +2 -12
  19. package/dist/TokenListController.d.mts.map +1 -1
  20. package/dist/TokenListController.mjs +3 -2
  21. package/dist/TokenListController.mjs.map +1 -1
  22. package/dist/TokenRatesController.cjs.map +1 -1
  23. package/dist/TokenRatesController.d.cts +0 -12
  24. package/dist/TokenRatesController.d.cts.map +1 -1
  25. package/dist/TokenRatesController.d.mts +0 -12
  26. package/dist/TokenRatesController.d.mts.map +1 -1
  27. package/dist/TokenRatesController.mjs.map +1 -1
  28. package/dist/TokensController.cjs +2 -5
  29. package/dist/TokensController.cjs.map +1 -1
  30. package/dist/TokensController.d.cts +0 -12
  31. package/dist/TokensController.d.cts.map +1 -1
  32. package/dist/TokensController.d.mts +0 -12
  33. package/dist/TokensController.d.mts.map +1 -1
  34. package/dist/TokensController.mjs +2 -5
  35. package/dist/TokensController.mjs.map +1 -1
  36. package/dist/selectors/token-selectors.cjs.map +1 -1
  37. package/dist/selectors/token-selectors.d.cts +0 -2
  38. package/dist/selectors/token-selectors.d.cts.map +1 -1
  39. package/dist/selectors/token-selectors.d.mts +0 -2
  40. package/dist/selectors/token-selectors.d.mts.map +1 -1
  41. package/dist/selectors/token-selectors.mjs.map +1 -1
  42. package/dist/token-prices-service/codefi-v2.cjs +1 -1
  43. package/dist/token-prices-service/codefi-v2.cjs.map +1 -1
  44. package/dist/token-prices-service/codefi-v2.d.cts +1 -1
  45. package/dist/token-prices-service/codefi-v2.d.mts +1 -1
  46. package/dist/token-prices-service/codefi-v2.mjs +1 -1
  47. package/dist/token-prices-service/codefi-v2.mjs.map +1 -1
  48. package/dist/token-service.cjs +32 -21
  49. package/dist/token-service.cjs.map +1 -1
  50. package/dist/token-service.d.cts +9 -5
  51. package/dist/token-service.d.cts.map +1 -1
  52. package/dist/token-service.d.mts +9 -5
  53. package/dist/token-service.d.mts.map +1 -1
  54. package/dist/token-service.mjs +32 -21
  55. package/dist/token-service.mjs.map +1 -1
  56. package/package.json +4 -4
@@ -234,7 +234,7 @@ export class TokenDetectionController extends StaticIntervalPollingController()
234
234
  console.warn(`Token metadata not found in cache for ${tokenAddress} on chain ${chainId}`);
235
235
  continue;
236
236
  }
237
- const { decimals, symbol, aggregators, iconUrl, name, rwaData } = tokenData;
237
+ const { decimals, symbol, aggregators, iconUrl, name } = tokenData;
238
238
  // Push to lists with checksummed address (for allTokens storage)
239
239
  eventTokensDetails.push(`${symbol} - ${checksummedTokenAddress}`);
240
240
  tokensWithBalance.push({
@@ -245,7 +245,6 @@ export class TokenDetectionController extends StaticIntervalPollingController()
245
245
  image: iconUrl,
246
246
  isERC721: false,
247
247
  name,
248
- ...(rwaData && { rwaData }),
249
248
  });
250
249
  }
251
250
  // Perform addition
@@ -314,7 +313,7 @@ export class TokenDetectionController extends StaticIntervalPollingController()
314
313
  console.warn(`Token metadata not found in cache for ${tokenAddress} on chain ${chainId}`);
315
314
  continue;
316
315
  }
317
- const { decimals, symbol, aggregators, iconUrl, name, rwaData } = tokenData;
316
+ const { decimals, symbol, aggregators, iconUrl, name } = tokenData;
318
317
  eventTokensDetails.push(`${symbol} - ${checksummedTokenAddress}`);
319
318
  tokensWithBalance.push({
320
319
  address: checksummedTokenAddress,
@@ -324,7 +323,6 @@ export class TokenDetectionController extends StaticIntervalPollingController()
324
323
  image: iconUrl,
325
324
  isERC721: false,
326
325
  name,
327
- ...(rwaData && { rwaData }),
328
326
  });
329
327
  }
330
328
  // Perform addition
@@ -533,7 +531,7 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
533
531
  const tokensWithBalance = [];
534
532
  const eventTokensDetails = [];
535
533
  for (const nonZeroTokenAddress of Object.keys(balances)) {
536
- const { decimals, symbol, aggregators, iconUrl, name, rwaData } = __classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId].data[nonZeroTokenAddress];
534
+ const { decimals, symbol, aggregators, iconUrl, name } = __classPrivateFieldGet(this, _TokenDetectionController_tokensChainsCache, "f")[chainId].data[nonZeroTokenAddress];
537
535
  eventTokensDetails.push(`${symbol} - ${nonZeroTokenAddress}`);
538
536
  tokensWithBalance.push({
539
537
  address: nonZeroTokenAddress,
@@ -543,7 +541,6 @@ async function _TokenDetectionController_restartTokenDetection({ selectedAddress
543
541
  image: iconUrl,
544
542
  isERC721: false,
545
543
  name,
546
- ...(rwaData && { rwaData }),
547
544
  });
548
545
  }
549
546
  if (tokensWithBalance.length) {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDetectionController.mjs","sourceRoot":"","sources":["../src/TokenDetectionController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerGetAccountAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport contractMap from '@metamask/contract-metadata';\nimport {\n ASSET_TYPES,\n ChainId,\n ERC20,\n safelyExecute,\n isEqualCaseInsensitive,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkClientId,\n NetworkControllerFindNetworkClientIdByChainIdAction,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetNetworkConfigurationByNetworkClientId,\n NetworkControllerGetStateAction,\n NetworkControllerNetworkDidChangeEvent,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type {\n PreferencesControllerGetStateAction,\n PreferencesControllerStateChangeEvent,\n} from '@metamask/preferences-controller';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { isEqual, mapValues, isObject, get } from 'lodash';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport { isTokenDetectionSupportedForNetwork } from './assetsUtil';\nimport { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from './constants';\nimport type {\n GetTokenListState,\n TokenListMap,\n TokenListStateChange,\n TokensChainsCache,\n} from './TokenListController';\nimport type { Token } from './TokenRatesController';\nimport type {\n TokensControllerAddDetectedTokensAction,\n TokensControllerAddTokensAction,\n TokensControllerGetStateAction,\n} from './TokensController';\n\nconst DEFAULT_INTERVAL = 180000;\n\ntype LegacyToken = {\n name: string;\n logo: `${string}.svg`;\n symbol: string;\n decimals: number;\n erc20?: boolean;\n erc721?: boolean;\n};\n\ntype TokenDetectionMap = {\n [P in keyof TokenListMap]: Omit<TokenListMap[P], 'occurrences'>;\n};\n\ntype NetworkClient = {\n chainId: Hex;\n networkClientId: string;\n};\n\nexport const STATIC_MAINNET_TOKEN_LIST = Object.entries<LegacyToken>(\n contractMap,\n).reduce<TokenDetectionMap>((acc, [base, contract]) => {\n const { logo, erc20, erc721, ...tokenMetadata } = contract;\n return {\n ...acc,\n [base.toLowerCase()]: {\n ...tokenMetadata,\n address: base.toLowerCase(),\n iconUrl: `images/contract/${logo}`,\n aggregators: [],\n },\n };\n}, {});\n\n/**\n * Function that takes a TokensChainsCache object and maps chainId with TokenListMap.\n *\n * @param tokensChainsCache - TokensChainsCache input object\n * @returns returns the map of chainId with TokenListMap\n */\nexport function mapChainIdWithTokenListMap(\n tokensChainsCache: TokensChainsCache,\n): Record<string, unknown> {\n return mapValues(tokensChainsCache, (value) => {\n if (isObject(value) && 'data' in value) {\n return get(value, ['data']);\n }\n return value;\n });\n}\n\nexport const controllerName = 'TokenDetectionController';\n\nexport type TokenDetectionState = Record<never, never>;\n\nexport type TokenDetectionControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenDetectionState\n>;\n\nexport type TokenDetectionControllerAddDetectedTokensViaWsAction = {\n type: `TokenDetectionController:addDetectedTokensViaWs`;\n handler: TokenDetectionController['addDetectedTokensViaWs'];\n};\n\nexport type TokenDetectionControllerAddDetectedTokensViaPollingAction = {\n type: `TokenDetectionController:addDetectedTokensViaPolling`;\n handler: TokenDetectionController['addDetectedTokensViaPolling'];\n};\n\nexport type TokenDetectionControllerDetectTokensAction = {\n type: `TokenDetectionController:detectTokens`;\n handler: TokenDetectionController['detectTokens'];\n};\n\nexport type TokenDetectionControllerActions =\n | TokenDetectionControllerGetStateAction\n | TokenDetectionControllerAddDetectedTokensViaWsAction\n | TokenDetectionControllerAddDetectedTokensViaPollingAction\n | TokenDetectionControllerDetectTokensAction;\n\nexport type AllowedActions =\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerGetAccountAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetNetworkConfigurationByNetworkClientId\n | NetworkControllerGetStateAction\n | GetTokenListState\n | KeyringControllerGetStateAction\n | PreferencesControllerGetStateAction\n | TokensControllerGetStateAction\n | TokensControllerAddDetectedTokensAction\n | TokensControllerAddTokensAction\n | NetworkControllerFindNetworkClientIdByChainIdAction\n | AuthenticationController.AuthenticationControllerGetBearerToken;\n\nexport type TokenDetectionControllerStateChangeEvent =\n ControllerStateChangeEvent<typeof controllerName, TokenDetectionState>;\n\nexport type TokenDetectionControllerEvents =\n TokenDetectionControllerStateChangeEvent;\n\nexport type AllowedEvents =\n | AccountsControllerSelectedEvmAccountChangeEvent\n | NetworkControllerNetworkDidChangeEvent\n | TokenListStateChange\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | PreferencesControllerStateChangeEvent\n | TransactionControllerTransactionConfirmedEvent;\n\nexport type TokenDetectionControllerMessenger = Messenger<\n typeof controllerName,\n TokenDetectionControllerActions | AllowedActions,\n TokenDetectionControllerEvents | AllowedEvents\n>;\n\n/** The input to start polling for the {@link TokenDetectionController} */\ntype TokenDetectionPollingInput = {\n chainIds: Hex[];\n address: string;\n};\n\n/**\n * Controller that passively polls on a set interval for Tokens auto detection\n *\n * intervalId - Polling interval used to fetch new token rates\n *\n * selectedAddress - Vault selected address\n *\n * networkClientId - The network client ID of the current selected network\n *\n * disabled - Boolean to track if network requests are blocked\n *\n * isUnlocked - Boolean to track if the keyring state is unlocked\n *\n * isDetectionEnabledFromPreferences - Boolean to track if detection is enabled from PreferencesController\n *\n */\nexport class TokenDetectionController extends StaticIntervalPollingController<TokenDetectionPollingInput>()<\n typeof controllerName,\n TokenDetectionState,\n TokenDetectionControllerMessenger\n> {\n #intervalId?: ReturnType<typeof setTimeout>;\n\n #selectedAccountId: string;\n\n #tokensChainsCache: TokensChainsCache = {};\n\n #disabled: boolean;\n\n #isUnlocked: boolean;\n\n #isDetectionEnabledFromPreferences: boolean;\n\n readonly #useTokenDetection: () => boolean;\n\n readonly #useExternalServices: () => boolean;\n\n readonly #getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n\n readonly #trackMetaMetricsEvent: (options: {\n event: string;\n category: string;\n properties: {\n tokens: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n token_standard: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n asset_type: string;\n };\n }) => void;\n\n /**\n * Creates a TokenDetectionController instance.\n *\n * @param options - The controller options.\n * @param options.messenger - The controller messenger.\n * @param options.disabled - If set to true, all network requests are blocked.\n * @param options.interval - Polling interval used to fetch new token rates\n * @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.\n * @param options.trackMetaMetricsEvent - Sets options for MetaMetrics event tracking.\n * @param options.useTokenDetection - Feature Switch for using token detection (default: true)\n * @param options.useExternalServices - Feature Switch for using external services (default: false)\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n disabled = true,\n getBalancesInSingleCall,\n trackMetaMetricsEvent,\n messenger,\n useTokenDetection = (): boolean => true,\n useExternalServices = (): boolean => true,\n }: {\n interval?: number;\n disabled?: boolean;\n getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n trackMetaMetricsEvent: (options: {\n event: string;\n category: string;\n properties: {\n tokens: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n token_standard: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n asset_type: string;\n };\n }) => void;\n messenger: TokenDetectionControllerMessenger;\n useTokenDetection?: () => boolean;\n useExternalServices?: () => boolean;\n }) {\n super({\n name: controllerName,\n messenger,\n state: {},\n metadata: {},\n });\n\n this.messenger.registerActionHandler(\n `${controllerName}:addDetectedTokensViaWs` as const,\n this.addDetectedTokensViaWs.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:addDetectedTokensViaPolling` as const,\n this.addDetectedTokensViaPolling.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:detectTokens` as const,\n this.detectTokens.bind(this),\n );\n\n this.#disabled = disabled;\n this.setIntervalLength(interval);\n\n this.#selectedAccountId = this.#getSelectedAccount().id;\n\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n\n this.#tokensChainsCache = tokensChainsCache;\n\n const { useTokenDetection: defaultUseTokenDetection } = this.messenger.call(\n 'PreferencesController:getState',\n );\n this.#isDetectionEnabledFromPreferences = defaultUseTokenDetection;\n\n this.#getBalancesInSingleCall = getBalancesInSingleCall;\n\n this.#trackMetaMetricsEvent = trackMetaMetricsEvent;\n\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n this.#isUnlocked = isUnlocked;\n\n this.#useTokenDetection = useTokenDetection;\n this.#useExternalServices = useExternalServices;\n\n this.#registerEventListeners();\n }\n\n /**\n * Constructor helper for registering this controller's messenger subscriptions to controller events.\n */\n #registerEventListeners(): void {\n this.messenger.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n this.#restartTokenDetection().catch(() => {\n // Silently handle token detection errors\n });\n });\n\n this.messenger.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n this.#stopPolling();\n });\n\n this.messenger.subscribe(\n 'TokenListController:stateChange',\n ({ tokensChainsCache }) => {\n const isEqualValues = this.#compareTokensChainsCache(\n tokensChainsCache,\n this.#tokensChainsCache,\n );\n if (!isEqualValues) {\n this.#restartTokenDetection().catch(() => {\n // Silently handle token detection errors\n });\n }\n },\n );\n\n this.messenger.subscribe(\n 'PreferencesController:stateChange',\n ({ useTokenDetection }) => {\n const selectedAccount = this.#getSelectedAccount();\n const isDetectionChangedFromPreferences =\n this.#isDetectionEnabledFromPreferences !== useTokenDetection;\n\n this.#isDetectionEnabledFromPreferences = useTokenDetection;\n\n if (isDetectionChangedFromPreferences) {\n this.#restartTokenDetection({\n selectedAddress: selectedAccount.address,\n }).catch(() => {\n // Silently handle token detection errors\n });\n }\n },\n );\n\n this.messenger.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n (selectedAccount) => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n\n const chainIds = Object.keys(networkConfigurationsByChainId) as Hex[];\n const isSelectedAccountIdChanged =\n this.#selectedAccountId !== selectedAccount.id;\n if (isSelectedAccountIdChanged) {\n this.#selectedAccountId = selectedAccount.id;\n this.#restartTokenDetection({\n selectedAddress: selectedAccount.address,\n chainIds,\n }).catch(() => {\n // Silently handle token detection errors\n });\n }\n },\n );\n\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n (transactionMeta) => {\n this.detectTokens({\n chainIds: [transactionMeta.chainId],\n }).catch(() => {\n // Silently handle token detection errors\n });\n },\n );\n }\n\n /**\n * Allows controller to make active and passive polling requests\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from making network calls\n */\n disable(): void {\n this.#disabled = true;\n }\n\n /**\n * Internal isActive state\n *\n * @returns Whether the controller is active (not disabled and keyring is unlocked)\n */\n get isActive(): boolean {\n return !this.#disabled && this.#isUnlocked;\n }\n\n /**\n * Start polling for detected tokens.\n */\n async start(): Promise<void> {\n this.enable();\n await this.#startPolling();\n }\n\n /**\n * Stop polling for detected tokens.\n */\n stop(): void {\n this.disable();\n this.#stopPolling();\n }\n\n #stopPolling(): void {\n if (this.#intervalId) {\n clearInterval(this.#intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n async #startPolling(): Promise<void> {\n if (!this.isActive) {\n return;\n }\n this.#stopPolling();\n await this.detectTokens();\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#intervalId = setInterval(async () => {\n await this.detectTokens();\n }, this.getIntervalLength());\n }\n\n /**\n * Compares current and previous tokensChainsCache object focusing only on the data object.\n *\n * @param tokensChainsCache - current tokensChainsCache input object\n * @param previousTokensChainsCache - previous tokensChainsCache input object\n * @returns boolean indicating if the two objects are equal\n */\n\n #compareTokensChainsCache(\n tokensChainsCache: TokensChainsCache,\n previousTokensChainsCache: TokensChainsCache,\n ): boolean {\n const cleanPreviousTokensChainsCache = mapChainIdWithTokenListMap(\n previousTokensChainsCache,\n );\n const cleanTokensChainsCache =\n mapChainIdWithTokenListMap(tokensChainsCache);\n const isEqualValues = isEqual(\n cleanTokensChainsCache,\n cleanPreviousTokensChainsCache,\n );\n return isEqualValues;\n }\n\n #getCorrectNetworkClientIdByChainId(\n chainIds: Hex[] | undefined,\n ): { chainId: Hex; networkClientId: NetworkClientId }[] {\n const { networkConfigurationsByChainId, selectedNetworkClientId } =\n this.messenger.call('NetworkController:getState');\n\n if (!chainIds) {\n const networkConfiguration = this.messenger.call(\n 'NetworkController:getNetworkConfigurationByNetworkClientId',\n selectedNetworkClientId,\n );\n\n return [\n {\n chainId: networkConfiguration?.chainId ?? ChainId.mainnet,\n networkClientId: selectedNetworkClientId,\n },\n ];\n }\n\n return chainIds.map((chainId) => {\n const configuration = networkConfigurationsByChainId[chainId];\n return {\n chainId,\n networkClientId:\n configuration.rpcEndpoints[configuration.defaultRpcEndpointIndex]\n .networkClientId,\n };\n });\n }\n\n async _executePoll({\n chainIds,\n address,\n }: TokenDetectionPollingInput): Promise<void> {\n if (!this.isActive) {\n return;\n }\n await this.detectTokens({\n chainIds,\n selectedAddress: address,\n });\n }\n\n /**\n * Restart token detection polling period and call detectNewTokens\n * in case of address change or user session initialization.\n *\n * @param options - Options for restart token detection.\n * @param options.selectedAddress - the selectedAddress against which to detect for token balances\n * @param options.chainIds - The chain IDs of the network client to use.\n */\n async #restartTokenDetection({\n selectedAddress,\n chainIds,\n }: {\n selectedAddress?: string;\n chainIds?: Hex[];\n } = {}): Promise<void> {\n await this.detectTokens({\n chainIds,\n selectedAddress,\n });\n this.setIntervalLength(DEFAULT_INTERVAL);\n }\n\n #shouldDetectTokens(chainId: Hex): boolean {\n if (!isTokenDetectionSupportedForNetwork(chainId)) {\n return false;\n }\n if (\n !this.#isDetectionEnabledFromPreferences &&\n chainId !== ChainId.mainnet\n ) {\n return false;\n }\n\n const isMainnetDetectionInactive =\n !this.#isDetectionEnabledFromPreferences && chainId === ChainId.mainnet;\n if (isMainnetDetectionInactive) {\n this.#tokensChainsCache = this.#getConvertedStaticMainnetTokenList();\n } else {\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n this.#tokensChainsCache = tokensChainsCache ?? {};\n }\n\n return true;\n }\n\n async #detectTokensUsingRpc(\n chainsToDetectUsingRpc: NetworkClient[],\n addressToDetect: string,\n ): Promise<void> {\n for (const { chainId, networkClientId } of chainsToDetectUsingRpc) {\n if (!this.#shouldDetectTokens(chainId)) {\n continue;\n }\n\n const tokenCandidateSlices = this.#getSlicesOfTokensToDetect({\n chainId,\n selectedAddress: addressToDetect,\n });\n const tokenDetectionPromises = tokenCandidateSlices.map((tokensSlice) =>\n this.#addDetectedTokens({\n tokensSlice,\n selectedAddress: addressToDetect,\n networkClientId,\n chainId,\n }),\n );\n\n await Promise.all(tokenDetectionPromises);\n }\n }\n\n /**\n * For each token in the token list provided by the TokenListController, checks the token's balance for the selected account address on the active network.\n * On mainnet, if token detection is disabled in preferences, ERC20 token auto detection will be triggered for each contract address in the legacy token list from the @metamask/contract-metadata repo.\n *\n * @param options - Options for token detection.\n * @param options.chainIds - The chain IDs of the network client to use.\n * @param options.selectedAddress - the selectedAddress against which to detect for token balances.\n * @param options.forceRpc - Force RPC-based token detection for all specified chains,\n * bypassing external services check and ensuring RPC is used even for chains\n * that might otherwise be handled by the Accounts API.\n */\n async detectTokens({\n chainIds,\n selectedAddress,\n forceRpc = false,\n }: {\n chainIds?: Hex[];\n selectedAddress?: string;\n forceRpc?: boolean;\n } = {}): Promise<void> {\n if (!this.isActive) {\n return;\n }\n\n // When forceRpc is true, bypass the useTokenDetection check to ensure RPC detection runs\n if (!forceRpc && !this.#useTokenDetection()) {\n return;\n }\n\n // If external services are disabled and not forcing RPC, skip all detection\n if (!forceRpc && !this.#useExternalServices()) {\n return;\n }\n\n const addressToDetect = selectedAddress ?? this.#getSelectedAddress();\n const clientNetworks = this.#getCorrectNetworkClientIdByChainId(chainIds);\n\n // If forceRpc is true, use RPC for all chains\n // Otherwise, skip chains supported by Accounts API (they are handled by TokenBalancesController)\n const chainsToDetectUsingRpc = forceRpc\n ? clientNetworks\n : clientNetworks.filter(\n ({ chainId }) =>\n !SUPPORTED_NETWORKS_ACCOUNTS_API_V4.includes(chainId),\n );\n\n if (chainsToDetectUsingRpc.length === 0) {\n return;\n }\n\n await this.#detectTokensUsingRpc(chainsToDetectUsingRpc, addressToDetect);\n }\n\n #getSlicesOfTokensToDetect({\n chainId,\n selectedAddress,\n }: {\n chainId: Hex;\n selectedAddress: string;\n }): string[][] {\n const { allTokens, allDetectedTokens, allIgnoredTokens } =\n this.messenger.call('TokensController:getState');\n const [tokensAddresses, detectedTokensAddresses, ignoredTokensAddresses] = [\n allTokens,\n allDetectedTokens,\n allIgnoredTokens,\n ].map((tokens) =>\n (tokens[chainId]?.[selectedAddress] ?? []).map((value) =>\n typeof value === 'string' ? value : value.address,\n ),\n );\n\n const tokensToDetect: string[] = [];\n for (const tokenAddress of Object.keys(\n this.#tokensChainsCache?.[chainId]?.data || {},\n )) {\n if (\n [\n tokensAddresses,\n detectedTokensAddresses,\n ignoredTokensAddresses,\n ].every(\n (addresses) =>\n !addresses.find((address) =>\n isEqualCaseInsensitive(address, tokenAddress),\n ),\n )\n ) {\n tokensToDetect.push(tokenAddress);\n }\n }\n\n const slicesOfTokensToDetect = [];\n for (let i = 0, size = 1000; i < tokensToDetect.length; i += size) {\n slicesOfTokensToDetect.push(tokensToDetect.slice(i, i + size));\n }\n\n return slicesOfTokensToDetect;\n }\n\n #getConvertedStaticMainnetTokenList(): TokensChainsCache {\n const data: TokenListMap = Object.entries(STATIC_MAINNET_TOKEN_LIST).reduce(\n (acc, [key, value]) => ({\n ...acc,\n [key]: {\n name: value.name,\n symbol: value.symbol,\n decimals: value.decimals,\n address: value.address,\n aggregators: [],\n iconUrl: value?.iconUrl,\n },\n }),\n {},\n );\n return {\n '0x1': {\n data,\n timestamp: 0,\n },\n };\n }\n\n async #addDetectedTokens({\n tokensSlice,\n selectedAddress,\n networkClientId,\n chainId,\n }: {\n tokensSlice: string[];\n selectedAddress: string;\n networkClientId: NetworkClientId;\n chainId: Hex;\n }): Promise<void> {\n await safelyExecute(async () => {\n const balances = await this.#getBalancesInSingleCall(\n selectedAddress,\n tokensSlice,\n networkClientId,\n );\n\n const tokensWithBalance: Token[] = [];\n const eventTokensDetails: string[] = [];\n for (const nonZeroTokenAddress of Object.keys(balances)) {\n const { decimals, symbol, aggregators, iconUrl, name, rwaData } =\n this.#tokensChainsCache[chainId].data[nonZeroTokenAddress];\n eventTokensDetails.push(`${symbol} - ${nonZeroTokenAddress}`);\n tokensWithBalance.push({\n address: nonZeroTokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n ...(rwaData && { rwaData }),\n });\n }\n\n if (tokensWithBalance.length) {\n this.#trackMetaMetricsEvent({\n event: 'Token Detected',\n category: 'Wallet',\n properties: {\n tokens: eventTokensDetails,\n token_standard: ERC20,\n asset_type: ASSET_TYPES.TOKEN,\n },\n });\n\n await this.messenger.call(\n 'TokensController:addTokens',\n tokensWithBalance,\n networkClientId,\n );\n }\n });\n }\n\n /**\n * Add tokens detected from websocket balance updates\n * This method:\n * - Checks if useTokenDetection preference is enabled (skips if disabled)\n * - Checks if external services are enabled (skips if disabled)\n * - Tokens are expected to be in the tokensChainsCache with full metadata\n * - Balance fetching is skipped since balances are provided by the websocket\n * - Ignored tokens have been filtered out by the caller\n *\n * @param options - The options object\n * @param options.tokensSlice - Array of token addresses detected from websocket (already filtered to exclude ignored tokens)\n * @param options.chainId - Hex chain ID\n * @returns Promise that resolves when tokens are added\n */\n async addDetectedTokensViaWs({\n tokensSlice,\n chainId,\n }: {\n tokensSlice: string[];\n chainId: Hex;\n }): Promise<void> {\n // Check if token detection is enabled via preferences\n if (!this.#useTokenDetection()) {\n return;\n }\n\n // Check if external services are enabled (websocket requires external services)\n if (!this.#useExternalServices()) {\n return;\n }\n\n // Refresh the token cache to ensure we have the latest token metadata\n // This fixes a bug where the cache from construction time could be stale/empty\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n this.#tokensChainsCache = tokensChainsCache ?? {};\n\n const tokensWithBalance: Token[] = [];\n const eventTokensDetails: string[] = [];\n\n for (const tokenAddress of tokensSlice) {\n // Normalize addresses explicitly (don't assume input format)\n const lowercaseTokenAddress = tokenAddress.toLowerCase();\n const checksummedTokenAddress = toChecksumHexAddress(tokenAddress);\n\n // Check map of validated tokens (cache keys are lowercase)\n const tokenData =\n this.#tokensChainsCache[chainId]?.data?.[lowercaseTokenAddress];\n\n if (!tokenData) {\n console.warn(\n `Token metadata not found in cache for ${tokenAddress} on chain ${chainId}`,\n );\n continue;\n }\n\n const { decimals, symbol, aggregators, iconUrl, name, rwaData } =\n tokenData;\n\n // Push to lists with checksummed address (for allTokens storage)\n eventTokensDetails.push(`${symbol} - ${checksummedTokenAddress}`);\n tokensWithBalance.push({\n address: checksummedTokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n ...(rwaData && { rwaData }),\n });\n }\n\n // Perform addition\n if (tokensWithBalance.length) {\n this.#trackMetaMetricsEvent({\n event: 'Token Detected',\n category: 'Wallet',\n properties: {\n tokens: eventTokensDetails,\n token_standard: ERC20,\n asset_type: ASSET_TYPES.TOKEN,\n },\n });\n\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n await this.messenger.call(\n 'TokensController:addTokens',\n tokensWithBalance,\n networkClientId,\n );\n }\n }\n\n /**\n * Add tokens detected from polling balance updates\n * This method:\n * - Checks if useTokenDetection preference is enabled (skips if disabled)\n * - Checks if external services are enabled (skips if disabled)\n * - Filters out tokens already in allTokens or allIgnoredTokens\n * - Tokens are expected to be in the tokensChainsCache with full metadata\n * - Balance fetching is skipped since balances are provided by the caller\n *\n * @param options - The options object\n * @param options.tokensSlice - Array of token addresses detected from polling\n * @param options.chainId - Hex chain ID\n * @returns Promise that resolves when tokens are added\n */\n async addDetectedTokensViaPolling({\n tokensSlice,\n chainId,\n }: {\n tokensSlice: string[];\n chainId: Hex;\n }): Promise<void> {\n // Check if token detection is enabled via preferences\n if (!this.#useTokenDetection()) {\n return;\n }\n\n // Check if external services are enabled (polling via API requires external services)\n if (!this.#useExternalServices()) {\n return;\n }\n\n // Refresh the token cache to ensure we have the latest token metadata\n // This fixes a bug where the cache from construction time could be stale/empty\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n this.#tokensChainsCache = tokensChainsCache ?? {};\n\n const selectedAddress = this.#getSelectedAddress();\n\n // Get current token states to filter out already tracked/ignored tokens\n const { allTokens, allIgnoredTokens } = this.messenger.call(\n 'TokensController:getState',\n );\n\n const existingTokenAddresses = (\n allTokens[chainId]?.[selectedAddress] ?? []\n ).map((token) => token.address.toLowerCase());\n\n const ignoredTokenAddresses = (\n allIgnoredTokens[chainId]?.[selectedAddress] ?? []\n ).map((address) => address.toLowerCase());\n\n const tokensWithBalance: Token[] = [];\n const eventTokensDetails: string[] = [];\n\n for (const tokenAddress of tokensSlice) {\n const lowercaseTokenAddress = tokenAddress.toLowerCase();\n const checksummedTokenAddress = toChecksumHexAddress(tokenAddress);\n\n // Skip tokens already in allTokens\n if (existingTokenAddresses.includes(lowercaseTokenAddress)) {\n continue;\n }\n\n // Skip tokens in allIgnoredTokens\n if (ignoredTokenAddresses.includes(lowercaseTokenAddress)) {\n continue;\n }\n\n // Check map of validated tokens (cache keys are lowercase)\n const tokenData =\n this.#tokensChainsCache[chainId]?.data?.[lowercaseTokenAddress];\n\n if (!tokenData) {\n console.warn(\n `Token metadata not found in cache for ${tokenAddress} on chain ${chainId}`,\n );\n continue;\n }\n\n const { decimals, symbol, aggregators, iconUrl, name, rwaData } =\n tokenData;\n\n eventTokensDetails.push(`${symbol} - ${checksummedTokenAddress}`);\n tokensWithBalance.push({\n address: checksummedTokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n ...(rwaData && { rwaData }),\n });\n }\n\n // Perform addition\n if (tokensWithBalance.length) {\n this.#trackMetaMetricsEvent({\n event: 'Token Detected',\n category: 'Wallet',\n properties: {\n tokens: eventTokensDetails,\n token_standard: ERC20,\n asset_type: ASSET_TYPES.TOKEN,\n },\n });\n\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n await this.messenger.call(\n 'TokensController:addTokens',\n tokensWithBalance,\n networkClientId,\n );\n }\n }\n\n #getSelectedAccount(): InternalAccount {\n return this.messenger.call('AccountsController:getSelectedAccount');\n }\n\n #getSelectedAddress(): string {\n // If the address is not defined (or empty), we fallback to the currently selected account's address\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n this.#selectedAccountId,\n );\n return account?.address ?? '';\n }\n}\n\nexport default TokenDetectionController;\n"]}
1
+ {"version":3,"file":"TokenDetectionController.mjs","sourceRoot":"","sources":["../src/TokenDetectionController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerGetAccountAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport contractMap from '@metamask/contract-metadata';\nimport {\n ASSET_TYPES,\n ChainId,\n ERC20,\n safelyExecute,\n isEqualCaseInsensitive,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkClientId,\n NetworkControllerFindNetworkClientIdByChainIdAction,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetNetworkConfigurationByNetworkClientId,\n NetworkControllerGetStateAction,\n NetworkControllerNetworkDidChangeEvent,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type {\n PreferencesControllerGetStateAction,\n PreferencesControllerStateChangeEvent,\n} from '@metamask/preferences-controller';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\nimport type { TransactionControllerTransactionConfirmedEvent } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { isEqual, mapValues, isObject, get } from 'lodash';\n\nimport type { AssetsContractController } from './AssetsContractController';\nimport { isTokenDetectionSupportedForNetwork } from './assetsUtil';\nimport { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from './constants';\nimport type {\n GetTokenListState,\n TokenListMap,\n TokenListStateChange,\n TokensChainsCache,\n} from './TokenListController';\nimport type { Token } from './TokenRatesController';\nimport type {\n TokensControllerAddDetectedTokensAction,\n TokensControllerAddTokensAction,\n TokensControllerGetStateAction,\n} from './TokensController';\n\nconst DEFAULT_INTERVAL = 180000;\n\ntype LegacyToken = {\n name: string;\n logo: `${string}.svg`;\n symbol: string;\n decimals: number;\n erc20?: boolean;\n erc721?: boolean;\n};\n\ntype TokenDetectionMap = {\n [P in keyof TokenListMap]: Omit<TokenListMap[P], 'occurrences'>;\n};\n\ntype NetworkClient = {\n chainId: Hex;\n networkClientId: string;\n};\n\nexport const STATIC_MAINNET_TOKEN_LIST = Object.entries<LegacyToken>(\n contractMap,\n).reduce<TokenDetectionMap>((acc, [base, contract]) => {\n const { logo, erc20, erc721, ...tokenMetadata } = contract;\n return {\n ...acc,\n [base.toLowerCase()]: {\n ...tokenMetadata,\n address: base.toLowerCase(),\n iconUrl: `images/contract/${logo}`,\n aggregators: [],\n },\n };\n}, {});\n\n/**\n * Function that takes a TokensChainsCache object and maps chainId with TokenListMap.\n *\n * @param tokensChainsCache - TokensChainsCache input object\n * @returns returns the map of chainId with TokenListMap\n */\nexport function mapChainIdWithTokenListMap(\n tokensChainsCache: TokensChainsCache,\n): Record<string, unknown> {\n return mapValues(tokensChainsCache, (value) => {\n if (isObject(value) && 'data' in value) {\n return get(value, ['data']);\n }\n return value;\n });\n}\n\nexport const controllerName = 'TokenDetectionController';\n\nexport type TokenDetectionState = Record<never, never>;\n\nexport type TokenDetectionControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TokenDetectionState\n>;\n\nexport type TokenDetectionControllerAddDetectedTokensViaWsAction = {\n type: `TokenDetectionController:addDetectedTokensViaWs`;\n handler: TokenDetectionController['addDetectedTokensViaWs'];\n};\n\nexport type TokenDetectionControllerAddDetectedTokensViaPollingAction = {\n type: `TokenDetectionController:addDetectedTokensViaPolling`;\n handler: TokenDetectionController['addDetectedTokensViaPolling'];\n};\n\nexport type TokenDetectionControllerDetectTokensAction = {\n type: `TokenDetectionController:detectTokens`;\n handler: TokenDetectionController['detectTokens'];\n};\n\nexport type TokenDetectionControllerActions =\n | TokenDetectionControllerGetStateAction\n | TokenDetectionControllerAddDetectedTokensViaWsAction\n | TokenDetectionControllerAddDetectedTokensViaPollingAction\n | TokenDetectionControllerDetectTokensAction;\n\nexport type AllowedActions =\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerGetAccountAction\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetNetworkConfigurationByNetworkClientId\n | NetworkControllerGetStateAction\n | GetTokenListState\n | KeyringControllerGetStateAction\n | PreferencesControllerGetStateAction\n | TokensControllerGetStateAction\n | TokensControllerAddDetectedTokensAction\n | TokensControllerAddTokensAction\n | NetworkControllerFindNetworkClientIdByChainIdAction\n | AuthenticationController.AuthenticationControllerGetBearerToken;\n\nexport type TokenDetectionControllerStateChangeEvent =\n ControllerStateChangeEvent<typeof controllerName, TokenDetectionState>;\n\nexport type TokenDetectionControllerEvents =\n TokenDetectionControllerStateChangeEvent;\n\nexport type AllowedEvents =\n | AccountsControllerSelectedEvmAccountChangeEvent\n | NetworkControllerNetworkDidChangeEvent\n | TokenListStateChange\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | PreferencesControllerStateChangeEvent\n | TransactionControllerTransactionConfirmedEvent;\n\nexport type TokenDetectionControllerMessenger = Messenger<\n typeof controllerName,\n TokenDetectionControllerActions | AllowedActions,\n TokenDetectionControllerEvents | AllowedEvents\n>;\n\n/** The input to start polling for the {@link TokenDetectionController} */\ntype TokenDetectionPollingInput = {\n chainIds: Hex[];\n address: string;\n};\n\n/**\n * Controller that passively polls on a set interval for Tokens auto detection\n *\n * intervalId - Polling interval used to fetch new token rates\n *\n * selectedAddress - Vault selected address\n *\n * networkClientId - The network client ID of the current selected network\n *\n * disabled - Boolean to track if network requests are blocked\n *\n * isUnlocked - Boolean to track if the keyring state is unlocked\n *\n * isDetectionEnabledFromPreferences - Boolean to track if detection is enabled from PreferencesController\n *\n */\nexport class TokenDetectionController extends StaticIntervalPollingController<TokenDetectionPollingInput>()<\n typeof controllerName,\n TokenDetectionState,\n TokenDetectionControllerMessenger\n> {\n #intervalId?: ReturnType<typeof setTimeout>;\n\n #selectedAccountId: string;\n\n #tokensChainsCache: TokensChainsCache = {};\n\n #disabled: boolean;\n\n #isUnlocked: boolean;\n\n #isDetectionEnabledFromPreferences: boolean;\n\n readonly #useTokenDetection: () => boolean;\n\n readonly #useExternalServices: () => boolean;\n\n readonly #getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n\n readonly #trackMetaMetricsEvent: (options: {\n event: string;\n category: string;\n properties: {\n tokens: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n token_standard: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n asset_type: string;\n };\n }) => void;\n\n /**\n * Creates a TokenDetectionController instance.\n *\n * @param options - The controller options.\n * @param options.messenger - The controller messenger.\n * @param options.disabled - If set to true, all network requests are blocked.\n * @param options.interval - Polling interval used to fetch new token rates\n * @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.\n * @param options.trackMetaMetricsEvent - Sets options for MetaMetrics event tracking.\n * @param options.useTokenDetection - Feature Switch for using token detection (default: true)\n * @param options.useExternalServices - Feature Switch for using external services (default: false)\n */\n constructor({\n interval = DEFAULT_INTERVAL,\n disabled = true,\n getBalancesInSingleCall,\n trackMetaMetricsEvent,\n messenger,\n useTokenDetection = (): boolean => true,\n useExternalServices = (): boolean => true,\n }: {\n interval?: number;\n disabled?: boolean;\n getBalancesInSingleCall: AssetsContractController['getBalancesInSingleCall'];\n trackMetaMetricsEvent: (options: {\n event: string;\n category: string;\n properties: {\n tokens: string[];\n // eslint-disable-next-line @typescript-eslint/naming-convention\n token_standard: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n asset_type: string;\n };\n }) => void;\n messenger: TokenDetectionControllerMessenger;\n useTokenDetection?: () => boolean;\n useExternalServices?: () => boolean;\n }) {\n super({\n name: controllerName,\n messenger,\n state: {},\n metadata: {},\n });\n\n this.messenger.registerActionHandler(\n `${controllerName}:addDetectedTokensViaWs` as const,\n this.addDetectedTokensViaWs.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:addDetectedTokensViaPolling` as const,\n this.addDetectedTokensViaPolling.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:detectTokens` as const,\n this.detectTokens.bind(this),\n );\n\n this.#disabled = disabled;\n this.setIntervalLength(interval);\n\n this.#selectedAccountId = this.#getSelectedAccount().id;\n\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n\n this.#tokensChainsCache = tokensChainsCache;\n\n const { useTokenDetection: defaultUseTokenDetection } = this.messenger.call(\n 'PreferencesController:getState',\n );\n this.#isDetectionEnabledFromPreferences = defaultUseTokenDetection;\n\n this.#getBalancesInSingleCall = getBalancesInSingleCall;\n\n this.#trackMetaMetricsEvent = trackMetaMetricsEvent;\n\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n this.#isUnlocked = isUnlocked;\n\n this.#useTokenDetection = useTokenDetection;\n this.#useExternalServices = useExternalServices;\n\n this.#registerEventListeners();\n }\n\n /**\n * Constructor helper for registering this controller's messenger subscriptions to controller events.\n */\n #registerEventListeners(): void {\n this.messenger.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n this.#restartTokenDetection().catch(() => {\n // Silently handle token detection errors\n });\n });\n\n this.messenger.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n this.#stopPolling();\n });\n\n this.messenger.subscribe(\n 'TokenListController:stateChange',\n ({ tokensChainsCache }) => {\n const isEqualValues = this.#compareTokensChainsCache(\n tokensChainsCache,\n this.#tokensChainsCache,\n );\n if (!isEqualValues) {\n this.#restartTokenDetection().catch(() => {\n // Silently handle token detection errors\n });\n }\n },\n );\n\n this.messenger.subscribe(\n 'PreferencesController:stateChange',\n ({ useTokenDetection }) => {\n const selectedAccount = this.#getSelectedAccount();\n const isDetectionChangedFromPreferences =\n this.#isDetectionEnabledFromPreferences !== useTokenDetection;\n\n this.#isDetectionEnabledFromPreferences = useTokenDetection;\n\n if (isDetectionChangedFromPreferences) {\n this.#restartTokenDetection({\n selectedAddress: selectedAccount.address,\n }).catch(() => {\n // Silently handle token detection errors\n });\n }\n },\n );\n\n this.messenger.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n (selectedAccount) => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n\n const chainIds = Object.keys(networkConfigurationsByChainId) as Hex[];\n const isSelectedAccountIdChanged =\n this.#selectedAccountId !== selectedAccount.id;\n if (isSelectedAccountIdChanged) {\n this.#selectedAccountId = selectedAccount.id;\n this.#restartTokenDetection({\n selectedAddress: selectedAccount.address,\n chainIds,\n }).catch(() => {\n // Silently handle token detection errors\n });\n }\n },\n );\n\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n (transactionMeta) => {\n this.detectTokens({\n chainIds: [transactionMeta.chainId],\n }).catch(() => {\n // Silently handle token detection errors\n });\n },\n );\n }\n\n /**\n * Allows controller to make active and passive polling requests\n */\n enable(): void {\n this.#disabled = false;\n }\n\n /**\n * Blocks controller from making network calls\n */\n disable(): void {\n this.#disabled = true;\n }\n\n /**\n * Internal isActive state\n *\n * @returns Whether the controller is active (not disabled and keyring is unlocked)\n */\n get isActive(): boolean {\n return !this.#disabled && this.#isUnlocked;\n }\n\n /**\n * Start polling for detected tokens.\n */\n async start(): Promise<void> {\n this.enable();\n await this.#startPolling();\n }\n\n /**\n * Stop polling for detected tokens.\n */\n stop(): void {\n this.disable();\n this.#stopPolling();\n }\n\n #stopPolling(): void {\n if (this.#intervalId) {\n clearInterval(this.#intervalId);\n }\n }\n\n /**\n * Starts a new polling interval.\n */\n async #startPolling(): Promise<void> {\n if (!this.isActive) {\n return;\n }\n this.#stopPolling();\n await this.detectTokens();\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#intervalId = setInterval(async () => {\n await this.detectTokens();\n }, this.getIntervalLength());\n }\n\n /**\n * Compares current and previous tokensChainsCache object focusing only on the data object.\n *\n * @param tokensChainsCache - current tokensChainsCache input object\n * @param previousTokensChainsCache - previous tokensChainsCache input object\n * @returns boolean indicating if the two objects are equal\n */\n\n #compareTokensChainsCache(\n tokensChainsCache: TokensChainsCache,\n previousTokensChainsCache: TokensChainsCache,\n ): boolean {\n const cleanPreviousTokensChainsCache = mapChainIdWithTokenListMap(\n previousTokensChainsCache,\n );\n const cleanTokensChainsCache =\n mapChainIdWithTokenListMap(tokensChainsCache);\n const isEqualValues = isEqual(\n cleanTokensChainsCache,\n cleanPreviousTokensChainsCache,\n );\n return isEqualValues;\n }\n\n #getCorrectNetworkClientIdByChainId(\n chainIds: Hex[] | undefined,\n ): { chainId: Hex; networkClientId: NetworkClientId }[] {\n const { networkConfigurationsByChainId, selectedNetworkClientId } =\n this.messenger.call('NetworkController:getState');\n\n if (!chainIds) {\n const networkConfiguration = this.messenger.call(\n 'NetworkController:getNetworkConfigurationByNetworkClientId',\n selectedNetworkClientId,\n );\n\n return [\n {\n chainId: networkConfiguration?.chainId ?? ChainId.mainnet,\n networkClientId: selectedNetworkClientId,\n },\n ];\n }\n\n return chainIds.map((chainId) => {\n const configuration = networkConfigurationsByChainId[chainId];\n return {\n chainId,\n networkClientId:\n configuration.rpcEndpoints[configuration.defaultRpcEndpointIndex]\n .networkClientId,\n };\n });\n }\n\n async _executePoll({\n chainIds,\n address,\n }: TokenDetectionPollingInput): Promise<void> {\n if (!this.isActive) {\n return;\n }\n await this.detectTokens({\n chainIds,\n selectedAddress: address,\n });\n }\n\n /**\n * Restart token detection polling period and call detectNewTokens\n * in case of address change or user session initialization.\n *\n * @param options - Options for restart token detection.\n * @param options.selectedAddress - the selectedAddress against which to detect for token balances\n * @param options.chainIds - The chain IDs of the network client to use.\n */\n async #restartTokenDetection({\n selectedAddress,\n chainIds,\n }: {\n selectedAddress?: string;\n chainIds?: Hex[];\n } = {}): Promise<void> {\n await this.detectTokens({\n chainIds,\n selectedAddress,\n });\n this.setIntervalLength(DEFAULT_INTERVAL);\n }\n\n #shouldDetectTokens(chainId: Hex): boolean {\n if (!isTokenDetectionSupportedForNetwork(chainId)) {\n return false;\n }\n if (\n !this.#isDetectionEnabledFromPreferences &&\n chainId !== ChainId.mainnet\n ) {\n return false;\n }\n\n const isMainnetDetectionInactive =\n !this.#isDetectionEnabledFromPreferences && chainId === ChainId.mainnet;\n if (isMainnetDetectionInactive) {\n this.#tokensChainsCache = this.#getConvertedStaticMainnetTokenList();\n } else {\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n this.#tokensChainsCache = tokensChainsCache ?? {};\n }\n\n return true;\n }\n\n async #detectTokensUsingRpc(\n chainsToDetectUsingRpc: NetworkClient[],\n addressToDetect: string,\n ): Promise<void> {\n for (const { chainId, networkClientId } of chainsToDetectUsingRpc) {\n if (!this.#shouldDetectTokens(chainId)) {\n continue;\n }\n\n const tokenCandidateSlices = this.#getSlicesOfTokensToDetect({\n chainId,\n selectedAddress: addressToDetect,\n });\n const tokenDetectionPromises = tokenCandidateSlices.map((tokensSlice) =>\n this.#addDetectedTokens({\n tokensSlice,\n selectedAddress: addressToDetect,\n networkClientId,\n chainId,\n }),\n );\n\n await Promise.all(tokenDetectionPromises);\n }\n }\n\n /**\n * For each token in the token list provided by the TokenListController, checks the token's balance for the selected account address on the active network.\n * On mainnet, if token detection is disabled in preferences, ERC20 token auto detection will be triggered for each contract address in the legacy token list from the @metamask/contract-metadata repo.\n *\n * @param options - Options for token detection.\n * @param options.chainIds - The chain IDs of the network client to use.\n * @param options.selectedAddress - the selectedAddress against which to detect for token balances.\n * @param options.forceRpc - Force RPC-based token detection for all specified chains,\n * bypassing external services check and ensuring RPC is used even for chains\n * that might otherwise be handled by the Accounts API.\n */\n async detectTokens({\n chainIds,\n selectedAddress,\n forceRpc = false,\n }: {\n chainIds?: Hex[];\n selectedAddress?: string;\n forceRpc?: boolean;\n } = {}): Promise<void> {\n if (!this.isActive) {\n return;\n }\n\n // When forceRpc is true, bypass the useTokenDetection check to ensure RPC detection runs\n if (!forceRpc && !this.#useTokenDetection()) {\n return;\n }\n\n // If external services are disabled and not forcing RPC, skip all detection\n if (!forceRpc && !this.#useExternalServices()) {\n return;\n }\n\n const addressToDetect = selectedAddress ?? this.#getSelectedAddress();\n const clientNetworks = this.#getCorrectNetworkClientIdByChainId(chainIds);\n\n // If forceRpc is true, use RPC for all chains\n // Otherwise, skip chains supported by Accounts API (they are handled by TokenBalancesController)\n const chainsToDetectUsingRpc = forceRpc\n ? clientNetworks\n : clientNetworks.filter(\n ({ chainId }) =>\n !SUPPORTED_NETWORKS_ACCOUNTS_API_V4.includes(chainId),\n );\n\n if (chainsToDetectUsingRpc.length === 0) {\n return;\n }\n\n await this.#detectTokensUsingRpc(chainsToDetectUsingRpc, addressToDetect);\n }\n\n #getSlicesOfTokensToDetect({\n chainId,\n selectedAddress,\n }: {\n chainId: Hex;\n selectedAddress: string;\n }): string[][] {\n const { allTokens, allDetectedTokens, allIgnoredTokens } =\n this.messenger.call('TokensController:getState');\n const [tokensAddresses, detectedTokensAddresses, ignoredTokensAddresses] = [\n allTokens,\n allDetectedTokens,\n allIgnoredTokens,\n ].map((tokens) =>\n (tokens[chainId]?.[selectedAddress] ?? []).map((value) =>\n typeof value === 'string' ? value : value.address,\n ),\n );\n\n const tokensToDetect: string[] = [];\n for (const tokenAddress of Object.keys(\n this.#tokensChainsCache?.[chainId]?.data || {},\n )) {\n if (\n [\n tokensAddresses,\n detectedTokensAddresses,\n ignoredTokensAddresses,\n ].every(\n (addresses) =>\n !addresses.find((address) =>\n isEqualCaseInsensitive(address, tokenAddress),\n ),\n )\n ) {\n tokensToDetect.push(tokenAddress);\n }\n }\n\n const slicesOfTokensToDetect = [];\n for (let i = 0, size = 1000; i < tokensToDetect.length; i += size) {\n slicesOfTokensToDetect.push(tokensToDetect.slice(i, i + size));\n }\n\n return slicesOfTokensToDetect;\n }\n\n #getConvertedStaticMainnetTokenList(): TokensChainsCache {\n const data: TokenListMap = Object.entries(STATIC_MAINNET_TOKEN_LIST).reduce(\n (acc, [key, value]) => ({\n ...acc,\n [key]: {\n name: value.name,\n symbol: value.symbol,\n decimals: value.decimals,\n address: value.address,\n aggregators: [],\n iconUrl: value?.iconUrl,\n },\n }),\n {},\n );\n return {\n '0x1': {\n data,\n timestamp: 0,\n },\n };\n }\n\n async #addDetectedTokens({\n tokensSlice,\n selectedAddress,\n networkClientId,\n chainId,\n }: {\n tokensSlice: string[];\n selectedAddress: string;\n networkClientId: NetworkClientId;\n chainId: Hex;\n }): Promise<void> {\n await safelyExecute(async () => {\n const balances = await this.#getBalancesInSingleCall(\n selectedAddress,\n tokensSlice,\n networkClientId,\n );\n\n const tokensWithBalance: Token[] = [];\n const eventTokensDetails: string[] = [];\n for (const nonZeroTokenAddress of Object.keys(balances)) {\n const { decimals, symbol, aggregators, iconUrl, name } =\n this.#tokensChainsCache[chainId].data[nonZeroTokenAddress];\n eventTokensDetails.push(`${symbol} - ${nonZeroTokenAddress}`);\n tokensWithBalance.push({\n address: nonZeroTokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n });\n }\n\n if (tokensWithBalance.length) {\n this.#trackMetaMetricsEvent({\n event: 'Token Detected',\n category: 'Wallet',\n properties: {\n tokens: eventTokensDetails,\n token_standard: ERC20,\n asset_type: ASSET_TYPES.TOKEN,\n },\n });\n\n await this.messenger.call(\n 'TokensController:addTokens',\n tokensWithBalance,\n networkClientId,\n );\n }\n });\n }\n\n /**\n * Add tokens detected from websocket balance updates\n * This method:\n * - Checks if useTokenDetection preference is enabled (skips if disabled)\n * - Checks if external services are enabled (skips if disabled)\n * - Tokens are expected to be in the tokensChainsCache with full metadata\n * - Balance fetching is skipped since balances are provided by the websocket\n * - Ignored tokens have been filtered out by the caller\n *\n * @param options - The options object\n * @param options.tokensSlice - Array of token addresses detected from websocket (already filtered to exclude ignored tokens)\n * @param options.chainId - Hex chain ID\n * @returns Promise that resolves when tokens are added\n */\n async addDetectedTokensViaWs({\n tokensSlice,\n chainId,\n }: {\n tokensSlice: string[];\n chainId: Hex;\n }): Promise<void> {\n // Check if token detection is enabled via preferences\n if (!this.#useTokenDetection()) {\n return;\n }\n\n // Check if external services are enabled (websocket requires external services)\n if (!this.#useExternalServices()) {\n return;\n }\n\n // Refresh the token cache to ensure we have the latest token metadata\n // This fixes a bug where the cache from construction time could be stale/empty\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n this.#tokensChainsCache = tokensChainsCache ?? {};\n\n const tokensWithBalance: Token[] = [];\n const eventTokensDetails: string[] = [];\n\n for (const tokenAddress of tokensSlice) {\n // Normalize addresses explicitly (don't assume input format)\n const lowercaseTokenAddress = tokenAddress.toLowerCase();\n const checksummedTokenAddress = toChecksumHexAddress(tokenAddress);\n\n // Check map of validated tokens (cache keys are lowercase)\n const tokenData =\n this.#tokensChainsCache[chainId]?.data?.[lowercaseTokenAddress];\n\n if (!tokenData) {\n console.warn(\n `Token metadata not found in cache for ${tokenAddress} on chain ${chainId}`,\n );\n continue;\n }\n\n const { decimals, symbol, aggregators, iconUrl, name } = tokenData;\n\n // Push to lists with checksummed address (for allTokens storage)\n eventTokensDetails.push(`${symbol} - ${checksummedTokenAddress}`);\n tokensWithBalance.push({\n address: checksummedTokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n });\n }\n\n // Perform addition\n if (tokensWithBalance.length) {\n this.#trackMetaMetricsEvent({\n event: 'Token Detected',\n category: 'Wallet',\n properties: {\n tokens: eventTokensDetails,\n token_standard: ERC20,\n asset_type: ASSET_TYPES.TOKEN,\n },\n });\n\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n await this.messenger.call(\n 'TokensController:addTokens',\n tokensWithBalance,\n networkClientId,\n );\n }\n }\n\n /**\n * Add tokens detected from polling balance updates\n * This method:\n * - Checks if useTokenDetection preference is enabled (skips if disabled)\n * - Checks if external services are enabled (skips if disabled)\n * - Filters out tokens already in allTokens or allIgnoredTokens\n * - Tokens are expected to be in the tokensChainsCache with full metadata\n * - Balance fetching is skipped since balances are provided by the caller\n *\n * @param options - The options object\n * @param options.tokensSlice - Array of token addresses detected from polling\n * @param options.chainId - Hex chain ID\n * @returns Promise that resolves when tokens are added\n */\n async addDetectedTokensViaPolling({\n tokensSlice,\n chainId,\n }: {\n tokensSlice: string[];\n chainId: Hex;\n }): Promise<void> {\n // Check if token detection is enabled via preferences\n if (!this.#useTokenDetection()) {\n return;\n }\n\n // Check if external services are enabled (polling via API requires external services)\n if (!this.#useExternalServices()) {\n return;\n }\n\n // Refresh the token cache to ensure we have the latest token metadata\n // This fixes a bug where the cache from construction time could be stale/empty\n const { tokensChainsCache } = this.messenger.call(\n 'TokenListController:getState',\n );\n this.#tokensChainsCache = tokensChainsCache ?? {};\n\n const selectedAddress = this.#getSelectedAddress();\n\n // Get current token states to filter out already tracked/ignored tokens\n const { allTokens, allIgnoredTokens } = this.messenger.call(\n 'TokensController:getState',\n );\n\n const existingTokenAddresses = (\n allTokens[chainId]?.[selectedAddress] ?? []\n ).map((token) => token.address.toLowerCase());\n\n const ignoredTokenAddresses = (\n allIgnoredTokens[chainId]?.[selectedAddress] ?? []\n ).map((address) => address.toLowerCase());\n\n const tokensWithBalance: Token[] = [];\n const eventTokensDetails: string[] = [];\n\n for (const tokenAddress of tokensSlice) {\n const lowercaseTokenAddress = tokenAddress.toLowerCase();\n const checksummedTokenAddress = toChecksumHexAddress(tokenAddress);\n\n // Skip tokens already in allTokens\n if (existingTokenAddresses.includes(lowercaseTokenAddress)) {\n continue;\n }\n\n // Skip tokens in allIgnoredTokens\n if (ignoredTokenAddresses.includes(lowercaseTokenAddress)) {\n continue;\n }\n\n // Check map of validated tokens (cache keys are lowercase)\n const tokenData =\n this.#tokensChainsCache[chainId]?.data?.[lowercaseTokenAddress];\n\n if (!tokenData) {\n console.warn(\n `Token metadata not found in cache for ${tokenAddress} on chain ${chainId}`,\n );\n continue;\n }\n\n const { decimals, symbol, aggregators, iconUrl, name } = tokenData;\n\n eventTokensDetails.push(`${symbol} - ${checksummedTokenAddress}`);\n tokensWithBalance.push({\n address: checksummedTokenAddress,\n decimals,\n symbol,\n aggregators,\n image: iconUrl,\n isERC721: false,\n name,\n });\n }\n\n // Perform addition\n if (tokensWithBalance.length) {\n this.#trackMetaMetricsEvent({\n event: 'Token Detected',\n category: 'Wallet',\n properties: {\n tokens: eventTokensDetails,\n token_standard: ERC20,\n asset_type: ASSET_TYPES.TOKEN,\n },\n });\n\n const networkClientId = this.messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n await this.messenger.call(\n 'TokensController:addTokens',\n tokensWithBalance,\n networkClientId,\n );\n }\n }\n\n #getSelectedAccount(): InternalAccount {\n return this.messenger.call('AccountsController:getSelectedAccount');\n }\n\n #getSelectedAddress(): string {\n // If the address is not defined (or empty), we fallback to the currently selected account's address\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n this.#selectedAccountId,\n );\n return account?.address ?? '';\n }\n}\n\nexport default TokenDetectionController;\n"]}
@@ -12,8 +12,9 @@ const polling_controller_1 = require("@metamask/polling-controller");
12
12
  const async_mutex_1 = require("async-mutex");
13
13
  const assetsUtil_1 = require("./assetsUtil.cjs");
14
14
  const token_service_1 = require("./token-service.cjs");
15
- const DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;
16
- const DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;
15
+ // 4 Hour Interval Cache Refresh Threshold
16
+ const DEFAULT_INTERVAL = 4 * 60 * 60 * 1000;
17
+ const DEFAULT_THRESHOLD = 4 * 60 * 60 * 1000;
17
18
  const name = 'TokenListController';
18
19
  const metadata = {
19
20
  tokensChainsCache: {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenListController.cjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n rwaData?: {\n instrumentType: string;\n ticker: string;\n market: {\n nextOpen: string;\n nextClose: string;\n };\n nextPause: {\n start: string;\n end: string;\n };\n };\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = Messenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents\n>;\n\nconst metadata: StateMetadata<TokenListState> = {\n tokensChainsCache: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n preventPollingOnNetworkRestart: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messenger.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(\n networkControllerState: NetworkState,\n ): Promise<void> {\n const selectedNetworkClient = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n }\n }\n }\n\n // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API\n // Maintaining these functions for now until we can safely deprecate them for backwards compatibility\n /**\n * Start polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async start(): Promise<void> {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Restart polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async restart(): Promise<void> {\n this.stopPolling();\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Stop polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n stop(): void {\n this.stopPolling();\n }\n\n /**\n * This stops any active polling.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n override destroy(): void {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * This stops any active polling intervals.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async #startDeprecatedPolling(): Promise<void> {\n // renaming this to avoid collision with base class\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n }, this.intervalDelay);\n }\n\n /**\n * This starts a new polling loop for any given chain. Under the hood it is deduping polls\n *\n * @param input - The input for the poll.\n * @param input.chainId - The chainId of the chain to trigger the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({ chainId }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(chainId);\n }\n\n /**\n * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)\n *\n * @param chainId - The chainId of the current chain triggering the fetch.\n */\n async fetchTokenList(chainId: Hex): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n if (this.isCacheValid(chainId)) {\n return;\n }\n\n // Fetch fresh token list from the API\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n // Have response - process and update list\n if (tokensFromAPI) {\n // Format tokens from API (HTTP) and update tokenList\n const tokenList: TokenListMap = {};\n for (const token of tokensFromAPI) {\n tokenList[token.address] = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n }\n\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].data = tokenList;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n return;\n }\n\n // No response - fallback to previous state, or initialise empty\n if (!tokensFromAPI) {\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n }\n } finally {\n releaseLock();\n }\n }\n\n isCacheValid(chainId: Hex): boolean {\n const { tokensChainsCache }: TokenListState = this.state;\n const timestamp: number | undefined = tokensChainsCache[chainId]?.timestamp;\n const now = Date.now();\n return (\n timestamp !== undefined && now - timestamp < this.cacheRefreshThreshold\n );\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
1
+ {"version":3,"file":"TokenListController.cjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { TokenRwaData, fetchTokenListByChainId } from './token-service';\n\n// 4 Hour Interval Cache Refresh Threshold\nconst DEFAULT_INTERVAL = 4 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 4 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n rwaData?: TokenRwaData;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = Messenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents\n>;\n\nconst metadata: StateMetadata<TokenListState> = {\n tokensChainsCache: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n preventPollingOnNetworkRestart: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messenger.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n const selectedNetworkClient = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n }\n }\n }\n\n // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API\n // Maintaining these functions for now until we can safely deprecate them for backwards compatibility\n /**\n * Start polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Restart polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async restart() {\n this.stopPolling();\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Stop polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n stop() {\n this.stopPolling();\n }\n\n /**\n * This stops any active polling.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * This stops any active polling intervals.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async #startDeprecatedPolling(): Promise<void> {\n // renaming this to avoid collision with base class\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n }, this.intervalDelay);\n }\n\n /**\n * This starts a new polling loop for any given chain. Under the hood it is deduping polls\n *\n * @param input - The input for the poll.\n * @param input.chainId - The chainId of the chain to trigger the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({ chainId }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(chainId);\n }\n\n /**\n * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)\n *\n * @param chainId - The chainId of the current chain triggering the fetch.\n */\n async fetchTokenList(chainId: Hex): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n if (this.isCacheValid(chainId)) {\n return;\n }\n\n // Fetch fresh token list from the API\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n // Have response - process and update list\n if (tokensFromAPI) {\n // Format tokens from API (HTTP) and update tokenList\n const tokenList: TokenListMap = {};\n for (const token of tokensFromAPI) {\n tokenList[token.address] = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n }\n\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].data = tokenList;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n return;\n }\n\n // No response - fallback to previous state, or initialise empty\n if (!tokensFromAPI) {\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n }\n } finally {\n releaseLock();\n }\n }\n\n isCacheValid(chainId: Hex): boolean {\n const { tokensChainsCache }: TokenListState = this.state;\n const timestamp: number | undefined = tokensChainsCache[chainId]?.timestamp;\n const now = Date.now();\n return (\n timestamp !== undefined && now - timestamp < this.cacheRefreshThreshold\n );\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
@@ -2,6 +2,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent } from "@meta
2
2
  import type { Messenger } from "@metamask/messenger";
3
3
  import type { NetworkControllerStateChangeEvent, NetworkState, NetworkControllerGetNetworkClientByIdAction } from "@metamask/network-controller";
4
4
  import type { Hex } from "@metamask/utils";
5
+ import { TokenRwaData } from "./token-service.cjs";
5
6
  declare const name = "TokenListController";
6
7
  export type TokenListToken = {
7
8
  name: string;
@@ -11,18 +12,7 @@ export type TokenListToken = {
11
12
  occurrences: number;
12
13
  aggregators: string[];
13
14
  iconUrl: string;
14
- rwaData?: {
15
- instrumentType: string;
16
- ticker: string;
17
- market: {
18
- nextOpen: string;
19
- nextClose: string;
20
- };
21
- nextPause: {
22
- start: string;
23
- end: string;
24
- };
25
- };
15
+ rwaData?: TokenRwaData;
26
16
  };
27
17
  export type TokenListMap = Record<string, TokenListToken>;
28
18
  type DataCache = {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenListController.d.cts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenListController.d.cts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent } from "@meta
2
2
  import type { Messenger } from "@metamask/messenger";
3
3
  import type { NetworkControllerStateChangeEvent, NetworkState, NetworkControllerGetNetworkClientByIdAction } from "@metamask/network-controller";
4
4
  import type { Hex } from "@metamask/utils";
5
+ import { TokenRwaData } from "./token-service.mjs";
5
6
  declare const name = "TokenListController";
6
7
  export type TokenListToken = {
7
8
  name: string;
@@ -11,18 +12,7 @@ export type TokenListToken = {
11
12
  occurrences: number;
12
13
  aggregators: string[];
13
14
  iconUrl: string;
14
- rwaData?: {
15
- instrumentType: string;
16
- ticker: string;
17
- market: {
18
- nextOpen: string;
19
- nextClose: string;
20
- };
21
- nextPause: {
22
- start: string;
23
- end: string;
24
- };
25
- };
15
+ rwaData?: TokenRwaData;
26
16
  };
27
17
  export type TokenListMap = Record<string, TokenListToken>;
28
18
  type DataCache = {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenListController.d.mts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenListController.d.mts","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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"}
@@ -9,8 +9,9 @@ import { StaticIntervalPollingController } from "@metamask/polling-controller";
9
9
  import { Mutex } from "async-mutex";
10
10
  import { isTokenListSupportedForNetwork, formatAggregatorNames, formatIconUrlWithProxy } from "./assetsUtil.mjs";
11
11
  import { fetchTokenListByChainId } from "./token-service.mjs";
12
- const DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;
13
- const DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;
12
+ // 4 Hour Interval Cache Refresh Threshold
13
+ const DEFAULT_INTERVAL = 4 * 60 * 60 * 1000;
14
+ const DEFAULT_THRESHOLD = 4 * 60 * 60 * 1000;
14
15
  const name = 'TokenListController';
15
16
  const metadata = {
16
17
  tokensChainsCache: {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenListController.mjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { fetchTokenListByChainId } from './token-service';\n\nconst DEFAULT_INTERVAL = 24 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 24 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n rwaData?: {\n instrumentType: string;\n ticker: string;\n market: {\n nextOpen: string;\n nextClose: string;\n };\n nextPause: {\n start: string;\n end: string;\n };\n };\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = Messenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents\n>;\n\nconst metadata: StateMetadata<TokenListState> = {\n tokensChainsCache: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n preventPollingOnNetworkRestart: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messenger.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(\n networkControllerState: NetworkState,\n ): Promise<void> {\n const selectedNetworkClient = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n }\n }\n }\n\n // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API\n // Maintaining these functions for now until we can safely deprecate them for backwards compatibility\n /**\n * Start polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async start(): Promise<void> {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Restart polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async restart(): Promise<void> {\n this.stopPolling();\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Stop polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n stop(): void {\n this.stopPolling();\n }\n\n /**\n * This stops any active polling.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n override destroy(): void {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * This stops any active polling intervals.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async #startDeprecatedPolling(): Promise<void> {\n // renaming this to avoid collision with base class\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n }, this.intervalDelay);\n }\n\n /**\n * This starts a new polling loop for any given chain. Under the hood it is deduping polls\n *\n * @param input - The input for the poll.\n * @param input.chainId - The chainId of the chain to trigger the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({ chainId }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(chainId);\n }\n\n /**\n * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)\n *\n * @param chainId - The chainId of the current chain triggering the fetch.\n */\n async fetchTokenList(chainId: Hex): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n if (this.isCacheValid(chainId)) {\n return;\n }\n\n // Fetch fresh token list from the API\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n // Have response - process and update list\n if (tokensFromAPI) {\n // Format tokens from API (HTTP) and update tokenList\n const tokenList: TokenListMap = {};\n for (const token of tokensFromAPI) {\n tokenList[token.address] = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n }\n\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].data = tokenList;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n return;\n }\n\n // No response - fallback to previous state, or initialise empty\n if (!tokensFromAPI) {\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n }\n } finally {\n releaseLock();\n }\n }\n\n isCacheValid(chainId: Hex): boolean {\n const { tokensChainsCache }: TokenListState = this.state;\n const timestamp: number | undefined = tokensChainsCache[chainId]?.timestamp;\n const now = Date.now();\n return (\n timestamp !== undefined && now - timestamp < this.cacheRefreshThreshold\n );\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}
1
+ {"version":3,"file":"TokenListController.mjs","sourceRoot":"","sources":["../src/TokenListController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n NetworkControllerStateChangeEvent,\n NetworkState,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport {\n isTokenListSupportedForNetwork,\n formatAggregatorNames,\n formatIconUrlWithProxy,\n} from './assetsUtil';\nimport { TokenRwaData, fetchTokenListByChainId } from './token-service';\n\n// 4 Hour Interval Cache Refresh Threshold\nconst DEFAULT_INTERVAL = 4 * 60 * 60 * 1000;\nconst DEFAULT_THRESHOLD = 4 * 60 * 60 * 1000;\n\nconst name = 'TokenListController';\n\nexport type TokenListToken = {\n name: string;\n symbol: string;\n decimals: number;\n address: string;\n occurrences: number;\n aggregators: string[];\n iconUrl: string;\n rwaData?: TokenRwaData;\n};\n\nexport type TokenListMap = Record<string, TokenListToken>;\n\ntype DataCache = {\n timestamp: number;\n data: TokenListMap;\n};\nexport type TokensChainsCache = {\n [chainId: Hex]: DataCache;\n};\n\nexport type TokenListState = {\n tokensChainsCache: TokensChainsCache;\n preventPollingOnNetworkRestart: boolean;\n};\n\nexport type TokenListStateChange = ControllerStateChangeEvent<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerEvents = TokenListStateChange;\n\nexport type GetTokenListState = ControllerGetStateAction<\n typeof name,\n TokenListState\n>;\n\nexport type TokenListControllerActions = GetTokenListState;\n\ntype AllowedActions = NetworkControllerGetNetworkClientByIdAction;\n\ntype AllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type TokenListControllerMessenger = Messenger<\n typeof name,\n TokenListControllerActions | AllowedActions,\n TokenListControllerEvents | AllowedEvents\n>;\n\nconst metadata: StateMetadata<TokenListState> = {\n tokensChainsCache: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n preventPollingOnNetworkRestart: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n};\n\nexport const getDefaultTokenListState = (): TokenListState => {\n return {\n tokensChainsCache: {},\n preventPollingOnNetworkRestart: false,\n };\n};\n\n/** The input to start polling for the {@link TokenListController} */\ntype TokenListPollingInput = {\n chainId: Hex;\n};\n\n/**\n * Controller that passively polls on a set interval for the list of tokens from metaswaps api\n */\nexport class TokenListController extends StaticIntervalPollingController<TokenListPollingInput>()<\n typeof name,\n TokenListState,\n TokenListControllerMessenger\n> {\n private readonly mutex = new Mutex();\n\n private intervalId?: ReturnType<typeof setTimeout>;\n\n private readonly intervalDelay: number;\n\n private readonly cacheRefreshThreshold: number;\n\n private chainId: Hex;\n\n private abortController: AbortController;\n\n /**\n * Creates a TokenListController instance.\n *\n * @param options - The controller options.\n * @param options.chainId - The chain ID of the current network.\n * @param options.onNetworkStateChange - A function for registering an event handler for network state changes.\n * @param options.interval - The polling interval, in milliseconds.\n * @param options.cacheRefreshThreshold - The token cache expiry time, in milliseconds.\n * @param options.messenger - A restricted messenger.\n * @param options.state - Initial state to set on this controller.\n * @param options.preventPollingOnNetworkRestart - Determines whether to prevent poilling on network restart in extension.\n */\n constructor({\n chainId,\n preventPollingOnNetworkRestart = false,\n onNetworkStateChange,\n interval = DEFAULT_INTERVAL,\n cacheRefreshThreshold = DEFAULT_THRESHOLD,\n messenger,\n state,\n }: {\n chainId: Hex;\n preventPollingOnNetworkRestart?: boolean;\n onNetworkStateChange?: (\n listener: (networkState: NetworkState) => void,\n ) => void;\n interval?: number;\n cacheRefreshThreshold?: number;\n messenger: TokenListControllerMessenger;\n state?: Partial<TokenListState>;\n }) {\n super({\n name,\n metadata,\n messenger,\n state: { ...getDefaultTokenListState(), ...state },\n });\n this.intervalDelay = interval;\n this.setIntervalLength(interval);\n this.cacheRefreshThreshold = cacheRefreshThreshold;\n this.chainId = chainId;\n this.updatePreventPollingOnNetworkRestart(preventPollingOnNetworkRestart);\n this.abortController = new AbortController();\n if (onNetworkStateChange) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n onNetworkStateChange(async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n });\n } else {\n this.messenger.subscribe(\n 'NetworkController:stateChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async (networkControllerState) => {\n await this.#onNetworkControllerStateChange(networkControllerState);\n },\n );\n }\n }\n\n /**\n * Updates state and restarts polling on changes to the network controller\n * state.\n *\n * @param networkControllerState - The updated network controller state.\n */\n async #onNetworkControllerStateChange(networkControllerState: NetworkState) {\n const selectedNetworkClient = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkControllerState.selectedNetworkClientId,\n );\n const { chainId } = selectedNetworkClient.configuration;\n\n if (this.chainId !== chainId) {\n this.abortController.abort();\n this.abortController = new AbortController();\n this.chainId = chainId;\n if (this.state.preventPollingOnNetworkRestart) {\n this.clearingTokenListData();\n }\n }\n }\n\n // Eventually we want to remove start/restart/stop controls in favor of new _executePoll API\n // Maintaining these functions for now until we can safely deprecate them for backwards compatibility\n /**\n * Start polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async start() {\n if (!isTokenListSupportedForNetwork(this.chainId)) {\n return;\n }\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Restart polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async restart() {\n this.stopPolling();\n await this.#startDeprecatedPolling();\n }\n\n /**\n * Stop polling for the token list.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n stop() {\n this.stopPolling();\n }\n\n /**\n * This stops any active polling.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n override destroy() {\n super.destroy();\n this.stopPolling();\n }\n\n /**\n * This stops any active polling intervals.\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n private stopPolling() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n }\n\n /**\n * Starts a new polling interval for a given chainId (this should be deprecated in favor of _executePoll)\n *\n * @deprecated This method is deprecated and will be removed in the future.\n * Consider using the new polling approach instead\n */\n async #startDeprecatedPolling(): Promise<void> {\n // renaming this to avoid collision with base class\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.intervalId = setInterval(async () => {\n await safelyExecute(() => this.fetchTokenList(this.chainId));\n }, this.intervalDelay);\n }\n\n /**\n * This starts a new polling loop for any given chain. Under the hood it is deduping polls\n *\n * @param input - The input for the poll.\n * @param input.chainId - The chainId of the chain to trigger the fetch.\n * @returns A promise that resolves when this operation completes.\n */\n async _executePoll({ chainId }: TokenListPollingInput): Promise<void> {\n return this.fetchTokenList(chainId);\n }\n\n /**\n * Fetching token list from the Token Service API. This will fetch tokens across chains. It will update tokensChainsCache (scoped across chains), and also the tokenList (scoped for the selected chain)\n *\n * @param chainId - The chainId of the current chain triggering the fetch.\n */\n async fetchTokenList(chainId: Hex): Promise<void> {\n const releaseLock = await this.mutex.acquire();\n try {\n if (this.isCacheValid(chainId)) {\n return;\n }\n\n // Fetch fresh token list from the API\n const tokensFromAPI = await safelyExecute(\n () =>\n fetchTokenListByChainId(\n chainId,\n this.abortController.signal,\n ) as Promise<TokenListToken[]>,\n );\n\n // Have response - process and update list\n if (tokensFromAPI) {\n // Format tokens from API (HTTP) and update tokenList\n const tokenList: TokenListMap = {};\n for (const token of tokensFromAPI) {\n tokenList[token.address] = {\n ...token,\n aggregators: formatAggregatorNames(token.aggregators),\n iconUrl: formatIconUrlWithProxy({\n chainId,\n tokenAddress: token.address,\n }),\n };\n }\n\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].data = tokenList;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n return;\n }\n\n // No response - fallback to previous state, or initialise empty\n if (!tokensFromAPI) {\n this.update((state) => {\n const newDataCache: DataCache = { data: {}, timestamp: Date.now() };\n state.tokensChainsCache[chainId] ??= newDataCache;\n state.tokensChainsCache[chainId].timestamp = Date.now();\n });\n }\n } finally {\n releaseLock();\n }\n }\n\n isCacheValid(chainId: Hex): boolean {\n const { tokensChainsCache }: TokenListState = this.state;\n const timestamp: number | undefined = tokensChainsCache[chainId]?.timestamp;\n const now = Date.now();\n return (\n timestamp !== undefined && now - timestamp < this.cacheRefreshThreshold\n );\n }\n\n /**\n * Clearing tokenList and tokensChainsCache explicitly.\n */\n clearingTokenListData(): void {\n this.update(() => {\n return {\n ...this.state,\n tokensChainsCache: {},\n };\n });\n }\n\n /**\n * Updates preventPollingOnNetworkRestart from extension.\n *\n * @param shouldPreventPolling - Determine whether to prevent polling on network change\n */\n updatePreventPollingOnNetworkRestart(shouldPreventPolling: boolean): void {\n this.update(() => {\n return {\n ...this.state,\n preventPollingOnNetworkRestart: shouldPreventPolling,\n };\n });\n }\n}\n\nexport default TokenListController;\n"]}