@metamask-previews/assets-controllers 94.0.0-preview-6c59381c → 94.0.0-preview-cb4a07d5
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.
- package/CHANGELOG.md +8 -0
- package/dist/AccountTrackerController.cjs +71 -57
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +3 -2
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +3 -2
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +71 -57
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +9 -7
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts +6 -4
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts +6 -4
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +9 -7
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/token-service.cjs +11 -3
- package/dist/token-service.cjs.map +1 -1
- package/dist/token-service.d.cts +3 -1
- package/dist/token-service.d.cts.map +1 -1
- package/dist/token-service.d.mts +3 -1
- package/dist/token-service.d.mts.map +1 -1
- package/dist/token-service.mjs +11 -3
- package/dist/token-service.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenBalancesController.mjs","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport {\n BNToHex,\n isValidHexAddress,\n safelyExecuteWithTimeout,\n toChecksumHexAddress,\n toHex,\n} from '@metamask/controller-utils';\nimport type {\n BalanceUpdate,\n AccountActivityServiceBalanceUpdatedEvent,\n AccountActivityServiceStatusChangedEvent,\n} from '@metamask/core-backend';\nimport type {\n KeyringControllerAccountRemovedEvent,\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 NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerStateChangeEvent,\n NetworkState,\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 {\n TransactionControllerIncomingTransactionsReceivedEvent,\n TransactionControllerTransactionConfirmedEvent,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport {\n isCaipAssetType,\n isCaipChainId,\n isStrictHexString,\n parseCaipAssetType,\n parseCaipChainId,\n} from '@metamask/utils';\nimport { produce } from 'immer';\nimport { isEqual } from 'lodash';\n\nimport type {\n AccountTrackerControllerGetStateAction,\n AccountTrackerUpdateNativeBalancesAction,\n AccountTrackerUpdateStakedBalancesAction,\n} from './AccountTrackerController';\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from './AssetsContractController';\nimport { AccountsApiBalanceFetcher } from './multi-chain-accounts-service/api-balance-fetcher';\nimport type {\n BalanceFetcher,\n ProcessedBalance,\n} from './multi-chain-accounts-service/api-balance-fetcher';\nimport { RpcBalanceFetcher } from './rpc-service/rpc-balance-fetcher';\nimport type {\n TokenDetectionControllerAddDetectedTokensViaPollingAction,\n TokenDetectionControllerAddDetectedTokensViaWsAction,\n TokenDetectionControllerDetectTokensAction,\n} from './TokenDetectionController';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerState,\n TokensControllerStateChangeEvent,\n} from './TokensController';\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nconst CONTROLLER = 'TokenBalancesController' as const;\nconst DEFAULT_INTERVAL_MS = 30_000; // 30 seconds\nconst DEFAULT_WEBSOCKET_ACTIVE_POLLING_INTERVAL_MS = 300_000; // 5 minutes\n\nconst metadata: StateMetadata<TokenBalancesControllerState> = {\n tokenBalances: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n// account → chain → token → balance\nexport type TokenBalances = Record<\n ChecksumAddress,\n Record<ChainIdHex, Record<ChecksumAddress, Hex>>\n>;\n\nexport type TokenBalancesControllerState = {\n tokenBalances: TokenBalances;\n};\n\nexport type TokenBalancesControllerGetStateAction = ControllerGetStateAction<\n typeof CONTROLLER,\n TokenBalancesControllerState\n>;\n\nexport type TokenBalancesControllerUpdateChainPollingConfigsAction = {\n type: `TokenBalancesController:updateChainPollingConfigs`;\n handler: TokenBalancesController['updateChainPollingConfigs'];\n};\n\nexport type TokenBalancesControllerGetChainPollingConfigAction = {\n type: `TokenBalancesController:getChainPollingConfig`;\n handler: TokenBalancesController['getChainPollingConfig'];\n};\n\nexport type TokenBalancesControllerActions =\n | TokenBalancesControllerGetStateAction\n | TokenBalancesControllerUpdateChainPollingConfigsAction\n | TokenBalancesControllerGetChainPollingConfigAction;\n\nexport type TokenBalancesControllerStateChangeEvent =\n ControllerStateChangeEvent<typeof CONTROLLER, TokenBalancesControllerState>;\n\nexport type NativeBalanceEvent = {\n type: `${typeof CONTROLLER}:updatedNativeBalance`;\n payload: unknown[];\n};\n\nexport type TokenBalancesControllerEvents =\n | TokenBalancesControllerStateChangeEvent\n | NativeBalanceEvent;\n\nexport type AllowedActions =\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | TokensControllerGetStateAction\n | TokenDetectionControllerAddDetectedTokensViaPollingAction\n | TokenDetectionControllerAddDetectedTokensViaWsAction\n | TokenDetectionControllerDetectTokensAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerListAccountsAction\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction\n | KeyringControllerGetStateAction\n | AuthenticationController.AuthenticationControllerGetBearerToken;\n\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | PreferencesControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | KeyringControllerAccountRemovedEvent\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceStatusChangedEvent\n | AccountsControllerSelectedEvmAccountChangeEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerIncomingTransactionsReceivedEvent;\n\nexport type TokenBalancesControllerMessenger = Messenger<\n typeof CONTROLLER,\n TokenBalancesControllerActions | AllowedActions,\n TokenBalancesControllerEvents | AllowedEvents\n>;\n\nexport type ChainPollingConfig = {\n /** Polling interval in milliseconds for this chain */\n interval: number;\n};\n\nexport type UpdateChainPollingConfigsOptions = {\n /** Whether to immediately fetch balances after updating configs (default: true) */\n immediateUpdate?: boolean;\n};\n\nexport type TokenBalancesControllerOptions = {\n messenger: TokenBalancesControllerMessenger;\n /** Default interval for chains not specified in chainPollingIntervals */\n interval?: number;\n /** Per-chain polling configuration */\n chainPollingIntervals?: Record<ChainIdHex, ChainPollingConfig>;\n state?: Partial<TokenBalancesControllerState>;\n /** When `true`, balances for *all* known accounts are queried. */\n queryMultipleAccounts?: boolean;\n /** Array of chainIds that should use Accounts-API strategy (if supported by API). */\n accountsApiChainIds?: () => ChainIdHex[];\n /** Disable external HTTP calls (privacy / offline mode). */\n allowExternalServices?: () => boolean;\n /** Custom logger. */\n log?: (...args: unknown[]) => void;\n platform?: 'extension' | 'mobile';\n /** Polling interval when WebSocket is active and providing real-time updates */\n websocketActivePollingInterval?: number;\n};\n\nconst draft = <State>(base: State, fn: (draftState: State) => void): State =>\n produce(base, fn);\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\n/**\n * Convert CAIP chain ID or hex chain ID to hex chain ID.\n *\n * @param chainId - CAIP chain ID or hex chain ID.\n * @returns Hex chain ID.\n */\nexport const caipChainIdToHex = (chainId: string): ChainIdHex => {\n if (isStrictHexString(chainId)) {\n return chainId;\n }\n\n if (isCaipChainId(chainId)) {\n return toHex(parseCaipChainId(chainId).reference);\n }\n\n throw new Error('caipChainIdToHex - Failed to provide CAIP-2 or Hex chainId');\n};\n\n/**\n * Extract token address from asset type.\n *\n * @param assetType - Asset type string.\n * @returns Tuple of [tokenAddress, isNativeToken] or null if invalid.\n */\nexport const parseAssetType = (assetType: string): [string, boolean] | null => {\n if (!isCaipAssetType(assetType)) {\n return null;\n }\n\n const parsed = parseCaipAssetType(assetType);\n\n if (parsed.assetNamespace === 'erc20') {\n return [parsed.assetReference, false];\n }\n\n if (parsed.assetNamespace === 'slip44') {\n return [ZERO_ADDRESS, true];\n }\n\n return null;\n};\n\ntype NativeBalanceUpdate = { address: string; chainId: Hex; balance: Hex };\ntype StakedBalanceUpdate = {\n address: string;\n chainId: Hex;\n stakedBalance: Hex;\n};\nexport class TokenBalancesController extends StaticIntervalPollingController<{\n chainIds: ChainIdHex[];\n}>()<\n typeof CONTROLLER,\n TokenBalancesControllerState,\n TokenBalancesControllerMessenger\n> {\n readonly #platform: 'extension' | 'mobile';\n\n readonly #queryAllAccounts: boolean;\n\n readonly #accountsApiChainIds: () => ChainIdHex[];\n\n readonly #allowExternalServices: () => boolean;\n\n readonly #balanceFetchers: BalanceFetcher[];\n\n #allTokens: TokensControllerState['allTokens'] = {};\n\n #detectedTokens: TokensControllerState['allDetectedTokens'] = {};\n\n #allIgnoredTokens: TokensControllerState['allIgnoredTokens'] = {};\n\n /** Default polling interval for chains without specific configuration */\n readonly #defaultInterval: number;\n\n /** Polling interval when WebSocket is active and providing real-time updates */\n readonly #websocketActivePollingInterval: number;\n\n /** Per-chain polling configuration */\n readonly #chainPollingConfig: Record<ChainIdHex, ChainPollingConfig>;\n\n /** Active polling timers grouped by interval */\n readonly #intervalPollingTimers: Map<number, NodeJS.Timeout> = new Map();\n\n /** Track if controller-level polling is active */\n #isControllerPollingActive = false;\n\n /** Track if the keyring is unlocked */\n #isUnlocked = false;\n\n /** Store original chainIds from startPolling to preserve intent */\n #requestedChainIds: ChainIdHex[] = [];\n\n /** Debouncing for rapid status changes to prevent excessive HTTP calls */\n readonly #statusChangeDebouncer: {\n timer: NodeJS.Timeout | null;\n pendingChanges: Map<string, 'up' | 'down'>;\n } = {\n timer: null,\n pendingChanges: new Map(),\n };\n\n constructor({\n messenger,\n interval = DEFAULT_INTERVAL_MS,\n websocketActivePollingInterval = DEFAULT_WEBSOCKET_ACTIVE_POLLING_INTERVAL_MS,\n chainPollingIntervals = {},\n state = {},\n queryMultipleAccounts = true,\n accountsApiChainIds = (): ChainIdHex[] => [],\n allowExternalServices = (): boolean => true,\n platform,\n }: TokenBalancesControllerOptions) {\n super({\n name: CONTROLLER,\n messenger,\n metadata,\n state: { tokenBalances: {}, ...state },\n });\n\n this.#normalizeAccountAddresses();\n\n this.#platform = platform ?? 'extension';\n this.#queryAllAccounts = queryMultipleAccounts;\n this.#accountsApiChainIds = accountsApiChainIds;\n this.#allowExternalServices = allowExternalServices;\n this.#defaultInterval = interval;\n this.#websocketActivePollingInterval = websocketActivePollingInterval;\n this.#chainPollingConfig = { ...chainPollingIntervals };\n\n // Always include AccountsApiFetcher - it dynamically checks allowExternalServices() in supports()\n this.#balanceFetchers = [\n this.#createAccountsApiFetcher(),\n new RpcBalanceFetcher(this.#getProvider, this.#getNetworkClient, () => ({\n allTokens: this.#allTokens,\n allDetectedTokens: this.#detectedTokens,\n })),\n ];\n\n this.setIntervalLength(interval);\n\n const { allTokens, allDetectedTokens, allIgnoredTokens } =\n this.messenger.call('TokensController:getState');\n this.#allTokens = allTokens;\n this.#detectedTokens = allDetectedTokens;\n this.#allIgnoredTokens = allIgnoredTokens;\n\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n this.#isUnlocked = isUnlocked;\n\n this.#subscribeToControllers();\n this.#registerActions();\n }\n\n #subscribeToControllers(): void {\n this.messenger.subscribe(\n 'TokensController:stateChange',\n (tokensState: TokensControllerState) => {\n this.#onTokensChanged(tokensState).catch((error) => {\n console.warn('Error handling token state change:', error);\n });\n },\n );\n\n this.messenger.subscribe(\n 'NetworkController:stateChange',\n this.#onNetworkChanged,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n });\n\n this.messenger.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n });\n\n this.messenger.subscribe(\n 'KeyringController:accountRemoved',\n this.#onAccountRemoved,\n );\n\n this.messenger.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n this.#onAccountChanged,\n );\n\n this.messenger.subscribe(\n 'AccountActivityService:balanceUpdated',\n (event) => {\n this.#onAccountActivityBalanceUpdate(event).catch((error) => {\n console.warn('Error handling balance update:', error);\n });\n },\n );\n\n this.messenger.subscribe(\n 'AccountActivityService:statusChanged',\n this.#onAccountActivityStatusChanged.bind(this),\n );\n\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n (transactionMeta) => {\n this.updateBalances({\n chainIds: [transactionMeta.chainId],\n }).catch(() => {\n // Silently handle balance update errors\n });\n },\n );\n\n this.messenger.subscribe(\n 'TransactionController:incomingTransactionsReceived',\n (incomingTransactions) => {\n this.updateBalances({\n chainIds: incomingTransactions.map((tx) => tx.chainId),\n }).catch(() => {\n // Silently handle balance update errors\n });\n },\n );\n }\n\n #registerActions(): void {\n this.messenger.registerActionHandler(\n `TokenBalancesController:updateChainPollingConfigs`,\n this.updateChainPollingConfigs.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `TokenBalancesController:getChainPollingConfig`,\n this.getChainPollingConfig.bind(this),\n );\n }\n\n /**\n * Whether the controller is active (keyring is unlocked).\n * When locked, balance updates should be skipped.\n *\n * @returns Whether the keyring is unlocked.\n */\n get isActive(): boolean {\n return this.#isUnlocked;\n }\n\n /**\n * Normalize all account addresses to lowercase and merge duplicates\n * Handles migration from old state where addresses might be checksummed.\n */\n #normalizeAccountAddresses(): void {\n const currentState = this.state.tokenBalances;\n const normalizedBalances: TokenBalances = {};\n\n for (const address of Object.keys(currentState)) {\n const lowercaseAddress = address.toLowerCase() as ChecksumAddress;\n const accountBalances = currentState[address as ChecksumAddress];\n\n if (!accountBalances) {\n continue;\n }\n\n normalizedBalances[lowercaseAddress] ??= {};\n\n for (const chainId of Object.keys(accountBalances)) {\n const chainIdKey = chainId as ChainIdHex;\n normalizedBalances[lowercaseAddress][chainIdKey] ??= {};\n\n Object.assign(\n normalizedBalances[lowercaseAddress][chainIdKey],\n accountBalances[chainIdKey],\n );\n }\n }\n\n if (\n Object.keys(currentState).length !==\n Object.keys(normalizedBalances).length ||\n Object.keys(currentState).some((addr) => addr !== addr.toLowerCase())\n ) {\n this.update(() => ({ tokenBalances: normalizedBalances }));\n }\n }\n\n #chainIdsWithTokens(): ChainIdHex[] {\n return [\n ...new Set([\n ...Object.keys(this.#allTokens),\n ...Object.keys(this.#detectedTokens),\n ]),\n ] as ChainIdHex[];\n }\n\n readonly #getProvider = (chainId: ChainIdHex): Web3Provider => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n const networkConfig = networkConfigurationsByChainId[chainId];\n const { networkClientId } =\n networkConfig.rpcEndpoints[networkConfig.defaultRpcEndpointIndex];\n const client = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (\n chainId: ChainIdHex,\n ): ReturnType<NetworkControllerGetNetworkClientByIdAction['handler']> => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n const networkConfig = networkConfigurationsByChainId[chainId];\n const { networkClientId } =\n networkConfig.rpcEndpoints[networkConfig.defaultRpcEndpointIndex];\n return this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n };\n\n readonly #createAccountsApiFetcher = (): BalanceFetcher => {\n const originalFetcher = new AccountsApiBalanceFetcher(\n this.#platform,\n this.#getProvider,\n );\n\n return {\n // Dynamically check allowExternalServices() at call time, not just at construction time\n supports: (chainId: ChainIdHex): boolean =>\n this.#allowExternalServices() &&\n this.#accountsApiChainIds().includes(chainId) &&\n originalFetcher.supports(chainId),\n fetch: originalFetcher.fetch.bind(originalFetcher),\n };\n };\n\n override _startPolling({ chainIds }: { chainIds: ChainIdHex[] }): void {\n this.#requestedChainIds = [...chainIds];\n this.#isControllerPollingActive = true;\n this.#startIntervalGroupPolling(chainIds, true);\n }\n\n #startIntervalGroupPolling(chainIds: ChainIdHex[], immediate = true): void {\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n const intervalGroups = new Map<number, ChainIdHex[]>();\n\n for (const chainId of chainIds) {\n const config = this.getChainPollingConfig(chainId);\n const group = intervalGroups.get(config.interval) ?? [];\n group.push(chainId);\n intervalGroups.set(config.interval, group);\n }\n\n for (const [interval, chainIdsGroup] of intervalGroups) {\n this.#startPollingForInterval(interval, chainIdsGroup, immediate);\n }\n }\n\n #startPollingForInterval(\n interval: number,\n chainIds: ChainIdHex[],\n immediate = true,\n ): void {\n const pollFunction = async (): Promise<void> => {\n if (!this.#isControllerPollingActive) {\n return;\n }\n\n try {\n await this._executePoll({ chainIds });\n } catch (error) {\n console.warn(\n `Polling failed for chains ${chainIds.join(', ')} with interval ${interval}:`,\n error,\n );\n }\n };\n\n if (immediate) {\n pollFunction().catch((error) => {\n console.warn(\n `Immediate polling failed for chains ${chainIds.join(', ')}:`,\n error,\n );\n });\n }\n\n this.#setPollingTimer(interval, chainIds, pollFunction);\n }\n\n #setPollingTimer(\n interval: number,\n chainIds: ChainIdHex[],\n pollFunction: () => Promise<void>,\n ): void {\n const timer = setInterval(() => {\n pollFunction().catch((error) => {\n console.warn(\n `Interval polling failed for chains ${chainIds.join(', ')}:`,\n error,\n );\n });\n }, interval);\n\n this.#intervalPollingTimers.set(interval, timer);\n }\n\n override _stopPollingByPollingTokenSetId(tokenSetId: string): void {\n let chainsToStop: ChainIdHex[] = [];\n\n try {\n const parsedTokenSetId = JSON.parse(tokenSetId);\n chainsToStop = parsedTokenSetId.chainIds ?? [];\n } catch (error) {\n console.warn('Failed to parse tokenSetId, stopping all polling:', error);\n this.#stopAllPolling();\n return;\n }\n\n const currentChainsSet = new Set(this.#requestedChainIds);\n const stopChainsSet = new Set(chainsToStop);\n\n const isCurrentSession =\n currentChainsSet.size === stopChainsSet.size &&\n [...currentChainsSet].every((chain) => stopChainsSet.has(chain));\n\n if (isCurrentSession) {\n this.#stopAllPolling();\n }\n }\n\n #stopAllPolling(): void {\n this.#isControllerPollingActive = false;\n this.#requestedChainIds = [];\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n }\n\n getChainPollingConfig(chainId: ChainIdHex): ChainPollingConfig {\n return (\n this.#chainPollingConfig[chainId] ?? {\n interval: this.#defaultInterval,\n }\n );\n }\n\n override async _executePoll({\n chainIds,\n queryAllAccounts = false,\n }: {\n chainIds: ChainIdHex[];\n queryAllAccounts?: boolean;\n }): Promise<void> {\n await this.updateBalances({ chainIds, queryAllAccounts });\n }\n\n updateChainPollingConfigs(\n configs: Record<ChainIdHex, ChainPollingConfig>,\n options: UpdateChainPollingConfigsOptions = { immediateUpdate: true },\n ): void {\n Object.assign(this.#chainPollingConfig, configs);\n\n if (this.#isControllerPollingActive) {\n this.#startIntervalGroupPolling(\n this.#requestedChainIds,\n options.immediateUpdate,\n );\n }\n }\n\n async updateBalances({\n chainIds,\n tokenAddresses,\n queryAllAccounts = false,\n }: {\n chainIds?: ChainIdHex[];\n tokenAddresses?: string[];\n queryAllAccounts?: boolean;\n } = {}): Promise<void> {\n if (!this.isActive) {\n return;\n }\n\n const targetChains = this.#getTargetChains(chainIds);\n if (!targetChains.length) {\n return;\n }\n\n const { selectedAccount, allAccounts, jwtToken } =\n await this.#getAccountsAndJwt();\n\n const aggregatedBalances = await this.#fetchAllBalances({\n targetChains,\n selectedAccount,\n allAccounts,\n jwtToken,\n queryAllAccounts: queryAllAccounts ?? this.#queryAllAccounts,\n });\n\n const filteredAggregated = this.#filterByTokenAddresses(\n aggregatedBalances,\n tokenAddresses,\n );\n\n const accountsToProcess = this.#getAccountsToProcess(\n queryAllAccounts,\n allAccounts,\n selectedAccount,\n );\n\n const prev = this.state;\n const next = this.#applyTokenBalancesToState({\n prev,\n targetChains,\n accountsToProcess,\n balances: filteredAggregated,\n });\n\n if (!isEqual(prev, next)) {\n this.update(() => next);\n\n const accountTrackerState = this.messenger.call(\n 'AccountTrackerController:getState',\n );\n\n const nativeUpdates = this.#buildNativeBalanceUpdates(\n filteredAggregated,\n accountTrackerState,\n );\n\n if (nativeUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n nativeUpdates,\n );\n }\n\n const stakedUpdates = this.#buildStakedBalanceUpdates(\n filteredAggregated,\n accountTrackerState,\n );\n\n if (stakedUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateStakedBalances',\n stakedUpdates,\n );\n }\n }\n\n await this.#importUntrackedTokens(filteredAggregated);\n }\n\n #getTargetChains(chainIds?: ChainIdHex[]): ChainIdHex[] {\n return chainIds?.length ? chainIds : this.#chainIdsWithTokens();\n }\n\n async #getAccountsAndJwt(): Promise<{\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n jwtToken: string | undefined;\n }> {\n const { address: selected } = this.messenger.call(\n 'AccountsController:getSelectedAccount',\n );\n const allAccounts = this.messenger.call('AccountsController:listAccounts');\n\n const jwtToken = await safelyExecuteWithTimeout<string | undefined>(\n () => {\n return this.messenger.call('AuthenticationController:getBearerToken');\n },\n false,\n 5000,\n );\n\n return {\n selectedAccount: selected as ChecksumAddress,\n allAccounts,\n jwtToken,\n };\n }\n\n async #fetchAllBalances({\n targetChains,\n selectedAccount,\n allAccounts,\n jwtToken,\n queryAllAccounts,\n }: {\n targetChains: ChainIdHex[];\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n jwtToken?: string;\n queryAllAccounts: boolean;\n }): Promise<ProcessedBalance[]> {\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...targetChains];\n\n for (const fetcher of this.#balanceFetchers) {\n const supportedChains = remainingChains.filter((chain) =>\n fetcher.supports(chain),\n );\n if (!supportedChains.length) {\n continue;\n }\n\n try {\n const result = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n jwtToken,\n });\n\n if (result.balances?.length) {\n aggregated.push(...result.balances);\n\n const processed = new Set(result.balances.map((b) => b.chainId));\n remainingChains = remainingChains.filter(\n (chain) => !processed.has(chain),\n );\n }\n\n if (result.unprocessedChainIds?.length) {\n const currentRemaining = [...remainingChains];\n const chainsToAdd = result.unprocessedChainIds.filter(\n (chainId) =>\n supportedChains.includes(chainId) &&\n !currentRemaining.includes(chainId),\n );\n remainingChains.push(...chainsToAdd);\n\n this.messenger\n .call('TokenDetectionController:detectTokens', {\n chainIds: result.unprocessedChainIds,\n forceRpc: true,\n })\n .catch(() => {\n // Silently handle token detection errors\n });\n }\n } catch (error) {\n console.warn(\n `Balance fetcher failed for chains ${supportedChains.join(', ')}: ${String(error)}`,\n );\n\n this.messenger\n .call('TokenDetectionController:detectTokens', {\n chainIds: supportedChains,\n forceRpc: true,\n })\n .catch(() => {\n // Silently handle token detection errors\n });\n }\n\n if (!remainingChains.length) {\n break;\n }\n }\n\n return aggregated;\n }\n\n #filterByTokenAddresses(\n balances: ProcessedBalance[],\n tokenAddresses?: string[],\n ): ProcessedBalance[] {\n if (!tokenAddresses?.length) {\n return balances;\n }\n\n const lowered = tokenAddresses.map((a) => a.toLowerCase());\n return balances.filter((balance) =>\n lowered.includes(balance.token.toLowerCase()),\n );\n }\n\n #getAccountsToProcess(\n queryAllAccountsParam: boolean | undefined,\n allAccounts: InternalAccount[],\n selectedAccount: ChecksumAddress,\n ): ChecksumAddress[] {\n const effectiveQueryAll =\n queryAllAccountsParam ?? this.#queryAllAccounts ?? false;\n\n if (!effectiveQueryAll) {\n return [selectedAccount];\n }\n\n return allAccounts.map((account) => account.address as ChecksumAddress);\n }\n\n #applyTokenBalancesToState({\n prev,\n targetChains,\n accountsToProcess,\n balances,\n }: {\n prev: TokenBalancesControllerState;\n targetChains: ChainIdHex[];\n accountsToProcess: ChecksumAddress[];\n balances: ProcessedBalance[];\n }): TokenBalancesControllerState {\n return draft(prev, (draftState) => {\n for (const chainId of targetChains) {\n for (const account of accountsToProcess) {\n draftState.tokenBalances[account] ??= {};\n draftState.tokenBalances[account][chainId] ??= {};\n\n const chainTokens = this.#allTokens[chainId];\n if (chainTokens?.[account]) {\n Object.values(chainTokens[account]).forEach(\n (token: { address: string }) => {\n const tokenAddress = checksum(token.address);\n draftState.tokenBalances[account][chainId][tokenAddress] ??=\n '0x0';\n },\n );\n }\n\n const detectedChainTokens = this.#detectedTokens[chainId];\n if (detectedChainTokens?.[account]) {\n Object.values(detectedChainTokens[account]).forEach(\n (token: { address: string }) => {\n const tokenAddress = checksum(token.address);\n draftState.tokenBalances[account][chainId][tokenAddress] ??=\n '0x0';\n },\n );\n }\n }\n }\n\n balances.forEach(({ success, value, account, token, chainId }) => {\n if (!success || value === undefined) {\n return;\n }\n\n const lowerCaseAccount = account.toLowerCase() as ChecksumAddress;\n const newBalance = toHex(value);\n const tokenAddress = checksum(token);\n\n const currentBalance =\n draftState.tokenBalances[lowerCaseAccount]?.[chainId]?.[tokenAddress];\n\n if (currentBalance !== newBalance) {\n ((draftState.tokenBalances[lowerCaseAccount] ??= {})[chainId] ??= {})[\n tokenAddress\n ] = newBalance;\n }\n });\n });\n }\n\n #buildNativeBalanceUpdates(\n balances: ProcessedBalance[],\n accountTrackerState: {\n accountsByChainId: Record<\n string,\n Record<string, { balance?: string; stakedBalance?: string }>\n >;\n },\n ): NativeBalanceUpdate[] {\n const nativeBalances = balances.filter(\n (balance) => balance.success && balance.token === ZERO_ADDRESS,\n );\n\n if (!nativeBalances.length) {\n return [];\n }\n\n return nativeBalances\n .map((balance) => ({\n address: balance.account,\n chainId: balance.chainId,\n balance: balance.value ? BNToHex(balance.value) : '0x0',\n }))\n .filter((update) => {\n const currentBalance =\n accountTrackerState.accountsByChainId[update.chainId]?.[\n checksum(update.address)\n ]?.balance;\n return currentBalance !== update.balance;\n });\n }\n\n #buildStakedBalanceUpdates(\n balances: ProcessedBalance[],\n accountTrackerState: {\n accountsByChainId: Record<\n string,\n Record<string, { balance?: string; stakedBalance?: string }>\n >;\n },\n ): StakedBalanceUpdate[] {\n const stakedBalances = balances.filter((balance) => {\n if (!balance.success || balance.token === ZERO_ADDRESS) {\n return false;\n }\n\n const stakingContractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[balance.chainId];\n return (\n stakingContractAddress &&\n stakingContractAddress.toLowerCase() === balance.token.toLowerCase()\n );\n });\n\n if (!stakedBalances.length) {\n return [];\n }\n\n return stakedBalances\n .map((balance) => ({\n address: balance.account,\n chainId: balance.chainId,\n stakedBalance: balance.value ? toHex(balance.value) : '0x0',\n }))\n .filter((update) => {\n const currentStakedBalance =\n accountTrackerState.accountsByChainId[update.chainId]?.[\n checksum(update.address)\n ]?.stakedBalance;\n return currentStakedBalance !== update.stakedBalance;\n });\n }\n\n /**\n * Import untracked tokens that have non-zero balances.\n * This mirrors the v2 behavior where only tokens with actual balances are added.\n * Delegates to TokenDetectionController:addDetectedTokensViaPolling which handles:\n * - Checking if useTokenDetection preference is enabled\n * - Filtering tokens already in allTokens or allIgnoredTokens\n * - Token metadata lookup and addition via TokensController\n *\n * @param balances - Array of processed balance results from fetchers\n */\n async #importUntrackedTokens(balances: ProcessedBalance[]): Promise<void> {\n const tokensByChain = new Map<ChainIdHex, string[]>();\n\n for (const balance of balances) {\n // Skip failed fetches, native tokens, and zero balances (like v2 did)\n if (\n !balance.success ||\n balance.token === ZERO_ADDRESS ||\n !balance.value ||\n balance.value.isZero()\n ) {\n continue;\n }\n\n const tokenAddress = checksum(balance.token);\n const existing = tokensByChain.get(balance.chainId) ?? [];\n if (!existing.includes(tokenAddress)) {\n existing.push(tokenAddress);\n tokensByChain.set(balance.chainId, existing);\n }\n }\n\n // Add detected tokens via TokenDetectionController (handles preference check,\n // filtering of allTokens/allIgnoredTokens, and metadata lookup)\n for (const [chainId, tokenAddresses] of tokensByChain) {\n if (tokenAddresses.length) {\n await this.messenger.call(\n 'TokenDetectionController:addDetectedTokensViaPolling',\n {\n tokensSlice: tokenAddresses,\n chainId,\n },\n );\n }\n }\n }\n\n resetState(): void {\n this.update(() => ({ tokenBalances: {} }));\n }\n\n #isTokenTracked(\n tokenAddress: string,\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): boolean {\n const normalizedAccount = account.toLowerCase();\n\n if (\n this.#allTokens?.[chainId]?.[normalizedAccount]?.some(\n (token) => token.address === tokenAddress,\n )\n ) {\n return true;\n }\n\n if (\n this.#allIgnoredTokens?.[chainId]?.[normalizedAccount]?.some(\n (token) => token === tokenAddress,\n )\n ) {\n return true;\n }\n\n return false;\n }\n\n readonly #onTokensChanged = async (\n state: TokensControllerState,\n ): Promise<void> => {\n const changed: ChainIdHex[] = [];\n let hasChanges = false;\n\n const incomingChainIds = new Set([\n ...Object.keys(state.allTokens),\n ...Object.keys(state.allDetectedTokens),\n ]);\n\n const relevantChainIds = Array.from(incomingChainIds).filter((chainId) => {\n const id = chainId as ChainIdHex;\n\n const hasTokensNow =\n (state.allTokens[id] && Object.keys(state.allTokens[id]).length > 0) ||\n (state.allDetectedTokens[id] &&\n Object.keys(state.allDetectedTokens[id]).length > 0);\n const hadTokensBefore =\n (this.#allTokens[id] && Object.keys(this.#allTokens[id]).length > 0) ||\n (this.#detectedTokens[id] &&\n Object.keys(this.#detectedTokens[id]).length > 0);\n\n const hasTokenChange =\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id]);\n\n return hasTokenChange || (!hadTokensBefore && hasTokensNow);\n });\n\n if (!relevantChainIds.length) {\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n return;\n }\n\n this.update((currentState) => {\n for (const chainId of relevantChainIds) {\n const id = chainId as ChainIdHex;\n const hasTokensNow =\n (state.allTokens[id] &&\n Object.keys(state.allTokens[id]).length > 0) ||\n (state.allDetectedTokens[id] &&\n Object.keys(state.allDetectedTokens[id]).length > 0);\n const hadTokensBefore =\n (this.#allTokens[id] &&\n Object.keys(this.#allTokens[id]).length > 0) ||\n (this.#detectedTokens[id] &&\n Object.keys(this.#detectedTokens[id]).length > 0);\n\n const tokensChanged =\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id]);\n\n if (!tokensChanged) {\n continue;\n }\n\n if (hasTokensNow) {\n changed.push(id);\n } else if (hadTokensBefore) {\n for (const address of Object.keys(currentState.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n if (currentState.tokenBalances[addressKey]?.[id]) {\n currentState.tokenBalances[addressKey][id] = {};\n hasChanges = true;\n }\n }\n }\n }\n });\n\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n this.#allIgnoredTokens = state.allIgnoredTokens;\n\n if (changed.length && !hasChanges) {\n this.updateBalances({ chainIds: changed }).catch((error) => {\n console.warn('Error updating balances after token change:', error);\n });\n }\n };\n\n readonly #onNetworkChanged = (state: NetworkState): void => {\n const currentNetworks = new Set(\n Object.keys(state.networkConfigurationsByChainId),\n );\n\n const networksWithBalances = new Set<string>();\n for (const address of Object.keys(this.state.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const network of Object.keys(\n this.state.tokenBalances[addressKey] || {},\n )) {\n networksWithBalances.add(network);\n }\n }\n\n const removedNetworks = Array.from(networksWithBalances).filter(\n (network) => !currentNetworks.has(network),\n );\n\n if (!removedNetworks.length) {\n return;\n }\n\n this.update((currentState) => {\n for (const address of Object.keys(currentState.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const removedNetwork of removedNetworks) {\n const networkKey = removedNetwork as ChainIdHex;\n if (currentState.tokenBalances[addressKey]?.[networkKey]) {\n delete currentState.tokenBalances[addressKey][networkKey];\n }\n }\n }\n });\n };\n\n readonly #onAccountRemoved = (addr: string): void => {\n if (!isStrictHexString(addr) || !isValidHexAddress(addr)) {\n return;\n }\n this.update((currentState) => {\n delete currentState.tokenBalances[addr];\n });\n };\n\n readonly #onAccountChanged = (): void => {\n const chainIds = this.#chainIdsWithTokens();\n if (!chainIds.length) {\n return;\n }\n\n this.updateBalances({ chainIds }).catch(() => {\n // Silently handle polling errors\n });\n };\n\n #prepareBalanceUpdates(\n updates: BalanceUpdate[],\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): {\n tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[];\n newTokens: string[];\n nativeBalanceUpdates: NativeBalanceUpdate[];\n } {\n const tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[] = [];\n const newTokens: string[] = [];\n const nativeBalanceUpdates: NativeBalanceUpdate[] = [];\n\n for (const update of updates) {\n const { asset, postBalance } = update;\n\n if (postBalance.error) {\n throw new Error('Balance update has error');\n }\n\n const parsed = parseAssetType(asset.type);\n if (!parsed) {\n throw new Error('Failed to parse asset type');\n }\n\n const [tokenAddress, isNativeToken] = parsed;\n\n if (\n !isStrictHexString(tokenAddress) ||\n !isValidHexAddress(tokenAddress)\n ) {\n throw new Error('Invalid token address');\n }\n\n const checksumTokenAddress = checksum(tokenAddress);\n const isTracked = this.#isTokenTracked(\n checksumTokenAddress,\n account,\n chainId,\n );\n\n const balanceHex = postBalance.amount as Hex;\n\n tokenBalances.push({\n tokenAddress: checksumTokenAddress,\n balance: balanceHex,\n });\n\n if (isNativeToken) {\n nativeBalanceUpdates.push({\n address: account,\n chainId,\n balance: balanceHex,\n });\n }\n\n if (!isNativeToken && !isTracked) {\n newTokens.push(checksumTokenAddress);\n }\n }\n\n return { tokenBalances, newTokens, nativeBalanceUpdates };\n }\n\n readonly #onAccountActivityBalanceUpdate = async ({\n address,\n chain,\n updates,\n }: {\n address: string;\n chain: string;\n updates: BalanceUpdate[];\n }): Promise<void> => {\n const chainId = caipChainIdToHex(chain);\n const checksummedAccount = checksum(address);\n\n try {\n const { tokenBalances, newTokens, nativeBalanceUpdates } =\n this.#prepareBalanceUpdates(updates, checksummedAccount, chainId);\n\n if (tokenBalances.length > 0) {\n this.update((state) => {\n const lowercaseAccount =\n checksummedAccount.toLowerCase() as ChecksumAddress;\n state.tokenBalances[lowercaseAccount] ??= {};\n state.tokenBalances[lowercaseAccount][chainId] ??= {};\n\n for (const { tokenAddress, balance } of tokenBalances) {\n state.tokenBalances[lowercaseAccount][chainId][tokenAddress] =\n balance;\n }\n });\n }\n\n if (nativeBalanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n nativeBalanceUpdates,\n );\n }\n\n if (newTokens.length > 0) {\n await this.messenger.call(\n 'TokenDetectionController:addDetectedTokensViaWs',\n {\n tokensSlice: newTokens,\n chainId,\n },\n );\n }\n } catch (error) {\n console.warn(\n `Error updating balances from AccountActivityService for chain ${chain}, account ${address}:`,\n error,\n );\n console.warn('Balance update data:', JSON.stringify(updates, null, 2));\n\n await this.updateBalances({ chainIds: [chainId] }).catch(() => {\n // Silently handle polling errors\n });\n }\n };\n\n readonly #onAccountActivityStatusChanged = ({\n chainIds,\n status,\n }: {\n chainIds: string[];\n status: 'up' | 'down';\n }): void => {\n for (const chainId of chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, status);\n }\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, 5000);\n };\n\n #processAccumulatedStatusChanges(): void {\n const changes = Array.from(\n this.#statusChangeDebouncer.pendingChanges.entries(),\n );\n this.#statusChangeDebouncer.pendingChanges.clear();\n this.#statusChangeDebouncer.timer = null;\n\n if (!changes.length) {\n return;\n }\n\n const chainConfigs: Record<ChainIdHex, { interval: number }> = {};\n\n for (const [chainId, status] of changes) {\n const hexChainId = caipChainIdToHex(chainId);\n\n chainConfigs[hexChainId] =\n status === 'down'\n ? { interval: this.#defaultInterval }\n : { interval: this.#websocketActivePollingInterval };\n }\n\n const jitterDelay = Math.random() * this.#defaultInterval;\n\n setTimeout(() => {\n this.updateChainPollingConfigs(chainConfigs, { immediateUpdate: true });\n }, jitterDelay);\n }\n\n override destroy(): void {\n this.#isControllerPollingActive = false;\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n this.messenger.unregisterActionHandler(\n `TokenBalancesController:updateChainPollingConfigs`,\n );\n this.messenger.unregisterActionHandler(\n `TokenBalancesController:getChainPollingConfig`,\n );\n\n super.destroy();\n }\n}\n\nexport default TokenBalancesController;\n"]}
|
|
1
|
+
{"version":3,"file":"TokenBalancesController.mjs","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n AccountsControllerSelectedEvmAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport {\n BNToHex,\n isValidHexAddress,\n safelyExecuteWithTimeout,\n toChecksumHexAddress,\n toHex,\n} from '@metamask/controller-utils';\nimport type {\n BalanceUpdate,\n AccountActivityServiceBalanceUpdatedEvent,\n AccountActivityServiceStatusChangedEvent,\n} from '@metamask/core-backend';\nimport type {\n KeyringControllerAccountRemovedEvent,\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 NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n NetworkControllerStateChangeEvent,\n NetworkState,\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 {\n TransactionControllerIncomingTransactionsReceivedEvent,\n TransactionControllerTransactionConfirmedEvent,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport {\n isCaipAssetType,\n isCaipChainId,\n isStrictHexString,\n parseCaipAssetType,\n parseCaipChainId,\n} from '@metamask/utils';\nimport { produce } from 'immer';\nimport { isEqual } from 'lodash';\n\nimport type {\n AccountTrackerControllerGetStateAction,\n AccountTrackerUpdateNativeBalancesAction,\n AccountTrackerUpdateStakedBalancesAction,\n} from './AccountTrackerController';\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from './AssetsContractController';\nimport { AccountsApiBalanceFetcher } from './multi-chain-accounts-service/api-balance-fetcher';\nimport type {\n BalanceFetcher,\n ProcessedBalance,\n} from './multi-chain-accounts-service/api-balance-fetcher';\nimport { RpcBalanceFetcher } from './rpc-service/rpc-balance-fetcher';\nimport type {\n TokenDetectionControllerAddDetectedTokensViaPollingAction,\n TokenDetectionControllerAddDetectedTokensViaWsAction,\n TokenDetectionControllerDetectTokensAction,\n} from './TokenDetectionController';\nimport type {\n TokensControllerGetStateAction,\n TokensControllerState,\n TokensControllerStateChangeEvent,\n} from './TokensController';\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nconst CONTROLLER = 'TokenBalancesController' as const;\nconst DEFAULT_INTERVAL_MS = 30_000; // 30 seconds\nconst DEFAULT_WEBSOCKET_ACTIVE_POLLING_INTERVAL_MS = 300_000; // 5 minutes\n\nconst metadata: StateMetadata<TokenBalancesControllerState> = {\n tokenBalances: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n};\n\n// account → chain → token → balance\nexport type TokenBalances = Record<\n ChecksumAddress,\n Record<ChainIdHex, Record<ChecksumAddress, Hex>>\n>;\n\nexport type TokenBalancesControllerState = {\n tokenBalances: TokenBalances;\n};\n\nexport type TokenBalancesControllerGetStateAction = ControllerGetStateAction<\n typeof CONTROLLER,\n TokenBalancesControllerState\n>;\n\nexport type TokenBalancesControllerUpdateChainPollingConfigsAction = {\n type: `TokenBalancesController:updateChainPollingConfigs`;\n handler: TokenBalancesController['updateChainPollingConfigs'];\n};\n\nexport type TokenBalancesControllerGetChainPollingConfigAction = {\n type: `TokenBalancesController:getChainPollingConfig`;\n handler: TokenBalancesController['getChainPollingConfig'];\n};\n\nexport type TokenBalancesControllerActions =\n | TokenBalancesControllerGetStateAction\n | TokenBalancesControllerUpdateChainPollingConfigsAction\n | TokenBalancesControllerGetChainPollingConfigAction;\n\nexport type TokenBalancesControllerStateChangeEvent =\n ControllerStateChangeEvent<typeof CONTROLLER, TokenBalancesControllerState>;\n\nexport type NativeBalanceEvent = {\n type: `${typeof CONTROLLER}:updatedNativeBalance`;\n payload: unknown[];\n};\n\nexport type TokenBalancesControllerEvents =\n | TokenBalancesControllerStateChangeEvent\n | NativeBalanceEvent;\n\nexport type AllowedActions =\n | NetworkControllerGetNetworkClientByIdAction\n | NetworkControllerGetStateAction\n | TokensControllerGetStateAction\n | TokenDetectionControllerAddDetectedTokensViaPollingAction\n | TokenDetectionControllerAddDetectedTokensViaWsAction\n | TokenDetectionControllerDetectTokensAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerListAccountsAction\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction\n | KeyringControllerGetStateAction\n | AuthenticationController.AuthenticationControllerGetBearerToken;\n\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | PreferencesControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | KeyringControllerAccountRemovedEvent\n | KeyringControllerLockEvent\n | KeyringControllerUnlockEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceStatusChangedEvent\n | AccountsControllerSelectedEvmAccountChangeEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerIncomingTransactionsReceivedEvent;\n\nexport type TokenBalancesControllerMessenger = Messenger<\n typeof CONTROLLER,\n TokenBalancesControllerActions | AllowedActions,\n TokenBalancesControllerEvents | AllowedEvents\n>;\n\nexport type ChainPollingConfig = {\n /** Polling interval in milliseconds for this chain */\n interval: number;\n};\n\nexport type UpdateChainPollingConfigsOptions = {\n /** Whether to immediately fetch balances after updating configs (default: true) */\n immediateUpdate?: boolean;\n};\n\nexport type TokenBalancesControllerOptions = {\n messenger: TokenBalancesControllerMessenger;\n /** Default interval for chains not specified in chainPollingIntervals */\n interval?: number;\n /** Per-chain polling configuration */\n chainPollingIntervals?: Record<ChainIdHex, ChainPollingConfig>;\n state?: Partial<TokenBalancesControllerState>;\n /** When `true`, balances for *all* known accounts are queried. */\n queryMultipleAccounts?: boolean;\n /** Array of chainIds that should use Accounts-API strategy (if supported by API). */\n accountsApiChainIds?: () => ChainIdHex[];\n /** Disable external HTTP calls (privacy / offline mode). */\n allowExternalServices?: () => boolean;\n /** Custom logger. */\n log?: (...args: unknown[]) => void;\n platform?: 'extension' | 'mobile';\n /** Polling interval when WebSocket is active and providing real-time updates */\n websocketActivePollingInterval?: number;\n /** Whether the user has completed onboarding. If false, balance updates are skipped. */\n isOnboarded?: () => boolean;\n};\n\nconst draft = <State>(base: State, fn: (draftState: State) => void): State =>\n produce(base, fn);\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\n/**\n * Convert CAIP chain ID or hex chain ID to hex chain ID.\n *\n * @param chainId - CAIP chain ID or hex chain ID.\n * @returns Hex chain ID.\n */\nexport const caipChainIdToHex = (chainId: string): ChainIdHex => {\n if (isStrictHexString(chainId)) {\n return chainId;\n }\n\n if (isCaipChainId(chainId)) {\n return toHex(parseCaipChainId(chainId).reference);\n }\n\n throw new Error('caipChainIdToHex - Failed to provide CAIP-2 or Hex chainId');\n};\n\n/**\n * Extract token address from asset type.\n *\n * @param assetType - Asset type string.\n * @returns Tuple of [tokenAddress, isNativeToken] or null if invalid.\n */\nexport const parseAssetType = (assetType: string): [string, boolean] | null => {\n if (!isCaipAssetType(assetType)) {\n return null;\n }\n\n const parsed = parseCaipAssetType(assetType);\n\n if (parsed.assetNamespace === 'erc20') {\n return [parsed.assetReference, false];\n }\n\n if (parsed.assetNamespace === 'slip44') {\n return [ZERO_ADDRESS, true];\n }\n\n return null;\n};\n\ntype NativeBalanceUpdate = { address: string; chainId: Hex; balance: Hex };\ntype StakedBalanceUpdate = {\n address: string;\n chainId: Hex;\n stakedBalance: Hex;\n};\nexport class TokenBalancesController extends StaticIntervalPollingController<{\n chainIds: ChainIdHex[];\n}>()<\n typeof CONTROLLER,\n TokenBalancesControllerState,\n TokenBalancesControllerMessenger\n> {\n readonly #platform: 'extension' | 'mobile';\n\n readonly #queryAllAccounts: boolean;\n\n readonly #accountsApiChainIds: () => ChainIdHex[];\n\n readonly #allowExternalServices: () => boolean;\n\n readonly #isOnboarded: () => boolean;\n\n readonly #balanceFetchers: BalanceFetcher[];\n\n #allTokens: TokensControllerState['allTokens'] = {};\n\n #detectedTokens: TokensControllerState['allDetectedTokens'] = {};\n\n #allIgnoredTokens: TokensControllerState['allIgnoredTokens'] = {};\n\n /** Default polling interval for chains without specific configuration */\n readonly #defaultInterval: number;\n\n /** Polling interval when WebSocket is active and providing real-time updates */\n readonly #websocketActivePollingInterval: number;\n\n /** Per-chain polling configuration */\n readonly #chainPollingConfig: Record<ChainIdHex, ChainPollingConfig>;\n\n /** Active polling timers grouped by interval */\n readonly #intervalPollingTimers: Map<number, NodeJS.Timeout> = new Map();\n\n /** Track if controller-level polling is active */\n #isControllerPollingActive = false;\n\n /** Track if the keyring is unlocked */\n #isUnlocked = false;\n\n /** Store original chainIds from startPolling to preserve intent */\n #requestedChainIds: ChainIdHex[] = [];\n\n /** Debouncing for rapid status changes to prevent excessive HTTP calls */\n readonly #statusChangeDebouncer: {\n timer: NodeJS.Timeout | null;\n pendingChanges: Map<string, 'up' | 'down'>;\n } = {\n timer: null,\n pendingChanges: new Map(),\n };\n\n constructor({\n messenger,\n interval = DEFAULT_INTERVAL_MS,\n websocketActivePollingInterval = DEFAULT_WEBSOCKET_ACTIVE_POLLING_INTERVAL_MS,\n chainPollingIntervals = {},\n state = {},\n queryMultipleAccounts = true,\n accountsApiChainIds = (): ChainIdHex[] => [],\n allowExternalServices = (): boolean => true,\n platform,\n isOnboarded = (): boolean => true,\n }: TokenBalancesControllerOptions) {\n super({\n name: CONTROLLER,\n messenger,\n metadata,\n state: { tokenBalances: {}, ...state },\n });\n\n this.#normalizeAccountAddresses();\n\n this.#platform = platform ?? 'extension';\n this.#queryAllAccounts = queryMultipleAccounts;\n this.#accountsApiChainIds = accountsApiChainIds;\n this.#allowExternalServices = allowExternalServices;\n this.#isOnboarded = isOnboarded;\n this.#defaultInterval = interval;\n this.#websocketActivePollingInterval = websocketActivePollingInterval;\n this.#chainPollingConfig = { ...chainPollingIntervals };\n\n // Always include AccountsApiFetcher - it dynamically checks allowExternalServices() in supports()\n this.#balanceFetchers = [\n this.#createAccountsApiFetcher(),\n new RpcBalanceFetcher(this.#getProvider, this.#getNetworkClient, () => ({\n allTokens: this.#allTokens,\n allDetectedTokens: this.#detectedTokens,\n })),\n ];\n\n this.setIntervalLength(interval);\n\n const { allTokens, allDetectedTokens, allIgnoredTokens } =\n this.messenger.call('TokensController:getState');\n this.#allTokens = allTokens;\n this.#detectedTokens = allDetectedTokens;\n this.#allIgnoredTokens = allIgnoredTokens;\n\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n this.#isUnlocked = isUnlocked;\n\n this.#subscribeToControllers();\n this.#registerActions();\n }\n\n #subscribeToControllers(): void {\n this.messenger.subscribe(\n 'TokensController:stateChange',\n (tokensState: TokensControllerState) => {\n this.#onTokensChanged(tokensState).catch((error) => {\n console.warn('Error handling token state change:', error);\n });\n },\n );\n\n this.messenger.subscribe(\n 'NetworkController:stateChange',\n this.#onNetworkChanged,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n this.#isUnlocked = true;\n });\n\n this.messenger.subscribe('KeyringController:lock', () => {\n this.#isUnlocked = false;\n });\n\n this.messenger.subscribe(\n 'KeyringController:accountRemoved',\n this.#onAccountRemoved,\n );\n\n this.messenger.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n this.#onAccountChanged,\n );\n\n this.messenger.subscribe(\n 'AccountActivityService:balanceUpdated',\n (event) => {\n this.#onAccountActivityBalanceUpdate(event).catch((error) => {\n console.warn('Error handling balance update:', error);\n });\n },\n );\n\n this.messenger.subscribe(\n 'AccountActivityService:statusChanged',\n this.#onAccountActivityStatusChanged.bind(this),\n );\n\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n (transactionMeta) => {\n this.updateBalances({\n chainIds: [transactionMeta.chainId],\n }).catch(() => {\n // Silently handle balance update errors\n });\n },\n );\n\n this.messenger.subscribe(\n 'TransactionController:incomingTransactionsReceived',\n (incomingTransactions) => {\n this.updateBalances({\n chainIds: incomingTransactions.map((tx) => tx.chainId),\n }).catch(() => {\n // Silently handle balance update errors\n });\n },\n );\n }\n\n #registerActions(): void {\n this.messenger.registerActionHandler(\n `TokenBalancesController:updateChainPollingConfigs`,\n this.updateChainPollingConfigs.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `TokenBalancesController:getChainPollingConfig`,\n this.getChainPollingConfig.bind(this),\n );\n }\n\n /**\n * Whether the controller is active (keyring is unlocked and user is onboarded).\n * When locked or not onboarded, balance updates should be skipped.\n *\n * @returns Whether the controller should perform balance updates.\n */\n get isActive(): boolean {\n return this.#isUnlocked && this.#isOnboarded();\n }\n\n /**\n * Normalize all account addresses to lowercase and merge duplicates\n * Handles migration from old state where addresses might be checksummed.\n */\n #normalizeAccountAddresses(): void {\n const currentState = this.state.tokenBalances;\n const normalizedBalances: TokenBalances = {};\n\n for (const address of Object.keys(currentState)) {\n const lowercaseAddress = address.toLowerCase() as ChecksumAddress;\n const accountBalances = currentState[address as ChecksumAddress];\n\n if (!accountBalances) {\n continue;\n }\n\n normalizedBalances[lowercaseAddress] ??= {};\n\n for (const chainId of Object.keys(accountBalances)) {\n const chainIdKey = chainId as ChainIdHex;\n normalizedBalances[lowercaseAddress][chainIdKey] ??= {};\n\n Object.assign(\n normalizedBalances[lowercaseAddress][chainIdKey],\n accountBalances[chainIdKey],\n );\n }\n }\n\n if (\n Object.keys(currentState).length !==\n Object.keys(normalizedBalances).length ||\n Object.keys(currentState).some((addr) => addr !== addr.toLowerCase())\n ) {\n this.update(() => ({ tokenBalances: normalizedBalances }));\n }\n }\n\n #chainIdsWithTokens(): ChainIdHex[] {\n return [\n ...new Set([\n ...Object.keys(this.#allTokens),\n ...Object.keys(this.#detectedTokens),\n ]),\n ] as ChainIdHex[];\n }\n\n readonly #getProvider = (chainId: ChainIdHex): Web3Provider => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n const networkConfig = networkConfigurationsByChainId[chainId];\n const { networkClientId } =\n networkConfig.rpcEndpoints[networkConfig.defaultRpcEndpointIndex];\n const client = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (\n chainId: ChainIdHex,\n ): ReturnType<NetworkControllerGetNetworkClientByIdAction['handler']> => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n const networkConfig = networkConfigurationsByChainId[chainId];\n const { networkClientId } =\n networkConfig.rpcEndpoints[networkConfig.defaultRpcEndpointIndex];\n return this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n };\n\n readonly #createAccountsApiFetcher = (): BalanceFetcher => {\n const originalFetcher = new AccountsApiBalanceFetcher(\n this.#platform,\n this.#getProvider,\n );\n\n return {\n // Dynamically check allowExternalServices() at call time, not just at construction time\n supports: (chainId: ChainIdHex): boolean =>\n this.#allowExternalServices() &&\n this.#accountsApiChainIds().includes(chainId) &&\n originalFetcher.supports(chainId),\n fetch: originalFetcher.fetch.bind(originalFetcher),\n };\n };\n\n override _startPolling({ chainIds }: { chainIds: ChainIdHex[] }): void {\n this.#requestedChainIds = [...chainIds];\n this.#isControllerPollingActive = true;\n this.#startIntervalGroupPolling(chainIds, true);\n }\n\n #startIntervalGroupPolling(chainIds: ChainIdHex[], immediate = true): void {\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n const intervalGroups = new Map<number, ChainIdHex[]>();\n\n for (const chainId of chainIds) {\n const config = this.getChainPollingConfig(chainId);\n const group = intervalGroups.get(config.interval) ?? [];\n group.push(chainId);\n intervalGroups.set(config.interval, group);\n }\n\n for (const [interval, chainIdsGroup] of intervalGroups) {\n this.#startPollingForInterval(interval, chainIdsGroup, immediate);\n }\n }\n\n #startPollingForInterval(\n interval: number,\n chainIds: ChainIdHex[],\n immediate = true,\n ): void {\n const pollFunction = async (): Promise<void> => {\n if (!this.#isControllerPollingActive) {\n return;\n }\n\n try {\n await this._executePoll({ chainIds });\n } catch (error) {\n console.warn(\n `Polling failed for chains ${chainIds.join(', ')} with interval ${interval}:`,\n error,\n );\n }\n };\n\n if (immediate) {\n pollFunction().catch((error) => {\n console.warn(\n `Immediate polling failed for chains ${chainIds.join(', ')}:`,\n error,\n );\n });\n }\n\n this.#setPollingTimer(interval, chainIds, pollFunction);\n }\n\n #setPollingTimer(\n interval: number,\n chainIds: ChainIdHex[],\n pollFunction: () => Promise<void>,\n ): void {\n const timer = setInterval(() => {\n pollFunction().catch((error) => {\n console.warn(\n `Interval polling failed for chains ${chainIds.join(', ')}:`,\n error,\n );\n });\n }, interval);\n\n this.#intervalPollingTimers.set(interval, timer);\n }\n\n override _stopPollingByPollingTokenSetId(tokenSetId: string): void {\n let chainsToStop: ChainIdHex[] = [];\n\n try {\n const parsedTokenSetId = JSON.parse(tokenSetId);\n chainsToStop = parsedTokenSetId.chainIds ?? [];\n } catch (error) {\n console.warn('Failed to parse tokenSetId, stopping all polling:', error);\n this.#stopAllPolling();\n return;\n }\n\n const currentChainsSet = new Set(this.#requestedChainIds);\n const stopChainsSet = new Set(chainsToStop);\n\n const isCurrentSession =\n currentChainsSet.size === stopChainsSet.size &&\n [...currentChainsSet].every((chain) => stopChainsSet.has(chain));\n\n if (isCurrentSession) {\n this.#stopAllPolling();\n }\n }\n\n #stopAllPolling(): void {\n this.#isControllerPollingActive = false;\n this.#requestedChainIds = [];\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n }\n\n getChainPollingConfig(chainId: ChainIdHex): ChainPollingConfig {\n return (\n this.#chainPollingConfig[chainId] ?? {\n interval: this.#defaultInterval,\n }\n );\n }\n\n override async _executePoll({\n chainIds,\n queryAllAccounts = false,\n }: {\n chainIds: ChainIdHex[];\n queryAllAccounts?: boolean;\n }): Promise<void> {\n await this.updateBalances({ chainIds, queryAllAccounts });\n }\n\n updateChainPollingConfigs(\n configs: Record<ChainIdHex, ChainPollingConfig>,\n options: UpdateChainPollingConfigsOptions = { immediateUpdate: true },\n ): void {\n Object.assign(this.#chainPollingConfig, configs);\n\n if (this.#isControllerPollingActive) {\n this.#startIntervalGroupPolling(\n this.#requestedChainIds,\n options.immediateUpdate,\n );\n }\n }\n\n async updateBalances({\n chainIds,\n tokenAddresses,\n queryAllAccounts = false,\n }: {\n chainIds?: ChainIdHex[];\n tokenAddresses?: string[];\n queryAllAccounts?: boolean;\n } = {}): Promise<void> {\n if (!this.isActive) {\n return;\n }\n\n const targetChains = this.#getTargetChains(chainIds);\n if (!targetChains.length) {\n return;\n }\n\n const { selectedAccount, allAccounts, jwtToken } =\n await this.#getAccountsAndJwt();\n\n const aggregatedBalances = await this.#fetchAllBalances({\n targetChains,\n selectedAccount,\n allAccounts,\n jwtToken,\n queryAllAccounts: queryAllAccounts ?? this.#queryAllAccounts,\n });\n\n const filteredAggregated = this.#filterByTokenAddresses(\n aggregatedBalances,\n tokenAddresses,\n );\n\n const accountsToProcess = this.#getAccountsToProcess(\n queryAllAccounts,\n allAccounts,\n selectedAccount,\n );\n\n const prev = this.state;\n const next = this.#applyTokenBalancesToState({\n prev,\n targetChains,\n accountsToProcess,\n balances: filteredAggregated,\n });\n\n if (!isEqual(prev, next)) {\n this.update(() => next);\n\n const accountTrackerState = this.messenger.call(\n 'AccountTrackerController:getState',\n );\n\n const nativeUpdates = this.#buildNativeBalanceUpdates(\n filteredAggregated,\n accountTrackerState,\n );\n\n if (nativeUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n nativeUpdates,\n );\n }\n\n const stakedUpdates = this.#buildStakedBalanceUpdates(\n filteredAggregated,\n accountTrackerState,\n );\n\n if (stakedUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateStakedBalances',\n stakedUpdates,\n );\n }\n }\n\n await this.#importUntrackedTokens(filteredAggregated);\n }\n\n #getTargetChains(chainIds?: ChainIdHex[]): ChainIdHex[] {\n return chainIds?.length ? chainIds : this.#chainIdsWithTokens();\n }\n\n async #getAccountsAndJwt(): Promise<{\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n jwtToken: string | undefined;\n }> {\n const { address: selected } = this.messenger.call(\n 'AccountsController:getSelectedAccount',\n );\n const allAccounts = this.messenger.call('AccountsController:listAccounts');\n\n const jwtToken = await safelyExecuteWithTimeout<string | undefined>(\n () => {\n return this.messenger.call('AuthenticationController:getBearerToken');\n },\n false,\n 5000,\n );\n\n return {\n selectedAccount: selected as ChecksumAddress,\n allAccounts,\n jwtToken,\n };\n }\n\n async #fetchAllBalances({\n targetChains,\n selectedAccount,\n allAccounts,\n jwtToken,\n queryAllAccounts,\n }: {\n targetChains: ChainIdHex[];\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n jwtToken?: string;\n queryAllAccounts: boolean;\n }): Promise<ProcessedBalance[]> {\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...targetChains];\n\n for (const fetcher of this.#balanceFetchers) {\n const supportedChains = remainingChains.filter((chain) =>\n fetcher.supports(chain),\n );\n if (!supportedChains.length) {\n continue;\n }\n\n try {\n const result = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n jwtToken,\n });\n\n if (result.balances?.length) {\n aggregated.push(...result.balances);\n\n const processed = new Set(result.balances.map((b) => b.chainId));\n remainingChains = remainingChains.filter(\n (chain) => !processed.has(chain),\n );\n }\n\n if (result.unprocessedChainIds?.length) {\n const currentRemaining = [...remainingChains];\n const chainsToAdd = result.unprocessedChainIds.filter(\n (chainId) =>\n supportedChains.includes(chainId) &&\n !currentRemaining.includes(chainId),\n );\n remainingChains.push(...chainsToAdd);\n\n this.messenger\n .call('TokenDetectionController:detectTokens', {\n chainIds: result.unprocessedChainIds,\n forceRpc: true,\n })\n .catch(() => {\n // Silently handle token detection errors\n });\n }\n } catch (error) {\n console.warn(\n `Balance fetcher failed for chains ${supportedChains.join(', ')}: ${String(error)}`,\n );\n\n this.messenger\n .call('TokenDetectionController:detectTokens', {\n chainIds: supportedChains,\n forceRpc: true,\n })\n .catch(() => {\n // Silently handle token detection errors\n });\n }\n\n if (!remainingChains.length) {\n break;\n }\n }\n\n return aggregated;\n }\n\n #filterByTokenAddresses(\n balances: ProcessedBalance[],\n tokenAddresses?: string[],\n ): ProcessedBalance[] {\n if (!tokenAddresses?.length) {\n return balances;\n }\n\n const lowered = tokenAddresses.map((a) => a.toLowerCase());\n return balances.filter((balance) =>\n lowered.includes(balance.token.toLowerCase()),\n );\n }\n\n #getAccountsToProcess(\n queryAllAccountsParam: boolean | undefined,\n allAccounts: InternalAccount[],\n selectedAccount: ChecksumAddress,\n ): ChecksumAddress[] {\n const effectiveQueryAll =\n queryAllAccountsParam ?? this.#queryAllAccounts ?? false;\n\n if (!effectiveQueryAll) {\n return [selectedAccount];\n }\n\n return allAccounts.map((account) => account.address as ChecksumAddress);\n }\n\n #applyTokenBalancesToState({\n prev,\n targetChains,\n accountsToProcess,\n balances,\n }: {\n prev: TokenBalancesControllerState;\n targetChains: ChainIdHex[];\n accountsToProcess: ChecksumAddress[];\n balances: ProcessedBalance[];\n }): TokenBalancesControllerState {\n return draft(prev, (draftState) => {\n for (const chainId of targetChains) {\n for (const account of accountsToProcess) {\n draftState.tokenBalances[account] ??= {};\n draftState.tokenBalances[account][chainId] ??= {};\n\n const chainTokens = this.#allTokens[chainId];\n if (chainTokens?.[account]) {\n Object.values(chainTokens[account]).forEach(\n (token: { address: string }) => {\n const tokenAddress = checksum(token.address);\n draftState.tokenBalances[account][chainId][tokenAddress] ??=\n '0x0';\n },\n );\n }\n\n const detectedChainTokens = this.#detectedTokens[chainId];\n if (detectedChainTokens?.[account]) {\n Object.values(detectedChainTokens[account]).forEach(\n (token: { address: string }) => {\n const tokenAddress = checksum(token.address);\n draftState.tokenBalances[account][chainId][tokenAddress] ??=\n '0x0';\n },\n );\n }\n }\n }\n\n balances.forEach(({ success, value, account, token, chainId }) => {\n if (!success || value === undefined) {\n return;\n }\n\n const lowerCaseAccount = account.toLowerCase() as ChecksumAddress;\n const newBalance = toHex(value);\n const tokenAddress = checksum(token);\n\n const currentBalance =\n draftState.tokenBalances[lowerCaseAccount]?.[chainId]?.[tokenAddress];\n\n if (currentBalance !== newBalance) {\n ((draftState.tokenBalances[lowerCaseAccount] ??= {})[chainId] ??= {})[\n tokenAddress\n ] = newBalance;\n }\n });\n });\n }\n\n #buildNativeBalanceUpdates(\n balances: ProcessedBalance[],\n accountTrackerState: {\n accountsByChainId: Record<\n string,\n Record<string, { balance?: string; stakedBalance?: string }>\n >;\n },\n ): NativeBalanceUpdate[] {\n const nativeBalances = balances.filter(\n (balance) => balance.success && balance.token === ZERO_ADDRESS,\n );\n\n if (!nativeBalances.length) {\n return [];\n }\n\n return nativeBalances\n .map((balance) => ({\n address: balance.account,\n chainId: balance.chainId,\n balance: balance.value ? BNToHex(balance.value) : '0x0',\n }))\n .filter((update) => {\n const currentBalance =\n accountTrackerState.accountsByChainId[update.chainId]?.[\n checksum(update.address)\n ]?.balance;\n return currentBalance !== update.balance;\n });\n }\n\n #buildStakedBalanceUpdates(\n balances: ProcessedBalance[],\n accountTrackerState: {\n accountsByChainId: Record<\n string,\n Record<string, { balance?: string; stakedBalance?: string }>\n >;\n },\n ): StakedBalanceUpdate[] {\n const stakedBalances = balances.filter((balance) => {\n if (!balance.success || balance.token === ZERO_ADDRESS) {\n return false;\n }\n\n const stakingContractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[balance.chainId];\n return (\n stakingContractAddress &&\n stakingContractAddress.toLowerCase() === balance.token.toLowerCase()\n );\n });\n\n if (!stakedBalances.length) {\n return [];\n }\n\n return stakedBalances\n .map((balance) => ({\n address: balance.account,\n chainId: balance.chainId,\n stakedBalance: balance.value ? toHex(balance.value) : '0x0',\n }))\n .filter((update) => {\n const currentStakedBalance =\n accountTrackerState.accountsByChainId[update.chainId]?.[\n checksum(update.address)\n ]?.stakedBalance;\n return currentStakedBalance !== update.stakedBalance;\n });\n }\n\n /**\n * Import untracked tokens that have non-zero balances.\n * This mirrors the v2 behavior where only tokens with actual balances are added.\n * Delegates to TokenDetectionController:addDetectedTokensViaPolling which handles:\n * - Checking if useTokenDetection preference is enabled\n * - Filtering tokens already in allTokens or allIgnoredTokens\n * - Token metadata lookup and addition via TokensController\n *\n * @param balances - Array of processed balance results from fetchers\n */\n async #importUntrackedTokens(balances: ProcessedBalance[]): Promise<void> {\n const tokensByChain = new Map<ChainIdHex, string[]>();\n\n for (const balance of balances) {\n // Skip failed fetches, native tokens, and zero balances (like v2 did)\n if (\n !balance.success ||\n balance.token === ZERO_ADDRESS ||\n !balance.value ||\n balance.value.isZero()\n ) {\n continue;\n }\n\n const tokenAddress = checksum(balance.token);\n const existing = tokensByChain.get(balance.chainId) ?? [];\n if (!existing.includes(tokenAddress)) {\n existing.push(tokenAddress);\n tokensByChain.set(balance.chainId, existing);\n }\n }\n\n // Add detected tokens via TokenDetectionController (handles preference check,\n // filtering of allTokens/allIgnoredTokens, and metadata lookup)\n for (const [chainId, tokenAddresses] of tokensByChain) {\n if (tokenAddresses.length) {\n await this.messenger.call(\n 'TokenDetectionController:addDetectedTokensViaPolling',\n {\n tokensSlice: tokenAddresses,\n chainId,\n },\n );\n }\n }\n }\n\n resetState(): void {\n this.update(() => ({ tokenBalances: {} }));\n }\n\n #isTokenTracked(\n tokenAddress: string,\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): boolean {\n const normalizedAccount = account.toLowerCase();\n\n if (\n this.#allTokens?.[chainId]?.[normalizedAccount]?.some(\n (token) => token.address === tokenAddress,\n )\n ) {\n return true;\n }\n\n if (\n this.#allIgnoredTokens?.[chainId]?.[normalizedAccount]?.some(\n (token) => token === tokenAddress,\n )\n ) {\n return true;\n }\n\n return false;\n }\n\n readonly #onTokensChanged = async (\n state: TokensControllerState,\n ): Promise<void> => {\n const changed: ChainIdHex[] = [];\n let hasChanges = false;\n\n const incomingChainIds = new Set([\n ...Object.keys(state.allTokens),\n ...Object.keys(state.allDetectedTokens),\n ]);\n\n const relevantChainIds = Array.from(incomingChainIds).filter((chainId) => {\n const id = chainId as ChainIdHex;\n\n const hasTokensNow =\n (state.allTokens[id] && Object.keys(state.allTokens[id]).length > 0) ||\n (state.allDetectedTokens[id] &&\n Object.keys(state.allDetectedTokens[id]).length > 0);\n const hadTokensBefore =\n (this.#allTokens[id] && Object.keys(this.#allTokens[id]).length > 0) ||\n (this.#detectedTokens[id] &&\n Object.keys(this.#detectedTokens[id]).length > 0);\n\n const hasTokenChange =\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id]);\n\n return hasTokenChange || (!hadTokensBefore && hasTokensNow);\n });\n\n if (!relevantChainIds.length) {\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n return;\n }\n\n this.update((currentState) => {\n for (const chainId of relevantChainIds) {\n const id = chainId as ChainIdHex;\n const hasTokensNow =\n (state.allTokens[id] &&\n Object.keys(state.allTokens[id]).length > 0) ||\n (state.allDetectedTokens[id] &&\n Object.keys(state.allDetectedTokens[id]).length > 0);\n const hadTokensBefore =\n (this.#allTokens[id] &&\n Object.keys(this.#allTokens[id]).length > 0) ||\n (this.#detectedTokens[id] &&\n Object.keys(this.#detectedTokens[id]).length > 0);\n\n const tokensChanged =\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id]);\n\n if (!tokensChanged) {\n continue;\n }\n\n if (hasTokensNow) {\n changed.push(id);\n } else if (hadTokensBefore) {\n for (const address of Object.keys(currentState.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n if (currentState.tokenBalances[addressKey]?.[id]) {\n currentState.tokenBalances[addressKey][id] = {};\n hasChanges = true;\n }\n }\n }\n }\n });\n\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n this.#allIgnoredTokens = state.allIgnoredTokens;\n\n if (changed.length && !hasChanges) {\n this.updateBalances({ chainIds: changed }).catch((error) => {\n console.warn('Error updating balances after token change:', error);\n });\n }\n };\n\n readonly #onNetworkChanged = (state: NetworkState): void => {\n const currentNetworks = new Set(\n Object.keys(state.networkConfigurationsByChainId),\n );\n\n const networksWithBalances = new Set<string>();\n for (const address of Object.keys(this.state.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const network of Object.keys(\n this.state.tokenBalances[addressKey] || {},\n )) {\n networksWithBalances.add(network);\n }\n }\n\n const removedNetworks = Array.from(networksWithBalances).filter(\n (network) => !currentNetworks.has(network),\n );\n\n if (!removedNetworks.length) {\n return;\n }\n\n this.update((currentState) => {\n for (const address of Object.keys(currentState.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const removedNetwork of removedNetworks) {\n const networkKey = removedNetwork as ChainIdHex;\n if (currentState.tokenBalances[addressKey]?.[networkKey]) {\n delete currentState.tokenBalances[addressKey][networkKey];\n }\n }\n }\n });\n };\n\n readonly #onAccountRemoved = (addr: string): void => {\n if (!isStrictHexString(addr) || !isValidHexAddress(addr)) {\n return;\n }\n this.update((currentState) => {\n delete currentState.tokenBalances[addr];\n });\n };\n\n readonly #onAccountChanged = (): void => {\n const chainIds = this.#chainIdsWithTokens();\n if (!chainIds.length) {\n return;\n }\n\n this.updateBalances({ chainIds }).catch(() => {\n // Silently handle polling errors\n });\n };\n\n #prepareBalanceUpdates(\n updates: BalanceUpdate[],\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): {\n tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[];\n newTokens: string[];\n nativeBalanceUpdates: NativeBalanceUpdate[];\n } {\n const tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[] = [];\n const newTokens: string[] = [];\n const nativeBalanceUpdates: NativeBalanceUpdate[] = [];\n\n for (const update of updates) {\n const { asset, postBalance } = update;\n\n if (postBalance.error) {\n throw new Error('Balance update has error');\n }\n\n const parsed = parseAssetType(asset.type);\n if (!parsed) {\n throw new Error('Failed to parse asset type');\n }\n\n const [tokenAddress, isNativeToken] = parsed;\n\n if (\n !isStrictHexString(tokenAddress) ||\n !isValidHexAddress(tokenAddress)\n ) {\n throw new Error('Invalid token address');\n }\n\n const checksumTokenAddress = checksum(tokenAddress);\n const isTracked = this.#isTokenTracked(\n checksumTokenAddress,\n account,\n chainId,\n );\n\n const balanceHex = postBalance.amount as Hex;\n\n tokenBalances.push({\n tokenAddress: checksumTokenAddress,\n balance: balanceHex,\n });\n\n if (isNativeToken) {\n nativeBalanceUpdates.push({\n address: account,\n chainId,\n balance: balanceHex,\n });\n }\n\n if (!isNativeToken && !isTracked) {\n newTokens.push(checksumTokenAddress);\n }\n }\n\n return { tokenBalances, newTokens, nativeBalanceUpdates };\n }\n\n readonly #onAccountActivityBalanceUpdate = async ({\n address,\n chain,\n updates,\n }: {\n address: string;\n chain: string;\n updates: BalanceUpdate[];\n }): Promise<void> => {\n const chainId = caipChainIdToHex(chain);\n const checksummedAccount = checksum(address);\n\n try {\n const { tokenBalances, newTokens, nativeBalanceUpdates } =\n this.#prepareBalanceUpdates(updates, checksummedAccount, chainId);\n\n if (tokenBalances.length > 0) {\n this.update((state) => {\n const lowercaseAccount =\n checksummedAccount.toLowerCase() as ChecksumAddress;\n state.tokenBalances[lowercaseAccount] ??= {};\n state.tokenBalances[lowercaseAccount][chainId] ??= {};\n\n for (const { tokenAddress, balance } of tokenBalances) {\n state.tokenBalances[lowercaseAccount][chainId][tokenAddress] =\n balance;\n }\n });\n }\n\n if (nativeBalanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n nativeBalanceUpdates,\n );\n }\n\n if (newTokens.length > 0) {\n await this.messenger.call(\n 'TokenDetectionController:addDetectedTokensViaWs',\n {\n tokensSlice: newTokens,\n chainId,\n },\n );\n }\n } catch (error) {\n console.warn(\n `Error updating balances from AccountActivityService for chain ${chain}, account ${address}:`,\n error,\n );\n console.warn('Balance update data:', JSON.stringify(updates, null, 2));\n\n await this.updateBalances({ chainIds: [chainId] }).catch(() => {\n // Silently handle polling errors\n });\n }\n };\n\n readonly #onAccountActivityStatusChanged = ({\n chainIds,\n status,\n }: {\n chainIds: string[];\n status: 'up' | 'down';\n }): void => {\n for (const chainId of chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, status);\n }\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, 5000);\n };\n\n #processAccumulatedStatusChanges(): void {\n const changes = Array.from(\n this.#statusChangeDebouncer.pendingChanges.entries(),\n );\n this.#statusChangeDebouncer.pendingChanges.clear();\n this.#statusChangeDebouncer.timer = null;\n\n if (!changes.length) {\n return;\n }\n\n const chainConfigs: Record<ChainIdHex, { interval: number }> = {};\n\n for (const [chainId, status] of changes) {\n const hexChainId = caipChainIdToHex(chainId);\n\n chainConfigs[hexChainId] =\n status === 'down'\n ? { interval: this.#defaultInterval }\n : { interval: this.#websocketActivePollingInterval };\n }\n\n const jitterDelay = Math.random() * this.#defaultInterval;\n\n setTimeout(() => {\n this.updateChainPollingConfigs(chainConfigs, { immediateUpdate: true });\n }, jitterDelay);\n }\n\n override destroy(): void {\n this.#isControllerPollingActive = false;\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n this.messenger.unregisterActionHandler(\n `TokenBalancesController:updateChainPollingConfigs`,\n );\n this.messenger.unregisterActionHandler(\n `TokenBalancesController:getChainPollingConfig`,\n );\n\n super.destroy();\n }\n}\n\nexport default TokenBalancesController;\n"]}
|
package/dist/token-service.cjs
CHANGED
|
@@ -52,6 +52,7 @@ function getTokenSearchURL(chainIds, query, limit = 10, includeMarketData = fals
|
|
|
52
52
|
* @param options.maxVolume24hUsd - The maximum volume 24h in USD.
|
|
53
53
|
* @param options.minMarketCap - The minimum market cap.
|
|
54
54
|
* @param options.maxMarketCap - The maximum market cap.
|
|
55
|
+
* @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).
|
|
55
56
|
* @returns The trending tokens URL.
|
|
56
57
|
*/
|
|
57
58
|
function getTrendingTokensURL(options) {
|
|
@@ -60,13 +61,18 @@ function getTrendingTokensURL(options) {
|
|
|
60
61
|
.join(',');
|
|
61
62
|
// Add the rest of query params if they are defined
|
|
62
63
|
const queryParams = new URLSearchParams();
|
|
63
|
-
const { chainIds, ...rest } = options;
|
|
64
|
+
const { chainIds, excludeLabels, ...rest } = options;
|
|
64
65
|
Object.entries(rest).forEach(([key, value]) => {
|
|
65
66
|
if (value !== undefined) {
|
|
66
67
|
queryParams.append(key, String(value));
|
|
67
68
|
}
|
|
68
69
|
});
|
|
69
|
-
|
|
70
|
+
// Handle excludeLabels separately to avoid encoding the commas
|
|
71
|
+
// The API expects: excludeLabels=stable_coin,blue_chip (not %2C)
|
|
72
|
+
const excludeLabelsParam = excludeLabels !== undefined && excludeLabels.length > 0
|
|
73
|
+
? `&excludeLabels=${excludeLabels.join(',')}`
|
|
74
|
+
: '';
|
|
75
|
+
return `${exports.TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}${excludeLabelsParam}`;
|
|
70
76
|
}
|
|
71
77
|
const tenSecondsInMilliseconds = 10000;
|
|
72
78
|
// Token list averages 1.6 MB in size
|
|
@@ -137,10 +143,11 @@ exports.searchTokens = searchTokens;
|
|
|
137
143
|
* @param options.maxVolume24hUsd - The maximum volume 24h in USD.
|
|
138
144
|
* @param options.minMarketCap - The minimum market cap.
|
|
139
145
|
* @param options.maxMarketCap - The maximum market cap.
|
|
146
|
+
* @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).
|
|
140
147
|
* @returns The trending tokens.
|
|
141
148
|
* @throws Will throw if the request fails.
|
|
142
149
|
*/
|
|
143
|
-
async function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hUsd, maxVolume24hUsd, minMarketCap, maxMarketCap, }) {
|
|
150
|
+
async function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hUsd, maxVolume24hUsd, minMarketCap, maxMarketCap, excludeLabels, }) {
|
|
144
151
|
if (chainIds.length === 0) {
|
|
145
152
|
console.error('No chains provided');
|
|
146
153
|
return [];
|
|
@@ -153,6 +160,7 @@ async function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hU
|
|
|
153
160
|
maxVolume24hUsd,
|
|
154
161
|
minMarketCap,
|
|
155
162
|
maxMarketCap,
|
|
163
|
+
excludeLabels,
|
|
156
164
|
});
|
|
157
165
|
try {
|
|
158
166
|
const result = await (0, controller_utils_1.handleFetch)(trendingTokensURL);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.cjs","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChainId,\n convertHexToDecimal,\n handleFetch,\n timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { CaipChainId, Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex) {\n const occurrenceFloor = chainId === ChainId['linea-mainnet'] ? 1 : 3;\n\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string) {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}`;\n}\n\n/**\n * The sort by field for trending tokens.\n */\nexport type SortTrendingBy =\n | 'm5_trending'\n | 'h1_trending'\n | 'h6_trending'\n | 'h24_trending';\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param query - The search query (token name, symbol, or address).\n * @param limit - Optional limit for the number of results (defaults to 10).\n * @param includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(\n chainIds: CaipChainId[],\n query: string,\n limit = 10,\n includeMarketData = false,\n) {\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}&limit=${limit}&includeMarketData=${includeMarketData}`;\n}\n\n/**\n * Get the trending tokens URL for the given networks and search query.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param options.sort - The sort field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @returns The trending tokens URL.\n */\nfunction getTrendingTokensURL(options: {\n chainIds: CaipChainId[];\n sort?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n}): string {\n const encodedChainIds = options.chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n // Add the rest of query params if they are defined\n const queryParams = new URLSearchParams();\n const { chainIds, ...rest } = options;\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n return `${TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n const result = await parseJsonResponse(response);\n if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {\n return result.filter(\n (elm) =>\n elm.aggregators.includes('lineaTeam') || elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\n}\n\n/**\n * Search for tokens across one or more networks by query string using CAIP format chain IDs.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param query - The search query (token name, symbol, or address).\n * @param options - Additional fetch options.\n * @param options.limit - The maximum number of results to return.\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @returns Object containing count and data array. Returns { count: 0, data: [] } if request fails.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n { limit = 10, includeMarketData = false } = {},\n): Promise<{ count: number; data: unknown[] }> {\n const tokenSearchURL = getTokenSearchURL(\n chainIds,\n query,\n limit,\n includeMarketData,\n );\n\n try {\n const result = await handleFetch(tokenSearchURL);\n\n // The API returns an object with structure: { count: number, data: array, pageInfo: object }\n if (result && typeof result === 'object' && Array.isArray(result.data)) {\n return {\n count: result.count || result.data.length,\n data: result.data,\n };\n }\n\n // Handle non-expected responses\n return { count: 0, data: [] };\n } catch (error) {\n // Handle 400 errors and other failures by returning count 0 and empty array\n console.log('Search request failed:', error);\n return { count: 0, data: [] };\n }\n}\n\n/**\n * The trending asset type.\n */\nexport type TrendingAsset = {\n assetId: string;\n name: string;\n symbol: string;\n decimals: number;\n price: string;\n aggregatedUsdVolume: number;\n marketCap: number;\n priceChangePct?: {\n m5?: string;\n m15?: string;\n m30?: string;\n h1?: string;\n h6?: string;\n h24?: string;\n };\n labels?: string[];\n};\n\n/**\n * Get the trending tokens for the given chains.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - The chains to get the trending tokens for.\n * @param options.sortBy - The sort by field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @returns The trending tokens.\n * @throws Will throw if the request fails.\n */\nexport async function getTrendingTokens({\n chainIds,\n sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n}: {\n chainIds: CaipChainId[];\n sortBy?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n}): Promise<TrendingAsset[]> {\n if (chainIds.length === 0) {\n console.error('No chains provided');\n return [];\n }\n\n const trendingTokensURL = getTrendingTokensURL({\n chainIds,\n sort: sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n });\n\n try {\n const result = await handleFetch(trendingTokensURL);\n\n // Validate that the API returned an array\n if (Array.isArray(result)) {\n return result;\n }\n\n // Handle non-expected responses\n console.error('Trending tokens API returned non-array response:', result);\n return [];\n } catch (error) {\n console.error('Trending tokens request failed:', error);\n return [];\n }\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<T>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<T | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<T>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n };\n fetchOptions.headers = new window.Headers();\n fetchOptions.headers.set('Content-Type', 'application/json');\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"token-service.cjs","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ChainId,\n convertHexToDecimal,\n handleFetch,\n timeoutFetch,\n} from '@metamask/controller-utils';\nimport type { CaipChainId, Hex } from '@metamask/utils';\n\nimport { isTokenListSupportedForNetwork } from './assetsUtil';\n\nexport const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';\nexport const TOKEN_METADATA_NO_SUPPORT_ERROR =\n 'TokenService Error: Network does not support fetchTokenMetadata';\n\n/**\n * Get the tokens URL for a specific network.\n *\n * @param chainId - The chain ID of the network the tokens requested are on.\n * @returns The tokens URL.\n */\nfunction getTokensURL(chainId: Hex) {\n const occurrenceFloor = chainId === ChainId['linea-mainnet'] ? 1 : 3;\n\n return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(\n chainId,\n )}?occurrenceFloor=${occurrenceFloor}&includeNativeAssets=false&includeTokenFees=false&includeAssetType=false&includeERC20Permit=false&includeStorage=false`;\n}\n\n/**\n * Get the token metadata URL for the given network and token.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The token address.\n * @returns The token metadata URL.\n */\nfunction getTokenMetadataURL(chainId: Hex, tokenAddress: string) {\n return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(\n chainId,\n )}?address=${tokenAddress}`;\n}\n\n/**\n * The sort by field for trending tokens.\n */\nexport type SortTrendingBy =\n | 'm5_trending'\n | 'h1_trending'\n | 'h6_trending'\n | 'h24_trending';\n\n/**\n * Get the token search URL for the given networks and search query.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., 'eip155:1', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp').\n * @param query - The search query (token name, symbol, or address).\n * @param limit - Optional limit for the number of results (defaults to 10).\n * @param includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @returns The token search URL.\n */\nfunction getTokenSearchURL(\n chainIds: CaipChainId[],\n query: string,\n limit = 10,\n includeMarketData = false,\n) {\n const encodedQuery = encodeURIComponent(query);\n const encodedChainIds = chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}&limit=${limit}&includeMarketData=${includeMarketData}`;\n}\n\n/**\n * Get the trending tokens URL for the given networks and search query.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param options.sort - The sort field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @returns The trending tokens URL.\n */\nfunction getTrendingTokensURL(options: {\n chainIds: CaipChainId[];\n sort?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n}): string {\n const encodedChainIds = options.chainIds\n .map((id) => encodeURIComponent(id))\n .join(',');\n // Add the rest of query params if they are defined\n const queryParams = new URLSearchParams();\n const { chainIds, excludeLabels, ...rest } = options;\n Object.entries(rest).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, String(value));\n }\n });\n\n // Handle excludeLabels separately to avoid encoding the commas\n // The API expects: excludeLabels=stable_coin,blue_chip (not %2C)\n const excludeLabelsParam =\n excludeLabels !== undefined && excludeLabels.length > 0\n ? `&excludeLabels=${excludeLabels.join(',')}`\n : '';\n\n return `${TOKEN_END_POINT_API}/v3/tokens/trending?chainIds=${encodedChainIds}${queryParams.toString() ? `&${queryParams.toString()}` : ''}${excludeLabelsParam}`;\n}\n\nconst tenSecondsInMilliseconds = 10_000;\n\n// Token list averages 1.6 MB in size\n// timeoutFetch by default has a 500ms timeout, which will almost always timeout given the response size.\nconst defaultTimeout = tenSecondsInMilliseconds;\n\n/**\n * Fetch the list of token metadata for a given network. This request is cancellable using the\n * abort signal passed in.\n *\n * @param chainId - The chain ID of the network the requested tokens are on.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token list, or `undefined` if the request was cancelled.\n */\nexport async function fetchTokenListByChainId(\n chainId: Hex,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<unknown> {\n const tokenURL = getTokensURL(chainId);\n const response = await queryApi(tokenURL, abortSignal, timeout);\n if (response) {\n const result = await parseJsonResponse(response);\n if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {\n return result.filter(\n (elm) =>\n elm.aggregators.includes('lineaTeam') || elm.aggregators.length >= 3,\n );\n }\n return result;\n }\n return undefined;\n}\n\n/**\n * Search for tokens across one or more networks by query string using CAIP format chain IDs.\n *\n * @param chainIds - Array of CAIP format chain IDs (e.g., ['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp']).\n * @param query - The search query (token name, symbol, or address).\n * @param options - Additional fetch options.\n * @param options.limit - The maximum number of results to return.\n * @param options.includeMarketData - Optional flag to include market data in the results (defaults to false).\n * @returns Object containing count and data array. Returns { count: 0, data: [] } if request fails.\n */\nexport async function searchTokens(\n chainIds: CaipChainId[],\n query: string,\n { limit = 10, includeMarketData = false } = {},\n): Promise<{ count: number; data: unknown[] }> {\n const tokenSearchURL = getTokenSearchURL(\n chainIds,\n query,\n limit,\n includeMarketData,\n );\n\n try {\n const result = await handleFetch(tokenSearchURL);\n\n // The API returns an object with structure: { count: number, data: array, pageInfo: object }\n if (result && typeof result === 'object' && Array.isArray(result.data)) {\n return {\n count: result.count || result.data.length,\n data: result.data,\n };\n }\n\n // Handle non-expected responses\n return { count: 0, data: [] };\n } catch (error) {\n // Handle 400 errors and other failures by returning count 0 and empty array\n console.log('Search request failed:', error);\n return { count: 0, data: [] };\n }\n}\n\n/**\n * The trending asset type.\n */\nexport type TrendingAsset = {\n assetId: string;\n name: string;\n symbol: string;\n decimals: number;\n price: string;\n aggregatedUsdVolume: number;\n marketCap: number;\n priceChangePct?: {\n m5?: string;\n m15?: string;\n m30?: string;\n h1?: string;\n h6?: string;\n h24?: string;\n };\n labels?: string[];\n};\n\n/**\n * Get the trending tokens for the given chains.\n *\n * @param options - Options for getting trending tokens.\n * @param options.chainIds - The chains to get the trending tokens for.\n * @param options.sortBy - The sort by field.\n * @param options.minLiquidity - The minimum liquidity.\n * @param options.minVolume24hUsd - The minimum volume 24h in USD.\n * @param options.maxVolume24hUsd - The maximum volume 24h in USD.\n * @param options.minMarketCap - The minimum market cap.\n * @param options.maxMarketCap - The maximum market cap.\n * @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).\n * @returns The trending tokens.\n * @throws Will throw if the request fails.\n */\nexport async function getTrendingTokens({\n chainIds,\n sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n}: {\n chainIds: CaipChainId[];\n sortBy?: SortTrendingBy;\n minLiquidity?: number;\n minVolume24hUsd?: number;\n maxVolume24hUsd?: number;\n minMarketCap?: number;\n maxMarketCap?: number;\n excludeLabels?: string[];\n}): Promise<TrendingAsset[]> {\n if (chainIds.length === 0) {\n console.error('No chains provided');\n return [];\n }\n\n const trendingTokensURL = getTrendingTokensURL({\n chainIds,\n sort: sortBy,\n minLiquidity,\n minVolume24hUsd,\n maxVolume24hUsd,\n minMarketCap,\n maxMarketCap,\n excludeLabels,\n });\n\n try {\n const result = await handleFetch(trendingTokensURL);\n\n // Validate that the API returned an array\n if (Array.isArray(result)) {\n return result;\n }\n\n // Handle non-expected responses\n console.error('Trending tokens API returned non-array response:', result);\n return [];\n } catch (error) {\n console.error('Trending tokens request failed:', error);\n return [];\n }\n}\n\n/**\n * Fetch metadata for the token address provided for a given network. This request is cancellable\n * using the abort signal passed in.\n *\n * @param chainId - The chain ID of the network the token is on.\n * @param tokenAddress - The address of the token to fetch metadata for.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param options - Additional fetch options.\n * @param options.timeout - The fetch timeout.\n * @returns The token metadata, or `undefined` if the request was either aborted or failed.\n */\nexport async function fetchTokenMetadata<T>(\n chainId: Hex,\n tokenAddress: string,\n abortSignal: AbortSignal,\n { timeout = defaultTimeout } = {},\n): Promise<T | undefined> {\n if (!isTokenListSupportedForNetwork(chainId)) {\n throw new Error(TOKEN_METADATA_NO_SUPPORT_ERROR);\n }\n const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);\n const response = await queryApi(tokenMetadataURL, abortSignal, timeout);\n if (response) {\n return parseJsonResponse(response) as Promise<T>;\n }\n return undefined;\n}\n\n/**\n * Perform fetch request against the api.\n *\n * @param apiURL - The URL of the API to fetch.\n * @param abortSignal - The abort signal used to cancel the request if necessary.\n * @param timeout - The fetch timeout.\n * @returns Promise resolving request response.\n */\nasync function queryApi(\n apiURL: string,\n abortSignal: AbortSignal,\n timeout: number,\n): Promise<Response | undefined> {\n const fetchOptions: RequestInit = {\n referrer: apiURL,\n referrerPolicy: 'no-referrer-when-downgrade',\n method: 'GET',\n mode: 'cors',\n signal: abortSignal,\n cache: 'default',\n };\n fetchOptions.headers = new window.Headers();\n fetchOptions.headers.set('Content-Type', 'application/json');\n try {\n return await timeoutFetch(apiURL, fetchOptions, timeout);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n console.log('Request is aborted');\n }\n }\n return undefined;\n}\n\n/**\n * Parse an API response and return the response JSON data.\n *\n * @param apiResponse - The API response to parse.\n * @returns The response JSON data.\n * @throws Will throw if the response includes an error.\n */\nasync function parseJsonResponse(apiResponse: Response): Promise<unknown> {\n const responseObj = await apiResponse.json();\n // api may return errors as json without setting an error http status code\n if (responseObj?.error) {\n throw new Error(`TokenService Error: ${responseObj.error}`);\n }\n return responseObj;\n}\n"]}
|
package/dist/token-service.d.cts
CHANGED
|
@@ -67,10 +67,11 @@ export type TrendingAsset = {
|
|
|
67
67
|
* @param options.maxVolume24hUsd - The maximum volume 24h in USD.
|
|
68
68
|
* @param options.minMarketCap - The minimum market cap.
|
|
69
69
|
* @param options.maxMarketCap - The maximum market cap.
|
|
70
|
+
* @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).
|
|
70
71
|
* @returns The trending tokens.
|
|
71
72
|
* @throws Will throw if the request fails.
|
|
72
73
|
*/
|
|
73
|
-
export declare function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hUsd, maxVolume24hUsd, minMarketCap, maxMarketCap, }: {
|
|
74
|
+
export declare function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hUsd, maxVolume24hUsd, minMarketCap, maxMarketCap, excludeLabels, }: {
|
|
74
75
|
chainIds: CaipChainId[];
|
|
75
76
|
sortBy?: SortTrendingBy;
|
|
76
77
|
minLiquidity?: number;
|
|
@@ -78,6 +79,7 @@ export declare function getTrendingTokens({ chainIds, sortBy, minLiquidity, minV
|
|
|
78
79
|
maxVolume24hUsd?: number;
|
|
79
80
|
minMarketCap?: number;
|
|
80
81
|
maxMarketCap?: number;
|
|
82
|
+
excludeLabels?: string[];
|
|
81
83
|
}): Promise<TrendingAsset[]>;
|
|
82
84
|
/**
|
|
83
85
|
* Fetch metadata for the token address provided for a given network. This request is cancellable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.d.cts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,wBAAwB;AAIxD,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AACtE,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AA6BpE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,aAAa,GACb,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"token-service.d.cts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,wBAAwB;AAIxD,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AACtE,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AA6BpE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,aAAa,GACb,cAAc,CAAC;AA4EnB;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,GAAG,EACZ,WAAW,EAAE,WAAW,EACxB,EAAE,OAAwB,EAAE;;CAAK,GAChC,OAAO,CAAC,OAAO,CAAC,CAclB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,KAAK,EAAE,MAAM,EACb,EAAE,KAAU,EAAE,iBAAyB,EAAE;;;CAAK,GAC7C,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CA0B7C;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE;QACf,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAgC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,EACxB,EAAE,OAAwB,EAAE;;CAAK,GAChC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAUxB"}
|
package/dist/token-service.d.mts
CHANGED
|
@@ -67,10 +67,11 @@ export type TrendingAsset = {
|
|
|
67
67
|
* @param options.maxVolume24hUsd - The maximum volume 24h in USD.
|
|
68
68
|
* @param options.minMarketCap - The minimum market cap.
|
|
69
69
|
* @param options.maxMarketCap - The maximum market cap.
|
|
70
|
+
* @param options.excludeLabels - Array of labels to exclude (e.g., ['stable_coin', 'blue_chip']).
|
|
70
71
|
* @returns The trending tokens.
|
|
71
72
|
* @throws Will throw if the request fails.
|
|
72
73
|
*/
|
|
73
|
-
export declare function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hUsd, maxVolume24hUsd, minMarketCap, maxMarketCap, }: {
|
|
74
|
+
export declare function getTrendingTokens({ chainIds, sortBy, minLiquidity, minVolume24hUsd, maxVolume24hUsd, minMarketCap, maxMarketCap, excludeLabels, }: {
|
|
74
75
|
chainIds: CaipChainId[];
|
|
75
76
|
sortBy?: SortTrendingBy;
|
|
76
77
|
minLiquidity?: number;
|
|
@@ -78,6 +79,7 @@ export declare function getTrendingTokens({ chainIds, sortBy, minLiquidity, minV
|
|
|
78
79
|
maxVolume24hUsd?: number;
|
|
79
80
|
minMarketCap?: number;
|
|
80
81
|
maxMarketCap?: number;
|
|
82
|
+
excludeLabels?: string[];
|
|
81
83
|
}): Promise<TrendingAsset[]>;
|
|
82
84
|
/**
|
|
83
85
|
* Fetch metadata for the token address provided for a given network. This request is cancellable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-service.d.mts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,wBAAwB;AAIxD,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AACtE,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AA6BpE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,aAAa,GACb,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"token-service.d.mts","sourceRoot":"","sources":["../src/token-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,wBAAwB;AAIxD,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AACtE,eAAO,MAAM,+BAA+B,oEACuB,CAAC;AA6BpE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,aAAa,GACb,aAAa,GACb,cAAc,CAAC;AA4EnB;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,GAAG,EACZ,WAAW,EAAE,WAAW,EACxB,EAAE,OAAwB,EAAE;;CAAK,GAChC,OAAO,CAAC,OAAO,CAAC,CAclB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,WAAW,EAAE,EACvB,KAAK,EAAE,MAAM,EACb,EAAE,KAAU,EAAE,iBAAyB,EAAE;;;CAAK,GAC7C,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CA0B7C;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE;QACf,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,eAAe,EACf,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAgC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,EACxB,EAAE,OAAwB,EAAE;;CAAK,GAChC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAUxB"}
|