@metamask/assets-controllers 75.0.0 → 75.1.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.
- package/CHANGELOG.md +14 -1
- package/dist/AccountTrackerController.cjs +15 -4
- package/dist/AccountTrackerController.cjs.map +1 -1
- package/dist/AccountTrackerController.d.cts +5 -2
- package/dist/AccountTrackerController.d.cts.map +1 -1
- package/dist/AccountTrackerController.d.mts +5 -2
- package/dist/AccountTrackerController.d.mts.map +1 -1
- package/dist/AccountTrackerController.mjs +15 -4
- package/dist/AccountTrackerController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +4 -4
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts +4 -2
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts +4 -2
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +4 -4
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/utils/formatters.cjs +251 -0
- package/dist/utils/formatters.cjs.map +1 -0
- package/dist/utils/formatters.d.cts +56 -0
- package/dist/utils/formatters.d.cts.map +1 -0
- package/dist/utils/formatters.d.mts +56 -0
- package/dist/utils/formatters.d.mts.map +1 -0
- package/dist/utils/formatters.mjs +247 -0
- package/dist/utils/formatters.mjs.map +1 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [75.1.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Shared fiat currency and token formatters ([#6577](https://github.com/MetaMask/core/pull/6577))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Add `queryAllAccounts` parameter support to `AccountTrackerController.refresh()`, `AccountTrackerController._executePoll()`, and `TokenBalancesController.updateBalances()` for flexible account selection during balance updates ([#6600](https://github.com/MetaMask/core/pull/6600))
|
|
19
|
+
- Bump `@metamask/utils` from `^11.4.2` to `^11.8.0` ([#6588](https://github.com/MetaMask/core/pull/6588))
|
|
20
|
+
- Bump `@metamask/controller-utils` from `^11.12.0` to `^11.13.0` ([#6620](https://github.com/MetaMask/core/pull/6620))
|
|
21
|
+
|
|
10
22
|
## [75.0.0]
|
|
11
23
|
|
|
12
24
|
### Added
|
|
@@ -1972,7 +1984,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1972
1984
|
|
|
1973
1985
|
- Use Ethers for AssetsContractController ([#845](https://github.com/MetaMask/core/pull/845))
|
|
1974
1986
|
|
|
1975
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@75.
|
|
1987
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@75.1.0...HEAD
|
|
1988
|
+
[75.1.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@75.0.0...@metamask/assets-controllers@75.1.0
|
|
1976
1989
|
[75.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@74.3.3...@metamask/assets-controllers@75.0.0
|
|
1977
1990
|
[74.3.3]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@74.3.2...@metamask/assets-controllers@74.3.3
|
|
1978
1991
|
[74.3.2]: https://github.com/MetaMask/core/compare/@metamask/assets-controllers@74.3.1...@metamask/assets-controllers@74.3.2
|
|
@@ -200,11 +200,12 @@ class AccountTrackerController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
200
200
|
*
|
|
201
201
|
* @param input - The input for the poll.
|
|
202
202
|
* @param input.networkClientIds - The network client IDs used to get balances.
|
|
203
|
+
* @param input.queryAllAccounts - Whether to query all accounts or just the selected account
|
|
203
204
|
*/
|
|
204
|
-
async _executePoll({ networkClientIds, }) {
|
|
205
|
+
async _executePoll({ networkClientIds, queryAllAccounts = false, }) {
|
|
205
206
|
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
206
207
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
207
|
-
this.refresh(networkClientIds);
|
|
208
|
+
this.refresh(networkClientIds, queryAllAccounts);
|
|
208
209
|
}
|
|
209
210
|
/**
|
|
210
211
|
* Refreshes the balances of the accounts depending on the multi-account setting.
|
|
@@ -212,8 +213,9 @@ class AccountTrackerController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
212
213
|
* If multi-account is enabled, updates balances for all accounts.
|
|
213
214
|
*
|
|
214
215
|
* @param networkClientIds - Optional network client IDs to fetch a network client with
|
|
216
|
+
* @param queryAllAccounts - Whether to query all accounts or just the selected account
|
|
215
217
|
*/
|
|
216
|
-
async refresh(networkClientIds) {
|
|
218
|
+
async refresh(networkClientIds, queryAllAccounts = false) {
|
|
217
219
|
const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
|
|
218
220
|
const allAccounts = this.messagingSystem.call('AccountsController:listAccounts');
|
|
219
221
|
const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
|
|
@@ -236,7 +238,7 @@ class AccountTrackerController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
236
238
|
try {
|
|
237
239
|
const balances = await fetcher.fetch({
|
|
238
240
|
chainIds: supportedChains,
|
|
239
|
-
queryAllAccounts: isMultiAccountBalancesEnabled,
|
|
241
|
+
queryAllAccounts: queryAllAccounts ?? isMultiAccountBalancesEnabled,
|
|
240
242
|
selectedAccount: (0, controller_utils_1.toChecksumHexAddress)(selectedAccount.address),
|
|
241
243
|
allAccounts,
|
|
242
244
|
});
|
|
@@ -267,6 +269,15 @@ class AccountTrackerController extends (0, polling_controller_1.StaticIntervalPo
|
|
|
267
269
|
const hexValue = `0x${value.toString(16)}`;
|
|
268
270
|
if (token === ZERO_ADDRESS) {
|
|
269
271
|
// Native balance
|
|
272
|
+
// Ensure the account entry exists before accessing it
|
|
273
|
+
if (!nextAccountsByChainId[chainId]) {
|
|
274
|
+
nextAccountsByChainId[chainId] = {};
|
|
275
|
+
}
|
|
276
|
+
if (!nextAccountsByChainId[chainId][checksumAddress]) {
|
|
277
|
+
nextAccountsByChainId[chainId][checksumAddress] = {
|
|
278
|
+
balance: '0x0',
|
|
279
|
+
};
|
|
280
|
+
}
|
|
270
281
|
if (nextAccountsByChainId[chainId][checksumAddress].balance !==
|
|
271
282
|
hexValue) {
|
|
272
283
|
nextAccountsByChainId[chainId][checksumAddress].balance =
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTrackerController.cjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport 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 NetworkClient,\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, type Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} 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';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\n/**\n * Creates an RPC balance fetcher configured for AccountTracker use case.\n * Returns only native balances and staked balances (no token balances).\n *\n * @param getProvider - Function to get Web3Provider for a given chain ID\n * @param getNetworkClient - Function to get NetworkClient for a given chain ID\n * @param includeStakedAssets - Whether to include staked assets in the fetch\n * @returns BalanceFetcher configured to fetch only native and optionally staked balances\n */\nfunction createAccountTrackerRpcBalanceFetcher(\n getProvider: (chainId: Hex) => Web3Provider,\n getNetworkClient: (chainId: Hex) => NetworkClient,\n includeStakedAssets: boolean,\n): BalanceFetcher {\n // Provide empty tokens state to ensure only native and staked balances are fetched\n const getEmptyTokensState = () => ({\n allTokens: {},\n allDetectedTokens: {},\n });\n\n const rpcBalanceFetcher = new RpcBalanceFetcher(\n getProvider,\n getNetworkClient,\n getEmptyTokensState,\n );\n\n // Wrap the RpcBalanceFetcher to filter staked balances when not needed\n return {\n supports(_chainId: ChainIdHex): boolean {\n return rpcBalanceFetcher.supports();\n },\n\n async fetch(params) {\n const balances = await rpcBalanceFetcher.fetch(params);\n\n if (!includeStakedAssets) {\n // Filter out staked balances from the results\n return balances.filter((balance) => balance.token === ZERO_ADDRESS);\n }\n\n return balances;\n },\n };\n}\n\n/**\n * AccountInformation\n *\n * Account information object\n *\n * balance - Hex string of an account balance in wei\n *\n * stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * AccountTrackerControllerState\n *\n * Account tracker controller state\n *\n * 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 includeInStateLogs: false,\n persist: true,\n anonymous: false,\n usedInUi: true,\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 action that can be performed to update multiple native token balances in batch.\n */\nexport type AccountTrackerUpdateNativeBalancesAction = {\n type: `${typeof controllerName}:updateNativeBalances`;\n handler: AccountTrackerController['updateNativeBalances'];\n};\n\n/**\n * The action that can be performed to update multiple staked balances in batch.\n */\nexport type AccountTrackerUpdateStakedBalancesAction = {\n type: `${typeof controllerName}:updateStakedBalances`;\n handler: AccountTrackerController['updateStakedBalances'];\n};\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction;\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 #accountsApiChainIds: ChainIdHex[];\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n readonly #balanceFetchers: BalanceFetcher[];\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 * @param options.accountsApiChainIds - Array of chainIds that should use Accounts-API strategy (if supported by API).\n * @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n accountsApiChainIds = [],\n allowExternalServices = () => true,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n accountsApiChainIds?: ChainIdHex[];\n allowExternalServices?: () => 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 this.#accountsApiChainIds = [...accountsApiChainIds];\n\n // Initialize balance fetchers - Strategy order: API first, then RPC fallback\n this.#balanceFetchers = [\n ...(accountsApiChainIds.length > 0 && allowExternalServices()\n ? [this.#createAccountsApiFetcher()]\n : []),\n createAccountTrackerRpcBalanceFetcher(\n this.#getProvider,\n this.#getNetworkClient,\n this.#includeStakedAssets,\n ),\n ];\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n (newAddress, prevAddress) => {\n if (newAddress !== prevAddress) {\n // Making an async call for this new event\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(this.#getNetworkClientIds());\n }\n },\n (event): string => event.address,\n );\n\n this.#registerMessageHandlers();\n }\n\n private syncAccounts(newChainIds: 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 // Initialize new chain IDs if they don't exist\n newChainIds.forEach((newChainId) => {\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\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 if (!isEqual(this.state.accountsByChainId, accountsByChainId)) {\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n }\n\n readonly #getProvider = (chainId: Hex): Web3Provider => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n const client = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (chainId: Hex) => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n return this.messagingSystem.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 'extension',\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 * 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 const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n blockTracker,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n provider,\n ethQuery: new EthQuery(provider),\n blockTracker,\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 allAccounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n const chainIds = networkClientIds.map((networkClientId) => {\n const { chainId } = this.#getCorrectNetworkClient(networkClientId);\n return chainId;\n });\n\n this.syncAccounts(chainIds);\n\n // Use balance fetchers with fallback strategy\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...chainIds] as ChainIdHex[];\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 balances = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts: isMultiAccountBalancesEnabled,\n selectedAccount: toChecksumHexAddress(\n selectedAccount.address,\n ) as ChecksumAddress,\n allAccounts,\n });\n\n if (balances && balances.length > 0) {\n aggregated.push(...balances);\n // Remove chains that were successfully processed\n const processedChains = new Set(balances.map((b) => b.chainId));\n remainingChains = remainingChains.filter(\n (chain) => !processedChains.has(chain),\n );\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 // Build a _copy_ of the current state and track whether anything changed\n const nextAccountsByChainId: AccountTrackerControllerState['accountsByChainId'] =\n cloneDeep(this.state.accountsByChainId);\n let hasChanges = false;\n\n // Process the aggregated balance results\n const stakedBalancesByChainAndAddress: Record<\n string,\n Record<string, string>\n > = {};\n\n aggregated.forEach(({ success, value, account, token, chainId }) => {\n if (success && value !== undefined) {\n const checksumAddress = toChecksumHexAddress(account);\n const hexValue = `0x${value.toString(16)}`;\n\n if (token === ZERO_ADDRESS) {\n // Native balance\n if (\n nextAccountsByChainId[chainId][checksumAddress].balance !==\n hexValue\n ) {\n nextAccountsByChainId[chainId][checksumAddress].balance =\n hexValue;\n hasChanges = true;\n }\n } else {\n // Staked balance (from staking contract address)\n if (!stakedBalancesByChainAndAddress[chainId]) {\n stakedBalancesByChainAndAddress[chainId] = {};\n }\n stakedBalancesByChainAndAddress[chainId][checksumAddress] =\n hexValue;\n }\n }\n });\n\n // Apply staked balances\n Object.entries(stakedBalancesByChainAndAddress).forEach(\n ([chainId, balancesByAddress]) => {\n Object.entries(balancesByAddress).forEach(\n ([address, stakedBalance]) => {\n // Ensure account structure exists\n if (!nextAccountsByChainId[chainId]) {\n nextAccountsByChainId[chainId] = {};\n }\n if (!nextAccountsByChainId[chainId][address]) {\n nextAccountsByChainId[chainId][address] = { balance: '0x0' };\n }\n if (\n nextAccountsByChainId[chainId][address].stakedBalance !==\n stakedBalance\n ) {\n nextAccountsByChainId[chainId][address].stakedBalance =\n stakedBalance;\n hasChanges = true;\n }\n },\n );\n },\n );\n\n // Only update state if something changed\n if (hasChanges) {\n this.update((state) => {\n state.accountsByChainId = nextAccountsByChainId;\n });\n }\n } finally {\n releaseLock();\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 // TODO: This should use multicall when enabled by the user.\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 = (\n await this.#getStakedBalanceForChain([address], networkClientId)\n )[address];\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 /**\n * Updates the balances of multiple native tokens in a single batch operation.\n * This is more efficient than calling updateNativeToken multiple times as it\n * triggers only one state update.\n *\n * @param balances - Array of balance updates, each containing address, chainId, and balance.\n */\n updateNativeBalances(\n balances: { address: string; chainId: Hex; balance: Hex }[],\n ) {\n this.update((state) => {\n balances.forEach(({ address, chainId, balance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the balance\n state.accountsByChainId[chainId][checksumAddress].balance = balance;\n });\n });\n }\n\n /**\n * Updates the staked balances of multiple accounts in a single batch operation.\n * This is more efficient than updating staked balances individually as it\n * triggers only one state update.\n *\n * @param stakedBalances - Array of staked balance updates, each containing address, chainId, and stakedBalance.\n */\n updateStakedBalances(\n stakedBalances: {\n address: string;\n chainId: Hex;\n stakedBalance: StakedBalance;\n }[],\n ) {\n this.update((state) => {\n stakedBalances.forEach(({ address, chainId, stakedBalance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the staked balance\n state.accountsByChainId[chainId][checksumAddress].stakedBalance =\n stakedBalance;\n });\n });\n }\n\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateNativeBalances` as const,\n this.updateNativeBalances.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateStakedBalances` as const,\n this.updateStakedBalances.bind(this),\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 { Web3Provider } from '@ethersproject/providers';\nimport 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 NetworkClient,\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, type Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} 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';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\n/**\n * Creates an RPC balance fetcher configured for AccountTracker use case.\n * Returns only native balances and staked balances (no token balances).\n *\n * @param getProvider - Function to get Web3Provider for a given chain ID\n * @param getNetworkClient - Function to get NetworkClient for a given chain ID\n * @param includeStakedAssets - Whether to include staked assets in the fetch\n * @returns BalanceFetcher configured to fetch only native and optionally staked balances\n */\nfunction createAccountTrackerRpcBalanceFetcher(\n getProvider: (chainId: Hex) => Web3Provider,\n getNetworkClient: (chainId: Hex) => NetworkClient,\n includeStakedAssets: boolean,\n): BalanceFetcher {\n // Provide empty tokens state to ensure only native and staked balances are fetched\n const getEmptyTokensState = () => ({\n allTokens: {},\n allDetectedTokens: {},\n });\n\n const rpcBalanceFetcher = new RpcBalanceFetcher(\n getProvider,\n getNetworkClient,\n getEmptyTokensState,\n );\n\n // Wrap the RpcBalanceFetcher to filter staked balances when not needed\n return {\n supports(_chainId: ChainIdHex): boolean {\n return rpcBalanceFetcher.supports();\n },\n\n async fetch(params) {\n const balances = await rpcBalanceFetcher.fetch(params);\n\n if (!includeStakedAssets) {\n // Filter out staked balances from the results\n return balances.filter((balance) => balance.token === ZERO_ADDRESS);\n }\n\n return balances;\n },\n };\n}\n\n/**\n * AccountInformation\n *\n * Account information object\n *\n * balance - Hex string of an account balance in wei\n *\n * stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * AccountTrackerControllerState\n *\n * Account tracker controller state\n *\n * 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 includeInStateLogs: false,\n persist: true,\n anonymous: false,\n usedInUi: true,\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 action that can be performed to update multiple native token balances in batch.\n */\nexport type AccountTrackerUpdateNativeBalancesAction = {\n type: `${typeof controllerName}:updateNativeBalances`;\n handler: AccountTrackerController['updateNativeBalances'];\n};\n\n/**\n * The action that can be performed to update multiple staked balances in batch.\n */\nexport type AccountTrackerUpdateStakedBalancesAction = {\n type: `${typeof controllerName}:updateStakedBalances`;\n handler: AccountTrackerController['updateStakedBalances'];\n};\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction;\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 queryAllAccounts?: boolean;\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 #accountsApiChainIds: ChainIdHex[];\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n readonly #balanceFetchers: BalanceFetcher[];\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 * @param options.accountsApiChainIds - Array of chainIds that should use Accounts-API strategy (if supported by API).\n * @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n accountsApiChainIds = [],\n allowExternalServices = () => true,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n accountsApiChainIds?: ChainIdHex[];\n allowExternalServices?: () => 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 this.#accountsApiChainIds = [...accountsApiChainIds];\n\n // Initialize balance fetchers - Strategy order: API first, then RPC fallback\n this.#balanceFetchers = [\n ...(accountsApiChainIds.length > 0 && allowExternalServices()\n ? [this.#createAccountsApiFetcher()]\n : []),\n createAccountTrackerRpcBalanceFetcher(\n this.#getProvider,\n this.#getNetworkClient,\n this.#includeStakedAssets,\n ),\n ];\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n (newAddress, prevAddress) => {\n if (newAddress !== prevAddress) {\n // Making an async call for this new event\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(this.#getNetworkClientIds());\n }\n },\n (event): string => event.address,\n );\n\n this.#registerMessageHandlers();\n }\n\n private syncAccounts(newChainIds: 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 // Initialize new chain IDs if they don't exist\n newChainIds.forEach((newChainId) => {\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\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 if (!isEqual(this.state.accountsByChainId, accountsByChainId)) {\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n }\n\n readonly #getProvider = (chainId: Hex): Web3Provider => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n const client = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (chainId: Hex) => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n return this.messagingSystem.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 'extension',\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 * 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 const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n blockTracker,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n provider,\n ethQuery: new EthQuery(provider),\n blockTracker,\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 * @param input.queryAllAccounts - Whether to query all accounts or just the selected account\n */\n async _executePoll({\n networkClientIds,\n queryAllAccounts = false,\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, queryAllAccounts);\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 * @param queryAllAccounts - Whether to query all accounts or just the selected account\n */\n async refresh(\n networkClientIds: NetworkClientId[],\n queryAllAccounts: boolean = false,\n ) {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n const allAccounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n const chainIds = networkClientIds.map((networkClientId) => {\n const { chainId } = this.#getCorrectNetworkClient(networkClientId);\n return chainId;\n });\n\n this.syncAccounts(chainIds);\n\n // Use balance fetchers with fallback strategy\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...chainIds] as ChainIdHex[];\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 balances = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts: queryAllAccounts ?? isMultiAccountBalancesEnabled,\n selectedAccount: toChecksumHexAddress(\n selectedAccount.address,\n ) as ChecksumAddress,\n allAccounts,\n });\n\n if (balances && balances.length > 0) {\n aggregated.push(...balances);\n // Remove chains that were successfully processed\n const processedChains = new Set(balances.map((b) => b.chainId));\n remainingChains = remainingChains.filter(\n (chain) => !processedChains.has(chain),\n );\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 // Build a _copy_ of the current state and track whether anything changed\n const nextAccountsByChainId: AccountTrackerControllerState['accountsByChainId'] =\n cloneDeep(this.state.accountsByChainId);\n let hasChanges = false;\n\n // Process the aggregated balance results\n const stakedBalancesByChainAndAddress: Record<\n string,\n Record<string, string>\n > = {};\n\n aggregated.forEach(({ success, value, account, token, chainId }) => {\n if (success && value !== undefined) {\n const checksumAddress = toChecksumHexAddress(account);\n const hexValue = `0x${value.toString(16)}`;\n\n if (token === ZERO_ADDRESS) {\n // Native balance\n // Ensure the account entry exists before accessing it\n if (!nextAccountsByChainId[chainId]) {\n nextAccountsByChainId[chainId] = {};\n }\n if (!nextAccountsByChainId[chainId][checksumAddress]) {\n nextAccountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n if (\n nextAccountsByChainId[chainId][checksumAddress].balance !==\n hexValue\n ) {\n nextAccountsByChainId[chainId][checksumAddress].balance =\n hexValue;\n hasChanges = true;\n }\n } else {\n // Staked balance (from staking contract address)\n if (!stakedBalancesByChainAndAddress[chainId]) {\n stakedBalancesByChainAndAddress[chainId] = {};\n }\n stakedBalancesByChainAndAddress[chainId][checksumAddress] =\n hexValue;\n }\n }\n });\n\n // Apply staked balances\n Object.entries(stakedBalancesByChainAndAddress).forEach(\n ([chainId, balancesByAddress]) => {\n Object.entries(balancesByAddress).forEach(\n ([address, stakedBalance]) => {\n // Ensure account structure exists\n if (!nextAccountsByChainId[chainId]) {\n nextAccountsByChainId[chainId] = {};\n }\n if (!nextAccountsByChainId[chainId][address]) {\n nextAccountsByChainId[chainId][address] = { balance: '0x0' };\n }\n if (\n nextAccountsByChainId[chainId][address].stakedBalance !==\n stakedBalance\n ) {\n nextAccountsByChainId[chainId][address].stakedBalance =\n stakedBalance;\n hasChanges = true;\n }\n },\n );\n },\n );\n\n // Only update state if something changed\n if (hasChanges) {\n this.update((state) => {\n state.accountsByChainId = nextAccountsByChainId;\n });\n }\n } finally {\n releaseLock();\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 // TODO: This should use multicall when enabled by the user.\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 = (\n await this.#getStakedBalanceForChain([address], networkClientId)\n )[address];\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 /**\n * Updates the balances of multiple native tokens in a single batch operation.\n * This is more efficient than calling updateNativeToken multiple times as it\n * triggers only one state update.\n *\n * @param balances - Array of balance updates, each containing address, chainId, and balance.\n */\n updateNativeBalances(\n balances: { address: string; chainId: Hex; balance: Hex }[],\n ) {\n this.update((state) => {\n balances.forEach(({ address, chainId, balance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the balance\n state.accountsByChainId[chainId][checksumAddress].balance = balance;\n });\n });\n }\n\n /**\n * Updates the staked balances of multiple accounts in a single batch operation.\n * This is more efficient than updating staked balances individually as it\n * triggers only one state update.\n *\n * @param stakedBalances - Array of staked balance updates, each containing address, chainId, and stakedBalance.\n */\n updateStakedBalances(\n stakedBalances: {\n address: string;\n chainId: Hex;\n stakedBalance: StakedBalance;\n }[],\n ) {\n this.update((state) => {\n stakedBalances.forEach(({ address, chainId, stakedBalance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the staked balance\n state.accountsByChainId[chainId][checksumAddress].stakedBalance =\n stakedBalance;\n });\n });\n }\n\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateNativeBalances` as const,\n this.updateNativeBalances.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateStakedBalances` as const,\n this.updateStakedBalances.bind(this),\n );\n }\n}\n\nexport default AccountTrackerController;\n"]}
|
|
@@ -80,6 +80,7 @@ export type AccountTrackerControllerMessenger = RestrictedMessenger<typeof contr
|
|
|
80
80
|
/** The input to start polling for the {@link AccountTrackerController} */
|
|
81
81
|
type AccountTrackerPollingInput = {
|
|
82
82
|
networkClientIds: NetworkClientId[];
|
|
83
|
+
queryAllAccounts?: boolean;
|
|
83
84
|
};
|
|
84
85
|
declare const AccountTrackerController_base: (abstract new (...args: any[]) => {
|
|
85
86
|
readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
@@ -128,16 +129,18 @@ export declare class AccountTrackerController extends AccountTrackerController_b
|
|
|
128
129
|
*
|
|
129
130
|
* @param input - The input for the poll.
|
|
130
131
|
* @param input.networkClientIds - The network client IDs used to get balances.
|
|
132
|
+
* @param input.queryAllAccounts - Whether to query all accounts or just the selected account
|
|
131
133
|
*/
|
|
132
|
-
_executePoll({ networkClientIds, }: AccountTrackerPollingInput): Promise<void>;
|
|
134
|
+
_executePoll({ networkClientIds, queryAllAccounts, }: AccountTrackerPollingInput): Promise<void>;
|
|
133
135
|
/**
|
|
134
136
|
* Refreshes the balances of the accounts depending on the multi-account setting.
|
|
135
137
|
* If multi-account is disabled, only updates the selected account balance.
|
|
136
138
|
* If multi-account is enabled, updates balances for all accounts.
|
|
137
139
|
*
|
|
138
140
|
* @param networkClientIds - Optional network client IDs to fetch a network client with
|
|
141
|
+
* @param queryAllAccounts - Whether to query all accounts or just the selected account
|
|
139
142
|
*/
|
|
140
|
-
refresh(networkClientIds: NetworkClientId[]): Promise<void>;
|
|
143
|
+
refresh(networkClientIds: NetworkClientId[], queryAllAccounts?: boolean): Promise<void>;
|
|
141
144
|
/**
|
|
142
145
|
* Sync accounts balances with some additional addresses.
|
|
143
146
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTrackerController.d.cts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+CAA+C,EAC/C,0CAA0C,EAC1C,oCAAoC,EACpC,4CAA4C,EAC7C,sCAAsC;AACvC,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACpB,kCAAkC;AAOnC,OAAO,KAAK,EAEV,eAAe,EACf,2CAA2C,EAC3C,+BAA+B,EAChC,qCAAqC;AAEtC,OAAO,KAAK,EAAE,mCAAmC,EAAE,yCAAyC;AAC5F,OAAO,EAAU,KAAK,GAAG,EAAE,wBAAwB;AAInD,OAAO,KAAK,EACV,wBAAwB,EACxB,aAAa,EACd,uCAAmC;AAQpC;;GAEG;AACH,QAAA,MAAM,cAAc,6BAA6B,CAAC;AAElD,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAkDlC;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC,CAAC;CAC9E,CAAC;AAWF;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAAG,wBAAwB,CAC3E,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GACvC,sCAAsC,GACtC,wCAAwC,GACxC,wCAAwC,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,oCAAoC,GACpC,mCAAmC,GACnC,0CAA0C,GAC1C,+BAA+B,GAC/B,2CAA2C,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAClD,0BAA0B,CACxB,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,wCAAwC,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,+CAA+C,GAC/C,4CAA4C,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG,mBAAmB,CACjE,OAAO,cAAc,EACrB,+BAA+B,GAAG,cAAc,EAChD,8BAA8B,GAAG,aAAa,EAC9C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;AAEF,0EAA0E;AAC1E,KAAK,0BAA0B,GAAG;IAChC,gBAAgB,EAAE,eAAe,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"AccountTrackerController.d.cts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
|
|
@@ -80,6 +80,7 @@ export type AccountTrackerControllerMessenger = RestrictedMessenger<typeof contr
|
|
|
80
80
|
/** The input to start polling for the {@link AccountTrackerController} */
|
|
81
81
|
type AccountTrackerPollingInput = {
|
|
82
82
|
networkClientIds: NetworkClientId[];
|
|
83
|
+
queryAllAccounts?: boolean;
|
|
83
84
|
};
|
|
84
85
|
declare const AccountTrackerController_base: (abstract new (...args: any[]) => {
|
|
85
86
|
readonly "__#14@#intervalIds": Record<string, NodeJS.Timeout>;
|
|
@@ -128,16 +129,18 @@ export declare class AccountTrackerController extends AccountTrackerController_b
|
|
|
128
129
|
*
|
|
129
130
|
* @param input - The input for the poll.
|
|
130
131
|
* @param input.networkClientIds - The network client IDs used to get balances.
|
|
132
|
+
* @param input.queryAllAccounts - Whether to query all accounts or just the selected account
|
|
131
133
|
*/
|
|
132
|
-
_executePoll({ networkClientIds, }: AccountTrackerPollingInput): Promise<void>;
|
|
134
|
+
_executePoll({ networkClientIds, queryAllAccounts, }: AccountTrackerPollingInput): Promise<void>;
|
|
133
135
|
/**
|
|
134
136
|
* Refreshes the balances of the accounts depending on the multi-account setting.
|
|
135
137
|
* If multi-account is disabled, only updates the selected account balance.
|
|
136
138
|
* If multi-account is enabled, updates balances for all accounts.
|
|
137
139
|
*
|
|
138
140
|
* @param networkClientIds - Optional network client IDs to fetch a network client with
|
|
141
|
+
* @param queryAllAccounts - Whether to query all accounts or just the selected account
|
|
139
142
|
*/
|
|
140
|
-
refresh(networkClientIds: NetworkClientId[]): Promise<void>;
|
|
143
|
+
refresh(networkClientIds: NetworkClientId[], queryAllAccounts?: boolean): Promise<void>;
|
|
141
144
|
/**
|
|
142
145
|
* Sync accounts balances with some additional addresses.
|
|
143
146
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTrackerController.d.mts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,+CAA+C,EAC/C,0CAA0C,EAC1C,oCAAoC,EACpC,4CAA4C,EAC7C,sCAAsC;AACvC,OAAO,KAAK,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACpB,kCAAkC;AAOnC,OAAO,KAAK,EAEV,eAAe,EACf,2CAA2C,EAC3C,+BAA+B,EAChC,qCAAqC;AAEtC,OAAO,KAAK,EAAE,mCAAmC,EAAE,yCAAyC;AAC5F,OAAO,EAAU,KAAK,GAAG,EAAE,wBAAwB;AAInD,OAAO,KAAK,EACV,wBAAwB,EACxB,aAAa,EACd,uCAAmC;AAQpC;;GAEG;AACH,QAAA,MAAM,cAAc,6BAA6B,CAAC;AAElD,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAkDlC;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAAA;KAAE,CAAC,CAAC;CAC9E,CAAC;AAWF;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAAG,wBAAwB,CAC3E,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GACvC,sCAAsC,GACtC,wCAAwC,GACxC,wCAAwC,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,oCAAoC,GACpC,mCAAmC,GACnC,0CAA0C,GAC1C,+BAA+B,GAC/B,2CAA2C,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAClD,0BAA0B,CACxB,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,wCAAwC,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,+CAA+C,GAC/C,4CAA4C,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG,mBAAmB,CACjE,OAAO,cAAc,EACrB,+BAA+B,GAAG,cAAc,EAChD,8BAA8B,GAAG,aAAa,EAC9C,cAAc,CAAC,MAAM,CAAC,EACtB,aAAa,CAAC,MAAM,CAAC,CACtB,CAAC;AAEF,0EAA0E;AAC1E,KAAK,0BAA0B,GAAG;IAChC,gBAAgB,EAAE,eAAe,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"AccountTrackerController.d.mts","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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"}
|
|
@@ -202,11 +202,12 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
202
202
|
*
|
|
203
203
|
* @param input - The input for the poll.
|
|
204
204
|
* @param input.networkClientIds - The network client IDs used to get balances.
|
|
205
|
+
* @param input.queryAllAccounts - Whether to query all accounts or just the selected account
|
|
205
206
|
*/
|
|
206
|
-
async _executePoll({ networkClientIds, }) {
|
|
207
|
+
async _executePoll({ networkClientIds, queryAllAccounts = false, }) {
|
|
207
208
|
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
208
209
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
209
|
-
this.refresh(networkClientIds);
|
|
210
|
+
this.refresh(networkClientIds, queryAllAccounts);
|
|
210
211
|
}
|
|
211
212
|
/**
|
|
212
213
|
* Refreshes the balances of the accounts depending on the multi-account setting.
|
|
@@ -214,8 +215,9 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
214
215
|
* If multi-account is enabled, updates balances for all accounts.
|
|
215
216
|
*
|
|
216
217
|
* @param networkClientIds - Optional network client IDs to fetch a network client with
|
|
218
|
+
* @param queryAllAccounts - Whether to query all accounts or just the selected account
|
|
217
219
|
*/
|
|
218
|
-
async refresh(networkClientIds) {
|
|
220
|
+
async refresh(networkClientIds, queryAllAccounts = false) {
|
|
219
221
|
const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
|
|
220
222
|
const allAccounts = this.messagingSystem.call('AccountsController:listAccounts');
|
|
221
223
|
const { isMultiAccountBalancesEnabled } = this.messagingSystem.call('PreferencesController:getState');
|
|
@@ -238,7 +240,7 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
238
240
|
try {
|
|
239
241
|
const balances = await fetcher.fetch({
|
|
240
242
|
chainIds: supportedChains,
|
|
241
|
-
queryAllAccounts: isMultiAccountBalancesEnabled,
|
|
243
|
+
queryAllAccounts: queryAllAccounts ?? isMultiAccountBalancesEnabled,
|
|
242
244
|
selectedAccount: toChecksumHexAddress(selectedAccount.address),
|
|
243
245
|
allAccounts,
|
|
244
246
|
});
|
|
@@ -269,6 +271,15 @@ export class AccountTrackerController extends StaticIntervalPollingController()
|
|
|
269
271
|
const hexValue = `0x${value.toString(16)}`;
|
|
270
272
|
if (token === ZERO_ADDRESS) {
|
|
271
273
|
// Native balance
|
|
274
|
+
// Ensure the account entry exists before accessing it
|
|
275
|
+
if (!nextAccountsByChainId[chainId]) {
|
|
276
|
+
nextAccountsByChainId[chainId] = {};
|
|
277
|
+
}
|
|
278
|
+
if (!nextAccountsByChainId[chainId][checksumAddress]) {
|
|
279
|
+
nextAccountsByChainId[chainId][checksumAddress] = {
|
|
280
|
+
balance: '0x0',
|
|
281
|
+
};
|
|
282
|
+
}
|
|
272
283
|
if (nextAccountsByChainId[chainId][checksumAddress].balance !==
|
|
273
284
|
hexValue) {
|
|
274
285
|
nextAccountsByChainId[chainId][checksumAddress].balance =
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTrackerController.mjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport 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 NetworkClient,\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, type Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} 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';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\n/**\n * Creates an RPC balance fetcher configured for AccountTracker use case.\n * Returns only native balances and staked balances (no token balances).\n *\n * @param getProvider - Function to get Web3Provider for a given chain ID\n * @param getNetworkClient - Function to get NetworkClient for a given chain ID\n * @param includeStakedAssets - Whether to include staked assets in the fetch\n * @returns BalanceFetcher configured to fetch only native and optionally staked balances\n */\nfunction createAccountTrackerRpcBalanceFetcher(\n getProvider: (chainId: Hex) => Web3Provider,\n getNetworkClient: (chainId: Hex) => NetworkClient,\n includeStakedAssets: boolean,\n): BalanceFetcher {\n // Provide empty tokens state to ensure only native and staked balances are fetched\n const getEmptyTokensState = () => ({\n allTokens: {},\n allDetectedTokens: {},\n });\n\n const rpcBalanceFetcher = new RpcBalanceFetcher(\n getProvider,\n getNetworkClient,\n getEmptyTokensState,\n );\n\n // Wrap the RpcBalanceFetcher to filter staked balances when not needed\n return {\n supports(_chainId: ChainIdHex): boolean {\n return rpcBalanceFetcher.supports();\n },\n\n async fetch(params) {\n const balances = await rpcBalanceFetcher.fetch(params);\n\n if (!includeStakedAssets) {\n // Filter out staked balances from the results\n return balances.filter((balance) => balance.token === ZERO_ADDRESS);\n }\n\n return balances;\n },\n };\n}\n\n/**\n * AccountInformation\n *\n * Account information object\n *\n * balance - Hex string of an account balance in wei\n *\n * stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * AccountTrackerControllerState\n *\n * Account tracker controller state\n *\n * 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 includeInStateLogs: false,\n persist: true,\n anonymous: false,\n usedInUi: true,\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 action that can be performed to update multiple native token balances in batch.\n */\nexport type AccountTrackerUpdateNativeBalancesAction = {\n type: `${typeof controllerName}:updateNativeBalances`;\n handler: AccountTrackerController['updateNativeBalances'];\n};\n\n/**\n * The action that can be performed to update multiple staked balances in batch.\n */\nexport type AccountTrackerUpdateStakedBalancesAction = {\n type: `${typeof controllerName}:updateStakedBalances`;\n handler: AccountTrackerController['updateStakedBalances'];\n};\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction;\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 #accountsApiChainIds: ChainIdHex[];\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n readonly #balanceFetchers: BalanceFetcher[];\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 * @param options.accountsApiChainIds - Array of chainIds that should use Accounts-API strategy (if supported by API).\n * @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n accountsApiChainIds = [],\n allowExternalServices = () => true,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n accountsApiChainIds?: ChainIdHex[];\n allowExternalServices?: () => 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 this.#accountsApiChainIds = [...accountsApiChainIds];\n\n // Initialize balance fetchers - Strategy order: API first, then RPC fallback\n this.#balanceFetchers = [\n ...(accountsApiChainIds.length > 0 && allowExternalServices()\n ? [this.#createAccountsApiFetcher()]\n : []),\n createAccountTrackerRpcBalanceFetcher(\n this.#getProvider,\n this.#getNetworkClient,\n this.#includeStakedAssets,\n ),\n ];\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n (newAddress, prevAddress) => {\n if (newAddress !== prevAddress) {\n // Making an async call for this new event\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(this.#getNetworkClientIds());\n }\n },\n (event): string => event.address,\n );\n\n this.#registerMessageHandlers();\n }\n\n private syncAccounts(newChainIds: 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 // Initialize new chain IDs if they don't exist\n newChainIds.forEach((newChainId) => {\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\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 if (!isEqual(this.state.accountsByChainId, accountsByChainId)) {\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n }\n\n readonly #getProvider = (chainId: Hex): Web3Provider => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n const client = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (chainId: Hex) => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n return this.messagingSystem.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 'extension',\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 * 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 const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n blockTracker,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n provider,\n ethQuery: new EthQuery(provider),\n blockTracker,\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 allAccounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n const chainIds = networkClientIds.map((networkClientId) => {\n const { chainId } = this.#getCorrectNetworkClient(networkClientId);\n return chainId;\n });\n\n this.syncAccounts(chainIds);\n\n // Use balance fetchers with fallback strategy\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...chainIds] as ChainIdHex[];\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 balances = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts: isMultiAccountBalancesEnabled,\n selectedAccount: toChecksumHexAddress(\n selectedAccount.address,\n ) as ChecksumAddress,\n allAccounts,\n });\n\n if (balances && balances.length > 0) {\n aggregated.push(...balances);\n // Remove chains that were successfully processed\n const processedChains = new Set(balances.map((b) => b.chainId));\n remainingChains = remainingChains.filter(\n (chain) => !processedChains.has(chain),\n );\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 // Build a _copy_ of the current state and track whether anything changed\n const nextAccountsByChainId: AccountTrackerControllerState['accountsByChainId'] =\n cloneDeep(this.state.accountsByChainId);\n let hasChanges = false;\n\n // Process the aggregated balance results\n const stakedBalancesByChainAndAddress: Record<\n string,\n Record<string, string>\n > = {};\n\n aggregated.forEach(({ success, value, account, token, chainId }) => {\n if (success && value !== undefined) {\n const checksumAddress = toChecksumHexAddress(account);\n const hexValue = `0x${value.toString(16)}`;\n\n if (token === ZERO_ADDRESS) {\n // Native balance\n if (\n nextAccountsByChainId[chainId][checksumAddress].balance !==\n hexValue\n ) {\n nextAccountsByChainId[chainId][checksumAddress].balance =\n hexValue;\n hasChanges = true;\n }\n } else {\n // Staked balance (from staking contract address)\n if (!stakedBalancesByChainAndAddress[chainId]) {\n stakedBalancesByChainAndAddress[chainId] = {};\n }\n stakedBalancesByChainAndAddress[chainId][checksumAddress] =\n hexValue;\n }\n }\n });\n\n // Apply staked balances\n Object.entries(stakedBalancesByChainAndAddress).forEach(\n ([chainId, balancesByAddress]) => {\n Object.entries(balancesByAddress).forEach(\n ([address, stakedBalance]) => {\n // Ensure account structure exists\n if (!nextAccountsByChainId[chainId]) {\n nextAccountsByChainId[chainId] = {};\n }\n if (!nextAccountsByChainId[chainId][address]) {\n nextAccountsByChainId[chainId][address] = { balance: '0x0' };\n }\n if (\n nextAccountsByChainId[chainId][address].stakedBalance !==\n stakedBalance\n ) {\n nextAccountsByChainId[chainId][address].stakedBalance =\n stakedBalance;\n hasChanges = true;\n }\n },\n );\n },\n );\n\n // Only update state if something changed\n if (hasChanges) {\n this.update((state) => {\n state.accountsByChainId = nextAccountsByChainId;\n });\n }\n } finally {\n releaseLock();\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 // TODO: This should use multicall when enabled by the user.\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 = (\n await this.#getStakedBalanceForChain([address], networkClientId)\n )[address];\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 /**\n * Updates the balances of multiple native tokens in a single batch operation.\n * This is more efficient than calling updateNativeToken multiple times as it\n * triggers only one state update.\n *\n * @param balances - Array of balance updates, each containing address, chainId, and balance.\n */\n updateNativeBalances(\n balances: { address: string; chainId: Hex; balance: Hex }[],\n ) {\n this.update((state) => {\n balances.forEach(({ address, chainId, balance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the balance\n state.accountsByChainId[chainId][checksumAddress].balance = balance;\n });\n });\n }\n\n /**\n * Updates the staked balances of multiple accounts in a single batch operation.\n * This is more efficient than updating staked balances individually as it\n * triggers only one state update.\n *\n * @param stakedBalances - Array of staked balance updates, each containing address, chainId, and stakedBalance.\n */\n updateStakedBalances(\n stakedBalances: {\n address: string;\n chainId: Hex;\n stakedBalance: StakedBalance;\n }[],\n ) {\n this.update((state) => {\n stakedBalances.forEach(({ address, chainId, stakedBalance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the staked balance\n state.accountsByChainId[chainId][checksumAddress].stakedBalance =\n stakedBalance;\n });\n });\n }\n\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateNativeBalances` as const,\n this.updateNativeBalances.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateStakedBalances` as const,\n this.updateStakedBalances.bind(this),\n );\n }\n}\n\nexport default AccountTrackerController;\n"]}
|
|
1
|
+
{"version":3,"file":"AccountTrackerController.mjs","sourceRoot":"","sources":["../src/AccountTrackerController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport 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 NetworkClient,\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, type Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { cloneDeep, isEqual } from 'lodash';\n\nimport type {\n AssetsContractController,\n StakedBalance,\n} 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';\n\n/**\n * The name of the {@link AccountTrackerController}.\n */\nconst controllerName = 'AccountTrackerController';\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\n/**\n * Creates an RPC balance fetcher configured for AccountTracker use case.\n * Returns only native balances and staked balances (no token balances).\n *\n * @param getProvider - Function to get Web3Provider for a given chain ID\n * @param getNetworkClient - Function to get NetworkClient for a given chain ID\n * @param includeStakedAssets - Whether to include staked assets in the fetch\n * @returns BalanceFetcher configured to fetch only native and optionally staked balances\n */\nfunction createAccountTrackerRpcBalanceFetcher(\n getProvider: (chainId: Hex) => Web3Provider,\n getNetworkClient: (chainId: Hex) => NetworkClient,\n includeStakedAssets: boolean,\n): BalanceFetcher {\n // Provide empty tokens state to ensure only native and staked balances are fetched\n const getEmptyTokensState = () => ({\n allTokens: {},\n allDetectedTokens: {},\n });\n\n const rpcBalanceFetcher = new RpcBalanceFetcher(\n getProvider,\n getNetworkClient,\n getEmptyTokensState,\n );\n\n // Wrap the RpcBalanceFetcher to filter staked balances when not needed\n return {\n supports(_chainId: ChainIdHex): boolean {\n return rpcBalanceFetcher.supports();\n },\n\n async fetch(params) {\n const balances = await rpcBalanceFetcher.fetch(params);\n\n if (!includeStakedAssets) {\n // Filter out staked balances from the results\n return balances.filter((balance) => balance.token === ZERO_ADDRESS);\n }\n\n return balances;\n },\n };\n}\n\n/**\n * AccountInformation\n *\n * Account information object\n *\n * balance - Hex string of an account balance in wei\n *\n * stakedBalance - Hex string of an account staked balance in wei\n */\nexport type AccountInformation = {\n balance: string;\n stakedBalance?: string;\n};\n\n/**\n * AccountTrackerControllerState\n *\n * Account tracker controller state\n *\n * 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 includeInStateLogs: false,\n persist: true,\n anonymous: false,\n usedInUi: true,\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 action that can be performed to update multiple native token balances in batch.\n */\nexport type AccountTrackerUpdateNativeBalancesAction = {\n type: `${typeof controllerName}:updateNativeBalances`;\n handler: AccountTrackerController['updateNativeBalances'];\n};\n\n/**\n * The action that can be performed to update multiple staked balances in batch.\n */\nexport type AccountTrackerUpdateStakedBalancesAction = {\n type: `${typeof controllerName}:updateStakedBalances`;\n handler: AccountTrackerController['updateStakedBalances'];\n};\n\n/**\n * The actions that can be performed using the {@link AccountTrackerController}.\n */\nexport type AccountTrackerControllerActions =\n | AccountTrackerControllerGetStateAction\n | AccountTrackerUpdateNativeBalancesAction\n | AccountTrackerUpdateStakedBalancesAction;\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 queryAllAccounts?: boolean;\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 #accountsApiChainIds: ChainIdHex[];\n\n readonly #getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n\n readonly #balanceFetchers: BalanceFetcher[];\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 * @param options.accountsApiChainIds - Array of chainIds that should use Accounts-API strategy (if supported by API).\n * @param options.allowExternalServices - Disable external HTTP calls (privacy / offline mode).\n */\n constructor({\n interval = 10000,\n state,\n messenger,\n getStakedBalanceForChain,\n includeStakedAssets = false,\n accountsApiChainIds = [],\n allowExternalServices = () => true,\n }: {\n interval?: number;\n state?: Partial<AccountTrackerControllerState>;\n messenger: AccountTrackerControllerMessenger;\n getStakedBalanceForChain: AssetsContractController['getStakedBalanceForChain'];\n includeStakedAssets?: boolean;\n accountsApiChainIds?: ChainIdHex[];\n allowExternalServices?: () => 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 this.#accountsApiChainIds = [...accountsApiChainIds];\n\n // Initialize balance fetchers - Strategy order: API first, then RPC fallback\n this.#balanceFetchers = [\n ...(accountsApiChainIds.length > 0 && allowExternalServices()\n ? [this.#createAccountsApiFetcher()]\n : []),\n createAccountTrackerRpcBalanceFetcher(\n this.#getProvider,\n this.#getNetworkClient,\n this.#includeStakedAssets,\n ),\n ];\n\n this.setIntervalLength(interval);\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedEvmAccountChange',\n (newAddress, prevAddress) => {\n if (newAddress !== prevAddress) {\n // Making an async call for this new event\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.refresh(this.#getNetworkClientIds());\n }\n },\n (event): string => event.address,\n );\n\n this.#registerMessageHandlers();\n }\n\n private syncAccounts(newChainIds: 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 // Initialize new chain IDs if they don't exist\n newChainIds.forEach((newChainId) => {\n if (!accountsByChainId[newChainId]) {\n accountsByChainId[newChainId] = {};\n existing.forEach((address) => {\n accountsByChainId[newChainId][address] = { balance: '0x0' };\n });\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 if (!isEqual(this.state.accountsByChainId, accountsByChainId)) {\n this.update((state) => {\n state.accountsByChainId = accountsByChainId;\n });\n }\n }\n\n readonly #getProvider = (chainId: Hex): Web3Provider => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n const client = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n return new Web3Provider(client.provider);\n };\n\n readonly #getNetworkClient = (chainId: Hex) => {\n const { networkConfigurationsByChainId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const cfg = networkConfigurationsByChainId[chainId];\n const { networkClientId } = cfg.rpcEndpoints[cfg.defaultRpcEndpointIndex];\n return this.messagingSystem.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 'extension',\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 * 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 const selectedNetworkClientId =\n networkClientId ??\n this.messagingSystem.call('NetworkController:getState')\n .selectedNetworkClientId;\n const {\n configuration: { chainId },\n provider,\n blockTracker,\n } = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n\n return {\n chainId,\n provider,\n ethQuery: new EthQuery(provider),\n blockTracker,\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 * @param input.queryAllAccounts - Whether to query all accounts or just the selected account\n */\n async _executePoll({\n networkClientIds,\n queryAllAccounts = false,\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, queryAllAccounts);\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 * @param queryAllAccounts - Whether to query all accounts or just the selected account\n */\n async refresh(\n networkClientIds: NetworkClientId[],\n queryAllAccounts: boolean = false,\n ) {\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n const allAccounts = this.messagingSystem.call(\n 'AccountsController:listAccounts',\n );\n const { isMultiAccountBalancesEnabled } = this.messagingSystem.call(\n 'PreferencesController:getState',\n );\n\n const releaseLock = await this.#refreshMutex.acquire();\n try {\n const chainIds = networkClientIds.map((networkClientId) => {\n const { chainId } = this.#getCorrectNetworkClient(networkClientId);\n return chainId;\n });\n\n this.syncAccounts(chainIds);\n\n // Use balance fetchers with fallback strategy\n const aggregated: ProcessedBalance[] = [];\n let remainingChains = [...chainIds] as ChainIdHex[];\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 balances = await fetcher.fetch({\n chainIds: supportedChains,\n queryAllAccounts: queryAllAccounts ?? isMultiAccountBalancesEnabled,\n selectedAccount: toChecksumHexAddress(\n selectedAccount.address,\n ) as ChecksumAddress,\n allAccounts,\n });\n\n if (balances && balances.length > 0) {\n aggregated.push(...balances);\n // Remove chains that were successfully processed\n const processedChains = new Set(balances.map((b) => b.chainId));\n remainingChains = remainingChains.filter(\n (chain) => !processedChains.has(chain),\n );\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 // Build a _copy_ of the current state and track whether anything changed\n const nextAccountsByChainId: AccountTrackerControllerState['accountsByChainId'] =\n cloneDeep(this.state.accountsByChainId);\n let hasChanges = false;\n\n // Process the aggregated balance results\n const stakedBalancesByChainAndAddress: Record<\n string,\n Record<string, string>\n > = {};\n\n aggregated.forEach(({ success, value, account, token, chainId }) => {\n if (success && value !== undefined) {\n const checksumAddress = toChecksumHexAddress(account);\n const hexValue = `0x${value.toString(16)}`;\n\n if (token === ZERO_ADDRESS) {\n // Native balance\n // Ensure the account entry exists before accessing it\n if (!nextAccountsByChainId[chainId]) {\n nextAccountsByChainId[chainId] = {};\n }\n if (!nextAccountsByChainId[chainId][checksumAddress]) {\n nextAccountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n if (\n nextAccountsByChainId[chainId][checksumAddress].balance !==\n hexValue\n ) {\n nextAccountsByChainId[chainId][checksumAddress].balance =\n hexValue;\n hasChanges = true;\n }\n } else {\n // Staked balance (from staking contract address)\n if (!stakedBalancesByChainAndAddress[chainId]) {\n stakedBalancesByChainAndAddress[chainId] = {};\n }\n stakedBalancesByChainAndAddress[chainId][checksumAddress] =\n hexValue;\n }\n }\n });\n\n // Apply staked balances\n Object.entries(stakedBalancesByChainAndAddress).forEach(\n ([chainId, balancesByAddress]) => {\n Object.entries(balancesByAddress).forEach(\n ([address, stakedBalance]) => {\n // Ensure account structure exists\n if (!nextAccountsByChainId[chainId]) {\n nextAccountsByChainId[chainId] = {};\n }\n if (!nextAccountsByChainId[chainId][address]) {\n nextAccountsByChainId[chainId][address] = { balance: '0x0' };\n }\n if (\n nextAccountsByChainId[chainId][address].stakedBalance !==\n stakedBalance\n ) {\n nextAccountsByChainId[chainId][address].stakedBalance =\n stakedBalance;\n hasChanges = true;\n }\n },\n );\n },\n );\n\n // Only update state if something changed\n if (hasChanges) {\n this.update((state) => {\n state.accountsByChainId = nextAccountsByChainId;\n });\n }\n } finally {\n releaseLock();\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 // TODO: This should use multicall when enabled by the user.\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 = (\n await this.#getStakedBalanceForChain([address], networkClientId)\n )[address];\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 /**\n * Updates the balances of multiple native tokens in a single batch operation.\n * This is more efficient than calling updateNativeToken multiple times as it\n * triggers only one state update.\n *\n * @param balances - Array of balance updates, each containing address, chainId, and balance.\n */\n updateNativeBalances(\n balances: { address: string; chainId: Hex; balance: Hex }[],\n ) {\n this.update((state) => {\n balances.forEach(({ address, chainId, balance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the balance\n state.accountsByChainId[chainId][checksumAddress].balance = balance;\n });\n });\n }\n\n /**\n * Updates the staked balances of multiple accounts in a single batch operation.\n * This is more efficient than updating staked balances individually as it\n * triggers only one state update.\n *\n * @param stakedBalances - Array of staked balance updates, each containing address, chainId, and stakedBalance.\n */\n updateStakedBalances(\n stakedBalances: {\n address: string;\n chainId: Hex;\n stakedBalance: StakedBalance;\n }[],\n ) {\n this.update((state) => {\n stakedBalances.forEach(({ address, chainId, stakedBalance }) => {\n const checksumAddress = toChecksumHexAddress(address);\n\n // Ensure the chainId exists in the state\n if (!state.accountsByChainId[chainId]) {\n state.accountsByChainId[chainId] = {};\n }\n\n // Ensure the address exists for this chain\n if (!state.accountsByChainId[chainId][checksumAddress]) {\n state.accountsByChainId[chainId][checksumAddress] = {\n balance: '0x0',\n };\n }\n\n // Update the staked balance\n state.accountsByChainId[chainId][checksumAddress].stakedBalance =\n stakedBalance;\n });\n });\n }\n\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateNativeBalances` as const,\n this.updateNativeBalances.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateStakedBalances` as const,\n this.updateStakedBalances.bind(this),\n );\n }\n}\n\nexport default AccountTrackerController;\n"]}
|