@metamask-previews/assets-controllers 58.0.0-preview-7f6d081 → 58.0.0-preview-772debef

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.
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
- var _AccountTrackerController_instances, _AccountTrackerController_refreshMutex, _AccountTrackerController_includeStakedAssets, _AccountTrackerController_getStakedBalanceForChain, _AccountTrackerController_getCorrectNetworkClient, _AccountTrackerController_getBalanceFromChain;
16
+ var _AccountTrackerController_instances, _AccountTrackerController_refreshMutex, _AccountTrackerController_includeStakedAssets, _AccountTrackerController_getStakedBalanceForChain, _AccountTrackerController_getCorrectNetworkClient, _AccountTrackerController_getNetworkClientIds, _AccountTrackerController_getBalanceFromChain;
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.AccountTrackerController = void 0;
19
19
  const controller_utils_1 = require("@metamask/controller-utils");
@@ -70,7 +70,7 @@ class AccountTrackerController extends (0, polling_controller_1.StaticIntervalPo
70
70
  this.messagingSystem.subscribe('AccountsController:selectedEvmAccountChange',
71
71
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
72
72
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
73
- () => this.refresh());
73
+ () => this.refresh(__classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getNetworkClientIds).call(this)));
74
74
  }
75
75
  syncAccounts(newChainId) {
76
76
  const accountsByChainId = (0, lodash_1.cloneDeep)(this.state.accountsByChainId);
@@ -110,51 +110,70 @@ class AccountTrackerController extends (0, polling_controller_1.StaticIntervalPo
110
110
  * Refreshes the balances of the accounts using the networkClientId
111
111
  *
112
112
  * @param input - The input for the poll.
113
- * @param input.networkClientId - The network client ID used to get balances.
113
+ * @param input.networkClientIds - The network client IDs used to get balances.
114
114
  */
115
- async _executePoll({ networkClientId, }) {
115
+ async _executePoll({ networkClientIds, }) {
116
116
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
117
117
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
118
- this.refresh(networkClientId);
118
+ this.refresh(networkClientIds);
119
119
  }
120
120
  /**
121
121
  * Refreshes the balances of the accounts depending on the multi-account setting.
122
122
  * If multi-account is disabled, only updates the selected account balance.
123
123
  * If multi-account is enabled, updates balances for all accounts.
124
124
  *
125
- * @param networkClientId - Optional networkClientId to fetch a network client with
125
+ * @param networkClientIds - Optional network client IDs to fetch a network client with
126
126
  */
127
- async refresh(networkClientId) {
127
+ async refresh(networkClientIds) {
128
128
  const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
129
129
  const releaseLock = await __classPrivateFieldGet(this, _AccountTrackerController_refreshMutex, "f").acquire();
130
130
  try {
131
- const { chainId, ethQuery } = __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getCorrectNetworkClient).call(this, networkClientId);
132
- this.syncAccounts(chainId);
133
- const { accountsByChainId } = this.state;
134
- const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
135
- const accountsToUpdate = isMultiAccountBalancesEnabled
136
- ? Object.keys(accountsByChainId[chainId])
137
- : [(0, controller_utils_1.toChecksumHexAddress)(selectedAccount.address)];
138
- const accountsForChain = { ...accountsByChainId[chainId] };
139
- for (const address of accountsToUpdate) {
140
- const balance = await __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getBalanceFromChain).call(this, address, ethQuery);
141
- if (balance) {
142
- accountsForChain[address] = {
143
- balance,
144
- };
145
- }
146
- if (__classPrivateFieldGet(this, _AccountTrackerController_includeStakedAssets, "f")) {
147
- const stakedBalance = await __classPrivateFieldGet(this, _AccountTrackerController_getStakedBalanceForChain, "f").call(this, address, networkClientId);
148
- if (stakedBalance) {
131
+ // Create an array of promises for each networkClientId
132
+ const updatePromises = networkClientIds.map(async (networkClientId) => {
133
+ const { chainId, ethQuery } = __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getCorrectNetworkClient).call(this, networkClientId);
134
+ this.syncAccounts(chainId);
135
+ const { accountsByChainId } = this.state;
136
+ const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
137
+ const accountsToUpdate = isMultiAccountBalancesEnabled
138
+ ? Object.keys(accountsByChainId[chainId])
139
+ : [(0, controller_utils_1.toChecksumHexAddress)(selectedAccount.address)];
140
+ const accountsForChain = { ...accountsByChainId[chainId] };
141
+ // Create an array of promises for balance and staked balance fetching
142
+ const balancePromises = accountsToUpdate.map(async (address) => {
143
+ const balancePromise = __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getBalanceFromChain).call(this, address, ethQuery);
144
+ const stakedBalancePromise = __classPrivateFieldGet(this, _AccountTrackerController_includeStakedAssets, "f")
145
+ ? __classPrivateFieldGet(this, _AccountTrackerController_getStakedBalanceForChain, "f").call(this, address, networkClientId)
146
+ : Promise.resolve(null);
147
+ const [balanceResult, stakedBalanceResult] = await Promise.allSettled([balancePromise, stakedBalancePromise]);
148
+ // Update account balances
149
+ if (balanceResult.status === 'fulfilled' && balanceResult.value) {
150
+ accountsForChain[address] = {
151
+ balance: balanceResult.value,
152
+ };
153
+ }
154
+ if (stakedBalanceResult.status === 'fulfilled' &&
155
+ stakedBalanceResult.value) {
149
156
  accountsForChain[address] = {
150
157
  ...accountsForChain[address],
151
- stakedBalance,
158
+ stakedBalance: stakedBalanceResult.value,
152
159
  };
153
160
  }
161
+ });
162
+ // Wait for all balance-related promises to settle
163
+ await Promise.allSettled(balancePromises);
164
+ // After all promises for this networkClientId are settled, return the updated data
165
+ return { chainId, accountsForChain };
166
+ });
167
+ // Wait for all networkClientId updates to settle in parallel
168
+ const allResults = await Promise.allSettled(updatePromises);
169
+ // Update the state once all networkClientId updates are completed
170
+ allResults.forEach((result) => {
171
+ if (result.status === 'fulfilled') {
172
+ const { chainId, accountsForChain } = result.value;
173
+ this.update((state) => {
174
+ state.accountsByChainId[chainId] = accountsForChain;
175
+ });
154
176
  }
155
- }
156
- this.update((state) => {
157
- state.accountsByChainId[chainId] = accountsForChain;
158
177
  });
159
178
  }
160
179
  finally {
@@ -207,6 +226,9 @@ _AccountTrackerController_refreshMutex = new WeakMap(), _AccountTrackerControlle
207
226
  chainId,
208
227
  ethQuery: new eth_query_1.default(provider),
209
228
  };
229
+ }, _AccountTrackerController_getNetworkClientIds = function _AccountTrackerController_getNetworkClientIds() {
230
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
231
+ return Object.values(networkConfigurationsByChainId).flatMap((networkConfiguration) => networkConfiguration.rpcEndpoints.map((rpcEndpoint) => rpcEndpoint.networkClientId));
210
232
  }, _AccountTrackerController_getBalanceFromChain =
211
233
  /**
212
234
  * Fetches the balance of a given address from the blockchain.
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTrackerController.cjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerSelectedEvmAccountChangeEvent,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n AccountsControllerSelectedAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n query,\n safelyExecuteWithTimeout,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { PreferencesControllerGetStateAction } from '@metamask/preferences-controller';\nimport { assert } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} from './AssetsContractController';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\n/**\n * @type AccountInformation\n *\n * Account information object\n * @property balance - Hex string of an account balance in wei\n * @property stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * @type AccountTrackerControllerState\n *\n * Account tracker controller state\n * @property accountsByChainId - Map of addresses to account information by chain\n */\nexport type AccountTrackerControllerState = {\n accountsByChainId: Record<string, { [address: string]: AccountInformation }>;\n};\n\nconst accountTrackerMetadata = {\n accountsByChainId: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The action that can be performed to get the state of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTrackerControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n AccountTrackerControllerGetStateAction;\n\n/**\n * The messenger of the {@link AccountTrackerController} for communication.\n */\nexport type AllowedActions =\n | AccountsControllerListAccountsAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction;\n\n/**\n * The event that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n AccountTrackerControllerState\n >;\n\n/**\n * The events that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerEvents =\n AccountTrackerControllerStateChangeEvent;\n\n/**\n * The external events available to the {@link AccountTrackerController}.\n */\nexport type AllowedEvents =\n | AccountsControllerSelectedEvmAccountChangeEvent\n | AccountsControllerSelectedAccountChangeEvent;\n\n/**\n * The messenger of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n AccountTrackerControllerActions | AllowedActions,\n AccountTrackerControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/** The input to start polling for the {@link AccountTrackerController} */\ntype AccountTrackerPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * Controller that tracks the network balances for all user accounts.\n */\nexport class AccountTrackerController extends StaticIntervalPollingController<AccountTrackerPollingInput>()<\n typeof controllerName,\n AccountTrackerControllerState,\n AccountTrackerControllerMessenger\n> {\n readonly #refreshMutex = new Mutex();\n\n readonly #includeStakedAssets: boolean;\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n /**\n * Creates an AccountTracker instance.\n *\n * @param options - The controller options.\n * @param options.interval - Polling interval used to fetch new account balances.\n * @param options.state - Initial state to set on this controller.\n * @param options.messenger - The controller messaging system.\n * @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.\n * @param options.includeStakedAssets - Whether to include staked assets in the account balances.\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n }) {\n const { selectedNetworkClientId } = messenger.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId },\n } = messenger.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n super({\n name: controllerName,\n messenger,\n state: {\n accountsByChainId: {\n [chainId]: {},\n },\n ...state,\n },\n metadata: accountTrackerMetadata,\n });\n this.#getStakedBalanceForChain = getStakedBalanceForChain;\n\n this.#includeStakedAssets = includeStakedAssets;\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n () => this.refresh(),\n );\n }\n\n private syncAccounts(newChainId: string) {\n const accountsByChainId = cloneDeep(this.state.accountsByChainId);\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId: currentChainId },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n const existing = Object.keys(accountsByChainId?.[currentChainId] ?? {});\n\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\n }\n\n // Note: The address from the preferences controller are checksummed\n // The addresses from the accounts controller are lowercased\n const addresses = Object.values(\n this.messagingSystem\n .call('AccountsController:listAccounts')\n .map((internalAccount) =>\n toChecksumHexAddress(internalAccount.address),\n ),\n );\n const newAddresses = addresses.filter(\n (address) => !existing.includes(address),\n );\n const oldAddresses = existing.filter(\n (address) => !addresses.includes(address),\n );\n Object.keys(accountsByChainId).forEach((chainId) => {\n newAddresses.forEach((address) => {\n accountsByChainId[chainId][address] = {\n balance: '0x0',\n };\n });\n });\n\n Object.keys(accountsByChainId).forEach((chainId) => {\n oldAddresses.forEach((address) => {\n delete accountsByChainId[chainId][address];\n });\n });\n\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n\n /**\n * Resolves a networkClientId to a network client config\n * or globally selected network config if not provided\n *\n * @param networkClientId - Optional networkClientId to fetch a network client with\n * @returns network client config\n */\n #getCorrectNetworkClient(networkClientId?: NetworkClientId): {\n chainId: string;\n ethQuery?: EthQuery;\n } {\n const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n ethQuery: new EthQuery(provider),\n };\n }\n\n /**\n * Refreshes the balances of the accounts using the networkClientId\n *\n * @param input - The input for the poll.\n * @param input.networkClientId - The network client ID used to get balances.\n */\n async _executePoll({\n networkClientId,\n }: AccountTrackerPollingInput): Promise<void> {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(networkClientId);\n }\n\n /**\n * Refreshes the balances of the accounts depending on the multi-account setting.\n * If multi-account is disabled, only updates the selected account balance.\n * If multi-account is enabled, updates balances for all accounts.\n *\n * @param networkClientId - Optional networkClientId to fetch a network client with\n */\n async refresh(networkClientId?: NetworkClientId) {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n const { chainId, ethQuery } =\n this.#getCorrectNetworkClient(networkClientId);\n this.syncAccounts(chainId);\n const { accountsByChainId } = this.state;\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const accountsToUpdate = isMultiAccountBalancesEnabled\n ? Object.keys(accountsByChainId[chainId])\n : [toChecksumHexAddress(selectedAccount.address)];\n\n const accountsForChain = { ...accountsByChainId[chainId] };\n for (const address of accountsToUpdate) {\n const balance = await this.#getBalanceFromChain(address, ethQuery);\n if (balance) {\n accountsForChain[address] = {\n balance,\n };\n }\n if (this.#includeStakedAssets) {\n const stakedBalance = await this.#getStakedBalanceForChain(\n address,\n networkClientId,\n );\n if (stakedBalance) {\n accountsForChain[address] = {\n ...accountsForChain[address],\n stakedBalance,\n };\n }\n }\n }\n\n this.update((state) => {\n state.accountsByChainId[chainId] = accountsForChain;\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Fetches the balance of a given address from the blockchain.\n *\n * @param address - The account address to fetch the balance for.\n * @param ethQuery - The EthQuery instance to query getBalnce with.\n * @returns A promise that resolves to the balance in a hex string format.\n */\n async #getBalanceFromChain(\n address: string,\n ethQuery?: EthQuery,\n ): Promise<string | undefined> {\n return await safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n return await query(ethQuery, 'getBalance', [address]);\n });\n }\n\n /**\n * Sync accounts balances with some additional addresses.\n *\n * @param addresses - the additional addresses, may be hardware wallet addresses.\n * @param networkClientId - Optional networkClientId to fetch a network client with.\n * @returns accounts - addresses with synced balance\n */\n async syncBalanceWithAddresses(\n addresses: string[],\n networkClientId?: NetworkClientId,\n ): Promise<\n Record<string, { balance: string; stakedBalance?: StakedBalance }>\n > {\n const { ethQuery } = this.#getCorrectNetworkClient(networkClientId);\n\n return await Promise.all(\n addresses.map(\n (address): Promise<[string, string, StakedBalance] | undefined> => {\n return safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n const balance = await query(ethQuery, 'getBalance', [address]);\n\n let stakedBalance: StakedBalance;\n if (this.#includeStakedAssets) {\n stakedBalance = await this.#getStakedBalanceForChain(\n address,\n networkClientId,\n );\n }\n return [address, balance, stakedBalance];\n });\n },\n ),\n ).then((value) => {\n return value.reduce((obj, item) => {\n if (!item) {\n return obj;\n }\n\n const [address, balance, stakedBalance] = item;\n return {\n ...obj,\n [address]: {\n balance,\n stakedBalance,\n },\n };\n }, {});\n });\n }\n}\n\nexport default AccountTrackerController;\n"]}
1
+ {"version":3,"file":"AccountTrackerController.cjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerSelectedEvmAccountChangeEvent,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n AccountsControllerSelectedAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n query,\n safelyExecuteWithTimeout,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { PreferencesControllerGetStateAction } from '@metamask/preferences-controller';\nimport { assert } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} from './AssetsContractController';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\n/**\n * @type AccountInformation\n *\n * Account information object\n * @property balance - Hex string of an account balance in wei\n * @property stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * @type AccountTrackerControllerState\n *\n * Account tracker controller state\n * @property accountsByChainId - Map of addresses to account information by chain\n */\nexport type AccountTrackerControllerState = {\n accountsByChainId: Record<string, { [address: string]: AccountInformation }>;\n};\n\nconst accountTrackerMetadata = {\n accountsByChainId: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The action that can be performed to get the state of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTrackerControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n AccountTrackerControllerGetStateAction;\n\n/**\n * The messenger of the {@link AccountTrackerController} for communication.\n */\nexport type AllowedActions =\n | AccountsControllerListAccountsAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction;\n\n/**\n * The event that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n AccountTrackerControllerState\n >;\n\n/**\n * The events that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerEvents =\n AccountTrackerControllerStateChangeEvent;\n\n/**\n * The external events available to the {@link AccountTrackerController}.\n */\nexport type AllowedEvents =\n | AccountsControllerSelectedEvmAccountChangeEvent\n | AccountsControllerSelectedAccountChangeEvent;\n\n/**\n * The messenger of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n AccountTrackerControllerActions | AllowedActions,\n AccountTrackerControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/** The input to start polling for the {@link AccountTrackerController} */\ntype AccountTrackerPollingInput = {\n networkClientIds: NetworkClientId[];\n};\n\n/**\n * Controller that tracks the network balances for all user accounts.\n */\nexport class AccountTrackerController extends StaticIntervalPollingController<AccountTrackerPollingInput>()<\n typeof controllerName,\n AccountTrackerControllerState,\n AccountTrackerControllerMessenger\n> {\n readonly #refreshMutex = new Mutex();\n\n readonly #includeStakedAssets: boolean;\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n /**\n * Creates an AccountTracker instance.\n *\n * @param options - The controller options.\n * @param options.interval - Polling interval used to fetch new account balances.\n * @param options.state - Initial state to set on this controller.\n * @param options.messenger - The controller messaging system.\n * @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.\n * @param options.includeStakedAssets - Whether to include staked assets in the account balances.\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n }) {\n const { selectedNetworkClientId } = messenger.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId },\n } = messenger.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n super({\n name: controllerName,\n messenger,\n state: {\n accountsByChainId: {\n [chainId]: {},\n },\n ...state,\n },\n metadata: accountTrackerMetadata,\n });\n this.#getStakedBalanceForChain = getStakedBalanceForChain;\n\n this.#includeStakedAssets = includeStakedAssets;\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n () => this.refresh(this.#getNetworkClientIds()),\n );\n }\n\n private syncAccounts(newChainId: string) {\n const accountsByChainId = cloneDeep(this.state.accountsByChainId);\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId: currentChainId },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n const existing = Object.keys(accountsByChainId?.[currentChainId] ?? {});\n\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\n }\n\n // Note: The address from the preferences controller are checksummed\n // The addresses from the accounts controller are lowercased\n const addresses = Object.values(\n this.messagingSystem\n .call('AccountsController:listAccounts')\n .map((internalAccount) =>\n toChecksumHexAddress(internalAccount.address),\n ),\n );\n const newAddresses = addresses.filter(\n (address) => !existing.includes(address),\n );\n const oldAddresses = existing.filter(\n (address) => !addresses.includes(address),\n );\n Object.keys(accountsByChainId).forEach((chainId) => {\n newAddresses.forEach((address) => {\n accountsByChainId[chainId][address] = {\n balance: '0x0',\n };\n });\n });\n\n Object.keys(accountsByChainId).forEach((chainId) => {\n oldAddresses.forEach((address) => {\n delete accountsByChainId[chainId][address];\n });\n });\n\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n\n /**\n * Resolves a networkClientId to a network client config\n * or globally selected network config if not provided\n *\n * @param networkClientId - Optional networkClientId to fetch a network client with\n * @returns network client config\n */\n #getCorrectNetworkClient(networkClientId?: NetworkClientId): {\n chainId: string;\n ethQuery?: EthQuery;\n } {\n const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n ethQuery: new EthQuery(provider),\n };\n }\n\n /**\n * Retrieves the list of network client IDs.\n *\n * @returns An array of network client IDs.\n */\n #getNetworkClientIds(): NetworkClientId[] {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return Object.values(networkConfigurationsByChainId).flatMap(\n (networkConfiguration) =>\n networkConfiguration.rpcEndpoints.map(\n (rpcEndpoint) => rpcEndpoint.networkClientId,\n ),\n );\n }\n\n /**\n * Refreshes the balances of the accounts using the networkClientId\n *\n * @param input - The input for the poll.\n * @param input.networkClientIds - The network client IDs used to get balances.\n */\n async _executePoll({\n networkClientIds,\n }: AccountTrackerPollingInput): Promise<void> {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(networkClientIds);\n }\n\n /**\n * Refreshes the balances of the accounts depending on the multi-account setting.\n * If multi-account is disabled, only updates the selected account balance.\n * If multi-account is enabled, updates balances for all accounts.\n *\n * @param networkClientIds - Optional network client IDs to fetch a network client with\n */\n async refresh(networkClientIds: NetworkClientId[]) {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n // Create an array of promises for each networkClientId\n const updatePromises = networkClientIds.map(async (networkClientId) => {\n const { chainId, ethQuery } =\n this.#getCorrectNetworkClient(networkClientId);\n this.syncAccounts(chainId);\n const { accountsByChainId } = this.state;\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const accountsToUpdate = isMultiAccountBalancesEnabled\n ? Object.keys(accountsByChainId[chainId])\n : [toChecksumHexAddress(selectedAccount.address)];\n\n const accountsForChain = { ...accountsByChainId[chainId] };\n\n // Create an array of promises for balance and staked balance fetching\n const balancePromises = accountsToUpdate.map(async (address) => {\n const balancePromise = this.#getBalanceFromChain(address, ethQuery);\n const stakedBalancePromise = this.#includeStakedAssets\n ? this.#getStakedBalanceForChain(address, networkClientId)\n : Promise.resolve(null);\n\n const [balanceResult, stakedBalanceResult] = await Promise.allSettled(\n [balancePromise, stakedBalancePromise],\n );\n\n // Update account balances\n if (balanceResult.status === 'fulfilled' && balanceResult.value) {\n accountsForChain[address] = {\n balance: balanceResult.value,\n };\n }\n\n if (\n stakedBalanceResult.status === 'fulfilled' &&\n stakedBalanceResult.value\n ) {\n accountsForChain[address] = {\n ...accountsForChain[address],\n stakedBalance: stakedBalanceResult.value,\n };\n }\n });\n\n // Wait for all balance-related promises to settle\n await Promise.allSettled(balancePromises);\n\n // After all promises for this networkClientId are settled, return the updated data\n return { chainId, accountsForChain };\n });\n\n // Wait for all networkClientId updates to settle in parallel\n const allResults = await Promise.allSettled(updatePromises);\n\n // Update the state once all networkClientId updates are completed\n allResults.forEach((result) => {\n if (result.status === 'fulfilled') {\n const { chainId, accountsForChain } = result.value;\n this.update((state) => {\n state.accountsByChainId[chainId] = accountsForChain;\n });\n }\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Fetches the balance of a given address from the blockchain.\n *\n * @param address - The account address to fetch the balance for.\n * @param ethQuery - The EthQuery instance to query getBalnce with.\n * @returns A promise that resolves to the balance in a hex string format.\n */\n async #getBalanceFromChain(\n address: string,\n ethQuery?: EthQuery,\n ): Promise<string | undefined> {\n return await safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n return await query(ethQuery, 'getBalance', [address]);\n });\n }\n\n /**\n * Sync accounts balances with some additional addresses.\n *\n * @param addresses - the additional addresses, may be hardware wallet addresses.\n * @param networkClientId - Optional networkClientId to fetch a network client with.\n * @returns accounts - addresses with synced balance\n */\n async syncBalanceWithAddresses(\n addresses: string[],\n networkClientId?: NetworkClientId,\n ): Promise<\n Record<string, { balance: string; stakedBalance?: StakedBalance }>\n > {\n const { ethQuery } = this.#getCorrectNetworkClient(networkClientId);\n\n return await Promise.all(\n addresses.map(\n (address): Promise<[string, string, StakedBalance] | undefined> => {\n return safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n const balance = await query(ethQuery, 'getBalance', [address]);\n\n let stakedBalance: StakedBalance;\n if (this.#includeStakedAssets) {\n stakedBalance = await this.#getStakedBalanceForChain(\n address,\n networkClientId,\n );\n }\n return [address, balance, stakedBalance];\n });\n },\n ),\n ).then((value) => {\n return value.reduce((obj, item) => {\n if (!item) {\n return obj;\n }\n\n const [address, balance, stakedBalance] = item;\n return {\n ...obj,\n [address]: {\n balance,\n stakedBalance,\n },\n };\n }, {});\n });\n }\n}\n\nexport default AccountTrackerController;\n"]}
@@ -59,7 +59,7 @@ export type AllowedEvents = AccountsControllerSelectedEvmAccountChangeEvent | Ac
59
59
  export type AccountTrackerControllerMessenger = RestrictedMessenger<typeof controllerName, AccountTrackerControllerActions | AllowedActions, AccountTrackerControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
60
60
  /** The input to start polling for the {@link AccountTrackerController} */
61
61
  type AccountTrackerPollingInput = {
62
- networkClientId: NetworkClientId;
62
+ networkClientIds: NetworkClientId[];
63
63
  };
64
64
  declare const AccountTrackerController_base: (abstract new (...args: any[]) => {
65
65
  readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
@@ -106,17 +106,17 @@ export declare class AccountTrackerController extends AccountTrackerController_b
106
106
  * Refreshes the balances of the accounts using the networkClientId
107
107
  *
108
108
  * @param input - The input for the poll.
109
- * @param input.networkClientId - The network client ID used to get balances.
109
+ * @param input.networkClientIds - The network client IDs used to get balances.
110
110
  */
111
- _executePoll({ networkClientId, }: AccountTrackerPollingInput): Promise<void>;
111
+ _executePoll({ networkClientIds, }: AccountTrackerPollingInput): Promise<void>;
112
112
  /**
113
113
  * Refreshes the balances of the accounts depending on the multi-account setting.
114
114
  * If multi-account is disabled, only updates the selected account balance.
115
115
  * If multi-account is enabled, updates balances for all accounts.
116
116
  *
117
- * @param networkClientId - Optional networkClientId to fetch a network client with
117
+ * @param networkClientIds - Optional network client IDs to fetch a network client with
118
118
  */
119
- refresh(networkClientId?: NetworkClientId): Promise<void>;
119
+ refresh(networkClientIds: NetworkClientId[]): Promise<void>;
120
120
  /**
121
121
  * Sync accounts balances with some additional addresses.
122
122
  *
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTrackerController.d.cts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountTrackerController.d.cts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
@@ -59,7 +59,7 @@ export type AllowedEvents = AccountsControllerSelectedEvmAccountChangeEvent | Ac
59
59
  export type AccountTrackerControllerMessenger = RestrictedMessenger<typeof controllerName, AccountTrackerControllerActions | AllowedActions, AccountTrackerControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
60
60
  /** The input to start polling for the {@link AccountTrackerController} */
61
61
  type AccountTrackerPollingInput = {
62
- networkClientId: NetworkClientId;
62
+ networkClientIds: NetworkClientId[];
63
63
  };
64
64
  declare const AccountTrackerController_base: (abstract new (...args: any[]) => {
65
65
  readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
@@ -106,17 +106,17 @@ export declare class AccountTrackerController extends AccountTrackerController_b
106
106
  * Refreshes the balances of the accounts using the networkClientId
107
107
  *
108
108
  * @param input - The input for the poll.
109
- * @param input.networkClientId - The network client ID used to get balances.
109
+ * @param input.networkClientIds - The network client IDs used to get balances.
110
110
  */
111
- _executePoll({ networkClientId, }: AccountTrackerPollingInput): Promise<void>;
111
+ _executePoll({ networkClientIds, }: AccountTrackerPollingInput): Promise<void>;
112
112
  /**
113
113
  * Refreshes the balances of the accounts depending on the multi-account setting.
114
114
  * If multi-account is disabled, only updates the selected account balance.
115
115
  * If multi-account is enabled, updates balances for all accounts.
116
116
  *
117
- * @param networkClientId - Optional networkClientId to fetch a network client with
117
+ * @param networkClientIds - Optional network client IDs to fetch a network client with
118
118
  */
119
- refresh(networkClientId?: NetworkClientId): Promise<void>;
119
+ refresh(networkClientIds: NetworkClientId[]): Promise<void>;
120
120
  /**
121
121
  * Sync accounts balances with some additional addresses.
122
122
  *
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTrackerController.d.mts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountTrackerController.d.mts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  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");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _AccountTrackerController_instances, _AccountTrackerController_refreshMutex, _AccountTrackerController_includeStakedAssets, _AccountTrackerController_getStakedBalanceForChain, _AccountTrackerController_getCorrectNetworkClient, _AccountTrackerController_getBalanceFromChain;
12
+ var _AccountTrackerController_instances, _AccountTrackerController_refreshMutex, _AccountTrackerController_includeStakedAssets, _AccountTrackerController_getStakedBalanceForChain, _AccountTrackerController_getCorrectNetworkClient, _AccountTrackerController_getNetworkClientIds, _AccountTrackerController_getBalanceFromChain;
13
13
  function $importDefault(module) {
14
14
  if (module?.__esModule) {
15
15
  return module.default;
@@ -72,7 +72,7 @@ export class AccountTrackerController extends StaticIntervalPollingController()
72
72
  this.messagingSystem.subscribe('AccountsController:selectedEvmAccountChange',
73
73
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
74
74
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
75
- () => this.refresh());
75
+ () => this.refresh(__classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getNetworkClientIds).call(this)));
76
76
  }
77
77
  syncAccounts(newChainId) {
78
78
  const accountsByChainId = cloneDeep(this.state.accountsByChainId);
@@ -112,51 +112,70 @@ export class AccountTrackerController extends StaticIntervalPollingController()
112
112
  * Refreshes the balances of the accounts using the networkClientId
113
113
  *
114
114
  * @param input - The input for the poll.
115
- * @param input.networkClientId - The network client ID used to get balances.
115
+ * @param input.networkClientIds - The network client IDs used to get balances.
116
116
  */
117
- async _executePoll({ networkClientId, }) {
117
+ async _executePoll({ networkClientIds, }) {
118
118
  // TODO: Either fix this lint violation or explain why it's necessary to ignore.
119
119
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
120
- this.refresh(networkClientId);
120
+ this.refresh(networkClientIds);
121
121
  }
122
122
  /**
123
123
  * Refreshes the balances of the accounts depending on the multi-account setting.
124
124
  * If multi-account is disabled, only updates the selected account balance.
125
125
  * If multi-account is enabled, updates balances for all accounts.
126
126
  *
127
- * @param networkClientId - Optional networkClientId to fetch a network client with
127
+ * @param networkClientIds - Optional network client IDs to fetch a network client with
128
128
  */
129
- async refresh(networkClientId) {
129
+ async refresh(networkClientIds) {
130
130
  const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
131
131
  const releaseLock = await __classPrivateFieldGet(this, _AccountTrackerController_refreshMutex, "f").acquire();
132
132
  try {
133
- const { chainId, ethQuery } = __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getCorrectNetworkClient).call(this, networkClientId);
134
- this.syncAccounts(chainId);
135
- const { accountsByChainId } = this.state;
136
- const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
137
- const accountsToUpdate = isMultiAccountBalancesEnabled
138
- ? Object.keys(accountsByChainId[chainId])
139
- : [toChecksumHexAddress(selectedAccount.address)];
140
- const accountsForChain = { ...accountsByChainId[chainId] };
141
- for (const address of accountsToUpdate) {
142
- const balance = await __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getBalanceFromChain).call(this, address, ethQuery);
143
- if (balance) {
144
- accountsForChain[address] = {
145
- balance,
146
- };
147
- }
148
- if (__classPrivateFieldGet(this, _AccountTrackerController_includeStakedAssets, "f")) {
149
- const stakedBalance = await __classPrivateFieldGet(this, _AccountTrackerController_getStakedBalanceForChain, "f").call(this, address, networkClientId);
150
- if (stakedBalance) {
133
+ // Create an array of promises for each networkClientId
134
+ const updatePromises = networkClientIds.map(async (networkClientId) => {
135
+ const { chainId, ethQuery } = __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getCorrectNetworkClient).call(this, networkClientId);
136
+ this.syncAccounts(chainId);
137
+ const { accountsByChainId } = this.state;
138
+ const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
139
+ const accountsToUpdate = isMultiAccountBalancesEnabled
140
+ ? Object.keys(accountsByChainId[chainId])
141
+ : [toChecksumHexAddress(selectedAccount.address)];
142
+ const accountsForChain = { ...accountsByChainId[chainId] };
143
+ // Create an array of promises for balance and staked balance fetching
144
+ const balancePromises = accountsToUpdate.map(async (address) => {
145
+ const balancePromise = __classPrivateFieldGet(this, _AccountTrackerController_instances, "m", _AccountTrackerController_getBalanceFromChain).call(this, address, ethQuery);
146
+ const stakedBalancePromise = __classPrivateFieldGet(this, _AccountTrackerController_includeStakedAssets, "f")
147
+ ? __classPrivateFieldGet(this, _AccountTrackerController_getStakedBalanceForChain, "f").call(this, address, networkClientId)
148
+ : Promise.resolve(null);
149
+ const [balanceResult, stakedBalanceResult] = await Promise.allSettled([balancePromise, stakedBalancePromise]);
150
+ // Update account balances
151
+ if (balanceResult.status === 'fulfilled' && balanceResult.value) {
152
+ accountsForChain[address] = {
153
+ balance: balanceResult.value,
154
+ };
155
+ }
156
+ if (stakedBalanceResult.status === 'fulfilled' &&
157
+ stakedBalanceResult.value) {
151
158
  accountsForChain[address] = {
152
159
  ...accountsForChain[address],
153
- stakedBalance,
160
+ stakedBalance: stakedBalanceResult.value,
154
161
  };
155
162
  }
163
+ });
164
+ // Wait for all balance-related promises to settle
165
+ await Promise.allSettled(balancePromises);
166
+ // After all promises for this networkClientId are settled, return the updated data
167
+ return { chainId, accountsForChain };
168
+ });
169
+ // Wait for all networkClientId updates to settle in parallel
170
+ const allResults = await Promise.allSettled(updatePromises);
171
+ // Update the state once all networkClientId updates are completed
172
+ allResults.forEach((result) => {
173
+ if (result.status === 'fulfilled') {
174
+ const { chainId, accountsForChain } = result.value;
175
+ this.update((state) => {
176
+ state.accountsByChainId[chainId] = accountsForChain;
177
+ });
156
178
  }
157
- }
158
- this.update((state) => {
159
- state.accountsByChainId[chainId] = accountsForChain;
160
179
  });
161
180
  }
162
181
  finally {
@@ -208,6 +227,9 @@ _AccountTrackerController_refreshMutex = new WeakMap(), _AccountTrackerControlle
208
227
  chainId,
209
228
  ethQuery: new EthQuery(provider),
210
229
  };
230
+ }, _AccountTrackerController_getNetworkClientIds = function _AccountTrackerController_getNetworkClientIds() {
231
+ const { networkConfigurationsByChainId } = this.messagingSystem.call('NetworkController:getState');
232
+ return Object.values(networkConfigurationsByChainId).flatMap((networkConfiguration) => networkConfiguration.rpcEndpoints.map((rpcEndpoint) => rpcEndpoint.networkClientId));
211
233
  }, _AccountTrackerController_getBalanceFromChain =
212
234
  /**
213
235
  * Fetches the balance of a given address from the blockchain.
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTrackerController.mjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAWA,OAAO,EACL,KAAK,EACL,wBAAwB,EACxB,oBAAoB,EACrB,mCAAmC;AACpC,OAAO,SAAQ,4BAA4B;;AAM3C,OAAO,EAAE,+BAA+B,EAAE,qCAAqC;AAE/E,OAAO,EAAE,MAAM,EAAE,wBAAwB;AACzC,OAAO,EAAE,KAAK,EAAE,oBAAoB;;;AAQpC;;GAEG;AACH,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAwBlD,MAAM,sBAAsB,GAAG;IAC7B,iBAAiB,EAAE;QACjB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAgEF;;GAEG;AACH,MAAM,OAAO,wBAAyB,SAAQ,+BAA+B,EAI5E;IAOC;;;;;;;;;OASG;IACH,YAAY,EACV,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,SAAS,EACT,wBAAwB,EACxB,mBAAmB,GAAG,KAAK,GAO5B;QACC,MAAM,EAAE,uBAAuB,EAAE,GAAG,SAAS,CAAC,IAAI,CAChD,4BAA4B,CAC7B,CAAC;QACF,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,GAC3B,GAAG,SAAS,CAAC,IAAI,CAChB,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;QACF,KAAK,CAAC;YACJ,IAAI,EAAE,cAAc;YACpB,SAAS;YACT,KAAK,EAAE;gBACL,iBAAiB,EAAE;oBACjB,CAAC,OAAO,CAAC,EAAE,EAAE;iBACd;gBACD,GAAG,KAAK;aACT;YACD,QAAQ,EAAE,sBAAsB;SACjC,CAAC,CAAC;;QAhDI,iDAAgB,IAAI,KAAK,EAAE,EAAC;QAE5B,gEAA8B;QAE9B,qEAAgF;QA6CvF,uBAAA,IAAI,sDAA6B,wBAAwB,MAAA,CAAC;QAE1D,uBAAA,IAAI,iDAAwB,mBAAmB,MAAA,CAAC;QAEhD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEjC,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,6CAA6C;QAC7C,gFAAgF;QAChF,kEAAkE;QAClE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CACrB,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,UAAkB;QACrC,MAAM,iBAAiB,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAClE,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;QACF,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,GAC3C,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3B,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE;YAClC,iBAAiB,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YACnC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC3B,iBAAiB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC9D,CAAC,CAAC,CAAC;SACJ;QAED,oEAAoE;QACpE,4DAA4D;QAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAC7B,IAAI,CAAC,eAAe;aACjB,IAAI,CAAC,iCAAiC,CAAC;aACvC,GAAG,CAAC,CAAC,eAAe,EAAE,EAAE,CACvB,oBAAoB,CAAC,eAAe,CAAC,OAAO,CAAC,CAC9C,CACJ,CAAC;QACF,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CACnC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CACzC,CAAC;QACF,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC1C,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACjD,YAAY,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC/B,iBAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG;oBACpC,OAAO,EAAE,KAAK;iBACf,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACjD,YAAY,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC/B,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC;IA+BD;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,EACjB,eAAe,GACY;QAC3B,gFAAgF;QAChF,mEAAmE;QACnE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,eAAiC;QAC7C,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC/C,uCAAuC,CACxC,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,8CAAc,CAAC,OAAO,EAAE,CAAC;QACvD,IAAI;YACF,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GACzB,uBAAA,IAAI,8FAAyB,MAA7B,IAAI,EAA0B,eAAe,CAAC,CAAC;YACjD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC3B,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YACzC,MAAM,EAAE,6BAA6B,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CACjE,gCAAgC,CACjC,CAAC;YAEF,MAAM,gBAAgB,GAAG,6BAA6B;gBACpD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBACzC,CAAC,CAAC,CAAC,oBAAoB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;YAEpD,MAAM,gBAAgB,GAAG,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3D,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE;gBACtC,MAAM,OAAO,GAAG,MAAM,uBAAA,IAAI,0FAAqB,MAAzB,IAAI,EAAsB,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACnE,IAAI,OAAO,EAAE;oBACX,gBAAgB,CAAC,OAAO,CAAC,GAAG;wBAC1B,OAAO;qBACR,CAAC;iBACH;gBACD,IAAI,uBAAA,IAAI,qDAAqB,EAAE;oBAC7B,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,0DAA0B,MAA9B,IAAI,EAC9B,OAAO,EACP,eAAe,CAChB,CAAC;oBACF,IAAI,aAAa,EAAE;wBACjB,gBAAgB,CAAC,OAAO,CAAC,GAAG;4BAC1B,GAAG,gBAAgB,CAAC,OAAO,CAAC;4BAC5B,aAAa;yBACd,CAAC;qBACH;iBACF;aACF;YAED,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBACpB,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC;YACtD,CAAC,CAAC,CAAC;SACJ;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;IAmBD;;;;;;OAMG;IACH,KAAK,CAAC,wBAAwB,CAC5B,SAAmB,EACnB,eAAiC;QAIjC,MAAM,EAAE,QAAQ,EAAE,GAAG,uBAAA,IAAI,8FAAyB,MAA7B,IAAI,EAA0B,eAAe,CAAC,CAAC;QAEpE,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,SAAS,CAAC,GAAG,CACX,CAAC,OAAO,EAAwD,EAAE;YAChE,OAAO,wBAAwB,CAAC,KAAK,IAAI,EAAE;gBACzC,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;gBACtC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;gBAE/D,IAAI,aAA4B,CAAC;gBACjC,IAAI,uBAAA,IAAI,qDAAqB,EAAE;oBAC7B,aAAa,GAAG,MAAM,uBAAA,IAAI,0DAA0B,MAA9B,IAAI,EACxB,OAAO,EACP,eAAe,CAChB,CAAC;iBACH;gBACD,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CACF,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;gBAChC,IAAI,CAAC,IAAI,EAAE;oBACT,OAAO,GAAG,CAAC;iBACZ;gBAED,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,GAAG,IAAI,CAAC;gBAC/C,OAAO;oBACL,GAAG,GAAG;oBACN,CAAC,OAAO,CAAC,EAAE;wBACT,OAAO;wBACP,aAAa;qBACd;iBACF,CAAC;YACJ,CAAC,EAAE,EAAE,CAAC,CAAC;QACT,CAAC,CAAC,CAAC;IACL,CAAC;CACF;+VA9J0B,eAAiC;IAIxD,MAAM,uBAAuB,GAC3B,eAAe;QACf,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,4BAA4B,CAAC;aACpD,uBAAuB,CAAC;IAC7B,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,EAC1B,QAAQ,GACT,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3B,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IAEF,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,IAAI,QAAQ,CAAC,QAAQ,CAAC;KACjC,CAAC;AACJ,CAAC;AAuED;;;;;;GAMG;AACH,KAAK,wDACH,OAAe,EACf,QAAmB;IAEnB,OAAO,MAAM,wBAAwB,CAAC,KAAK,IAAI,EAAE;QAC/C,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QACtC,OAAO,MAAM,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAsDH,eAAe,wBAAwB,CAAC","sourcesContent":["import type {\n AccountsControllerSelectedEvmAccountChangeEvent,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n AccountsControllerSelectedAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n query,\n safelyExecuteWithTimeout,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { PreferencesControllerGetStateAction } from '@metamask/preferences-controller';\nimport { assert } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} from './AssetsContractController';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\n/**\n * @type AccountInformation\n *\n * Account information object\n * @property balance - Hex string of an account balance in wei\n * @property stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * @type AccountTrackerControllerState\n *\n * Account tracker controller state\n * @property accountsByChainId - Map of addresses to account information by chain\n */\nexport type AccountTrackerControllerState = {\n accountsByChainId: Record<string, { [address: string]: AccountInformation }>;\n};\n\nconst accountTrackerMetadata = {\n accountsByChainId: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The action that can be performed to get the state of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTrackerControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n AccountTrackerControllerGetStateAction;\n\n/**\n * The messenger of the {@link AccountTrackerController} for communication.\n */\nexport type AllowedActions =\n | AccountsControllerListAccountsAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction;\n\n/**\n * The event that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n AccountTrackerControllerState\n >;\n\n/**\n * The events that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerEvents =\n AccountTrackerControllerStateChangeEvent;\n\n/**\n * The external events available to the {@link AccountTrackerController}.\n */\nexport type AllowedEvents =\n | AccountsControllerSelectedEvmAccountChangeEvent\n | AccountsControllerSelectedAccountChangeEvent;\n\n/**\n * The messenger of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n AccountTrackerControllerActions | AllowedActions,\n AccountTrackerControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/** The input to start polling for the {@link AccountTrackerController} */\ntype AccountTrackerPollingInput = {\n networkClientId: NetworkClientId;\n};\n\n/**\n * Controller that tracks the network balances for all user accounts.\n */\nexport class AccountTrackerController extends StaticIntervalPollingController<AccountTrackerPollingInput>()<\n typeof controllerName,\n AccountTrackerControllerState,\n AccountTrackerControllerMessenger\n> {\n readonly #refreshMutex = new Mutex();\n\n readonly #includeStakedAssets: boolean;\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n /**\n * Creates an AccountTracker instance.\n *\n * @param options - The controller options.\n * @param options.interval - Polling interval used to fetch new account balances.\n * @param options.state - Initial state to set on this controller.\n * @param options.messenger - The controller messaging system.\n * @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.\n * @param options.includeStakedAssets - Whether to include staked assets in the account balances.\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n }) {\n const { selectedNetworkClientId } = messenger.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId },\n } = messenger.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n super({\n name: controllerName,\n messenger,\n state: {\n accountsByChainId: {\n [chainId]: {},\n },\n ...state,\n },\n metadata: accountTrackerMetadata,\n });\n this.#getStakedBalanceForChain = getStakedBalanceForChain;\n\n this.#includeStakedAssets = includeStakedAssets;\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n () => this.refresh(),\n );\n }\n\n private syncAccounts(newChainId: string) {\n const accountsByChainId = cloneDeep(this.state.accountsByChainId);\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId: currentChainId },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n const existing = Object.keys(accountsByChainId?.[currentChainId] ?? {});\n\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\n }\n\n // Note: The address from the preferences controller are checksummed\n // The addresses from the accounts controller are lowercased\n const addresses = Object.values(\n this.messagingSystem\n .call('AccountsController:listAccounts')\n .map((internalAccount) =>\n toChecksumHexAddress(internalAccount.address),\n ),\n );\n const newAddresses = addresses.filter(\n (address) => !existing.includes(address),\n );\n const oldAddresses = existing.filter(\n (address) => !addresses.includes(address),\n );\n Object.keys(accountsByChainId).forEach((chainId) => {\n newAddresses.forEach((address) => {\n accountsByChainId[chainId][address] = {\n balance: '0x0',\n };\n });\n });\n\n Object.keys(accountsByChainId).forEach((chainId) => {\n oldAddresses.forEach((address) => {\n delete accountsByChainId[chainId][address];\n });\n });\n\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n\n /**\n * Resolves a networkClientId to a network client config\n * or globally selected network config if not provided\n *\n * @param networkClientId - Optional networkClientId to fetch a network client with\n * @returns network client config\n */\n #getCorrectNetworkClient(networkClientId?: NetworkClientId): {\n chainId: string;\n ethQuery?: EthQuery;\n } {\n const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n ethQuery: new EthQuery(provider),\n };\n }\n\n /**\n * Refreshes the balances of the accounts using the networkClientId\n *\n * @param input - The input for the poll.\n * @param input.networkClientId - The network client ID used to get balances.\n */\n async _executePoll({\n networkClientId,\n }: AccountTrackerPollingInput): Promise<void> {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(networkClientId);\n }\n\n /**\n * Refreshes the balances of the accounts depending on the multi-account setting.\n * If multi-account is disabled, only updates the selected account balance.\n * If multi-account is enabled, updates balances for all accounts.\n *\n * @param networkClientId - Optional networkClientId to fetch a network client with\n */\n async refresh(networkClientId?: NetworkClientId) {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n const { chainId, ethQuery } =\n this.#getCorrectNetworkClient(networkClientId);\n this.syncAccounts(chainId);\n const { accountsByChainId } = this.state;\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const accountsToUpdate = isMultiAccountBalancesEnabled\n ? Object.keys(accountsByChainId[chainId])\n : [toChecksumHexAddress(selectedAccount.address)];\n\n const accountsForChain = { ...accountsByChainId[chainId] };\n for (const address of accountsToUpdate) {\n const balance = await this.#getBalanceFromChain(address, ethQuery);\n if (balance) {\n accountsForChain[address] = {\n balance,\n };\n }\n if (this.#includeStakedAssets) {\n const stakedBalance = await this.#getStakedBalanceForChain(\n address,\n networkClientId,\n );\n if (stakedBalance) {\n accountsForChain[address] = {\n ...accountsForChain[address],\n stakedBalance,\n };\n }\n }\n }\n\n this.update((state) => {\n state.accountsByChainId[chainId] = accountsForChain;\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Fetches the balance of a given address from the blockchain.\n *\n * @param address - The account address to fetch the balance for.\n * @param ethQuery - The EthQuery instance to query getBalnce with.\n * @returns A promise that resolves to the balance in a hex string format.\n */\n async #getBalanceFromChain(\n address: string,\n ethQuery?: EthQuery,\n ): Promise<string | undefined> {\n return await safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n return await query(ethQuery, 'getBalance', [address]);\n });\n }\n\n /**\n * Sync accounts balances with some additional addresses.\n *\n * @param addresses - the additional addresses, may be hardware wallet addresses.\n * @param networkClientId - Optional networkClientId to fetch a network client with.\n * @returns accounts - addresses with synced balance\n */\n async syncBalanceWithAddresses(\n addresses: string[],\n networkClientId?: NetworkClientId,\n ): Promise<\n Record<string, { balance: string; stakedBalance?: StakedBalance }>\n > {\n const { ethQuery } = this.#getCorrectNetworkClient(networkClientId);\n\n return await Promise.all(\n addresses.map(\n (address): Promise<[string, string, StakedBalance] | undefined> => {\n return safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n const balance = await query(ethQuery, 'getBalance', [address]);\n\n let stakedBalance: StakedBalance;\n if (this.#includeStakedAssets) {\n stakedBalance = await this.#getStakedBalanceForChain(\n address,\n networkClientId,\n );\n }\n return [address, balance, stakedBalance];\n });\n },\n ),\n ).then((value) => {\n return value.reduce((obj, item) => {\n if (!item) {\n return obj;\n }\n\n const [address, balance, stakedBalance] = item;\n return {\n ...obj,\n [address]: {\n balance,\n stakedBalance,\n },\n };\n }, {});\n });\n }\n}\n\nexport default AccountTrackerController;\n"]}
1
+ {"version":3,"file":"AccountTrackerController.mjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAWA,OAAO,EACL,KAAK,EACL,wBAAwB,EACxB,oBAAoB,EACrB,mCAAmC;AACpC,OAAO,SAAQ,4BAA4B;;AAM3C,OAAO,EAAE,+BAA+B,EAAE,qCAAqC;AAE/E,OAAO,EAAE,MAAM,EAAE,wBAAwB;AACzC,OAAO,EAAE,KAAK,EAAE,oBAAoB;;;AAQpC;;GAEG;AACH,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAwBlD,MAAM,sBAAsB,GAAG;IAC7B,iBAAiB,EAAE;QACjB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;KACjB;CACF,CAAC;AAgEF;;GAEG;AACH,MAAM,OAAO,wBAAyB,SAAQ,+BAA+B,EAI5E;IAOC;;;;;;;;;OASG;IACH,YAAY,EACV,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,SAAS,EACT,wBAAwB,EACxB,mBAAmB,GAAG,KAAK,GAO5B;QACC,MAAM,EAAE,uBAAuB,EAAE,GAAG,SAAS,CAAC,IAAI,CAChD,4BAA4B,CAC7B,CAAC;QACF,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,GAC3B,GAAG,SAAS,CAAC,IAAI,CAChB,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;QACF,KAAK,CAAC;YACJ,IAAI,EAAE,cAAc;YACpB,SAAS;YACT,KAAK,EAAE;gBACL,iBAAiB,EAAE;oBACjB,CAAC,OAAO,CAAC,EAAE,EAAE;iBACd;gBACD,GAAG,KAAK;aACT;YACD,QAAQ,EAAE,sBAAsB;SACjC,CAAC,CAAC;;QAhDI,iDAAgB,IAAI,KAAK,EAAE,EAAC;QAE5B,gEAA8B;QAE9B,qEAAgF;QA6CvF,uBAAA,IAAI,sDAA6B,wBAAwB,MAAA,CAAC;QAE1D,uBAAA,IAAI,iDAAwB,mBAAmB,MAAA,CAAC;QAEhD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEjC,IAAI,CAAC,eAAe,CAAC,SAAS,CAC5B,6CAA6C;QAC7C,gFAAgF;QAChF,kEAAkE;QAClE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,uBAAA,IAAI,0FAAqB,MAAzB,IAAI,CAAuB,CAAC,CAChD,CAAC;IACJ,CAAC;IAEO,YAAY,CAAC,UAAkB;QACrC,MAAM,iBAAiB,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAClE,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3D,4BAA4B,CAC7B,CAAC;QACF,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,GAC3C,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3B,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE;YAClC,iBAAiB,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YACnC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC3B,iBAAiB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC9D,CAAC,CAAC,CAAC;SACJ;QAED,oEAAoE;QACpE,4DAA4D;QAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAC7B,IAAI,CAAC,eAAe;aACjB,IAAI,CAAC,iCAAiC,CAAC;aACvC,GAAG,CAAC,CAAC,eAAe,EAAE,EAAE,CACvB,oBAAoB,CAAC,eAAe,CAAC,OAAO,CAAC,CAC9C,CACJ,CAAC;QACF,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CACnC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CACzC,CAAC;QACF,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC1C,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACjD,YAAY,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC/B,iBAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG;oBACpC,OAAO,EAAE,KAAK;iBACf,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACjD,YAAY,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC/B,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC;IAgDD;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,EACjB,gBAAgB,GACW;QAC3B,gFAAgF;QAChF,mEAAmE;QACnE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,gBAAmC;QAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC/C,uCAAuC,CACxC,CAAC;QACF,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,8CAAc,CAAC,OAAO,EAAE,CAAC;QACvD,IAAI;YACF,uDAAuD;YACvD,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE;gBACpE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GACzB,uBAAA,IAAI,8FAAyB,MAA7B,IAAI,EAA0B,eAAe,CAAC,CAAC;gBACjD,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;gBAC3B,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;gBACzC,MAAM,EAAE,6BAA6B,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CACjE,gCAAgC,CACjC,CAAC;gBAEF,MAAM,gBAAgB,GAAG,6BAA6B;oBACpD,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;oBACzC,CAAC,CAAC,CAAC,oBAAoB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;gBAEpD,MAAM,gBAAgB,GAAG,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAE3D,sEAAsE;gBACtE,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;oBAC7D,MAAM,cAAc,GAAG,uBAAA,IAAI,0FAAqB,MAAzB,IAAI,EAAsB,OAAO,EAAE,QAAQ,CAAC,CAAC;oBACpE,MAAM,oBAAoB,GAAG,uBAAA,IAAI,qDAAqB;wBACpD,CAAC,CAAC,uBAAA,IAAI,0DAA0B,MAA9B,IAAI,EAA2B,OAAO,EAAE,eAAe,CAAC;wBAC1D,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAE1B,MAAM,CAAC,aAAa,EAAE,mBAAmB,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CACnE,CAAC,cAAc,EAAE,oBAAoB,CAAC,CACvC,CAAC;oBAEF,0BAA0B;oBAC1B,IAAI,aAAa,CAAC,MAAM,KAAK,WAAW,IAAI,aAAa,CAAC,KAAK,EAAE;wBAC/D,gBAAgB,CAAC,OAAO,CAAC,GAAG;4BAC1B,OAAO,EAAE,aAAa,CAAC,KAAK;yBAC7B,CAAC;qBACH;oBAED,IACE,mBAAmB,CAAC,MAAM,KAAK,WAAW;wBAC1C,mBAAmB,CAAC,KAAK,EACzB;wBACA,gBAAgB,CAAC,OAAO,CAAC,GAAG;4BAC1B,GAAG,gBAAgB,CAAC,OAAO,CAAC;4BAC5B,aAAa,EAAE,mBAAmB,CAAC,KAAK;yBACzC,CAAC;qBACH;gBACH,CAAC,CAAC,CAAC;gBAEH,kDAAkD;gBAClD,MAAM,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;gBAE1C,mFAAmF;gBACnF,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;YACvC,CAAC,CAAC,CAAC;YAEH,6DAA6D;YAC7D,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YAE5D,kEAAkE;YAClE,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE;oBACjC,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;oBACnD,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;wBACpB,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC;oBACtD,CAAC,CAAC,CAAC;iBACJ;YACH,CAAC,CAAC,CAAC;SACJ;gBAAS;YACR,WAAW,EAAE,CAAC;SACf;IACH,CAAC;IAmBD;;;;;;OAMG;IACH,KAAK,CAAC,wBAAwB,CAC5B,SAAmB,EACnB,eAAiC;QAIjC,MAAM,EAAE,QAAQ,EAAE,GAAG,uBAAA,IAAI,8FAAyB,MAA7B,IAAI,EAA0B,eAAe,CAAC,CAAC;QAEpE,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,SAAS,CAAC,GAAG,CACX,CAAC,OAAO,EAAwD,EAAE;YAChE,OAAO,wBAAwB,CAAC,KAAK,IAAI,EAAE;gBACzC,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;gBACtC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;gBAE/D,IAAI,aAA4B,CAAC;gBACjC,IAAI,uBAAA,IAAI,qDAAqB,EAAE;oBAC7B,aAAa,GAAG,MAAM,uBAAA,IAAI,0DAA0B,MAA9B,IAAI,EACxB,OAAO,EACP,eAAe,CAChB,CAAC;iBACH;gBACD,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CACF,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;gBAChC,IAAI,CAAC,IAAI,EAAE;oBACT,OAAO,GAAG,CAAC;iBACZ;gBAED,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,GAAG,IAAI,CAAC;gBAC/C,OAAO;oBACL,GAAG,GAAG;oBACN,CAAC,OAAO,CAAC,EAAE;wBACT,OAAO;wBACP,aAAa;qBACd;iBACF,CAAC;YACJ,CAAC,EAAE,EAAE,CAAC,CAAC;QACT,CAAC,CAAC,CAAC;IACL,CAAC;CACF;+VA1M0B,eAAiC;IAIxD,MAAM,uBAAuB,GAC3B,eAAe;QACf,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,4BAA4B,CAAC;aACpD,uBAAuB,CAAC;IAC7B,MAAM,EACJ,aAAa,EAAE,EAAE,OAAO,EAAE,EAC1B,QAAQ,GACT,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAC3B,wCAAwC,EACxC,uBAAuB,CACxB,CAAC;IAEF,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,IAAI,QAAQ,CAAC,QAAQ,CAAC;KACjC,CAAC;AACJ,CAAC;IAQC,MAAM,EAAE,8BAA8B,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAClE,4BAA4B,CAC7B,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC,CAAC,OAAO,CAC1D,CAAC,oBAAoB,EAAE,EAAE,CACvB,oBAAoB,CAAC,YAAY,CAAC,GAAG,CACnC,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,eAAe,CAC7C,CACJ,CAAC;AACJ,CAAC;AAkGD;;;;;;GAMG;AACH,KAAK,wDACH,OAAe,EACf,QAAmB;IAEnB,OAAO,MAAM,wBAAwB,CAAC,KAAK,IAAI,EAAE;QAC/C,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;QACtC,OAAO,MAAM,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAsDH,eAAe,wBAAwB,CAAC","sourcesContent":["import type {\n AccountsControllerSelectedEvmAccountChangeEvent,\n AccountsControllerGetSelectedAccountAction,\n AccountsControllerListAccountsAction,\n AccountsControllerSelectedAccountChangeEvent,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerStateChangeEvent,\n ControllerGetStateAction,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport {\n query,\n safelyExecuteWithTimeout,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n NetworkClientId,\n NetworkControllerGetNetworkClientByIdAction,\n NetworkControllerGetStateAction,\n} from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { PreferencesControllerGetStateAction } from '@metamask/preferences-controller';\nimport { assert } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} from './AssetsContractController';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\n/**\n * @type AccountInformation\n *\n * Account information object\n * @property balance - Hex string of an account balance in wei\n * @property stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * @type AccountTrackerControllerState\n *\n * Account tracker controller state\n * @property accountsByChainId - Map of addresses to account information by chain\n */\nexport type AccountTrackerControllerState = {\n accountsByChainId: Record<string, { [address: string]: AccountInformation }>;\n};\n\nconst accountTrackerMetadata = {\n accountsByChainId: {\n persist: true,\n anonymous: false,\n },\n};\n\n/**\n * The action that can be performed to get the state of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTrackerControllerState\n>;\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n AccountTrackerControllerGetStateAction;\n\n/**\n * The messenger of the {@link AccountTrackerController} for communication.\n */\nexport type AllowedActions =\n | AccountsControllerListAccountsAction\n | PreferencesControllerGetStateAction\n | AccountsControllerGetSelectedAccountAction\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction;\n\n/**\n * The event that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n AccountTrackerControllerState\n >;\n\n/**\n * The events that {@link AccountTrackerController} can emit.\n */\nexport type AccountTrackerControllerEvents =\n AccountTrackerControllerStateChangeEvent;\n\n/**\n * The external events available to the {@link AccountTrackerController}.\n */\nexport type AllowedEvents =\n | AccountsControllerSelectedEvmAccountChangeEvent\n | AccountsControllerSelectedAccountChangeEvent;\n\n/**\n * The messenger of the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n AccountTrackerControllerActions | AllowedActions,\n AccountTrackerControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/** The input to start polling for the {@link AccountTrackerController} */\ntype AccountTrackerPollingInput = {\n networkClientIds: NetworkClientId[];\n};\n\n/**\n * Controller that tracks the network balances for all user accounts.\n */\nexport class AccountTrackerController extends StaticIntervalPollingController<AccountTrackerPollingInput>()<\n typeof controllerName,\n AccountTrackerControllerState,\n AccountTrackerControllerMessenger\n> {\n readonly #refreshMutex = new Mutex();\n\n readonly #includeStakedAssets: boolean;\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n /**\n * Creates an AccountTracker instance.\n *\n * @param options - The controller options.\n * @param options.interval - Polling interval used to fetch new account balances.\n * @param options.state - Initial state to set on this controller.\n * @param options.messenger - The controller messaging system.\n * @param options.getStakedBalanceForChain - The function to get the staked native asset balance for a chain.\n * @param options.includeStakedAssets - Whether to include staked assets in the account balances.\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n }) {\n const { selectedNetworkClientId } = messenger.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId },\n } = messenger.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n super({\n name: controllerName,\n messenger,\n state: {\n accountsByChainId: {\n [chainId]: {},\n },\n ...state,\n },\n metadata: accountTrackerMetadata,\n });\n this.#getStakedBalanceForChain = getStakedBalanceForChain;\n\n this.#includeStakedAssets = includeStakedAssets;\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n () => this.refresh(this.#getNetworkClientIds()),\n );\n }\n\n private syncAccounts(newChainId: string) {\n const accountsByChainId = cloneDeep(this.state.accountsByChainId);\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const {\n configuration: { chainId: currentChainId },\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n const existing = Object.keys(accountsByChainId?.[currentChainId] ?? {});\n\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\n }\n\n // Note: The address from the preferences controller are checksummed\n // The addresses from the accounts controller are lowercased\n const addresses = Object.values(\n this.messagingSystem\n .call('AccountsController:listAccounts')\n .map((internalAccount) =>\n toChecksumHexAddress(internalAccount.address),\n ),\n );\n const newAddresses = addresses.filter(\n (address) => !existing.includes(address),\n );\n const oldAddresses = existing.filter(\n (address) => !addresses.includes(address),\n );\n Object.keys(accountsByChainId).forEach((chainId) => {\n newAddresses.forEach((address) => {\n accountsByChainId[chainId][address] = {\n balance: '0x0',\n };\n });\n });\n\n Object.keys(accountsByChainId).forEach((chainId) => {\n oldAddresses.forEach((address) => {\n delete accountsByChainId[chainId][address];\n });\n });\n\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n\n /**\n * Resolves a networkClientId to a network client config\n * or globally selected network config if not provided\n *\n * @param networkClientId - Optional networkClientId to fetch a network client with\n * @returns network client config\n */\n #getCorrectNetworkClient(networkClientId?: NetworkClientId): {\n chainId: string;\n ethQuery?: EthQuery;\n } {\n const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n ethQuery: new EthQuery(provider),\n };\n }\n\n /**\n * Retrieves the list of network client IDs.\n *\n * @returns An array of network client IDs.\n */\n #getNetworkClientIds(): NetworkClientId[] {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return Object.values(networkConfigurationsByChainId).flatMap(\n (networkConfiguration) =>\n networkConfiguration.rpcEndpoints.map(\n (rpcEndpoint) => rpcEndpoint.networkClientId,\n ),\n );\n }\n\n /**\n * Refreshes the balances of the accounts using the networkClientId\n *\n * @param input - The input for the poll.\n * @param input.networkClientIds - The network client IDs used to get balances.\n */\n async _executePoll({\n networkClientIds,\n }: AccountTrackerPollingInput): Promise<void> {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(networkClientIds);\n }\n\n /**\n * Refreshes the balances of the accounts depending on the multi-account setting.\n * If multi-account is disabled, only updates the selected account balance.\n * If multi-account is enabled, updates balances for all accounts.\n *\n * @param networkClientIds - Optional network client IDs to fetch a network client with\n */\n async refresh(networkClientIds: NetworkClientId[]) {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n // Create an array of promises for each networkClientId\n const updatePromises = networkClientIds.map(async (networkClientId) => {\n const { chainId, ethQuery } =\n this.#getCorrectNetworkClient(networkClientId);\n this.syncAccounts(chainId);\n const { accountsByChainId } = this.state;\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const accountsToUpdate = isMultiAccountBalancesEnabled\n ? Object.keys(accountsByChainId[chainId])\n : [toChecksumHexAddress(selectedAccount.address)];\n\n const accountsForChain = { ...accountsByChainId[chainId] };\n\n // Create an array of promises for balance and staked balance fetching\n const balancePromises = accountsToUpdate.map(async (address) => {\n const balancePromise = this.#getBalanceFromChain(address, ethQuery);\n const stakedBalancePromise = this.#includeStakedAssets\n ? this.#getStakedBalanceForChain(address, networkClientId)\n : Promise.resolve(null);\n\n const [balanceResult, stakedBalanceResult] = await Promise.allSettled(\n [balancePromise, stakedBalancePromise],\n );\n\n // Update account balances\n if (balanceResult.status === 'fulfilled' && balanceResult.value) {\n accountsForChain[address] = {\n balance: balanceResult.value,\n };\n }\n\n if (\n stakedBalanceResult.status === 'fulfilled' &&\n stakedBalanceResult.value\n ) {\n accountsForChain[address] = {\n ...accountsForChain[address],\n stakedBalance: stakedBalanceResult.value,\n };\n }\n });\n\n // Wait for all balance-related promises to settle\n await Promise.allSettled(balancePromises);\n\n // After all promises for this networkClientId are settled, return the updated data\n return { chainId, accountsForChain };\n });\n\n // Wait for all networkClientId updates to settle in parallel\n const allResults = await Promise.allSettled(updatePromises);\n\n // Update the state once all networkClientId updates are completed\n allResults.forEach((result) => {\n if (result.status === 'fulfilled') {\n const { chainId, accountsForChain } = result.value;\n this.update((state) => {\n state.accountsByChainId[chainId] = accountsForChain;\n });\n }\n });\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Fetches the balance of a given address from the blockchain.\n *\n * @param address - The account address to fetch the balance for.\n * @param ethQuery - The EthQuery instance to query getBalnce with.\n * @returns A promise that resolves to the balance in a hex string format.\n */\n async #getBalanceFromChain(\n address: string,\n ethQuery?: EthQuery,\n ): Promise<string | undefined> {\n return await safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n return await query(ethQuery, 'getBalance', [address]);\n });\n }\n\n /**\n * Sync accounts balances with some additional addresses.\n *\n * @param addresses - the additional addresses, may be hardware wallet addresses.\n * @param networkClientId - Optional networkClientId to fetch a network client with.\n * @returns accounts - addresses with synced balance\n */\n async syncBalanceWithAddresses(\n addresses: string[],\n networkClientId?: NetworkClientId,\n ): Promise<\n Record<string, { balance: string; stakedBalance?: StakedBalance }>\n > {\n const { ethQuery } = this.#getCorrectNetworkClient(networkClientId);\n\n return await Promise.all(\n addresses.map(\n (address): Promise<[string, string, StakedBalance] | undefined> => {\n return safelyExecuteWithTimeout(async () => {\n assert(ethQuery, 'Provider not set.');\n const balance = await query(ethQuery, 'getBalance', [address]);\n\n let stakedBalance: StakedBalance;\n if (this.#includeStakedAssets) {\n stakedBalance = await this.#getStakedBalanceForChain(\n address,\n networkClientId,\n );\n }\n return [address, balance, stakedBalance];\n });\n },\n ),\n ).then((value) => {\n return value.reduce((obj, item) => {\n if (!item) {\n return obj;\n }\n\n const [address, balance, stakedBalance] = item;\n return {\n ...obj,\n [address]: {\n balance,\n stakedBalance,\n },\n };\n }, {});\n });\n }\n}\n\nexport default AccountTrackerController;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/assets-controllers",
3
- "version": "58.0.0-preview-7f6d081",
3
+ "version": "58.0.0-preview-772debef",
4
4
  "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)",
5
5
  "keywords": [
6
6
  "MetaMask",