@metamask/assets-controllers 91.0.0 → 92.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/dist/TokenBalancesController.cjs +48 -10
  3. package/dist/TokenBalancesController.cjs.map +1 -1
  4. package/dist/TokenBalancesController.d.cts +2 -1
  5. package/dist/TokenBalancesController.d.cts.map +1 -1
  6. package/dist/TokenBalancesController.d.mts +2 -1
  7. package/dist/TokenBalancesController.d.mts.map +1 -1
  8. package/dist/TokenBalancesController.mjs +49 -11
  9. package/dist/TokenBalancesController.mjs.map +1 -1
  10. package/dist/TokenDetectionController.cjs +12 -7
  11. package/dist/TokenDetectionController.cjs.map +1 -1
  12. package/dist/TokenDetectionController.d.cts +2 -1
  13. package/dist/TokenDetectionController.d.cts.map +1 -1
  14. package/dist/TokenDetectionController.d.mts +2 -1
  15. package/dist/TokenDetectionController.d.mts.map +1 -1
  16. package/dist/TokenDetectionController.mjs +12 -7
  17. package/dist/TokenDetectionController.mjs.map +1 -1
  18. package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs +8 -8
  19. package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs.map +1 -1
  20. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts +2 -1
  21. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts.map +1 -1
  22. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts +2 -1
  23. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts.map +1 -1
  24. package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs +8 -8
  25. package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs.map +1 -1
  26. package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs +18 -8
  27. package/dist/multi-chain-accounts-service/multi-chain-accounts.cjs.map +1 -1
  28. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts +4 -2
  29. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.cts.map +1 -1
  30. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts +4 -2
  31. package/dist/multi-chain-accounts-service/multi-chain-accounts.d.mts.map +1 -1
  32. package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs +18 -8
  33. package/dist/multi-chain-accounts-service/multi-chain-accounts.mjs.map +1 -1
  34. package/dist/token-prices-service/codefi-v2.cjs +2 -0
  35. package/dist/token-prices-service/codefi-v2.cjs.map +1 -1
  36. package/dist/token-prices-service/codefi-v2.d.cts +1 -1
  37. package/dist/token-prices-service/codefi-v2.d.cts.map +1 -1
  38. package/dist/token-prices-service/codefi-v2.d.mts +1 -1
  39. package/dist/token-prices-service/codefi-v2.d.mts.map +1 -1
  40. package/dist/token-prices-service/codefi-v2.mjs +2 -0
  41. package/dist/token-prices-service/codefi-v2.mjs.map +1 -1
  42. package/dist/token-service.cjs +6 -4
  43. package/dist/token-service.cjs.map +1 -1
  44. package/dist/token-service.d.cts +3 -1
  45. package/dist/token-service.d.cts.map +1 -1
  46. package/dist/token-service.d.mts +3 -1
  47. package/dist/token-service.d.mts.map +1 -1
  48. package/dist/token-service.mjs +6 -4
  49. package/dist/token-service.mjs.map +1 -1
  50. package/package.json +14 -24
package/CHANGELOG.md CHANGED
@@ -7,6 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [92.0.0]
11
+
12
+ ### Added
13
+
14
+ - Support for optionally fetching market data when calling searchTokens ([#7226](https://github.com/MetaMask/core/pull/7226))
15
+ - **BREAKING:** Add optional JWT token authentication to multi-chain accounts API calls ([#7165](https://github.com/MetaMask/core/pull/7165))
16
+ - `fetchMultiChainBalances` and `fetchMultiChainBalancesV4` now accept an optional `jwtToken` parameter
17
+ - `TokenDetectionController` fetches and passes JWT token from `AuthenticationController` when using Accounts API
18
+ - `TokenBalancesController` fetches and passes JWT token through balance fetcher chain
19
+ - JWT token is included in `Authorization: Bearer <token>` header when provided
20
+ - Backward compatible: token parameter is optional and APIs work without authentication
21
+
22
+ ### Changed
23
+
24
+ - Move peer dependencies for controller and service packages to direct dependencies ([#7209](https://github.com/MetaMask/core/pull/7209), [#7220](https://github.com/MetaMask/core/pull/7220), [#7236](https://github.com/MetaMask/core/pull/7236))
25
+ - The dependencies moved are:
26
+ - `@metamask/account-tree-controller` (^4.0.0)
27
+ - `@metamask/accounts-controller` (^35.0.0)
28
+ - `@metamask/approval-controller` (^8.0.0)
29
+ - `@metamask/core-backend` (^5.0.0)
30
+ - `@metamask/keyring-controller` (^25.0.0)
31
+ - `@metamask/multichain-account-service` (^4.0.0)
32
+ - `@metamask/network-controller` (^26.0.0)
33
+ - `@metamask/permission-controller` (^12.1.1)
34
+ - `@metamask/phishing-controller` (^16.1.0)
35
+ - `@metamask/preferences-controller` (^22.0.0)
36
+ - `@metamask/profile-sync-controller` (^27.0.0)
37
+ - `@metamask/snaps-controllers` (^14.0.1)
38
+ - `@metamask/transaction-controller` (^62.3.0)
39
+ - In clients, it is now possible for multiple versions of these packages to exist in the dependency tree.
40
+ - For example, this scenario would be valid: a client relies on `@metamask/controller-a` 1.0.0 and `@metamask/controller-b` 1.0.0, and `@metamask/controller-b` depends on `@metamask/controller-a` 1.1.0.
41
+ - Note, however, that the versions specified in the client's `package.json` always "win", and you are expected to keep them up to date so as not to break controller and service intercommunication.
42
+
43
+ ### Fixed
44
+
45
+ - Fix `TokenBalancesController` state that store both lowercase and checksum account addresses ([#7217](https://github.com/MetaMask/core/pull/7217))
46
+ - `TokenBalancesController`: state inconsistency by ensuring all account addresses are stored in lowercase format ([#7216](https://github.com/MetaMask/core/pull/7216))
47
+ - Add MON (Monad) to supported currencies list in token prices service ([#7250](https://github.com/MetaMask/core/pull/7250))
48
+
10
49
  ## [91.0.0]
11
50
 
12
51
  ### Changed
@@ -2316,7 +2355,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2316
2355
 
2317
2356
  - Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
2318
2357
 
2319
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@91.0.0...HEAD
2358
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@92.0.0...HEAD
2359
+ [92.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@91.0.0...@metamask/assets-controllers@92.0.0
2320
2360
  [91.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@90.0.0...@metamask/assets-controllers@91.0.0
2321
2361
  [90.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@89.0.1...@metamask/assets-controllers@90.0.0
2322
2362
  [89.0.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@89.0.0...@metamask/assets-controllers@89.0.1
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
2
7
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
8
  if (kind === "m") throw new TypeError("Private method is not writable");
4
9
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
11
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
12
  };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _TokenBalancesController_instances, _TokenBalancesController_platform, _TokenBalancesController_queryAllAccounts, _TokenBalancesController_accountsApiChainIds, _TokenBalancesController_balanceFetchers, _TokenBalancesController_allTokens, _TokenBalancesController_detectedTokens, _TokenBalancesController_allIgnoredTokens, _TokenBalancesController_defaultInterval, _TokenBalancesController_websocketActivePollingInterval, _TokenBalancesController_chainPollingConfig, _TokenBalancesController_intervalPollingTimers, _TokenBalancesController_isControllerPollingActive, _TokenBalancesController_requestedChainIds, _TokenBalancesController_statusChangeDebouncer, _TokenBalancesController_chainIdsWithTokens, _TokenBalancesController_getProvider, _TokenBalancesController_getNetworkClient, _TokenBalancesController_createAccountsApiFetcher, _TokenBalancesController_startIntervalGroupPolling, _TokenBalancesController_startPollingForInterval, _TokenBalancesController_setPollingTimer, _TokenBalancesController_isTokenTracked, _TokenBalancesController_onTokensChanged, _TokenBalancesController_onNetworkChanged, _TokenBalancesController_onAccountRemoved, _TokenBalancesController_prepareBalanceUpdates, _TokenBalancesController_onAccountActivityBalanceUpdate, _TokenBalancesController_onAccountActivityStatusChanged, _TokenBalancesController_processAccumulatedStatusChanges;
13
+ var _TokenBalancesController_instances, _TokenBalancesController_platform, _TokenBalancesController_queryAllAccounts, _TokenBalancesController_accountsApiChainIds, _TokenBalancesController_balanceFetchers, _TokenBalancesController_allTokens, _TokenBalancesController_detectedTokens, _TokenBalancesController_allIgnoredTokens, _TokenBalancesController_defaultInterval, _TokenBalancesController_websocketActivePollingInterval, _TokenBalancesController_chainPollingConfig, _TokenBalancesController_intervalPollingTimers, _TokenBalancesController_isControllerPollingActive, _TokenBalancesController_requestedChainIds, _TokenBalancesController_statusChangeDebouncer, _TokenBalancesController_normalizeAccountAddresses, _TokenBalancesController_chainIdsWithTokens, _TokenBalancesController_getProvider, _TokenBalancesController_getNetworkClient, _TokenBalancesController_createAccountsApiFetcher, _TokenBalancesController_startIntervalGroupPolling, _TokenBalancesController_startPollingForInterval, _TokenBalancesController_setPollingTimer, _TokenBalancesController_isTokenTracked, _TokenBalancesController_onTokensChanged, _TokenBalancesController_onNetworkChanged, _TokenBalancesController_onAccountRemoved, _TokenBalancesController_prepareBalanceUpdates, _TokenBalancesController_onAccountActivityBalanceUpdate, _TokenBalancesController_onAccountActivityStatusChanged, _TokenBalancesController_processAccumulatedStatusChanges;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.TokenBalancesController = exports.parseAssetType = exports.caipChainIdToHex = void 0;
16
16
  const providers_1 = require("@ethersproject/providers");
@@ -337,6 +337,8 @@ class TokenBalancesController extends (0, polling_controller_1.StaticIntervalPol
337
337
  __classPrivateFieldGet(this, _TokenBalancesController_instances, "m", _TokenBalancesController_processAccumulatedStatusChanges).call(this);
338
338
  }, 5000); // 5-second debounce window
339
339
  });
340
+ // Normalize all account addresses to lowercase in existing state
341
+ __classPrivateFieldGet(this, _TokenBalancesController_instances, "m", _TokenBalancesController_normalizeAccountAddresses).call(this);
340
342
  __classPrivateFieldSet(this, _TokenBalancesController_platform, platform ?? 'extension', "f");
341
343
  __classPrivateFieldSet(this, _TokenBalancesController_queryAllAccounts, queryMultipleAccounts, "f");
342
344
  __classPrivateFieldSet(this, _TokenBalancesController_accountsApiChainIds, accountsApiChainIds, "f");
@@ -457,6 +459,9 @@ class TokenBalancesController extends (0, polling_controller_1.StaticIntervalPol
457
459
  }
458
460
  const { address: selected } = this.messenger.call('AccountsController:getSelectedAccount');
459
461
  const allAccounts = this.messenger.call('AccountsController:listAccounts');
462
+ const jwtToken = await (0, controller_utils_1.safelyExecuteWithTimeout)(() => {
463
+ return this.messenger.call('AuthenticationController:getBearerToken');
464
+ }, false, 5000);
460
465
  const aggregated = [];
461
466
  let remainingChains = [...targetChains];
462
467
  // Try each fetcher in order, removing successfully processed chains
@@ -471,6 +476,7 @@ class TokenBalancesController extends (0, polling_controller_1.StaticIntervalPol
471
476
  queryAllAccounts: queryAllAccounts ?? __classPrivateFieldGet(this, _TokenBalancesController_queryAllAccounts, "f"),
472
477
  selectedAccount: selected,
473
478
  allAccounts,
479
+ jwtToken,
474
480
  });
475
481
  if (result.balances && result.balances.length > 0) {
476
482
  aggregated.push(...result.balances);
@@ -535,14 +541,16 @@ class TokenBalancesController extends (0, polling_controller_1.StaticIntervalPol
535
541
  }
536
542
  // Update with actual fetched balances only if the value has changed
537
543
  aggregated.forEach(({ success, value, account, token, chainId }) => {
538
- var _a, _b, _c;
544
+ var _a, _b;
539
545
  if (success && value !== undefined) {
546
+ // Ensure all accounts we add/update are in lower-case
547
+ const lowerCaseAccount = account.toLowerCase();
540
548
  const newBalance = (0, controller_utils_1.toHex)(value);
541
549
  const tokenAddress = checksum(token);
542
- const currentBalance = d.tokenBalances[account]?.[chainId]?.[tokenAddress];
550
+ const currentBalance = d.tokenBalances[lowerCaseAccount]?.[chainId]?.[tokenAddress];
543
551
  // Only update if the balance has actually changed
544
552
  if (currentBalance !== newBalance) {
545
- ((_c = ((_a = d.tokenBalances)[_b = account] ?? (_a[_b] = {})))[chainId] ?? (_c[chainId] = {}))[tokenAddress] = newBalance;
553
+ ((_b = ((_a = d.tokenBalances)[lowerCaseAccount] ?? (_a[lowerCaseAccount] = {})))[chainId] ?? (_b[chainId] = {}))[tokenAddress] = newBalance;
546
554
  }
547
555
  }
548
556
  });
@@ -619,7 +627,37 @@ class TokenBalancesController extends (0, polling_controller_1.StaticIntervalPol
619
627
  }
620
628
  }
621
629
  exports.TokenBalancesController = TokenBalancesController;
622
- _TokenBalancesController_platform = new WeakMap(), _TokenBalancesController_queryAllAccounts = new WeakMap(), _TokenBalancesController_accountsApiChainIds = new WeakMap(), _TokenBalancesController_balanceFetchers = new WeakMap(), _TokenBalancesController_allTokens = new WeakMap(), _TokenBalancesController_detectedTokens = new WeakMap(), _TokenBalancesController_allIgnoredTokens = new WeakMap(), _TokenBalancesController_defaultInterval = new WeakMap(), _TokenBalancesController_websocketActivePollingInterval = new WeakMap(), _TokenBalancesController_chainPollingConfig = new WeakMap(), _TokenBalancesController_intervalPollingTimers = new WeakMap(), _TokenBalancesController_isControllerPollingActive = new WeakMap(), _TokenBalancesController_requestedChainIds = new WeakMap(), _TokenBalancesController_statusChangeDebouncer = new WeakMap(), _TokenBalancesController_getProvider = new WeakMap(), _TokenBalancesController_getNetworkClient = new WeakMap(), _TokenBalancesController_createAccountsApiFetcher = new WeakMap(), _TokenBalancesController_onTokensChanged = new WeakMap(), _TokenBalancesController_onNetworkChanged = new WeakMap(), _TokenBalancesController_onAccountRemoved = new WeakMap(), _TokenBalancesController_onAccountActivityBalanceUpdate = new WeakMap(), _TokenBalancesController_onAccountActivityStatusChanged = new WeakMap(), _TokenBalancesController_instances = new WeakSet(), _TokenBalancesController_chainIdsWithTokens = function _TokenBalancesController_chainIdsWithTokens() {
630
+ _TokenBalancesController_platform = new WeakMap(), _TokenBalancesController_queryAllAccounts = new WeakMap(), _TokenBalancesController_accountsApiChainIds = new WeakMap(), _TokenBalancesController_balanceFetchers = new WeakMap(), _TokenBalancesController_allTokens = new WeakMap(), _TokenBalancesController_detectedTokens = new WeakMap(), _TokenBalancesController_allIgnoredTokens = new WeakMap(), _TokenBalancesController_defaultInterval = new WeakMap(), _TokenBalancesController_websocketActivePollingInterval = new WeakMap(), _TokenBalancesController_chainPollingConfig = new WeakMap(), _TokenBalancesController_intervalPollingTimers = new WeakMap(), _TokenBalancesController_isControllerPollingActive = new WeakMap(), _TokenBalancesController_requestedChainIds = new WeakMap(), _TokenBalancesController_statusChangeDebouncer = new WeakMap(), _TokenBalancesController_getProvider = new WeakMap(), _TokenBalancesController_getNetworkClient = new WeakMap(), _TokenBalancesController_createAccountsApiFetcher = new WeakMap(), _TokenBalancesController_onTokensChanged = new WeakMap(), _TokenBalancesController_onNetworkChanged = new WeakMap(), _TokenBalancesController_onAccountRemoved = new WeakMap(), _TokenBalancesController_onAccountActivityBalanceUpdate = new WeakMap(), _TokenBalancesController_onAccountActivityStatusChanged = new WeakMap(), _TokenBalancesController_instances = new WeakSet(), _TokenBalancesController_normalizeAccountAddresses = function _TokenBalancesController_normalizeAccountAddresses() {
631
+ const currentState = this.state.tokenBalances;
632
+ const normalizedBalances = {};
633
+ // Iterate through all accounts and normalize to lowercase
634
+ for (const address of Object.keys(currentState)) {
635
+ const lowercaseAddress = address.toLowerCase();
636
+ const accountBalances = currentState[address];
637
+ if (!accountBalances) {
638
+ continue;
639
+ }
640
+ // If this lowercase address doesn't exist yet, create it
641
+ if (!normalizedBalances[lowercaseAddress]) {
642
+ normalizedBalances[lowercaseAddress] = {};
643
+ }
644
+ // Merge chain data
645
+ for (const chainId of Object.keys(accountBalances)) {
646
+ const chainIdKey = chainId;
647
+ if (!normalizedBalances[lowercaseAddress][chainIdKey]) {
648
+ normalizedBalances[lowercaseAddress][chainIdKey] = {};
649
+ }
650
+ // Merge token balances (later values override earlier ones if duplicates exist)
651
+ Object.assign(normalizedBalances[lowercaseAddress][chainIdKey], accountBalances[chainIdKey]);
652
+ }
653
+ }
654
+ // Only update if there were changes
655
+ if (Object.keys(currentState).length !==
656
+ Object.keys(normalizedBalances).length ||
657
+ Object.keys(currentState).some((addr) => addr !== addr.toLowerCase())) {
658
+ this.update(() => ({ tokenBalances: normalizedBalances }));
659
+ }
660
+ }, _TokenBalancesController_chainIdsWithTokens = function _TokenBalancesController_chainIdsWithTokens() {
623
661
  return [
624
662
  ...new Set([
625
663
  ...Object.keys(__classPrivateFieldGet(this, _TokenBalancesController_allTokens, "f")),
@@ -1 +1 @@
1
- {"version":3,"file":"TokenBalancesController.cjs","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport {\n BNToHex,\n isValidHexAddress,\n toChecksumHexAddress,\n toHex,\n} from '@metamask/controller-utils';\nimport type {\n BalanceUpdate,\n AccountActivityServiceBalanceUpdatedEvent,\n AccountActivityServiceStatusChangedEvent,\n} from '@metamask/core-backend';\nimport type { KeyringControllerAccountRemovedEvent } from '@metamask/keyring-controller';\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 { 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 {\n AccountsApiBalanceFetcher,\n type BalanceFetcher,\n type ProcessedBalance,\n} from './multi-chain-accounts-service/api-balance-fetcher';\nimport { RpcBalanceFetcher } from './rpc-service/rpc-balance-fetcher';\nimport type { TokenDetectionControllerAddDetectedTokensViaWsAction } 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 | TokenDetectionControllerAddDetectedTokensViaWsAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerListAccountsAction\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction;\n\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | PreferencesControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | KeyringControllerAccountRemovedEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceStatusChangedEvent;\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// endregion\n\n// ────────────────────────────────────────────────────────────────────────────\n// region: Helper utilities\nconst draft = <T>(base: T, fn: (d: T) => void): T => 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 * Handles both CAIP-2 format (e.g., \"eip155:1\") and hex format (e.g., \"0x1\")\n *\n * @param chainId - CAIP chain ID (e.g., \"eip155:1\") or hex chain ID (e.g., \"0x1\")\n * @returns Hex chain ID (e.g., \"0x1\")\n * @throws {Error} If chainId is neither a valid CAIP-2 chain ID nor a hex string\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 * Returns tuple of [tokenAddress, isNativeToken] or null if invalid\n *\n * @param assetType - Asset type string (e.g., 'eip155:1/erc20:0x...' or 'eip155:1/slip44:60')\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 // ERC20 token (e.g., \"eip155:1/erc20:0x...\")\n if (parsed.assetNamespace === 'erc20') {\n return [parsed.assetReference, false];\n }\n\n // Native token (e.g., \"eip155:1/slip44:60\")\n if (parsed.assetNamespace === 'slip44') {\n return [ZERO_ADDRESS, true];\n }\n\n return null;\n};\n// endregion\n\n// ────────────────────────────────────────────────────────────────────────────\n// region: Main controller\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 #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 /** 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 = () => [],\n allowExternalServices = () => true,\n platform,\n }: TokenBalancesControllerOptions) {\n super({\n name: CONTROLLER,\n messenger,\n metadata,\n state: { tokenBalances: {}, ...state },\n });\n\n this.#platform = platform ?? 'extension';\n this.#queryAllAccounts = queryMultipleAccounts;\n this.#accountsApiChainIds = accountsApiChainIds;\n this.#defaultInterval = interval;\n this.#websocketActivePollingInterval = websocketActivePollingInterval;\n this.#chainPollingConfig = { ...chainPollingIntervals };\n\n // Strategy order: API first, then RPC fallback\n this.#balanceFetchers = [\n ...(accountsApiChainIds().length > 0 && allowExternalServices()\n ? [this.#createAccountsApiFetcher()]\n : []),\n new RpcBalanceFetcher(this.#getProvider, this.#getNetworkClient, () => ({\n allTokens: this.#allTokens,\n allDetectedTokens: this.#detectedTokens,\n })),\n ];\n\n this.setIntervalLength(interval);\n\n // initial token state & subscriptions\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 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 this.messenger.subscribe(\n 'NetworkController:stateChange',\n this.#onNetworkChanged,\n );\n this.messenger.subscribe(\n 'KeyringController:accountRemoved',\n this.#onAccountRemoved,\n );\n\n // Register action handlers for polling interval control\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 // Subscribe to AccountActivityService balance updates for real-time updates\n this.messenger.subscribe(\n 'AccountActivityService:balanceUpdated',\n this.#onAccountActivityBalanceUpdate.bind(this),\n );\n\n // Subscribe to AccountActivityService status changes for dynamic polling management\n this.messenger.subscribe(\n 'AccountActivityService:statusChanged',\n this.#onAccountActivityStatusChanged.bind(this),\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 cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n const client = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (chainId: ChainIdHex) => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n return this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n };\n\n /**\n * Creates an AccountsApiBalanceFetcher that only supports chains in the accountsApiChainIds array\n *\n * @returns A BalanceFetcher that wraps AccountsApiBalanceFetcher with chainId filtering\n */\n readonly #createAccountsApiFetcher = (): BalanceFetcher => {\n const originalFetcher = new AccountsApiBalanceFetcher(\n this.#platform,\n this.#getProvider,\n );\n\n return {\n supports: (chainId: ChainIdHex): boolean => {\n // Only support chains that are both:\n // 1. In our specified accountsApiChainIds array\n // 2. Actually supported by the AccountsApi\n return (\n this.#accountsApiChainIds().includes(chainId) &&\n originalFetcher.supports(chainId)\n );\n },\n fetch: originalFetcher.fetch.bind(originalFetcher),\n };\n };\n\n /**\n * Override to support per-chain polling intervals by grouping chains by interval\n *\n * @param options0 - The polling options\n * @param options0.chainIds - Chain IDs to start polling for\n */\n override _startPolling({ chainIds }: { chainIds: ChainIdHex[] }) {\n // Store the original chainIds to preserve intent across config updates\n this.#requestedChainIds = [...chainIds];\n this.#isControllerPollingActive = true;\n this.#startIntervalGroupPolling(chainIds, true);\n }\n\n /**\n * Start or restart interval-based polling for multiple chains\n *\n * @param chainIds - Chain IDs to start polling for\n * @param immediate - Whether to poll immediately before starting timers (default: true)\n */\n #startIntervalGroupPolling(chainIds: ChainIdHex[], immediate = true) {\n // Stop any existing interval timers\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n // Group chains by their polling intervals\n const intervalGroups = new Map<number, ChainIdHex[]>();\n\n for (const chainId of chainIds) {\n const config = this.getChainPollingConfig(chainId);\n const existing = intervalGroups.get(config.interval) || [];\n existing.push(chainId);\n intervalGroups.set(config.interval, existing);\n }\n\n // Start separate polling loop for each interval group\n for (const [interval, chainIdsGroup] of intervalGroups) {\n this.#startPollingForInterval(interval, chainIdsGroup, immediate);\n }\n }\n\n /**\n * Start polling loop for chains that share the same interval\n *\n * @param interval - The polling interval in milliseconds\n * @param chainIds - Chain IDs that share this interval\n * @param immediate - Whether to poll immediately before starting the timer (default: true)\n */\n #startPollingForInterval(\n interval: number,\n chainIds: ChainIdHex[],\n immediate = true,\n ) {\n const pollFunction = async () => {\n if (!this.#isControllerPollingActive) {\n return;\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 // Poll immediately first if requested\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 // Then start regular interval polling\n this.#setPollingTimer(interval, chainIds, pollFunction);\n }\n\n /**\n * Helper method to set up polling timer\n *\n * @param interval - The polling interval in milliseconds\n * @param chainIds - Chain IDs for this interval\n * @param pollFunction - The function to call on each poll\n */\n #setPollingTimer(\n interval: number,\n chainIds: ChainIdHex[],\n pollFunction: () => Promise<void>,\n ) {\n // Clear any existing timer for this interval first\n const existingTimer = this.#intervalPollingTimers.get(interval);\n if (existingTimer) {\n clearInterval(existingTimer);\n }\n\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 this.#intervalPollingTimers.set(interval, timer);\n }\n\n /**\n * Override to handle our custom polling approach\n *\n * @param tokenSetId - The token set ID to stop polling for\n */\n override _stopPollingByPollingTokenSetId(tokenSetId: string) {\n let parsedTokenSetId;\n let chainsToStop: ChainIdHex[] = [];\n\n try {\n parsedTokenSetId = JSON.parse(tokenSetId);\n chainsToStop = parsedTokenSetId.chainIds || [];\n } catch (error) {\n console.warn('Failed to parse tokenSetId, stopping all polling:', error);\n // Fallback: stop all polling if we can't parse the tokenSetId\n this.#isControllerPollingActive = false;\n this.#requestedChainIds = [];\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n return;\n }\n\n // Compare with current chains - only stop if it matches our current session\n const currentChainsSet = new Set(this.#requestedChainIds);\n const stopChainsSet = new Set(chainsToStop);\n\n // Check if this stop request is for our current session\n const isCurrentSession =\n currentChainsSet.size === stopChainsSet.size &&\n [...currentChainsSet].every((chain) => stopChainsSet.has(chain));\n\n if (isCurrentSession) {\n this.#isControllerPollingActive = false;\n this.#requestedChainIds = [];\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n }\n }\n\n /**\n * Get polling configuration for a chain (includes default fallback)\n *\n * @param chainId - The chain ID to get config for\n * @returns The polling configuration for the chain\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 }) {\n // This won't be called with our custom implementation, but keep for compatibility\n await this.updateBalances({ chainIds, queryAllAccounts });\n }\n\n /**\n * Update multiple chain polling configurations at once\n *\n * @param configs - Object mapping chain IDs to polling configurations\n * @param options - Optional configuration for the update behavior\n * @param options.immediateUpdate - Whether to immediately fetch balances after updating configs (default: true)\n */\n updateChainPollingConfigs(\n configs: Record<ChainIdHex, ChainPollingConfig>,\n options: UpdateChainPollingConfigsOptions = { immediateUpdate: true },\n ): void {\n Object.assign(this.#chainPollingConfig, configs);\n\n // If polling is currently active, restart with new interval groupings\n if (this.#isControllerPollingActive) {\n // Restart polling with immediate fetch by default, unless explicitly disabled\n this.#startIntervalGroupPolling(\n this.#requestedChainIds,\n options.immediateUpdate,\n );\n }\n }\n\n async updateBalances({\n chainIds,\n queryAllAccounts = false,\n }: { chainIds?: ChainIdHex[]; queryAllAccounts?: boolean } = {}) {\n const targetChains = chainIds ?? this.#chainIdsWithTokens();\n if (!targetChains.length) {\n return;\n }\n\n const { address: selected } = this.messenger.call(\n 'AccountsController:getSelectedAccount',\n );\n const allAccounts = this.messenger.call('AccountsController:listAccounts');\n\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...targetChains];\n\n // Try each fetcher in order, removing successfully processed chains\n for (const fetcher of this.#balanceFetchers) {\n const supportedChains = remainingChains.filter((c) =>\n fetcher.supports(c),\n );\n if (!supportedChains.length) {\n continue;\n }\n\n try {\n const result = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts: queryAllAccounts ?? this.#queryAllAccounts,\n selectedAccount: selected as ChecksumAddress,\n allAccounts,\n });\n\n if (result.balances && result.balances.length > 0) {\n aggregated.push(...result.balances);\n // Remove chains that were successfully processed\n const processedChains = new Set(\n result.balances.map((b) => b.chainId),\n );\n remainingChains = remainingChains.filter(\n (chain) => !processedChains.has(chain),\n );\n }\n\n // Add unprocessed chains back to remainingChains for next fetcher\n if (\n result.unprocessedChainIds &&\n result.unprocessedChainIds.length > 0\n ) {\n const currentRemainingChains = remainingChains;\n const chainsToAdd = result.unprocessedChainIds.filter(\n (chainId) =>\n supportedChains.includes(chainId) &&\n !currentRemainingChains.includes(chainId),\n );\n remainingChains.push(...chainsToAdd);\n }\n } catch (error) {\n console.warn(\n `Balance fetcher failed for chains ${supportedChains.join(', ')}: ${String(error)}`,\n );\n // Continue to next fetcher (fallback)\n }\n\n // If all chains have been processed, break early\n if (remainingChains.length === 0) {\n break;\n }\n }\n\n // Determine which accounts to process based on queryAllAccounts parameter\n const accountsToProcess =\n (queryAllAccounts ?? this.#queryAllAccounts)\n ? allAccounts.map((a) => a.address as ChecksumAddress)\n : [selected as ChecksumAddress];\n\n const prev = this.state;\n const next = draft(prev, (d) => {\n // Initialize account and chain structures if they don't exist, but preserve existing balances\n for (const chainId of targetChains) {\n for (const account of accountsToProcess) {\n // Ensure the nested structure exists without overwriting existing balances\n d.tokenBalances[account] ??= {};\n d.tokenBalances[account][chainId] ??= {};\n // Initialize tokens from allTokens only if they don't exist yet\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 // Only initialize if the token balance doesn't exist yet\n if (!(tokenAddress in d.tokenBalances[account][chainId])) {\n d.tokenBalances[account][chainId][tokenAddress] = '0x0';\n }\n },\n );\n }\n\n // Initialize tokens from allDetectedTokens only if they don't exist yet\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 // Only initialize if the token balance doesn't exist yet\n if (!(tokenAddress in d.tokenBalances[account][chainId])) {\n d.tokenBalances[account][chainId][tokenAddress] = '0x0';\n }\n },\n );\n }\n }\n }\n\n // Update with actual fetched balances only if the value has changed\n aggregated.forEach(({ success, value, account, token, chainId }) => {\n if (success && value !== undefined) {\n const newBalance = toHex(value);\n const tokenAddress = checksum(token);\n const currentBalance =\n d.tokenBalances[account as ChecksumAddress]?.[chainId]?.[\n tokenAddress\n ];\n\n // Only update if the balance has actually changed\n if (currentBalance !== newBalance) {\n ((d.tokenBalances[account as ChecksumAddress] ??= {})[chainId] ??=\n {})[tokenAddress] = newBalance;\n }\n }\n });\n });\n\n if (!isEqual(prev, next)) {\n this.update(() => next);\n\n const nativeBalances = aggregated.filter(\n (r) => r.success && r.token === ZERO_ADDRESS,\n );\n\n // Get current AccountTracker state to compare existing balances\n const accountTrackerState = this.messenger.call(\n 'AccountTrackerController:getState',\n );\n\n // Update native token balances only if they have changed\n if (nativeBalances.length > 0) {\n const balanceUpdates = 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 // Only include if the balance has actually changed\n return currentBalance !== update.balance;\n });\n\n if (balanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n balanceUpdates,\n );\n }\n }\n\n // Filter and update staked balances in a single batch operation for better performance\n const stakedBalances = aggregated.filter((r) => {\n if (!r.success || r.token === ZERO_ADDRESS) {\n return false;\n }\n\n // Check if the chainId and token address match any staking contract\n const stakingContractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n r.chainId as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n return (\n stakingContractAddress &&\n stakingContractAddress.toLowerCase() === r.token.toLowerCase()\n );\n });\n\n if (stakedBalances.length > 0) {\n const stakedBalanceUpdates = 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 // Only include if the staked balance has actually changed\n return currentStakedBalance !== update.stakedBalance;\n });\n\n if (stakedBalanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateStakedBalances',\n stakedBalanceUpdates,\n );\n }\n }\n }\n }\n\n resetState() {\n this.update(() => ({ tokenBalances: {} }));\n }\n\n /**\n * Helper method to check if a token is tracked (exists in allTokens or allIgnoredTokens)\n *\n * @param tokenAddress - The token address to check\n * @param account - The account address\n * @param chainId - The chain ID\n * @returns True if the token is tracked (imported or ignored)\n */\n #isTokenTracked(\n tokenAddress: string,\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): boolean {\n // Check if token exists in allTokens\n if (\n this.#allTokens?.[chainId]?.[account.toLowerCase()]?.some(\n (token) => token.address === tokenAddress,\n )\n ) {\n return true;\n }\n\n // Check if token exists in allIgnoredTokens\n if (\n this.#allIgnoredTokens?.[chainId]?.[account.toLowerCase()]?.some(\n (token) => token === tokenAddress,\n )\n ) {\n return true;\n }\n\n return false;\n }\n\n readonly #onTokensChanged = async (state: TokensControllerState) => {\n const changed: ChainIdHex[] = [];\n let hasChanges = false;\n\n // Get chains that have existing balances\n const chainsWithBalances = new Set<ChainIdHex>();\n for (const address of Object.keys(this.state.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const chainId of Object.keys(\n this.state.tokenBalances[addressKey] || {},\n )) {\n chainsWithBalances.add(chainId as ChainIdHex);\n }\n }\n\n // Only process chains that are explicitly mentioned in the incoming state change\n const incomingChainIds = new Set([\n ...Object.keys(state.allTokens),\n ...Object.keys(state.allDetectedTokens),\n ]);\n\n // Only proceed if there are actual changes to chains that have balances or are being added\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 // Check if there's an actual change in token state\n const hasTokenChange =\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id]);\n\n // Process chains that have actual changes OR are new chains getting tokens\n return hasTokenChange || (!hadTokensBefore && hasTokensNow);\n });\n\n if (relevantChainIds.length === 0) {\n // No relevant changes, just update internal state\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n return;\n }\n\n // Handle both cleanup and updates in a single state update\n this.update((s) => {\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 if (\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id])\n ) {\n if (hasTokensNow) {\n // Chain still has tokens - mark for async balance update\n changed.push(id);\n } else if (hadTokensBefore) {\n // Chain had tokens before but doesn't now - clean up balances immediately\n for (const address of Object.keys(s.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n if (s.tokenBalances[addressKey]?.[id]) {\n s.tokenBalances[addressKey][id] = {};\n hasChanges = true;\n }\n }\n }\n }\n }\n });\n\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n this.#allIgnoredTokens = state.allIgnoredTokens;\n\n // Only update balances for chains that still have tokens (and only if we haven't already updated state)\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) => {\n // Check if any networks were removed by comparing with previous state\n const currentNetworks = new Set(\n Object.keys(state.networkConfigurationsByChainId),\n );\n\n // Get all networks that currently have balances\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 // Find networks that were removed\n const removedNetworks = Array.from(networksWithBalances).filter(\n (network) => !currentNetworks.has(network),\n );\n\n if (removedNetworks.length > 0) {\n this.update((s) => {\n // Remove balances for all accounts on the deleted networks\n for (const address of Object.keys(s.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const removedNetwork of removedNetworks) {\n const networkKey = removedNetwork as ChainIdHex;\n if (s.tokenBalances[addressKey]?.[networkKey]) {\n delete s.tokenBalances[addressKey][networkKey];\n }\n }\n }\n });\n }\n };\n\n readonly #onAccountRemoved = (addr: string) => {\n if (!isStrictHexString(addr) || !isValidHexAddress(addr)) {\n return;\n }\n this.update((s) => {\n delete s.tokenBalances[addr as ChecksumAddress];\n });\n };\n\n // ────────────────────────────────────────────────────────────────────────────\n // AccountActivityService integration helpers\n\n /**\n * Prepare balance updates from AccountActivityService\n * Processes all updates and returns categorized results\n * Throws an error if any updates have validation/parsing issues\n *\n * @param updates - Array of balance updates from AccountActivityService\n * @param account - Lowercase account address (for consistency with tokenBalances state format)\n * @param chainId - Hex chain ID\n * @returns Object containing arrays of token balances, new token addresses to add, and native balance updates\n * @throws Error if any balance update has validation or parsing errors\n */\n #prepareBalanceUpdates(\n updates: BalanceUpdate[],\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): {\n tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[];\n newTokens: string[];\n nativeBalanceUpdates: { address: string; chainId: Hex; balance: Hex }[];\n } {\n const tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[] = [];\n const newTokens: string[] = [];\n const nativeBalanceUpdates: {\n address: string;\n chainId: Hex;\n balance: Hex;\n }[] = [];\n\n for (const update of updates) {\n const { asset, postBalance } = update;\n\n // Throw if balance update has an error\n if (postBalance.error) {\n throw new Error('Balance update has error');\n }\n\n // Parse token address from asset type\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 // Validate token address\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 // postBalance.amount is in hex format (raw units)\n const balanceHex = postBalance.amount as Hex;\n\n // Add token balance (tracked tokens, ignored tokens, and native tokens all get balance updates)\n tokenBalances.push({\n tokenAddress: checksumTokenAddress,\n balance: balanceHex,\n });\n\n // Add native balance update if this is a native token\n if (isNativeToken) {\n nativeBalanceUpdates.push({\n address: account,\n chainId,\n balance: balanceHex,\n });\n }\n\n // Handle untracked ERC20 tokens - queue for import\n if (!isNativeToken && !isTracked) {\n newTokens.push(checksumTokenAddress);\n }\n }\n\n return { tokenBalances, newTokens, nativeBalanceUpdates };\n }\n\n // ────────────────────────────────────────────────────────────────────────────\n // AccountActivityService event handlers\n\n /**\n * Handle real-time balance updates from AccountActivityService\n * Processes balance updates and updates the token balance state\n * If any balance update has an error, triggers fallback polling for the chain\n *\n * @param options0 - Balance update parameters\n * @param options0.address - Account address\n * @param options0.chain - CAIP chain identifier\n * @param options0.updates - Array of balance updates for the account\n */\n readonly #onAccountActivityBalanceUpdate = async ({\n address,\n chain,\n updates,\n }: {\n address: string;\n chain: string;\n updates: BalanceUpdate[];\n }) => {\n const chainId = caipChainIdToHex(chain);\n const checksummedAccount = checksum(address);\n\n try {\n // Process all balance updates at once\n const { tokenBalances, newTokens, nativeBalanceUpdates } =\n this.#prepareBalanceUpdates(updates, checksummedAccount, chainId);\n\n // Update state once with all token balances\n if (tokenBalances.length > 0) {\n this.update((state) => {\n // Temporary until ADR to normalize all keys - tokenBalances state requires: account in lowercase, token in checksum\n const lowercaseAccount =\n checksummedAccount.toLowerCase() as ChecksumAddress;\n state.tokenBalances[lowercaseAccount] ??= {};\n state.tokenBalances[lowercaseAccount][chainId] ??= {};\n\n // Apply all token balance updates\n for (const { tokenAddress, balance } of tokenBalances) {\n state.tokenBalances[lowercaseAccount][chainId][tokenAddress] =\n balance;\n }\n });\n }\n\n // Update native balances in AccountTrackerController\n if (nativeBalanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n nativeBalanceUpdates,\n );\n }\n\n // Import any new tokens that were discovered (balance already updated from websocket)\n if (newTokens.length > 0) {\n await this.messenger.call(\n 'TokenDetectionController:addDetectedTokensViaWs',\n {\n tokensSlice: newTokens,\n chainId: chainId as Hex,\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 // On error, trigger fallback polling\n await this.updateBalances({ chainIds: [chainId] }).catch(() => {\n // Silently handle polling errors\n });\n }\n };\n\n /**\n * Handle status changes from AccountActivityService\n * Uses aggressive debouncing to prevent excessive HTTP calls from rapid up/down changes\n *\n * @param options0 - Status change event data\n * @param options0.chainIds - Array of chain identifiers\n * @param options0.status - Connection status ('up' for connected, 'down' for disconnected)\n */\n readonly #onAccountActivityStatusChanged = ({\n chainIds,\n status,\n }: {\n chainIds: string[];\n status: 'up' | 'down';\n }) => {\n // Update pending changes (latest status wins for each chain)\n for (const chainId of chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, status);\n }\n\n // Clear existing timer to extend debounce window\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n // Set new timer - only process changes after activity settles\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, 5000); // 5-second debounce window\n };\n\n /**\n * Process all accumulated status changes in one batch to minimize HTTP calls\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 === 0) {\n return;\n }\n\n // Calculate final polling configurations\n const chainConfigs: Record<ChainIdHex, { interval: number }> = {};\n\n for (const [chainId, status] of changes) {\n // Convert CAIP format (eip155:1) to hex format (0x1)\n // chainId is always in CAIP format from AccountActivityService\n const hexChainId = caipChainIdToHex(chainId);\n\n if (status === 'down') {\n // Chain is down - use default polling since no real-time updates available\n chainConfigs[hexChainId] = { interval: this.#defaultInterval };\n } else {\n // Chain is up - use longer intervals since WebSocket provides real-time updates\n chainConfigs[hexChainId] = {\n interval: this.#websocketActivePollingInterval,\n };\n }\n }\n\n // Add jitter to prevent synchronized requests across instances\n const jitterDelay = Math.random() * this.#defaultInterval; // 0 to default interval\n\n setTimeout(() => {\n this.updateChainPollingConfigs(chainConfigs, { immediateUpdate: true });\n }, jitterDelay);\n }\n\n /**\n * Clean up all timers and resources when controller is destroyed\n */\n override destroy(): void {\n this.#isControllerPollingActive = false;\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n // Clean up debouncing timer\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n // Unregister action handlers\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.cjs","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type {\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\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 { KeyringControllerAccountRemovedEvent } from '@metamask/keyring-controller';\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 { 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 {\n AccountsApiBalanceFetcher,\n type BalanceFetcher,\n type ProcessedBalance,\n} from './multi-chain-accounts-service/api-balance-fetcher';\nimport { RpcBalanceFetcher } from './rpc-service/rpc-balance-fetcher';\nimport type { TokenDetectionControllerAddDetectedTokensViaWsAction } 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 | TokenDetectionControllerAddDetectedTokensViaWsAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerListAccountsAction\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction\n | AuthenticationController.AuthenticationControllerGetBearerToken;\n\nexport type AllowedEvents =\n | TokensControllerStateChangeEvent\n | PreferencesControllerStateChangeEvent\n | NetworkControllerStateChangeEvent\n | KeyringControllerAccountRemovedEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceStatusChangedEvent;\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// endregion\n\n// ────────────────────────────────────────────────────────────────────────────\n// region: Helper utilities\nconst draft = <T>(base: T, fn: (d: T) => void): T => 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 * Handles both CAIP-2 format (e.g., \"eip155:1\") and hex format (e.g., \"0x1\")\n *\n * @param chainId - CAIP chain ID (e.g., \"eip155:1\") or hex chain ID (e.g., \"0x1\")\n * @returns Hex chain ID (e.g., \"0x1\")\n * @throws {Error} If chainId is neither a valid CAIP-2 chain ID nor a hex string\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 * Returns tuple of [tokenAddress, isNativeToken] or null if invalid\n *\n * @param assetType - Asset type string (e.g., 'eip155:1/erc20:0x...' or 'eip155:1/slip44:60')\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 // ERC20 token (e.g., \"eip155:1/erc20:0x...\")\n if (parsed.assetNamespace === 'erc20') {\n return [parsed.assetReference, false];\n }\n\n // Native token (e.g., \"eip155:1/slip44:60\")\n if (parsed.assetNamespace === 'slip44') {\n return [ZERO_ADDRESS, true];\n }\n\n return null;\n};\n// endregion\n\n// ────────────────────────────────────────────────────────────────────────────\n// region: Main controller\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 #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 /** 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 = () => [],\n allowExternalServices = () => true,\n platform,\n }: TokenBalancesControllerOptions) {\n super({\n name: CONTROLLER,\n messenger,\n metadata,\n state: { tokenBalances: {}, ...state },\n });\n\n // Normalize all account addresses to lowercase in existing state\n this.#normalizeAccountAddresses();\n\n this.#platform = platform ?? 'extension';\n this.#queryAllAccounts = queryMultipleAccounts;\n this.#accountsApiChainIds = accountsApiChainIds;\n this.#defaultInterval = interval;\n this.#websocketActivePollingInterval = websocketActivePollingInterval;\n this.#chainPollingConfig = { ...chainPollingIntervals };\n\n // Strategy order: API first, then RPC fallback\n this.#balanceFetchers = [\n ...(accountsApiChainIds().length > 0 && allowExternalServices()\n ? [this.#createAccountsApiFetcher()]\n : []),\n new RpcBalanceFetcher(this.#getProvider, this.#getNetworkClient, () => ({\n allTokens: this.#allTokens,\n allDetectedTokens: this.#detectedTokens,\n })),\n ];\n\n this.setIntervalLength(interval);\n\n // initial token state & subscriptions\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 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 this.messenger.subscribe(\n 'NetworkController:stateChange',\n this.#onNetworkChanged,\n );\n this.messenger.subscribe(\n 'KeyringController:accountRemoved',\n this.#onAccountRemoved,\n );\n\n // Register action handlers for polling interval control\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 // Subscribe to AccountActivityService balance updates for real-time updates\n this.messenger.subscribe(\n 'AccountActivityService:balanceUpdated',\n this.#onAccountActivityBalanceUpdate.bind(this),\n );\n\n // Subscribe to AccountActivityService status changes for dynamic polling management\n this.messenger.subscribe(\n 'AccountActivityService:statusChanged',\n this.#onAccountActivityStatusChanged.bind(this),\n );\n }\n\n /**\n * Normalize all account addresses to lowercase and merge duplicates\n * This handles migration from old state where addresses might be checksummed\n */\n #normalizeAccountAddresses() {\n const currentState = this.state.tokenBalances;\n const normalizedBalances: TokenBalances = {};\n\n // Iterate through all accounts and normalize to lowercase\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 // If this lowercase address doesn't exist yet, create it\n if (!normalizedBalances[lowercaseAddress]) {\n normalizedBalances[lowercaseAddress] = {};\n }\n\n // Merge chain data\n for (const chainId of Object.keys(accountBalances)) {\n const chainIdKey = chainId as ChainIdHex;\n\n if (!normalizedBalances[lowercaseAddress][chainIdKey]) {\n normalizedBalances[lowercaseAddress][chainIdKey] = {};\n }\n\n // Merge token balances (later values override earlier ones if duplicates exist)\n Object.assign(\n normalizedBalances[lowercaseAddress][chainIdKey],\n accountBalances[chainIdKey],\n );\n }\n }\n\n // Only update if there were changes\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 cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n const client = this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (chainId: ChainIdHex) => {\n const { networkConfigurationsByChainId } = this.messenger.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n return this.messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n };\n\n /**\n * Creates an AccountsApiBalanceFetcher that only supports chains in the accountsApiChainIds array\n *\n * @returns A BalanceFetcher that wraps AccountsApiBalanceFetcher with chainId filtering\n */\n readonly #createAccountsApiFetcher = (): BalanceFetcher => {\n const originalFetcher = new AccountsApiBalanceFetcher(\n this.#platform,\n this.#getProvider,\n );\n\n return {\n supports: (chainId: ChainIdHex): boolean => {\n // Only support chains that are both:\n // 1. In our specified accountsApiChainIds array\n // 2. Actually supported by the AccountsApi\n return (\n this.#accountsApiChainIds().includes(chainId) &&\n originalFetcher.supports(chainId)\n );\n },\n fetch: originalFetcher.fetch.bind(originalFetcher),\n };\n };\n\n /**\n * Override to support per-chain polling intervals by grouping chains by interval\n *\n * @param options0 - The polling options\n * @param options0.chainIds - Chain IDs to start polling for\n */\n override _startPolling({ chainIds }: { chainIds: ChainIdHex[] }) {\n // Store the original chainIds to preserve intent across config updates\n this.#requestedChainIds = [...chainIds];\n this.#isControllerPollingActive = true;\n this.#startIntervalGroupPolling(chainIds, true);\n }\n\n /**\n * Start or restart interval-based polling for multiple chains\n *\n * @param chainIds - Chain IDs to start polling for\n * @param immediate - Whether to poll immediately before starting timers (default: true)\n */\n #startIntervalGroupPolling(chainIds: ChainIdHex[], immediate = true) {\n // Stop any existing interval timers\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n // Group chains by their polling intervals\n const intervalGroups = new Map<number, ChainIdHex[]>();\n\n for (const chainId of chainIds) {\n const config = this.getChainPollingConfig(chainId);\n const existing = intervalGroups.get(config.interval) || [];\n existing.push(chainId);\n intervalGroups.set(config.interval, existing);\n }\n\n // Start separate polling loop for each interval group\n for (const [interval, chainIdsGroup] of intervalGroups) {\n this.#startPollingForInterval(interval, chainIdsGroup, immediate);\n }\n }\n\n /**\n * Start polling loop for chains that share the same interval\n *\n * @param interval - The polling interval in milliseconds\n * @param chainIds - Chain IDs that share this interval\n * @param immediate - Whether to poll immediately before starting the timer (default: true)\n */\n #startPollingForInterval(\n interval: number,\n chainIds: ChainIdHex[],\n immediate = true,\n ) {\n const pollFunction = async () => {\n if (!this.#isControllerPollingActive) {\n return;\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 // Poll immediately first if requested\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 // Then start regular interval polling\n this.#setPollingTimer(interval, chainIds, pollFunction);\n }\n\n /**\n * Helper method to set up polling timer\n *\n * @param interval - The polling interval in milliseconds\n * @param chainIds - Chain IDs for this interval\n * @param pollFunction - The function to call on each poll\n */\n #setPollingTimer(\n interval: number,\n chainIds: ChainIdHex[],\n pollFunction: () => Promise<void>,\n ) {\n // Clear any existing timer for this interval first\n const existingTimer = this.#intervalPollingTimers.get(interval);\n if (existingTimer) {\n clearInterval(existingTimer);\n }\n\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 this.#intervalPollingTimers.set(interval, timer);\n }\n\n /**\n * Override to handle our custom polling approach\n *\n * @param tokenSetId - The token set ID to stop polling for\n */\n override _stopPollingByPollingTokenSetId(tokenSetId: string) {\n let parsedTokenSetId;\n let chainsToStop: ChainIdHex[] = [];\n\n try {\n parsedTokenSetId = JSON.parse(tokenSetId);\n chainsToStop = parsedTokenSetId.chainIds || [];\n } catch (error) {\n console.warn('Failed to parse tokenSetId, stopping all polling:', error);\n // Fallback: stop all polling if we can't parse the tokenSetId\n this.#isControllerPollingActive = false;\n this.#requestedChainIds = [];\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n return;\n }\n\n // Compare with current chains - only stop if it matches our current session\n const currentChainsSet = new Set(this.#requestedChainIds);\n const stopChainsSet = new Set(chainsToStop);\n\n // Check if this stop request is for our current session\n const isCurrentSession =\n currentChainsSet.size === stopChainsSet.size &&\n [...currentChainsSet].every((chain) => stopChainsSet.has(chain));\n\n if (isCurrentSession) {\n this.#isControllerPollingActive = false;\n this.#requestedChainIds = [];\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n }\n }\n\n /**\n * Get polling configuration for a chain (includes default fallback)\n *\n * @param chainId - The chain ID to get config for\n * @returns The polling configuration for the chain\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 }) {\n // This won't be called with our custom implementation, but keep for compatibility\n await this.updateBalances({ chainIds, queryAllAccounts });\n }\n\n /**\n * Update multiple chain polling configurations at once\n *\n * @param configs - Object mapping chain IDs to polling configurations\n * @param options - Optional configuration for the update behavior\n * @param options.immediateUpdate - Whether to immediately fetch balances after updating configs (default: true)\n */\n updateChainPollingConfigs(\n configs: Record<ChainIdHex, ChainPollingConfig>,\n options: UpdateChainPollingConfigsOptions = { immediateUpdate: true },\n ): void {\n Object.assign(this.#chainPollingConfig, configs);\n\n // If polling is currently active, restart with new interval groupings\n if (this.#isControllerPollingActive) {\n // Restart polling with immediate fetch by default, unless explicitly disabled\n this.#startIntervalGroupPolling(\n this.#requestedChainIds,\n options.immediateUpdate,\n );\n }\n }\n\n async updateBalances({\n chainIds,\n queryAllAccounts = false,\n }: { chainIds?: ChainIdHex[]; queryAllAccounts?: boolean } = {}) {\n const targetChains = chainIds ?? this.#chainIdsWithTokens();\n if (!targetChains.length) {\n return;\n }\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 const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...targetChains];\n\n // Try each fetcher in order, removing successfully processed chains\n for (const fetcher of this.#balanceFetchers) {\n const supportedChains = remainingChains.filter((c) =>\n fetcher.supports(c),\n );\n if (!supportedChains.length) {\n continue;\n }\n\n try {\n const result = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts: queryAllAccounts ?? this.#queryAllAccounts,\n selectedAccount: selected as ChecksumAddress,\n allAccounts,\n jwtToken,\n });\n\n if (result.balances && result.balances.length > 0) {\n aggregated.push(...result.balances);\n // Remove chains that were successfully processed\n const processedChains = new Set(\n result.balances.map((b) => b.chainId),\n );\n remainingChains = remainingChains.filter(\n (chain) => !processedChains.has(chain),\n );\n }\n\n // Add unprocessed chains back to remainingChains for next fetcher\n if (\n result.unprocessedChainIds &&\n result.unprocessedChainIds.length > 0\n ) {\n const currentRemainingChains = remainingChains;\n const chainsToAdd = result.unprocessedChainIds.filter(\n (chainId) =>\n supportedChains.includes(chainId) &&\n !currentRemainingChains.includes(chainId),\n );\n remainingChains.push(...chainsToAdd);\n }\n } catch (error) {\n console.warn(\n `Balance fetcher failed for chains ${supportedChains.join(', ')}: ${String(error)}`,\n );\n // Continue to next fetcher (fallback)\n }\n\n // If all chains have been processed, break early\n if (remainingChains.length === 0) {\n break;\n }\n }\n\n // Determine which accounts to process based on queryAllAccounts parameter\n const accountsToProcess =\n (queryAllAccounts ?? this.#queryAllAccounts)\n ? allAccounts.map((a) => a.address as ChecksumAddress)\n : [selected as ChecksumAddress];\n\n const prev = this.state;\n const next = draft(prev, (d) => {\n // Initialize account and chain structures if they don't exist, but preserve existing balances\n for (const chainId of targetChains) {\n for (const account of accountsToProcess) {\n // Ensure the nested structure exists without overwriting existing balances\n d.tokenBalances[account] ??= {};\n d.tokenBalances[account][chainId] ??= {};\n // Initialize tokens from allTokens only if they don't exist yet\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 // Only initialize if the token balance doesn't exist yet\n if (!(tokenAddress in d.tokenBalances[account][chainId])) {\n d.tokenBalances[account][chainId][tokenAddress] = '0x0';\n }\n },\n );\n }\n\n // Initialize tokens from allDetectedTokens only if they don't exist yet\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 // Only initialize if the token balance doesn't exist yet\n if (!(tokenAddress in d.tokenBalances[account][chainId])) {\n d.tokenBalances[account][chainId][tokenAddress] = '0x0';\n }\n },\n );\n }\n }\n }\n\n // Update with actual fetched balances only if the value has changed\n aggregated.forEach(({ success, value, account, token, chainId }) => {\n if (success && value !== undefined) {\n // Ensure all accounts we add/update are in lower-case\n const lowerCaseAccount = account.toLowerCase() as ChecksumAddress;\n const newBalance = toHex(value);\n const tokenAddress = checksum(token);\n const currentBalance =\n d.tokenBalances[lowerCaseAccount]?.[chainId]?.[tokenAddress];\n\n // Only update if the balance has actually changed\n if (currentBalance !== newBalance) {\n ((d.tokenBalances[lowerCaseAccount] ??= {})[chainId] ??= {})[\n tokenAddress\n ] = newBalance;\n }\n }\n });\n });\n\n if (!isEqual(prev, next)) {\n this.update(() => next);\n\n const nativeBalances = aggregated.filter(\n (r) => r.success && r.token === ZERO_ADDRESS,\n );\n\n // Get current AccountTracker state to compare existing balances\n const accountTrackerState = this.messenger.call(\n 'AccountTrackerController:getState',\n );\n\n // Update native token balances only if they have changed\n if (nativeBalances.length > 0) {\n const balanceUpdates = 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 // Only include if the balance has actually changed\n return currentBalance !== update.balance;\n });\n\n if (balanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n balanceUpdates,\n );\n }\n }\n\n // Filter and update staked balances in a single batch operation for better performance\n const stakedBalances = aggregated.filter((r) => {\n if (!r.success || r.token === ZERO_ADDRESS) {\n return false;\n }\n\n // Check if the chainId and token address match any staking contract\n const stakingContractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n r.chainId as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n return (\n stakingContractAddress &&\n stakingContractAddress.toLowerCase() === r.token.toLowerCase()\n );\n });\n\n if (stakedBalances.length > 0) {\n const stakedBalanceUpdates = 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 // Only include if the staked balance has actually changed\n return currentStakedBalance !== update.stakedBalance;\n });\n\n if (stakedBalanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateStakedBalances',\n stakedBalanceUpdates,\n );\n }\n }\n }\n }\n\n resetState() {\n this.update(() => ({ tokenBalances: {} }));\n }\n\n /**\n * Helper method to check if a token is tracked (exists in allTokens or allIgnoredTokens)\n *\n * @param tokenAddress - The token address to check\n * @param account - The account address\n * @param chainId - The chain ID\n * @returns True if the token is tracked (imported or ignored)\n */\n #isTokenTracked(\n tokenAddress: string,\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): boolean {\n // Check if token exists in allTokens\n if (\n this.#allTokens?.[chainId]?.[account.toLowerCase()]?.some(\n (token) => token.address === tokenAddress,\n )\n ) {\n return true;\n }\n\n // Check if token exists in allIgnoredTokens\n if (\n this.#allIgnoredTokens?.[chainId]?.[account.toLowerCase()]?.some(\n (token) => token === tokenAddress,\n )\n ) {\n return true;\n }\n\n return false;\n }\n\n readonly #onTokensChanged = async (state: TokensControllerState) => {\n const changed: ChainIdHex[] = [];\n let hasChanges = false;\n\n // Get chains that have existing balances\n const chainsWithBalances = new Set<ChainIdHex>();\n for (const address of Object.keys(this.state.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const chainId of Object.keys(\n this.state.tokenBalances[addressKey] || {},\n )) {\n chainsWithBalances.add(chainId as ChainIdHex);\n }\n }\n\n // Only process chains that are explicitly mentioned in the incoming state change\n const incomingChainIds = new Set([\n ...Object.keys(state.allTokens),\n ...Object.keys(state.allDetectedTokens),\n ]);\n\n // Only proceed if there are actual changes to chains that have balances or are being added\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 // Check if there's an actual change in token state\n const hasTokenChange =\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id]);\n\n // Process chains that have actual changes OR are new chains getting tokens\n return hasTokenChange || (!hadTokensBefore && hasTokensNow);\n });\n\n if (relevantChainIds.length === 0) {\n // No relevant changes, just update internal state\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n return;\n }\n\n // Handle both cleanup and updates in a single state update\n this.update((s) => {\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 if (\n !isEqual(state.allTokens[id], this.#allTokens[id]) ||\n !isEqual(state.allDetectedTokens[id], this.#detectedTokens[id])\n ) {\n if (hasTokensNow) {\n // Chain still has tokens - mark for async balance update\n changed.push(id);\n } else if (hadTokensBefore) {\n // Chain had tokens before but doesn't now - clean up balances immediately\n for (const address of Object.keys(s.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n if (s.tokenBalances[addressKey]?.[id]) {\n s.tokenBalances[addressKey][id] = {};\n hasChanges = true;\n }\n }\n }\n }\n }\n });\n\n this.#allTokens = state.allTokens;\n this.#detectedTokens = state.allDetectedTokens;\n this.#allIgnoredTokens = state.allIgnoredTokens;\n\n // Only update balances for chains that still have tokens (and only if we haven't already updated state)\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) => {\n // Check if any networks were removed by comparing with previous state\n const currentNetworks = new Set(\n Object.keys(state.networkConfigurationsByChainId),\n );\n\n // Get all networks that currently have balances\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 // Find networks that were removed\n const removedNetworks = Array.from(networksWithBalances).filter(\n (network) => !currentNetworks.has(network),\n );\n\n if (removedNetworks.length > 0) {\n this.update((s) => {\n // Remove balances for all accounts on the deleted networks\n for (const address of Object.keys(s.tokenBalances)) {\n const addressKey = address as ChecksumAddress;\n for (const removedNetwork of removedNetworks) {\n const networkKey = removedNetwork as ChainIdHex;\n if (s.tokenBalances[addressKey]?.[networkKey]) {\n delete s.tokenBalances[addressKey][networkKey];\n }\n }\n }\n });\n }\n };\n\n readonly #onAccountRemoved = (addr: string) => {\n if (!isStrictHexString(addr) || !isValidHexAddress(addr)) {\n return;\n }\n this.update((s) => {\n delete s.tokenBalances[addr as ChecksumAddress];\n });\n };\n\n // ────────────────────────────────────────────────────────────────────────────\n // AccountActivityService integration helpers\n\n /**\n * Prepare balance updates from AccountActivityService\n * Processes all updates and returns categorized results\n * Throws an error if any updates have validation/parsing issues\n *\n * @param updates - Array of balance updates from AccountActivityService\n * @param account - Lowercase account address (for consistency with tokenBalances state format)\n * @param chainId - Hex chain ID\n * @returns Object containing arrays of token balances, new token addresses to add, and native balance updates\n * @throws Error if any balance update has validation or parsing errors\n */\n #prepareBalanceUpdates(\n updates: BalanceUpdate[],\n account: ChecksumAddress,\n chainId: ChainIdHex,\n ): {\n tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[];\n newTokens: string[];\n nativeBalanceUpdates: { address: string; chainId: Hex; balance: Hex }[];\n } {\n const tokenBalances: { tokenAddress: ChecksumAddress; balance: Hex }[] = [];\n const newTokens: string[] = [];\n const nativeBalanceUpdates: {\n address: string;\n chainId: Hex;\n balance: Hex;\n }[] = [];\n\n for (const update of updates) {\n const { asset, postBalance } = update;\n\n // Throw if balance update has an error\n if (postBalance.error) {\n throw new Error('Balance update has error');\n }\n\n // Parse token address from asset type\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 // Validate token address\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 // postBalance.amount is in hex format (raw units)\n const balanceHex = postBalance.amount as Hex;\n\n // Add token balance (tracked tokens, ignored tokens, and native tokens all get balance updates)\n tokenBalances.push({\n tokenAddress: checksumTokenAddress,\n balance: balanceHex,\n });\n\n // Add native balance update if this is a native token\n if (isNativeToken) {\n nativeBalanceUpdates.push({\n address: account,\n chainId,\n balance: balanceHex,\n });\n }\n\n // Handle untracked ERC20 tokens - queue for import\n if (!isNativeToken && !isTracked) {\n newTokens.push(checksumTokenAddress);\n }\n }\n\n return { tokenBalances, newTokens, nativeBalanceUpdates };\n }\n\n // ────────────────────────────────────────────────────────────────────────────\n // AccountActivityService event handlers\n\n /**\n * Handle real-time balance updates from AccountActivityService\n * Processes balance updates and updates the token balance state\n * If any balance update has an error, triggers fallback polling for the chain\n *\n * @param options0 - Balance update parameters\n * @param options0.address - Account address\n * @param options0.chain - CAIP chain identifier\n * @param options0.updates - Array of balance updates for the account\n */\n readonly #onAccountActivityBalanceUpdate = async ({\n address,\n chain,\n updates,\n }: {\n address: string;\n chain: string;\n updates: BalanceUpdate[];\n }) => {\n const chainId = caipChainIdToHex(chain);\n const checksummedAccount = checksum(address);\n\n try {\n // Process all balance updates at once\n const { tokenBalances, newTokens, nativeBalanceUpdates } =\n this.#prepareBalanceUpdates(updates, checksummedAccount, chainId);\n\n // Update state once with all token balances\n if (tokenBalances.length > 0) {\n this.update((state) => {\n // Temporary until ADR to normalize all keys - tokenBalances state requires: account in lowercase, token in checksum\n const lowercaseAccount =\n checksummedAccount.toLowerCase() as ChecksumAddress;\n state.tokenBalances[lowercaseAccount] ??= {};\n state.tokenBalances[lowercaseAccount][chainId] ??= {};\n\n // Apply all token balance updates\n for (const { tokenAddress, balance } of tokenBalances) {\n state.tokenBalances[lowercaseAccount][chainId][tokenAddress] =\n balance;\n }\n });\n }\n\n // Update native balances in AccountTrackerController\n if (nativeBalanceUpdates.length > 0) {\n this.messenger.call(\n 'AccountTrackerController:updateNativeBalances',\n nativeBalanceUpdates,\n );\n }\n\n // Import any new tokens that were discovered (balance already updated from websocket)\n if (newTokens.length > 0) {\n await this.messenger.call(\n 'TokenDetectionController:addDetectedTokensViaWs',\n {\n tokensSlice: newTokens,\n chainId: chainId as Hex,\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 // On error, trigger fallback polling\n await this.updateBalances({ chainIds: [chainId] }).catch(() => {\n // Silently handle polling errors\n });\n }\n };\n\n /**\n * Handle status changes from AccountActivityService\n * Uses aggressive debouncing to prevent excessive HTTP calls from rapid up/down changes\n *\n * @param options0 - Status change event data\n * @param options0.chainIds - Array of chain identifiers\n * @param options0.status - Connection status ('up' for connected, 'down' for disconnected)\n */\n readonly #onAccountActivityStatusChanged = ({\n chainIds,\n status,\n }: {\n chainIds: string[];\n status: 'up' | 'down';\n }) => {\n // Update pending changes (latest status wins for each chain)\n for (const chainId of chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, status);\n }\n\n // Clear existing timer to extend debounce window\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n // Set new timer - only process changes after activity settles\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, 5000); // 5-second debounce window\n };\n\n /**\n * Process all accumulated status changes in one batch to minimize HTTP calls\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 === 0) {\n return;\n }\n\n // Calculate final polling configurations\n const chainConfigs: Record<ChainIdHex, { interval: number }> = {};\n\n for (const [chainId, status] of changes) {\n // Convert CAIP format (eip155:1) to hex format (0x1)\n // chainId is always in CAIP format from AccountActivityService\n const hexChainId = caipChainIdToHex(chainId);\n\n if (status === 'down') {\n // Chain is down - use default polling since no real-time updates available\n chainConfigs[hexChainId] = { interval: this.#defaultInterval };\n } else {\n // Chain is up - use longer intervals since WebSocket provides real-time updates\n chainConfigs[hexChainId] = {\n interval: this.#websocketActivePollingInterval,\n };\n }\n }\n\n // Add jitter to prevent synchronized requests across instances\n const jitterDelay = Math.random() * this.#defaultInterval; // 0 to default interval\n\n setTimeout(() => {\n this.updateChainPollingConfigs(chainConfigs, { immediateUpdate: true });\n }, jitterDelay);\n }\n\n /**\n * Clean up all timers and resources when controller is destroyed\n */\n override destroy(): void {\n this.#isControllerPollingActive = false;\n this.#intervalPollingTimers.forEach((timer) => clearInterval(timer));\n this.#intervalPollingTimers.clear();\n\n // Clean up debouncing timer\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n // Unregister action handlers\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"]}
@@ -5,6 +5,7 @@ import type { KeyringControllerAccountRemovedEvent } from "@metamask/keyring-con
5
5
  import type { Messenger } from "@metamask/messenger";
6
6
  import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, NetworkControllerStateChangeEvent } from "@metamask/network-controller";
7
7
  import type { PreferencesControllerGetStateAction, PreferencesControllerStateChangeEvent } from "@metamask/preferences-controller";
8
+ import type { AuthenticationController } from "@metamask/profile-sync-controller";
8
9
  import type { Hex } from "@metamask/utils";
9
10
  import type { AccountTrackerControllerGetStateAction, AccountTrackerUpdateNativeBalancesAction, AccountTrackerUpdateStakedBalancesAction } from "./AccountTrackerController.cjs";
10
11
  import type { TokenDetectionControllerAddDetectedTokensViaWsAction } from "./TokenDetectionController.cjs";
@@ -32,7 +33,7 @@ export type NativeBalanceEvent = {
32
33
  payload: unknown[];
33
34
  };
34
35
  export type TokenBalancesControllerEvents = TokenBalancesControllerStateChangeEvent | NativeBalanceEvent;
35
- export type AllowedActions = NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction | TokensControllerGetStateAction | TokenDetectionControllerAddDetectedTokensViaWsAction | PreferencesControllerGetStateAction | AccountsControllerGetSelectedAccountAction | AccountsControllerListAccountsAction | AccountTrackerControllerGetStateAction | AccountTrackerUpdateNativeBalancesAction | AccountTrackerUpdateStakedBalancesAction;
36
+ export type AllowedActions = NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction | TokensControllerGetStateAction | TokenDetectionControllerAddDetectedTokensViaWsAction | PreferencesControllerGetStateAction | AccountsControllerGetSelectedAccountAction | AccountsControllerListAccountsAction | AccountTrackerControllerGetStateAction | AccountTrackerUpdateNativeBalancesAction | AccountTrackerUpdateStakedBalancesAction | AuthenticationController.AuthenticationControllerGetBearerToken;
36
37
  export type AllowedEvents = TokensControllerStateChangeEvent | PreferencesControllerStateChangeEvent | NetworkControllerStateChangeEvent | KeyringControllerAccountRemovedEvent | AccountActivityServiceBalanceUpdatedEvent | AccountActivityServiceStatusChangedEvent;
37
38
  export type TokenBalancesControllerMessenger = Messenger<typeof CONTROLLER, TokenBalancesControllerActions | AllowedActions, TokenBalancesControllerEvents | AllowedEvents>;
38
39
  export type ChainPollingConfig = {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenBalancesController.d.cts","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TokenBalancesController.d.cts","sourceRoot":"","sources":["../src/TokenBalancesController.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import type { KeyringControllerAccountRemovedEvent } from "@metamask/keyring-con
5
5
  import type { Messenger } from "@metamask/messenger";
6
6
  import type { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, NetworkControllerStateChangeEvent } from "@metamask/network-controller";
7
7
  import type { PreferencesControllerGetStateAction, PreferencesControllerStateChangeEvent } from "@metamask/preferences-controller";
8
+ import type { AuthenticationController } from "@metamask/profile-sync-controller";
8
9
  import type { Hex } from "@metamask/utils";
9
10
  import type { AccountTrackerControllerGetStateAction, AccountTrackerUpdateNativeBalancesAction, AccountTrackerUpdateStakedBalancesAction } from "./AccountTrackerController.mjs";
10
11
  import type { TokenDetectionControllerAddDetectedTokensViaWsAction } from "./TokenDetectionController.mjs";
@@ -32,7 +33,7 @@ export type NativeBalanceEvent = {
32
33
  payload: unknown[];
33
34
  };
34
35
  export type TokenBalancesControllerEvents = TokenBalancesControllerStateChangeEvent | NativeBalanceEvent;
35
- export type AllowedActions = NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction | TokensControllerGetStateAction | TokenDetectionControllerAddDetectedTokensViaWsAction | PreferencesControllerGetStateAction | AccountsControllerGetSelectedAccountAction | AccountsControllerListAccountsAction | AccountTrackerControllerGetStateAction | AccountTrackerUpdateNativeBalancesAction | AccountTrackerUpdateStakedBalancesAction;
36
+ export type AllowedActions = NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction | TokensControllerGetStateAction | TokenDetectionControllerAddDetectedTokensViaWsAction | PreferencesControllerGetStateAction | AccountsControllerGetSelectedAccountAction | AccountsControllerListAccountsAction | AccountTrackerControllerGetStateAction | AccountTrackerUpdateNativeBalancesAction | AccountTrackerUpdateStakedBalancesAction | AuthenticationController.AuthenticationControllerGetBearerToken;
36
37
  export type AllowedEvents = TokensControllerStateChangeEvent | PreferencesControllerStateChangeEvent | NetworkControllerStateChangeEvent | KeyringControllerAccountRemovedEvent | AccountActivityServiceBalanceUpdatedEvent | AccountActivityServiceStatusChangedEvent;
37
38
  export type TokenBalancesControllerMessenger = Messenger<typeof CONTROLLER, TokenBalancesControllerActions | AllowedActions, TokenBalancesControllerEvents | AllowedEvents>;
38
39
  export type ChainPollingConfig = {