@metamask/assets-controllers 88.0.0 → 89.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/dist/AccountTrackerController.cjs +19 -7
  3. package/dist/AccountTrackerController.cjs.map +1 -1
  4. package/dist/AccountTrackerController.d.cts +1 -1
  5. package/dist/AccountTrackerController.d.cts.map +1 -1
  6. package/dist/AccountTrackerController.d.mts +1 -1
  7. package/dist/AccountTrackerController.d.mts.map +1 -1
  8. package/dist/AccountTrackerController.mjs +19 -7
  9. package/dist/AccountTrackerController.mjs.map +1 -1
  10. package/dist/CurrencyRateController.cjs +67 -15
  11. package/dist/CurrencyRateController.cjs.map +1 -1
  12. package/dist/CurrencyRateController.d.cts +4 -8
  13. package/dist/CurrencyRateController.d.cts.map +1 -1
  14. package/dist/CurrencyRateController.d.mts +4 -8
  15. package/dist/CurrencyRateController.d.mts.map +1 -1
  16. package/dist/CurrencyRateController.mjs +67 -15
  17. package/dist/CurrencyRateController.mjs.map +1 -1
  18. package/dist/DeFiPositionsController/DeFiPositionsController.d.cts +1 -1
  19. package/dist/DeFiPositionsController/DeFiPositionsController.d.mts +1 -1
  20. package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.d.cts +1 -1
  21. package/dist/MultichainAssetsRatesController/MultichainAssetsRatesController.d.mts +1 -1
  22. package/dist/NftController.cjs +0 -1
  23. package/dist/NftController.cjs.map +1 -1
  24. package/dist/NftController.d.cts.map +1 -1
  25. package/dist/NftController.d.mts.map +1 -1
  26. package/dist/NftController.mjs +0 -1
  27. package/dist/NftController.mjs.map +1 -1
  28. package/dist/NftDetectionController.cjs.map +1 -1
  29. package/dist/NftDetectionController.d.cts +5 -0
  30. package/dist/NftDetectionController.d.cts.map +1 -1
  31. package/dist/NftDetectionController.d.mts +5 -0
  32. package/dist/NftDetectionController.d.mts.map +1 -1
  33. package/dist/NftDetectionController.mjs.map +1 -1
  34. package/dist/RatesController/RatesController.cjs +3 -2
  35. package/dist/RatesController/RatesController.cjs.map +1 -1
  36. package/dist/RatesController/RatesController.d.cts +3 -0
  37. package/dist/RatesController/RatesController.d.cts.map +1 -1
  38. package/dist/RatesController/RatesController.d.mts +3 -0
  39. package/dist/RatesController/RatesController.d.mts.map +1 -1
  40. package/dist/RatesController/RatesController.mjs +3 -2
  41. package/dist/RatesController/RatesController.mjs.map +1 -1
  42. package/dist/RatesController/types.cjs.map +1 -1
  43. package/dist/RatesController/types.d.cts +1 -1
  44. package/dist/RatesController/types.d.cts.map +1 -1
  45. package/dist/RatesController/types.d.mts +1 -1
  46. package/dist/RatesController/types.d.mts.map +1 -1
  47. package/dist/RatesController/types.mjs.map +1 -1
  48. package/dist/Standards/NftStandards/ERC721/ERC721Standard.cjs.map +1 -1
  49. package/dist/Standards/NftStandards/ERC721/ERC721Standard.d.cts.map +1 -1
  50. package/dist/Standards/NftStandards/ERC721/ERC721Standard.d.mts.map +1 -1
  51. package/dist/Standards/NftStandards/ERC721/ERC721Standard.mjs.map +1 -1
  52. package/dist/TokenBalancesController.cjs +12 -4
  53. package/dist/TokenBalancesController.cjs.map +1 -1
  54. package/dist/TokenBalancesController.d.cts +1 -1
  55. package/dist/TokenBalancesController.d.cts.map +1 -1
  56. package/dist/TokenBalancesController.d.mts +1 -1
  57. package/dist/TokenBalancesController.d.mts.map +1 -1
  58. package/dist/TokenBalancesController.mjs +12 -4
  59. package/dist/TokenBalancesController.mjs.map +1 -1
  60. package/dist/TokenDetectionController.cjs +30 -11
  61. package/dist/TokenDetectionController.cjs.map +1 -1
  62. package/dist/TokenDetectionController.d.cts +1 -1
  63. package/dist/TokenDetectionController.d.cts.map +1 -1
  64. package/dist/TokenDetectionController.d.mts +1 -1
  65. package/dist/TokenDetectionController.d.mts.map +1 -1
  66. package/dist/TokenDetectionController.mjs +31 -12
  67. package/dist/TokenDetectionController.mjs.map +1 -1
  68. package/dist/TokenListController.d.cts +1 -1
  69. package/dist/TokenListController.d.mts +1 -1
  70. package/dist/TokenRatesController.cjs +34 -52
  71. package/dist/TokenRatesController.cjs.map +1 -1
  72. package/dist/TokenRatesController.d.cts +3 -1
  73. package/dist/TokenRatesController.d.cts.map +1 -1
  74. package/dist/TokenRatesController.d.mts +3 -1
  75. package/dist/TokenRatesController.d.mts.map +1 -1
  76. package/dist/TokenRatesController.mjs +35 -53
  77. package/dist/TokenRatesController.mjs.map +1 -1
  78. package/dist/TokensController.cjs +6 -20
  79. package/dist/TokensController.cjs.map +1 -1
  80. package/dist/TokensController.d.cts +2 -0
  81. package/dist/TokensController.d.cts.map +1 -1
  82. package/dist/TokensController.d.mts +2 -0
  83. package/dist/TokensController.d.mts.map +1 -1
  84. package/dist/TokensController.mjs +6 -20
  85. package/dist/TokensController.mjs.map +1 -1
  86. package/dist/assetsUtil.cjs +2 -46
  87. package/dist/assetsUtil.cjs.map +1 -1
  88. package/dist/assetsUtil.d.cts +2 -0
  89. package/dist/assetsUtil.d.cts.map +1 -1
  90. package/dist/assetsUtil.d.mts +2 -0
  91. package/dist/assetsUtil.d.mts.map +1 -1
  92. package/dist/assetsUtil.mjs +2 -46
  93. package/dist/assetsUtil.mjs.map +1 -1
  94. package/dist/crypto-compare-service/crypto-compare.cjs +1 -8
  95. package/dist/crypto-compare-service/crypto-compare.cjs.map +1 -1
  96. package/dist/crypto-compare-service/crypto-compare.d.cts.map +1 -1
  97. package/dist/crypto-compare-service/crypto-compare.d.mts.map +1 -1
  98. package/dist/crypto-compare-service/crypto-compare.mjs +1 -8
  99. package/dist/crypto-compare-service/crypto-compare.mjs.map +1 -1
  100. package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs +43 -51
  101. package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs.map +1 -1
  102. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts +6 -2
  103. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts.map +1 -1
  104. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts +6 -2
  105. package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts.map +1 -1
  106. package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs +44 -52
  107. package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs.map +1 -1
  108. package/dist/rpc-service/rpc-balance-fetcher.cjs +1 -1
  109. package/dist/rpc-service/rpc-balance-fetcher.cjs.map +1 -1
  110. package/dist/rpc-service/rpc-balance-fetcher.d.cts +6 -2
  111. package/dist/rpc-service/rpc-balance-fetcher.d.cts.map +1 -1
  112. package/dist/rpc-service/rpc-balance-fetcher.d.mts +6 -2
  113. package/dist/rpc-service/rpc-balance-fetcher.d.mts.map +1 -1
  114. package/dist/rpc-service/rpc-balance-fetcher.mjs +1 -1
  115. package/dist/rpc-service/rpc-balance-fetcher.mjs.map +1 -1
  116. package/dist/token-prices-service/codefi-v2.cjs +2 -0
  117. package/dist/token-prices-service/codefi-v2.cjs.map +1 -1
  118. package/dist/token-prices-service/codefi-v2.d.cts +2 -0
  119. package/dist/token-prices-service/codefi-v2.d.cts.map +1 -1
  120. package/dist/token-prices-service/codefi-v2.d.mts +2 -0
  121. package/dist/token-prices-service/codefi-v2.d.mts.map +1 -1
  122. package/dist/token-prices-service/codefi-v2.mjs +2 -0
  123. package/dist/token-prices-service/codefi-v2.mjs.map +1 -1
  124. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"api-balance-fetcher.cjs","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport type { Web3Provider } from '@ethersproject/providers';\nimport {\n safelyExecute,\n toHex,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { CaipAccountAddress, Hex } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport { fetchMultiChainBalancesV4 } from './multi-chain-accounts';\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from '../AssetsContractController';\nimport {\n accountAddressToCaipReference,\n reduceInBatchesSerially,\n SupportedStakedBalanceNetworks,\n} from '../assetsUtil';\nimport { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from '../constants';\n\n// Maximum number of account addresses that can be sent to the accounts API in a single request\nconst ACCOUNTS_API_BATCH_SIZE = 50;\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nexport type ProcessedBalance = {\n success: boolean;\n value?: BN;\n account: ChecksumAddress | string;\n token: ChecksumAddress;\n chainId: ChainIdHex;\n};\n\nexport type BalanceFetcher = {\n supports(chainId: ChainIdHex): boolean;\n fetch(input: {\n chainIds: ChainIdHex[];\n queryAllAccounts: boolean;\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n }): Promise<ProcessedBalance[]>;\n};\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\nconst toCaipAccount = (\n chainId: ChainIdHex,\n account: ChecksumAddress,\n): CaipAccountAddress => accountAddressToCaipReference(chainId, account);\n\nexport type GetProviderFunction = (chainId: ChainIdHex) => Web3Provider;\n\nexport class AccountsApiBalanceFetcher implements BalanceFetcher {\n readonly #platform: 'extension' | 'mobile' = 'extension';\n\n readonly #getProvider?: GetProviderFunction;\n\n constructor(\n platform: 'extension' | 'mobile' = 'extension',\n getProvider?: GetProviderFunction,\n ) {\n this.#platform = platform;\n this.#getProvider = getProvider;\n }\n\n supports(chainId: ChainIdHex): boolean {\n return SUPPORTED_NETWORKS_ACCOUNTS_API_V4.includes(chainId);\n }\n\n async #fetchStakedBalances(\n addrs: CaipAccountAddress[],\n ): Promise<ProcessedBalance[]> {\n // Return empty array if no provider is available for blockchain calls\n if (!this.#getProvider) {\n return [];\n }\n\n const results: ProcessedBalance[] = [];\n\n // Group addresses by chain ID\n const addressesByChain: Record<ChainIdHex, ChecksumAddress[]> = {};\n\n for (const caipAddr of addrs) {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressesByChain[chainId]) {\n addressesByChain[chainId] = [];\n }\n addressesByChain[chainId].push(checksumAddress);\n }\n\n // Process each supported chain\n for (const [chainId, addresses] of Object.entries(addressesByChain)) {\n const chainIdHex = chainId as ChainIdHex;\n\n // Only fetch staked balance on supported networks (mainnet and hoodi)\n if (\n ![\n SupportedStakedBalanceNetworks.mainnet,\n SupportedStakedBalanceNetworks.hoodi,\n ].includes(chainIdHex as SupportedStakedBalanceNetworks)\n ) {\n continue;\n }\n\n // Only fetch staked balance if contract address exists\n if (!(chainIdHex in STAKING_CONTRACT_ADDRESS_BY_CHAINID)) {\n continue;\n }\n\n const contractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n chainIdHex as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n const provider = this.#getProvider(chainIdHex);\n\n const abi = [\n {\n inputs: [\n { internalType: 'address', name: 'account', type: 'address' },\n ],\n name: 'getShares',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { internalType: 'uint256', name: 'shares', type: 'uint256' },\n ],\n name: 'convertToAssets',\n outputs: [\n { internalType: 'uint256', name: 'assets', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n ];\n\n try {\n const contract = new Contract(contractAddress, abi, provider);\n\n // Get shares for each address\n for (const address of addresses) {\n try {\n const shares = await safelyExecute(() =>\n contract.getShares(address),\n );\n\n if (shares && (shares as BigNumber).gt(0)) {\n // Convert shares to assets (actual staked ETH amount)\n const assets = await safelyExecute(() =>\n contract.convertToAssets(shares),\n );\n\n if (assets) {\n results.push({\n success: true,\n value: new BN((assets as BigNumber).toString()),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } else {\n // Return zero balance for accounts with no staked assets\n results.push({\n success: true,\n value: new BN('0'),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } catch (error) {\n // Log error and continue with next address\n console.error(\n `Error fetching staked balance for ${address}:`,\n error,\n );\n results.push({\n success: false,\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n }\n } catch (error) {\n console.error(\n `Error setting up staking contract for chain ${chainId}:`,\n error,\n );\n }\n }\n\n return results;\n }\n\n async #fetchBalances(addrs: CaipAccountAddress[]) {\n // If we have fewer than or equal to the batch size, make a single request\n if (addrs.length <= ACCOUNTS_API_BATCH_SIZE) {\n const { balances } = await fetchMultiChainBalancesV4(\n { accountAddresses: addrs },\n this.#platform,\n );\n return balances;\n }\n\n // Otherwise, batch the requests to respect the 50-element limit\n type BalanceData = Awaited<\n ReturnType<typeof fetchMultiChainBalancesV4>\n >['balances'][number];\n\n const allBalances = await reduceInBatchesSerially<\n CaipAccountAddress,\n BalanceData[]\n >({\n values: addrs,\n batchSize: ACCOUNTS_API_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const { balances } = await fetchMultiChainBalancesV4(\n { accountAddresses: batch },\n this.#platform,\n );\n return [...(workingResult || []), ...balances];\n },\n initialResult: [],\n });\n\n return allBalances;\n }\n\n async fetch({\n chainIds,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]> {\n const caipAddrs: CaipAccountAddress[] = [];\n\n for (const chainId of chainIds.filter((c) => this.supports(c))) {\n if (queryAllAccounts) {\n allAccounts.forEach((a) =>\n caipAddrs.push(toCaipAccount(chainId, a.address as ChecksumAddress)),\n );\n } else {\n caipAddrs.push(toCaipAccount(chainId, selectedAccount));\n }\n }\n\n if (!caipAddrs.length) {\n return [];\n }\n\n // Don't use safelyExecute here - let real errors propagate\n let balances;\n let apiError = false;\n\n try {\n balances = await this.#fetchBalances(caipAddrs);\n } catch (error) {\n // Mark that we had an API error so we don't add fake zero balances\n apiError = true;\n console.error('Failed to fetch balances from API:', error);\n balances = undefined;\n }\n\n const stakedBalances = await this.#fetchStakedBalances(caipAddrs);\n\n const results: ProcessedBalance[] = [];\n\n // Collect all unique addresses and chains from the CAIP addresses\n const addressChainMap = new Map<string, Set<ChainIdHex>>();\n caipAddrs.forEach((caipAddr) => {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressChainMap.has(checksumAddress)) {\n addressChainMap.set(checksumAddress, new Set());\n }\n addressChainMap.get(checksumAddress)?.add(chainId);\n });\n\n // Ensure native token entries exist for all addresses on all requested chains\n const ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n const nativeBalancesFromAPI = new Map<string, BN>(); // key: `${address}-${chainId}`\n\n // Process regular API balances\n if (balances) {\n const apiBalances = balances.flatMap((b) => {\n const addressPart = b.accountAddress?.split(':')[2];\n if (!addressPart) {\n return [];\n }\n const account = checksum(addressPart);\n const token = checksum(b.address);\n // Use original address for zero address tokens, checksummed for others\n // TODO: this is a hack to get the correct account address type but needs to be fixed\n // by mgrating tokenBalancesController to checksum addresses\n const finalAccount: ChecksumAddress | string =\n token === ZERO_ADDRESS ? account : addressPart;\n const chainId = toHex(b.chainId) as ChainIdHex;\n\n let value: BN | undefined;\n try {\n // Convert string balance to BN avoiding floating point precision issues\n const { balance: balanceStr, decimals } = b;\n\n // Split the balance string into integer and decimal parts\n const [integerPart = '0', decimalPart = ''] = balanceStr.split('.');\n\n // Pad or truncate decimal part to match token decimals\n const paddedDecimalPart = decimalPart\n .padEnd(decimals, '0')\n .slice(0, decimals);\n\n // Combine and create BN\n const fullIntegerStr = integerPart + paddedDecimalPart;\n value = new BN(fullIntegerStr);\n } catch {\n value = undefined;\n }\n\n // Track native balances for later\n if (token === ZERO_ADDRESS && value !== undefined) {\n nativeBalancesFromAPI.set(`${finalAccount}-${chainId}`, value);\n }\n\n return [\n {\n success: value !== undefined,\n value,\n account: finalAccount,\n token,\n chainId,\n },\n ];\n });\n results.push(...apiBalances);\n }\n\n // Only add zero native balance entries if API succeeded but didn't return balances\n // Don't add fake zero balances if the API failed entirely\n if (!apiError) {\n addressChainMap.forEach((chains, address) => {\n chains.forEach((chainId) => {\n const key = `${address}-${chainId}`;\n const existingBalance = nativeBalancesFromAPI.get(key);\n\n if (!existingBalance) {\n // Add zero native balance entry if API succeeded but didn't return one\n results.push({\n success: true,\n value: new BN('0'),\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n }\n });\n });\n } else {\n // If API failed, add error entries for all requested addresses/chains\n addressChainMap.forEach((chains, address) => {\n chains.forEach((chainId) => {\n results.push({\n success: false,\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n });\n });\n }\n\n // Add staked balances\n results.push(...stakedBalances);\n\n // If we had an API error and no successful results, throw the error\n if (apiError && results.every((r) => !r.success)) {\n throw new Error('Failed to fetch any balance data due to API error');\n }\n\n return results;\n }\n}\n"]}
1
+ {"version":3,"file":"api-balance-fetcher.cjs","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,wDAAoD;AAEpD,iEAKoC;AAGpC,kDAAuB;AAEvB,qEAAmE;AACnE,8EAAkF;AAClF,kDAIuB;AACvB,gDAAkE;AAElE,+FAA+F;AAC/F,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAEnC,iDAAiD;AACjD,MAAM,uBAAuB,GAAG,KAAM,CAAC;AA4BvC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAmB,EAAE,CACjD,IAAA,uCAAoB,EAAC,IAAI,CAAoB,CAAC;AAEhD,MAAM,aAAa,GAAG,CACpB,OAAmB,EACnB,OAAwB,EACJ,EAAE,CAAC,IAAA,0CAA6B,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAIzE,MAAa,yBAAyB;IAKpC,YACE,WAAmC,WAAW,EAC9C,WAAiC;;QAN1B,8CAAoC,WAAW,EAAC;QAEhD,yDAAmC;QAM1C,uBAAA,IAAI,uCAAa,QAAQ,MAAA,CAAC;QAC1B,uBAAA,IAAI,0CAAgB,WAAW,MAAA,CAAC;IAClC,CAAC;IAED,QAAQ,CAAC,OAAmB;QAC1B,OAAO,8CAAkC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC;IAmLD,KAAK,CAAC,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GAC4B;QACvC,MAAM,SAAS,GAAyB,EAAE,CAAC;QAE3C,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,IAAI,gBAAgB,EAAE,CAAC;gBACrB,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CACxB,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,OAA0B,CAAC,CAAC,CACrE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC1B,CAAC;QAED,mEAAmE;QACnE,wDAAwD;QACxD,MAAM,WAAW,GAAG,MAAM,IAAA,2CAAwB,EAChD,GAAG,EAAE,CAAC,uBAAA,IAAI,sFAAe,MAAnB,IAAI,EAAgB,SAAS,CAAC,EACpC,KAAK,EAAE,yCAAyC;QAChD,uBAAuB,CACxB,CAAC;QAEF,uEAAuE;QACvE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QAED,4DAA4D;QAC5D,MAAM,mBAAmB,GACvB,WAAW,CAAC,mBAAmB;YAC7B,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC,GAAG,CACjC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,wBAAK,EAAC,OAAO,CAAe,CAC1C;YACH,CAAC,CAAC,SAAS,CAAC;QAEhB,MAAM,cAAc,GAAG,MAAM,uBAAA,IAAI,4FAAqB,MAAzB,IAAI,EAAsB,SAAS,CAAC,CAAC;QAElE,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,kEAAkE;QAClE,MAAM,eAAe,GAAG,IAAI,GAAG,EAA2B,CAAC;QAC3D,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC7B,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAClD,MAAM,OAAO,GAAG,IAAA,wBAAK,EAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAe,CAAC;YAC5D,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAE1C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;gBAC1C,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YAClD,CAAC;YACD,eAAe,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,8EAA8E;QAC9E,MAAM,YAAY,GAChB,4CAA+D,CAAC;QAClE,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAc,CAAC,CAAC,+BAA+B;QAEpF,+BAA+B;QAC/B,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBACrD,MAAM,WAAW,GAAG,CAAC,CAAC,cAAc,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpD,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,EAAE,CAAC;gBACZ,CAAC;gBACD,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gBAClC,uEAAuE;gBACvE,qFAAqF;gBACrF,4DAA4D;gBAC5D,MAAM,YAAY,GAChB,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;gBACjD,MAAM,OAAO,GAAG,IAAA,wBAAK,EAAC,CAAC,CAAC,OAAO,CAAe,CAAC;gBAE/C,IAAI,KAAqB,CAAC;gBAC1B,IAAI,CAAC;oBACH,wEAAwE;oBACxE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;oBAE5C,0DAA0D;oBAC1D,MAAM,CAAC,WAAW,GAAG,GAAG,EAAE,WAAW,GAAG,EAAE,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAEpE,uDAAuD;oBACvD,MAAM,iBAAiB,GAAG,WAAW;yBAClC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC;yBACrB,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;oBAEtB,wBAAwB;oBACxB,MAAM,cAAc,GAAG,WAAW,GAAG,iBAAiB,CAAC;oBACvD,KAAK,GAAG,IAAI,eAAE,CAAC,cAAc,CAAC,CAAC;gBACjC,CAAC;gBAAC,MAAM,CAAC;oBACP,KAAK,GAAG,SAAS,CAAC;gBACpB,CAAC;gBAED,kCAAkC;gBAClC,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAClD,qBAAqB,CAAC,GAAG,CAAC,GAAG,YAAY,IAAI,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;gBACjE,CAAC;gBAED,OAAO;oBACL;wBACE,OAAO,EAAE,KAAK,KAAK,SAAS;wBAC5B,KAAK;wBACL,OAAO,EAAE,YAAY;wBACrB,KAAK;wBACL,OAAO;qBACR;iBACF,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QAC/B,CAAC;QAED,uEAAuE;QACvE,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBACzB,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;gBACpC,MAAM,eAAe,GAAG,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAEvD,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,uEAAuE;oBACvE,OAAO,CAAC,IAAI,CAAC;wBACX,OAAO,EAAE,IAAI;wBACb,KAAK,EAAE,IAAI,eAAE,CAAC,GAAG,CAAC;wBAClB,OAAO,EAAE,OAA0B;wBACnC,KAAK,EAAE,YAAY;wBACnB,OAAO;qBACR,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,sBAAsB;QACtB,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;QAEhC,OAAO;YACL,QAAQ,EAAE,OAAO;YACjB,mBAAmB;SACpB,CAAC;IACJ,CAAC;CACF;AApVD,8DAoVC;oNAnUC,KAAK,yDACH,KAA2B;IAE3B,sEAAsE;IACtE,IAAI,CAAC,uBAAA,IAAI,8CAAa,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,8BAA8B;IAC9B,MAAM,gBAAgB,GAA0C,EAAE,CAAC;IAEnE,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAA,wBAAK,EAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAe,CAAC;QAC5D,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAE1C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjC,CAAC;QACD,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAClD,CAAC;IAED,+BAA+B;IAC/B,KAAK,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACpE,MAAM,UAAU,GAAG,OAAqB,CAAC;QAEzC,sEAAsE;QACtE,IACE,CAAC;YACC,2CAA8B,CAAC,OAAO;YACtC,2CAA8B,CAAC,KAAK;SACrC,CAAC,QAAQ,CAAC,UAA4C,CAAC,EACxD,CAAC;YACD,SAAS;QACX,CAAC;QAED,uDAAuD;QACvD,IAAI,CAAC,CAAC,UAAU,IAAI,8DAAmC,CAAC,EAAE,CAAC;YACzD,SAAS;QACX,CAAC;QAED,MAAM,eAAe,GACnB,8DAAmC,CACjC,UAA8D,CAC/D,CAAC;QACJ,MAAM,QAAQ,GAAG,uBAAA,IAAI,8CAAa,MAAjB,IAAI,EAAc,UAAU,CAAC,CAAC;QAE/C,MAAM,GAAG,GAAG;YACV;gBACE,MAAM,EAAE;oBACN,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;iBAC9D;gBACD,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;gBACjE,eAAe,EAAE,MAAM;gBACvB,IAAI,EAAE,UAAU;aACjB;YACD;gBACE,MAAM,EAAE;oBACN,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;iBAC7D;gBACD,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE;oBACP,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;iBAC7D;gBACD,eAAe,EAAE,MAAM;gBACvB,IAAI,EAAE,UAAU;aACjB;SACF,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,oBAAQ,CAAC,eAAe,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;YAE9D,8BAA8B;YAC9B,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAA,gCAAa,EAAC,GAAG,EAAE,CACtC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAC5B,CAAC;oBAEF,IAAI,MAAM,IAAK,MAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC1C,sDAAsD;wBACtD,MAAM,MAAM,GAAG,MAAM,IAAA,gCAAa,EAAC,GAAG,EAAE,CACtC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CACjC,CAAC;wBAEF,IAAI,MAAM,EAAE,CAAC;4BACX,OAAO,CAAC,IAAI,CAAC;gCACX,OAAO,EAAE,IAAI;gCACb,KAAK,EAAE,IAAI,eAAE,CAAE,MAAoB,CAAC,QAAQ,EAAE,CAAC;gCAC/C,OAAO,EAAE,OAAO;gCAChB,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAoB;gCACnD,OAAO,EAAE,UAAU;6BACpB,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,yDAAyD;wBACzD,OAAO,CAAC,IAAI,CAAC;4BACX,OAAO,EAAE,IAAI;4BACb,KAAK,EAAE,IAAI,eAAE,CAAC,GAAG,CAAC;4BAClB,OAAO,EAAE,OAAO;4BAChB,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAoB;4BACnD,OAAO,EAAE,UAAU;yBACpB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,2CAA2C;oBAC3C,OAAO,CAAC,KAAK,CACX,qCAAqC,OAAO,GAAG,EAC/C,KAAK,CACN,CAAC;oBACF,OAAO,CAAC,IAAI,CAAC;wBACX,OAAO,EAAE,KAAK;wBACd,OAAO,EAAE,OAAO;wBAChB,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAoB;wBACnD,OAAO,EAAE,UAAU;qBACpB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,+CAA+C,OAAO,GAAG,EACzD,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,6CAED,KAAK,mDAAgB,KAA2B;IAC9C,0EAA0E;IAC1E,IAAI,KAAK,CAAC,MAAM,IAAI,uBAAuB,EAAE,CAAC;QAC5C,OAAO,MAAM,IAAA,gDAAyB,EACpC,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAC3B,uBAAA,IAAI,2CAAU,CACf,CAAC;IACJ,CAAC;IASD,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAU,CAAC;IACjD,MAAM,WAAW,GAAG,MAAM,IAAA,oCAAuB,EAG/C;QACA,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,uBAAuB;QAClC,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE;YACxC,MAAM,QAAQ,GAAG,MAAM,IAAA,gDAAyB,EAC9C,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAC3B,uBAAA,IAAI,2CAAU,CACf,CAAC;YACF,+CAA+C;YAC/C,IAAI,QAAQ,CAAC,mBAAmB,EAAE,CAAC;gBACjC,QAAQ,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAC/C,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,CACpC,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC1D,CAAC;QACD,aAAa,EAAE,EAAE;KAClB,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,mBAAmB,EAAE,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC;KACxC,CAAC;AACpB,CAAC","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport type { Web3Provider } from '@ethersproject/providers';\nimport {\n safelyExecute,\n safelyExecuteWithTimeout,\n toHex,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { CaipAccountAddress, Hex } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport { fetchMultiChainBalancesV4 } from './multi-chain-accounts';\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from '../AssetsContractController';\nimport {\n accountAddressToCaipReference,\n reduceInBatchesSerially,\n SupportedStakedBalanceNetworks,\n} from '../assetsUtil';\nimport { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from '../constants';\n\n// Maximum number of account addresses that can be sent to the accounts API in a single request\nconst ACCOUNTS_API_BATCH_SIZE = 50;\n\n// Timeout for accounts API requests (30 seconds)\nconst ACCOUNTS_API_TIMEOUT_MS = 30_000;\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nexport type ProcessedBalance = {\n success: boolean;\n value?: BN;\n account: ChecksumAddress | string;\n token: ChecksumAddress;\n chainId: ChainIdHex;\n};\n\nexport type BalanceFetchResult = {\n balances: ProcessedBalance[];\n unprocessedChainIds?: ChainIdHex[];\n};\n\nexport type BalanceFetcher = {\n supports(chainId: ChainIdHex): boolean;\n fetch(input: {\n chainIds: ChainIdHex[];\n queryAllAccounts: boolean;\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n }): Promise<BalanceFetchResult>;\n};\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\nconst toCaipAccount = (\n chainId: ChainIdHex,\n account: ChecksumAddress,\n): CaipAccountAddress => accountAddressToCaipReference(chainId, account);\n\nexport type GetProviderFunction = (chainId: ChainIdHex) => Web3Provider;\n\nexport class AccountsApiBalanceFetcher implements BalanceFetcher {\n readonly #platform: 'extension' | 'mobile' = 'extension';\n\n readonly #getProvider?: GetProviderFunction;\n\n constructor(\n platform: 'extension' | 'mobile' = 'extension',\n getProvider?: GetProviderFunction,\n ) {\n this.#platform = platform;\n this.#getProvider = getProvider;\n }\n\n supports(chainId: ChainIdHex): boolean {\n return SUPPORTED_NETWORKS_ACCOUNTS_API_V4.includes(chainId);\n }\n\n async #fetchStakedBalances(\n addrs: CaipAccountAddress[],\n ): Promise<ProcessedBalance[]> {\n // Return empty array if no provider is available for blockchain calls\n if (!this.#getProvider) {\n return [];\n }\n\n const results: ProcessedBalance[] = [];\n\n // Group addresses by chain ID\n const addressesByChain: Record<ChainIdHex, ChecksumAddress[]> = {};\n\n for (const caipAddr of addrs) {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressesByChain[chainId]) {\n addressesByChain[chainId] = [];\n }\n addressesByChain[chainId].push(checksumAddress);\n }\n\n // Process each supported chain\n for (const [chainId, addresses] of Object.entries(addressesByChain)) {\n const chainIdHex = chainId as ChainIdHex;\n\n // Only fetch staked balance on supported networks (mainnet and hoodi)\n if (\n ![\n SupportedStakedBalanceNetworks.mainnet,\n SupportedStakedBalanceNetworks.hoodi,\n ].includes(chainIdHex as SupportedStakedBalanceNetworks)\n ) {\n continue;\n }\n\n // Only fetch staked balance if contract address exists\n if (!(chainIdHex in STAKING_CONTRACT_ADDRESS_BY_CHAINID)) {\n continue;\n }\n\n const contractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n chainIdHex as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n const provider = this.#getProvider(chainIdHex);\n\n const abi = [\n {\n inputs: [\n { internalType: 'address', name: 'account', type: 'address' },\n ],\n name: 'getShares',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { internalType: 'uint256', name: 'shares', type: 'uint256' },\n ],\n name: 'convertToAssets',\n outputs: [\n { internalType: 'uint256', name: 'assets', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n ];\n\n try {\n const contract = new Contract(contractAddress, abi, provider);\n\n // Get shares for each address\n for (const address of addresses) {\n try {\n const shares = await safelyExecute(() =>\n contract.getShares(address),\n );\n\n if (shares && (shares as BigNumber).gt(0)) {\n // Convert shares to assets (actual staked ETH amount)\n const assets = await safelyExecute(() =>\n contract.convertToAssets(shares),\n );\n\n if (assets) {\n results.push({\n success: true,\n value: new BN((assets as BigNumber).toString()),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } else {\n // Return zero balance for accounts with no staked assets\n results.push({\n success: true,\n value: new BN('0'),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } catch (error) {\n // Log error and continue with next address\n console.error(\n `Error fetching staked balance for ${address}:`,\n error,\n );\n results.push({\n success: false,\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n }\n } catch (error) {\n console.error(\n `Error setting up staking contract for chain ${chainId}:`,\n error,\n );\n }\n }\n\n return results;\n }\n\n async #fetchBalances(addrs: CaipAccountAddress[]) {\n // If we have fewer than or equal to the batch size, make a single request\n if (addrs.length <= ACCOUNTS_API_BATCH_SIZE) {\n return await fetchMultiChainBalancesV4(\n { accountAddresses: addrs },\n this.#platform,\n );\n }\n\n // Otherwise, batch the requests to respect the 50-element limit\n type BalanceData = Awaited<\n ReturnType<typeof fetchMultiChainBalancesV4>\n >['balances'][number];\n\n type ResponseData = Awaited<ReturnType<typeof fetchMultiChainBalancesV4>>;\n\n const allUnprocessedNetworks = new Set<number>();\n const allBalances = await reduceInBatchesSerially<\n CaipAccountAddress,\n BalanceData[]\n >({\n values: addrs,\n batchSize: ACCOUNTS_API_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const response = await fetchMultiChainBalancesV4(\n { accountAddresses: batch },\n this.#platform,\n );\n // Collect unprocessed networks from each batch\n if (response.unprocessedNetworks) {\n response.unprocessedNetworks.forEach((network) =>\n allUnprocessedNetworks.add(network),\n );\n }\n return [...(workingResult || []), ...response.balances];\n },\n initialResult: [],\n });\n\n return {\n balances: allBalances,\n unprocessedNetworks: Array.from(allUnprocessedNetworks),\n } as ResponseData;\n }\n\n async fetch({\n chainIds,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult> {\n const caipAddrs: CaipAccountAddress[] = [];\n\n for (const chainId of chainIds.filter((c) => this.supports(c))) {\n if (queryAllAccounts) {\n allAccounts.forEach((a) =>\n caipAddrs.push(toCaipAccount(chainId, a.address as ChecksumAddress)),\n );\n } else {\n caipAddrs.push(toCaipAccount(chainId, selectedAccount));\n }\n }\n\n if (!caipAddrs.length) {\n return { balances: [] };\n }\n\n // Let errors propagate to TokenBalancesController for RPC fallback\n // Use timeout to prevent hanging API calls (30 seconds)\n const apiResponse = await safelyExecuteWithTimeout(\n () => this.#fetchBalances(caipAddrs),\n false, // don't log error here, let it propagate\n ACCOUNTS_API_TIMEOUT_MS,\n );\n\n // If API call timed out or failed, throw error to trigger RPC fallback\n if (!apiResponse) {\n throw new Error('Accounts API request timed out or failed');\n }\n\n // Extract unprocessed networks and convert to hex chain IDs\n const unprocessedChainIds: ChainIdHex[] | undefined =\n apiResponse.unprocessedNetworks\n ? apiResponse.unprocessedNetworks.map(\n (chainId) => toHex(chainId) as ChainIdHex,\n )\n : undefined;\n\n const stakedBalances = await this.#fetchStakedBalances(caipAddrs);\n\n const results: ProcessedBalance[] = [];\n\n // Collect all unique addresses and chains from the CAIP addresses\n const addressChainMap = new Map<string, Set<ChainIdHex>>();\n caipAddrs.forEach((caipAddr) => {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressChainMap.has(checksumAddress)) {\n addressChainMap.set(checksumAddress, new Set());\n }\n addressChainMap.get(checksumAddress)?.add(chainId);\n });\n\n // Ensure native token entries exist for all addresses on all requested chains\n const ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n const nativeBalancesFromAPI = new Map<string, BN>(); // key: `${address}-${chainId}`\n\n // Process regular API balances\n if (apiResponse.balances) {\n const apiBalances = apiResponse.balances.flatMap((b) => {\n const addressPart = b.accountAddress?.split(':')[2];\n if (!addressPart) {\n return [];\n }\n const account = checksum(addressPart);\n const token = checksum(b.address);\n // Use original address for zero address tokens, checksummed for others\n // TODO: this is a hack to get the correct account address type but needs to be fixed\n // by mgrating tokenBalancesController to checksum addresses\n const finalAccount: ChecksumAddress | string =\n token === ZERO_ADDRESS ? account : addressPart;\n const chainId = toHex(b.chainId) as ChainIdHex;\n\n let value: BN | undefined;\n try {\n // Convert string balance to BN avoiding floating point precision issues\n const { balance: balanceStr, decimals } = b;\n\n // Split the balance string into integer and decimal parts\n const [integerPart = '0', decimalPart = ''] = balanceStr.split('.');\n\n // Pad or truncate decimal part to match token decimals\n const paddedDecimalPart = decimalPart\n .padEnd(decimals, '0')\n .slice(0, decimals);\n\n // Combine and create BN\n const fullIntegerStr = integerPart + paddedDecimalPart;\n value = new BN(fullIntegerStr);\n } catch {\n value = undefined;\n }\n\n // Track native balances for later\n if (token === ZERO_ADDRESS && value !== undefined) {\n nativeBalancesFromAPI.set(`${finalAccount}-${chainId}`, value);\n }\n\n return [\n {\n success: value !== undefined,\n value,\n account: finalAccount,\n token,\n chainId,\n },\n ];\n });\n results.push(...apiBalances);\n }\n\n // Add zero native balance entries for addresses that API didn't return\n addressChainMap.forEach((chains, address) => {\n chains.forEach((chainId) => {\n const key = `${address}-${chainId}`;\n const existingBalance = nativeBalancesFromAPI.get(key);\n\n if (!existingBalance) {\n // Add zero native balance entry if API succeeded but didn't return one\n results.push({\n success: true,\n value: new BN('0'),\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n }\n });\n });\n\n // Add staked balances\n results.push(...stakedBalances);\n\n return {\n balances: results,\n unprocessedChainIds,\n };\n }\n}\n"]}
@@ -11,6 +11,10 @@ export type ProcessedBalance = {
11
11
  token: ChecksumAddress;
12
12
  chainId: ChainIdHex;
13
13
  };
14
+ export type BalanceFetchResult = {
15
+ balances: ProcessedBalance[];
16
+ unprocessedChainIds?: ChainIdHex[];
17
+ };
14
18
  export type BalanceFetcher = {
15
19
  supports(chainId: ChainIdHex): boolean;
16
20
  fetch(input: {
@@ -18,13 +22,13 @@ export type BalanceFetcher = {
18
22
  queryAllAccounts: boolean;
19
23
  selectedAccount: ChecksumAddress;
20
24
  allAccounts: InternalAccount[];
21
- }): Promise<ProcessedBalance[]>;
25
+ }): Promise<BalanceFetchResult>;
22
26
  };
23
27
  export type GetProviderFunction = (chainId: ChainIdHex) => Web3Provider;
24
28
  export declare class AccountsApiBalanceFetcher implements BalanceFetcher {
25
29
  #private;
26
30
  constructor(platform?: 'extension' | 'mobile', getProvider?: GetProviderFunction);
27
31
  supports(chainId: ChainIdHex): boolean;
28
- fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]>;
32
+ fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult>;
29
33
  }
30
34
  //# sourceMappingURL=api-balance-fetcher.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-balance-fetcher.d.cts","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAM7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAsB,GAAG,EAAE,wBAAwB;AAC/D,OAAO,EAAE,cAAc;AAcvB,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACjC,CAAC;AAUF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,CAAC;AAExE,qBAAa,yBAA0B,YAAW,cAAc;;gBAM5D,QAAQ,GAAE,WAAW,GAAG,QAAsB,EAC9C,WAAW,CAAC,EAAE,mBAAmB;IAMnC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IA0KhC,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAsJxE"}
1
+ {"version":3,"file":"api-balance-fetcher.d.cts","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAO7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAsB,GAAG,EAAE,wBAAwB;AAC/D,OAAO,EAAE,cAAc;AAiBvB,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mBAAmB,CAAC,EAAE,UAAU,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjC,CAAC;AAUF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,CAAC;AAExE,qBAAa,yBAA0B,YAAW,cAAc;;gBAM5D,QAAQ,GAAE,WAAW,GAAG,QAAsB,EAC9C,WAAW,CAAC,EAAE,mBAAmB;IAMnC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IAqLhC,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA6IxE"}
@@ -11,6 +11,10 @@ export type ProcessedBalance = {
11
11
  token: ChecksumAddress;
12
12
  chainId: ChainIdHex;
13
13
  };
14
+ export type BalanceFetchResult = {
15
+ balances: ProcessedBalance[];
16
+ unprocessedChainIds?: ChainIdHex[];
17
+ };
14
18
  export type BalanceFetcher = {
15
19
  supports(chainId: ChainIdHex): boolean;
16
20
  fetch(input: {
@@ -18,13 +22,13 @@ export type BalanceFetcher = {
18
22
  queryAllAccounts: boolean;
19
23
  selectedAccount: ChecksumAddress;
20
24
  allAccounts: InternalAccount[];
21
- }): Promise<ProcessedBalance[]>;
25
+ }): Promise<BalanceFetchResult>;
22
26
  };
23
27
  export type GetProviderFunction = (chainId: ChainIdHex) => Web3Provider;
24
28
  export declare class AccountsApiBalanceFetcher implements BalanceFetcher {
25
29
  #private;
26
30
  constructor(platform?: 'extension' | 'mobile', getProvider?: GetProviderFunction);
27
31
  supports(chainId: ChainIdHex): boolean;
28
- fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]>;
32
+ fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult>;
29
33
  }
30
34
  //# sourceMappingURL=api-balance-fetcher.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-balance-fetcher.d.mts","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAM7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAsB,GAAG,EAAE,wBAAwB;AAC/D,OAAO,EAAE,cAAc;AAcvB,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACjC,CAAC;AAUF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,CAAC;AAExE,qBAAa,yBAA0B,YAAW,cAAc;;gBAM5D,QAAQ,GAAE,WAAW,GAAG,QAAsB,EAC9C,WAAW,CAAC,EAAE,mBAAmB;IAMnC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IA0KhC,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAsJxE"}
1
+ {"version":3,"file":"api-balance-fetcher.d.mts","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAO7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAsB,GAAG,EAAE,wBAAwB;AAC/D,OAAO,EAAE,cAAc;AAiBvB,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mBAAmB,CAAC,EAAE,UAAU,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjC,CAAC;AAUF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,CAAC;AAExE,qBAAa,yBAA0B,YAAW,cAAc;;gBAM5D,QAAQ,GAAE,WAAW,GAAG,QAAsB,EAC9C,WAAW,CAAC,EAAE,mBAAmB;IAMnC,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO;IAqLhC,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA6IxE"}
@@ -17,7 +17,7 @@ function $importDefault(module) {
17
17
  return module;
18
18
  }
19
19
  import { Contract } from "@ethersproject/contracts";
20
- import { safelyExecute, toHex, toChecksumHexAddress } from "@metamask/controller-utils";
20
+ import { safelyExecute, safelyExecuteWithTimeout, toHex, toChecksumHexAddress } from "@metamask/controller-utils";
21
21
  import $BN from "bn.js";
22
22
  const BN = $importDefault($BN);
23
23
  import { fetchMultiChainBalancesV4 } from "./multi-chain-accounts.mjs";
@@ -26,6 +26,8 @@ import { accountAddressToCaipReference, reduceInBatchesSerially, SupportedStaked
26
26
  import { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from "../constants.mjs";
27
27
  // Maximum number of account addresses that can be sent to the accounts API in a single request
28
28
  const ACCOUNTS_API_BATCH_SIZE = 50;
29
+ // Timeout for accounts API requests (30 seconds)
30
+ const ACCOUNTS_API_TIMEOUT_MS = 30000;
29
31
  const checksum = (addr) => toChecksumHexAddress(addr);
30
32
  const toCaipAccount = (chainId, account) => accountAddressToCaipReference(chainId, account);
31
33
  export class AccountsApiBalanceFetcher {
@@ -50,20 +52,20 @@ export class AccountsApiBalanceFetcher {
50
52
  }
51
53
  }
52
54
  if (!caipAddrs.length) {
53
- return [];
55
+ return { balances: [] };
54
56
  }
55
- // Don't use safelyExecute here - let real errors propagate
56
- let balances;
57
- let apiError = false;
58
- try {
59
- balances = await __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_instances, "m", _AccountsApiBalanceFetcher_fetchBalances).call(this, caipAddrs);
60
- }
61
- catch (error) {
62
- // Mark that we had an API error so we don't add fake zero balances
63
- apiError = true;
64
- console.error('Failed to fetch balances from API:', error);
65
- balances = undefined;
57
+ // Let errors propagate to TokenBalancesController for RPC fallback
58
+ // Use timeout to prevent hanging API calls (30 seconds)
59
+ const apiResponse = await safelyExecuteWithTimeout(() => __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_instances, "m", _AccountsApiBalanceFetcher_fetchBalances).call(this, caipAddrs), false, // don't log error here, let it propagate
60
+ ACCOUNTS_API_TIMEOUT_MS);
61
+ // If API call timed out or failed, throw error to trigger RPC fallback
62
+ if (!apiResponse) {
63
+ throw new Error('Accounts API request timed out or failed');
66
64
  }
65
+ // Extract unprocessed networks and convert to hex chain IDs
66
+ const unprocessedChainIds = apiResponse.unprocessedNetworks
67
+ ? apiResponse.unprocessedNetworks.map((chainId) => toHex(chainId))
68
+ : undefined;
67
69
  const stakedBalances = await __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_instances, "m", _AccountsApiBalanceFetcher_fetchStakedBalances).call(this, caipAddrs);
68
70
  const results = [];
69
71
  // Collect all unique addresses and chains from the CAIP addresses
@@ -81,8 +83,8 @@ export class AccountsApiBalanceFetcher {
81
83
  const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
82
84
  const nativeBalancesFromAPI = new Map(); // key: `${address}-${chainId}`
83
85
  // Process regular API balances
84
- if (balances) {
85
- const apiBalances = balances.flatMap((b) => {
86
+ if (apiResponse.balances) {
87
+ const apiBalances = apiResponse.balances.flatMap((b) => {
86
88
  const addressPart = b.accountAddress?.split(':')[2];
87
89
  if (!addressPart) {
88
90
  return [];
@@ -127,46 +129,29 @@ export class AccountsApiBalanceFetcher {
127
129
  });
128
130
  results.push(...apiBalances);
129
131
  }
130
- // Only add zero native balance entries if API succeeded but didn't return balances
131
- // Don't add fake zero balances if the API failed entirely
132
- if (!apiError) {
133
- addressChainMap.forEach((chains, address) => {
134
- chains.forEach((chainId) => {
135
- const key = `${address}-${chainId}`;
136
- const existingBalance = nativeBalancesFromAPI.get(key);
137
- if (!existingBalance) {
138
- // Add zero native balance entry if API succeeded but didn't return one
139
- results.push({
140
- success: true,
141
- value: new BN('0'),
142
- account: address,
143
- token: ZERO_ADDRESS,
144
- chainId,
145
- });
146
- }
147
- });
148
- });
149
- }
150
- else {
151
- // If API failed, add error entries for all requested addresses/chains
152
- addressChainMap.forEach((chains, address) => {
153
- chains.forEach((chainId) => {
132
+ // Add zero native balance entries for addresses that API didn't return
133
+ addressChainMap.forEach((chains, address) => {
134
+ chains.forEach((chainId) => {
135
+ const key = `${address}-${chainId}`;
136
+ const existingBalance = nativeBalancesFromAPI.get(key);
137
+ if (!existingBalance) {
138
+ // Add zero native balance entry if API succeeded but didn't return one
154
139
  results.push({
155
- success: false,
140
+ success: true,
141
+ value: new BN('0'),
156
142
  account: address,
157
143
  token: ZERO_ADDRESS,
158
144
  chainId,
159
145
  });
160
- });
146
+ }
161
147
  });
162
- }
148
+ });
163
149
  // Add staked balances
164
150
  results.push(...stakedBalances);
165
- // If we had an API error and no successful results, throw the error
166
- if (apiError && results.every((r) => !r.success)) {
167
- throw new Error('Failed to fetch any balance data due to API error');
168
- }
169
- return results;
151
+ return {
152
+ balances: results,
153
+ unprocessedChainIds,
154
+ };
170
155
  }
171
156
  }
172
157
  _AccountsApiBalanceFetcher_platform = new WeakMap(), _AccountsApiBalanceFetcher_getProvider = new WeakMap(), _AccountsApiBalanceFetcher_instances = new WeakSet(), _AccountsApiBalanceFetcher_fetchStakedBalances = async function _AccountsApiBalanceFetcher_fetchStakedBalances(addrs) {
@@ -274,18 +259,25 @@ _AccountsApiBalanceFetcher_platform = new WeakMap(), _AccountsApiBalanceFetcher_
274
259
  }, _AccountsApiBalanceFetcher_fetchBalances = async function _AccountsApiBalanceFetcher_fetchBalances(addrs) {
275
260
  // If we have fewer than or equal to the batch size, make a single request
276
261
  if (addrs.length <= ACCOUNTS_API_BATCH_SIZE) {
277
- const { balances } = await fetchMultiChainBalancesV4({ accountAddresses: addrs }, __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_platform, "f"));
278
- return balances;
262
+ return await fetchMultiChainBalancesV4({ accountAddresses: addrs }, __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_platform, "f"));
279
263
  }
264
+ const allUnprocessedNetworks = new Set();
280
265
  const allBalances = await reduceInBatchesSerially({
281
266
  values: addrs,
282
267
  batchSize: ACCOUNTS_API_BATCH_SIZE,
283
268
  eachBatch: async (workingResult, batch) => {
284
- const { balances } = await fetchMultiChainBalancesV4({ accountAddresses: batch }, __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_platform, "f"));
285
- return [...(workingResult || []), ...balances];
269
+ const response = await fetchMultiChainBalancesV4({ accountAddresses: batch }, __classPrivateFieldGet(this, _AccountsApiBalanceFetcher_platform, "f"));
270
+ // Collect unprocessed networks from each batch
271
+ if (response.unprocessedNetworks) {
272
+ response.unprocessedNetworks.forEach((network) => allUnprocessedNetworks.add(network));
273
+ }
274
+ return [...(workingResult || []), ...response.balances];
286
275
  },
287
276
  initialResult: [],
288
277
  });
289
- return allBalances;
278
+ return {
279
+ balances: allBalances,
280
+ unprocessedNetworks: Array.from(allUnprocessedNetworks),
281
+ };
290
282
  };
291
283
  //# sourceMappingURL=api-balance-fetcher.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-balance-fetcher.mjs","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport type { Web3Provider } from '@ethersproject/providers';\nimport {\n safelyExecute,\n toHex,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { CaipAccountAddress, Hex } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport { fetchMultiChainBalancesV4 } from './multi-chain-accounts';\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from '../AssetsContractController';\nimport {\n accountAddressToCaipReference,\n reduceInBatchesSerially,\n SupportedStakedBalanceNetworks,\n} from '../assetsUtil';\nimport { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from '../constants';\n\n// Maximum number of account addresses that can be sent to the accounts API in a single request\nconst ACCOUNTS_API_BATCH_SIZE = 50;\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nexport type ProcessedBalance = {\n success: boolean;\n value?: BN;\n account: ChecksumAddress | string;\n token: ChecksumAddress;\n chainId: ChainIdHex;\n};\n\nexport type BalanceFetcher = {\n supports(chainId: ChainIdHex): boolean;\n fetch(input: {\n chainIds: ChainIdHex[];\n queryAllAccounts: boolean;\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n }): Promise<ProcessedBalance[]>;\n};\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\nconst toCaipAccount = (\n chainId: ChainIdHex,\n account: ChecksumAddress,\n): CaipAccountAddress => accountAddressToCaipReference(chainId, account);\n\nexport type GetProviderFunction = (chainId: ChainIdHex) => Web3Provider;\n\nexport class AccountsApiBalanceFetcher implements BalanceFetcher {\n readonly #platform: 'extension' | 'mobile' = 'extension';\n\n readonly #getProvider?: GetProviderFunction;\n\n constructor(\n platform: 'extension' | 'mobile' = 'extension',\n getProvider?: GetProviderFunction,\n ) {\n this.#platform = platform;\n this.#getProvider = getProvider;\n }\n\n supports(chainId: ChainIdHex): boolean {\n return SUPPORTED_NETWORKS_ACCOUNTS_API_V4.includes(chainId);\n }\n\n async #fetchStakedBalances(\n addrs: CaipAccountAddress[],\n ): Promise<ProcessedBalance[]> {\n // Return empty array if no provider is available for blockchain calls\n if (!this.#getProvider) {\n return [];\n }\n\n const results: ProcessedBalance[] = [];\n\n // Group addresses by chain ID\n const addressesByChain: Record<ChainIdHex, ChecksumAddress[]> = {};\n\n for (const caipAddr of addrs) {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressesByChain[chainId]) {\n addressesByChain[chainId] = [];\n }\n addressesByChain[chainId].push(checksumAddress);\n }\n\n // Process each supported chain\n for (const [chainId, addresses] of Object.entries(addressesByChain)) {\n const chainIdHex = chainId as ChainIdHex;\n\n // Only fetch staked balance on supported networks (mainnet and hoodi)\n if (\n ![\n SupportedStakedBalanceNetworks.mainnet,\n SupportedStakedBalanceNetworks.hoodi,\n ].includes(chainIdHex as SupportedStakedBalanceNetworks)\n ) {\n continue;\n }\n\n // Only fetch staked balance if contract address exists\n if (!(chainIdHex in STAKING_CONTRACT_ADDRESS_BY_CHAINID)) {\n continue;\n }\n\n const contractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n chainIdHex as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n const provider = this.#getProvider(chainIdHex);\n\n const abi = [\n {\n inputs: [\n { internalType: 'address', name: 'account', type: 'address' },\n ],\n name: 'getShares',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { internalType: 'uint256', name: 'shares', type: 'uint256' },\n ],\n name: 'convertToAssets',\n outputs: [\n { internalType: 'uint256', name: 'assets', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n ];\n\n try {\n const contract = new Contract(contractAddress, abi, provider);\n\n // Get shares for each address\n for (const address of addresses) {\n try {\n const shares = await safelyExecute(() =>\n contract.getShares(address),\n );\n\n if (shares && (shares as BigNumber).gt(0)) {\n // Convert shares to assets (actual staked ETH amount)\n const assets = await safelyExecute(() =>\n contract.convertToAssets(shares),\n );\n\n if (assets) {\n results.push({\n success: true,\n value: new BN((assets as BigNumber).toString()),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } else {\n // Return zero balance for accounts with no staked assets\n results.push({\n success: true,\n value: new BN('0'),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } catch (error) {\n // Log error and continue with next address\n console.error(\n `Error fetching staked balance for ${address}:`,\n error,\n );\n results.push({\n success: false,\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n }\n } catch (error) {\n console.error(\n `Error setting up staking contract for chain ${chainId}:`,\n error,\n );\n }\n }\n\n return results;\n }\n\n async #fetchBalances(addrs: CaipAccountAddress[]) {\n // If we have fewer than or equal to the batch size, make a single request\n if (addrs.length <= ACCOUNTS_API_BATCH_SIZE) {\n const { balances } = await fetchMultiChainBalancesV4(\n { accountAddresses: addrs },\n this.#platform,\n );\n return balances;\n }\n\n // Otherwise, batch the requests to respect the 50-element limit\n type BalanceData = Awaited<\n ReturnType<typeof fetchMultiChainBalancesV4>\n >['balances'][number];\n\n const allBalances = await reduceInBatchesSerially<\n CaipAccountAddress,\n BalanceData[]\n >({\n values: addrs,\n batchSize: ACCOUNTS_API_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const { balances } = await fetchMultiChainBalancesV4(\n { accountAddresses: batch },\n this.#platform,\n );\n return [...(workingResult || []), ...balances];\n },\n initialResult: [],\n });\n\n return allBalances;\n }\n\n async fetch({\n chainIds,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]> {\n const caipAddrs: CaipAccountAddress[] = [];\n\n for (const chainId of chainIds.filter((c) => this.supports(c))) {\n if (queryAllAccounts) {\n allAccounts.forEach((a) =>\n caipAddrs.push(toCaipAccount(chainId, a.address as ChecksumAddress)),\n );\n } else {\n caipAddrs.push(toCaipAccount(chainId, selectedAccount));\n }\n }\n\n if (!caipAddrs.length) {\n return [];\n }\n\n // Don't use safelyExecute here - let real errors propagate\n let balances;\n let apiError = false;\n\n try {\n balances = await this.#fetchBalances(caipAddrs);\n } catch (error) {\n // Mark that we had an API error so we don't add fake zero balances\n apiError = true;\n console.error('Failed to fetch balances from API:', error);\n balances = undefined;\n }\n\n const stakedBalances = await this.#fetchStakedBalances(caipAddrs);\n\n const results: ProcessedBalance[] = [];\n\n // Collect all unique addresses and chains from the CAIP addresses\n const addressChainMap = new Map<string, Set<ChainIdHex>>();\n caipAddrs.forEach((caipAddr) => {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressChainMap.has(checksumAddress)) {\n addressChainMap.set(checksumAddress, new Set());\n }\n addressChainMap.get(checksumAddress)?.add(chainId);\n });\n\n // Ensure native token entries exist for all addresses on all requested chains\n const ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n const nativeBalancesFromAPI = new Map<string, BN>(); // key: `${address}-${chainId}`\n\n // Process regular API balances\n if (balances) {\n const apiBalances = balances.flatMap((b) => {\n const addressPart = b.accountAddress?.split(':')[2];\n if (!addressPart) {\n return [];\n }\n const account = checksum(addressPart);\n const token = checksum(b.address);\n // Use original address for zero address tokens, checksummed for others\n // TODO: this is a hack to get the correct account address type but needs to be fixed\n // by mgrating tokenBalancesController to checksum addresses\n const finalAccount: ChecksumAddress | string =\n token === ZERO_ADDRESS ? account : addressPart;\n const chainId = toHex(b.chainId) as ChainIdHex;\n\n let value: BN | undefined;\n try {\n // Convert string balance to BN avoiding floating point precision issues\n const { balance: balanceStr, decimals } = b;\n\n // Split the balance string into integer and decimal parts\n const [integerPart = '0', decimalPart = ''] = balanceStr.split('.');\n\n // Pad or truncate decimal part to match token decimals\n const paddedDecimalPart = decimalPart\n .padEnd(decimals, '0')\n .slice(0, decimals);\n\n // Combine and create BN\n const fullIntegerStr = integerPart + paddedDecimalPart;\n value = new BN(fullIntegerStr);\n } catch {\n value = undefined;\n }\n\n // Track native balances for later\n if (token === ZERO_ADDRESS && value !== undefined) {\n nativeBalancesFromAPI.set(`${finalAccount}-${chainId}`, value);\n }\n\n return [\n {\n success: value !== undefined,\n value,\n account: finalAccount,\n token,\n chainId,\n },\n ];\n });\n results.push(...apiBalances);\n }\n\n // Only add zero native balance entries if API succeeded but didn't return balances\n // Don't add fake zero balances if the API failed entirely\n if (!apiError) {\n addressChainMap.forEach((chains, address) => {\n chains.forEach((chainId) => {\n const key = `${address}-${chainId}`;\n const existingBalance = nativeBalancesFromAPI.get(key);\n\n if (!existingBalance) {\n // Add zero native balance entry if API succeeded but didn't return one\n results.push({\n success: true,\n value: new BN('0'),\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n }\n });\n });\n } else {\n // If API failed, add error entries for all requested addresses/chains\n addressChainMap.forEach((chains, address) => {\n chains.forEach((chainId) => {\n results.push({\n success: false,\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n });\n });\n }\n\n // Add staked balances\n results.push(...stakedBalances);\n\n // If we had an API error and no successful results, throw the error\n if (apiError && results.every((r) => !r.success)) {\n throw new Error('Failed to fetch any balance data due to API error');\n }\n\n return results;\n }\n}\n"]}
1
+ {"version":3,"file":"api-balance-fetcher.mjs","sourceRoot":"","sources":["../../src/multi-chain-accounts-service/api-balance-fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport type { Web3Provider } from '@ethersproject/providers';\nimport {\n safelyExecute,\n safelyExecuteWithTimeout,\n toHex,\n toChecksumHexAddress,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { CaipAccountAddress, Hex } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport { fetchMultiChainBalancesV4 } from './multi-chain-accounts';\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from '../AssetsContractController';\nimport {\n accountAddressToCaipReference,\n reduceInBatchesSerially,\n SupportedStakedBalanceNetworks,\n} from '../assetsUtil';\nimport { SUPPORTED_NETWORKS_ACCOUNTS_API_V4 } from '../constants';\n\n// Maximum number of account addresses that can be sent to the accounts API in a single request\nconst ACCOUNTS_API_BATCH_SIZE = 50;\n\n// Timeout for accounts API requests (30 seconds)\nconst ACCOUNTS_API_TIMEOUT_MS = 30_000;\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nexport type ProcessedBalance = {\n success: boolean;\n value?: BN;\n account: ChecksumAddress | string;\n token: ChecksumAddress;\n chainId: ChainIdHex;\n};\n\nexport type BalanceFetchResult = {\n balances: ProcessedBalance[];\n unprocessedChainIds?: ChainIdHex[];\n};\n\nexport type BalanceFetcher = {\n supports(chainId: ChainIdHex): boolean;\n fetch(input: {\n chainIds: ChainIdHex[];\n queryAllAccounts: boolean;\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n }): Promise<BalanceFetchResult>;\n};\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\nconst toCaipAccount = (\n chainId: ChainIdHex,\n account: ChecksumAddress,\n): CaipAccountAddress => accountAddressToCaipReference(chainId, account);\n\nexport type GetProviderFunction = (chainId: ChainIdHex) => Web3Provider;\n\nexport class AccountsApiBalanceFetcher implements BalanceFetcher {\n readonly #platform: 'extension' | 'mobile' = 'extension';\n\n readonly #getProvider?: GetProviderFunction;\n\n constructor(\n platform: 'extension' | 'mobile' = 'extension',\n getProvider?: GetProviderFunction,\n ) {\n this.#platform = platform;\n this.#getProvider = getProvider;\n }\n\n supports(chainId: ChainIdHex): boolean {\n return SUPPORTED_NETWORKS_ACCOUNTS_API_V4.includes(chainId);\n }\n\n async #fetchStakedBalances(\n addrs: CaipAccountAddress[],\n ): Promise<ProcessedBalance[]> {\n // Return empty array if no provider is available for blockchain calls\n if (!this.#getProvider) {\n return [];\n }\n\n const results: ProcessedBalance[] = [];\n\n // Group addresses by chain ID\n const addressesByChain: Record<ChainIdHex, ChecksumAddress[]> = {};\n\n for (const caipAddr of addrs) {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressesByChain[chainId]) {\n addressesByChain[chainId] = [];\n }\n addressesByChain[chainId].push(checksumAddress);\n }\n\n // Process each supported chain\n for (const [chainId, addresses] of Object.entries(addressesByChain)) {\n const chainIdHex = chainId as ChainIdHex;\n\n // Only fetch staked balance on supported networks (mainnet and hoodi)\n if (\n ![\n SupportedStakedBalanceNetworks.mainnet,\n SupportedStakedBalanceNetworks.hoodi,\n ].includes(chainIdHex as SupportedStakedBalanceNetworks)\n ) {\n continue;\n }\n\n // Only fetch staked balance if contract address exists\n if (!(chainIdHex in STAKING_CONTRACT_ADDRESS_BY_CHAINID)) {\n continue;\n }\n\n const contractAddress =\n STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n chainIdHex as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n const provider = this.#getProvider(chainIdHex);\n\n const abi = [\n {\n inputs: [\n { internalType: 'address', name: 'account', type: 'address' },\n ],\n name: 'getShares',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [\n { internalType: 'uint256', name: 'shares', type: 'uint256' },\n ],\n name: 'convertToAssets',\n outputs: [\n { internalType: 'uint256', name: 'assets', type: 'uint256' },\n ],\n stateMutability: 'view',\n type: 'function',\n },\n ];\n\n try {\n const contract = new Contract(contractAddress, abi, provider);\n\n // Get shares for each address\n for (const address of addresses) {\n try {\n const shares = await safelyExecute(() =>\n contract.getShares(address),\n );\n\n if (shares && (shares as BigNumber).gt(0)) {\n // Convert shares to assets (actual staked ETH amount)\n const assets = await safelyExecute(() =>\n contract.convertToAssets(shares),\n );\n\n if (assets) {\n results.push({\n success: true,\n value: new BN((assets as BigNumber).toString()),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } else {\n // Return zero balance for accounts with no staked assets\n results.push({\n success: true,\n value: new BN('0'),\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n } catch (error) {\n // Log error and continue with next address\n console.error(\n `Error fetching staked balance for ${address}:`,\n error,\n );\n results.push({\n success: false,\n account: address,\n token: checksum(contractAddress) as ChecksumAddress,\n chainId: chainIdHex,\n });\n }\n }\n } catch (error) {\n console.error(\n `Error setting up staking contract for chain ${chainId}:`,\n error,\n );\n }\n }\n\n return results;\n }\n\n async #fetchBalances(addrs: CaipAccountAddress[]) {\n // If we have fewer than or equal to the batch size, make a single request\n if (addrs.length <= ACCOUNTS_API_BATCH_SIZE) {\n return await fetchMultiChainBalancesV4(\n { accountAddresses: addrs },\n this.#platform,\n );\n }\n\n // Otherwise, batch the requests to respect the 50-element limit\n type BalanceData = Awaited<\n ReturnType<typeof fetchMultiChainBalancesV4>\n >['balances'][number];\n\n type ResponseData = Awaited<ReturnType<typeof fetchMultiChainBalancesV4>>;\n\n const allUnprocessedNetworks = new Set<number>();\n const allBalances = await reduceInBatchesSerially<\n CaipAccountAddress,\n BalanceData[]\n >({\n values: addrs,\n batchSize: ACCOUNTS_API_BATCH_SIZE,\n eachBatch: async (workingResult, batch) => {\n const response = await fetchMultiChainBalancesV4(\n { accountAddresses: batch },\n this.#platform,\n );\n // Collect unprocessed networks from each batch\n if (response.unprocessedNetworks) {\n response.unprocessedNetworks.forEach((network) =>\n allUnprocessedNetworks.add(network),\n );\n }\n return [...(workingResult || []), ...response.balances];\n },\n initialResult: [],\n });\n\n return {\n balances: allBalances,\n unprocessedNetworks: Array.from(allUnprocessedNetworks),\n } as ResponseData;\n }\n\n async fetch({\n chainIds,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult> {\n const caipAddrs: CaipAccountAddress[] = [];\n\n for (const chainId of chainIds.filter((c) => this.supports(c))) {\n if (queryAllAccounts) {\n allAccounts.forEach((a) =>\n caipAddrs.push(toCaipAccount(chainId, a.address as ChecksumAddress)),\n );\n } else {\n caipAddrs.push(toCaipAccount(chainId, selectedAccount));\n }\n }\n\n if (!caipAddrs.length) {\n return { balances: [] };\n }\n\n // Let errors propagate to TokenBalancesController for RPC fallback\n // Use timeout to prevent hanging API calls (30 seconds)\n const apiResponse = await safelyExecuteWithTimeout(\n () => this.#fetchBalances(caipAddrs),\n false, // don't log error here, let it propagate\n ACCOUNTS_API_TIMEOUT_MS,\n );\n\n // If API call timed out or failed, throw error to trigger RPC fallback\n if (!apiResponse) {\n throw new Error('Accounts API request timed out or failed');\n }\n\n // Extract unprocessed networks and convert to hex chain IDs\n const unprocessedChainIds: ChainIdHex[] | undefined =\n apiResponse.unprocessedNetworks\n ? apiResponse.unprocessedNetworks.map(\n (chainId) => toHex(chainId) as ChainIdHex,\n )\n : undefined;\n\n const stakedBalances = await this.#fetchStakedBalances(caipAddrs);\n\n const results: ProcessedBalance[] = [];\n\n // Collect all unique addresses and chains from the CAIP addresses\n const addressChainMap = new Map<string, Set<ChainIdHex>>();\n caipAddrs.forEach((caipAddr) => {\n const [, chainRef, address] = caipAddr.split(':');\n const chainId = toHex(parseInt(chainRef, 10)) as ChainIdHex;\n const checksumAddress = checksum(address);\n\n if (!addressChainMap.has(checksumAddress)) {\n addressChainMap.set(checksumAddress, new Set());\n }\n addressChainMap.get(checksumAddress)?.add(chainId);\n });\n\n // Ensure native token entries exist for all addresses on all requested chains\n const ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n const nativeBalancesFromAPI = new Map<string, BN>(); // key: `${address}-${chainId}`\n\n // Process regular API balances\n if (apiResponse.balances) {\n const apiBalances = apiResponse.balances.flatMap((b) => {\n const addressPart = b.accountAddress?.split(':')[2];\n if (!addressPart) {\n return [];\n }\n const account = checksum(addressPart);\n const token = checksum(b.address);\n // Use original address for zero address tokens, checksummed for others\n // TODO: this is a hack to get the correct account address type but needs to be fixed\n // by mgrating tokenBalancesController to checksum addresses\n const finalAccount: ChecksumAddress | string =\n token === ZERO_ADDRESS ? account : addressPart;\n const chainId = toHex(b.chainId) as ChainIdHex;\n\n let value: BN | undefined;\n try {\n // Convert string balance to BN avoiding floating point precision issues\n const { balance: balanceStr, decimals } = b;\n\n // Split the balance string into integer and decimal parts\n const [integerPart = '0', decimalPart = ''] = balanceStr.split('.');\n\n // Pad or truncate decimal part to match token decimals\n const paddedDecimalPart = decimalPart\n .padEnd(decimals, '0')\n .slice(0, decimals);\n\n // Combine and create BN\n const fullIntegerStr = integerPart + paddedDecimalPart;\n value = new BN(fullIntegerStr);\n } catch {\n value = undefined;\n }\n\n // Track native balances for later\n if (token === ZERO_ADDRESS && value !== undefined) {\n nativeBalancesFromAPI.set(`${finalAccount}-${chainId}`, value);\n }\n\n return [\n {\n success: value !== undefined,\n value,\n account: finalAccount,\n token,\n chainId,\n },\n ];\n });\n results.push(...apiBalances);\n }\n\n // Add zero native balance entries for addresses that API didn't return\n addressChainMap.forEach((chains, address) => {\n chains.forEach((chainId) => {\n const key = `${address}-${chainId}`;\n const existingBalance = nativeBalancesFromAPI.get(key);\n\n if (!existingBalance) {\n // Add zero native balance entry if API succeeded but didn't return one\n results.push({\n success: true,\n value: new BN('0'),\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n }\n });\n });\n\n // Add staked balances\n results.push(...stakedBalances);\n\n return {\n balances: results,\n unprocessedChainIds,\n };\n }\n}\n"]}
@@ -123,7 +123,7 @@ class RpcBalanceFetcher {
123
123
  console.warn('Chain processing failed:', chainResult.reason);
124
124
  }
125
125
  });
126
- return results;
126
+ return { balances: results };
127
127
  }
128
128
  }
129
129
  exports.RpcBalanceFetcher = RpcBalanceFetcher;
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-balance-fetcher.cjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-balance-fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Web3Provider } from '@ethersproject/providers';\nimport {\n toChecksumHexAddress,\n safelyExecuteWithTimeout,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { NetworkClient } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from '../AssetsContractController';\nimport { getTokenBalancesForMultipleAddresses } from '../multicall';\nimport type { TokensControllerState } from '../TokensController';\n\nconst RPC_TIMEOUT_MS = 30000;\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nexport type ProcessedBalance = {\n success: boolean;\n value?: BN;\n account: ChecksumAddress;\n token: ChecksumAddress;\n chainId: ChainIdHex;\n};\n\nexport type BalanceFetcher = {\n supports(chainId: ChainIdHex): boolean;\n fetch(input: {\n chainIds: ChainIdHex[];\n queryAllAccounts: boolean;\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n }): Promise<ProcessedBalance[]>;\n};\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\nexport class RpcBalanceFetcher implements BalanceFetcher {\n readonly #getProvider: (chainId: ChainIdHex) => Web3Provider;\n\n readonly #getNetworkClient: (chainId: ChainIdHex) => NetworkClient;\n\n readonly #getTokensState: () => {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n };\n\n constructor(\n getProvider: (chainId: ChainIdHex) => Web3Provider,\n getNetworkClient: (chainId: ChainIdHex) => NetworkClient,\n getTokensState: () => {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n },\n ) {\n this.#getProvider = getProvider;\n this.#getNetworkClient = getNetworkClient;\n this.#getTokensState = getTokensState;\n }\n\n supports(): boolean {\n return true; // fallback – supports every chain\n }\n\n #getStakingContractAddress(chainId: ChainIdHex): string | undefined {\n return STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n chainId as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n }\n\n async fetch({\n chainIds,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]> {\n // Process all chains in parallel for better performance\n const chainProcessingPromises = chainIds.map(async (chainId) => {\n const tokensState = this.#getTokensState();\n const accountTokenGroups = buildAccountTokenGroupsStatic(\n chainId,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n tokensState.allTokens,\n tokensState.allDetectedTokens,\n );\n if (!accountTokenGroups.length) {\n return [];\n }\n\n const provider = this.#getProvider(chainId);\n await this.#ensureFreshBlockData(chainId);\n\n const balanceResult = await safelyExecuteWithTimeout(\n async () => {\n return await getTokenBalancesForMultipleAddresses(\n accountTokenGroups,\n chainId,\n provider,\n true, // include native\n true, // include staked\n );\n },\n true,\n RPC_TIMEOUT_MS,\n );\n\n // If timeout or error occurred, return empty array for this chain\n if (!balanceResult) {\n return [];\n }\n\n const { tokenBalances, stakedBalances } = balanceResult;\n const chainResults: ProcessedBalance[] = [];\n\n // Add native token entries for all addresses being processed\n const allAddressesForNative = new Set<string>();\n accountTokenGroups.forEach((group) => {\n allAddressesForNative.add(group.accountAddress);\n });\n\n // Ensure native token entries exist for all addresses\n allAddressesForNative.forEach((address) => {\n const nativeBalance = tokenBalances[ZERO_ADDRESS]?.[address] || null;\n chainResults.push({\n success: true,\n value: nativeBalance ? (nativeBalance as BN) : new BN('0'),\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n });\n\n // Add other token balances\n Object.entries(tokenBalances).forEach(([tokenAddr, balances]) => {\n // Skip native token since we handled it explicitly above\n if (tokenAddr === ZERO_ADDRESS) {\n return;\n }\n Object.entries(balances).forEach(([acct, bn]) => {\n chainResults.push({\n success: bn !== null,\n value: bn as BN,\n account: acct as ChecksumAddress,\n token: checksum(tokenAddr),\n chainId,\n });\n });\n });\n\n // Add staked balances for all addresses being processed\n const stakingContractAddress = this.#getStakingContractAddress(chainId);\n if (stakingContractAddress) {\n // Get all unique addresses being processed for this chain\n const allAddresses = new Set<string>();\n accountTokenGroups.forEach((group) => {\n allAddresses.add(group.accountAddress);\n });\n\n // Add staked balance entry for each address\n const checksummedStakingAddress = checksum(stakingContractAddress);\n allAddresses.forEach((address) => {\n const stakedBalance = stakedBalances?.[address] || null;\n chainResults.push({\n success: true,\n value: stakedBalance ? (stakedBalance as BN) : new BN('0'),\n account: address as ChecksumAddress,\n token: checksummedStakingAddress,\n chainId,\n });\n });\n }\n\n return chainResults;\n });\n\n // Wait for all chains to complete (or fail) and collect results\n const chainResultsArray = await Promise.allSettled(chainProcessingPromises);\n const results: ProcessedBalance[] = [];\n\n chainResultsArray.forEach((chainResult) => {\n if (chainResult.status === 'fulfilled') {\n results.push(...chainResult.value);\n } else {\n // Log error but continue with other chains\n console.warn('Chain processing failed:', chainResult.reason);\n }\n });\n\n return results;\n }\n\n /**\n * Ensures that the block tracker has the latest block data before performing multicall operations.\n * This is a temporary fix to ensure that the block number is up to date.\n *\n * @param chainId - The chain id to update block data for.\n */\n async #ensureFreshBlockData(chainId: Hex): Promise<void> {\n // Force fresh block data before multicall\n // TODO: This is a temporary fix to ensure that the block number is up to date.\n // We should remove this once we have a better solution for this on the block tracker controller.\n const networkClient = this.#getNetworkClient(chainId);\n await networkClient.blockTracker?.checkForLatestBlock?.();\n }\n}\n\n/**\n * Merges imported & detected tokens for the requested chain and returns a list\n * of `{ accountAddress, tokenAddresses[] }` suitable for getTokenBalancesForMultipleAddresses.\n *\n * @param chainId - The chain ID to build account token groups for\n * @param queryAllAccounts - Whether to query all accounts or just the selected one\n * @param selectedAccount - The currently selected account\n * @param allAccounts - All available accounts\n * @param allTokens - All tokens from TokensController\n * @param allDetectedTokens - All detected tokens from TokensController\n * @returns Array of account/token groups for multicall\n */\nfunction buildAccountTokenGroupsStatic(\n chainId: ChainIdHex,\n queryAllAccounts: boolean,\n selectedAccount: ChecksumAddress,\n allAccounts: InternalAccount[],\n allTokens: TokensControllerState['allTokens'],\n allDetectedTokens: TokensControllerState['allDetectedTokens'],\n): { accountAddress: ChecksumAddress; tokenAddresses: ChecksumAddress[] }[] {\n const pairs: {\n accountAddress: ChecksumAddress;\n tokenAddress: ChecksumAddress;\n }[] = [];\n\n const add = ([account, tokens]: [string, unknown[]]) => {\n const shouldInclude =\n queryAllAccounts || checksum(account) === checksum(selectedAccount);\n if (!shouldInclude) {\n return;\n }\n (tokens as unknown[]).forEach((t: unknown) =>\n pairs.push({\n accountAddress: account as ChecksumAddress,\n tokenAddress: checksum((t as { address: string }).address),\n }),\n );\n };\n\n Object.entries(allTokens[chainId] ?? {}).forEach(\n add as (entry: [string, unknown]) => void,\n );\n Object.entries(allDetectedTokens[chainId] ?? {}).forEach(\n add as (entry: [string, unknown]) => void,\n );\n\n // Always include native token for relevant accounts\n if (queryAllAccounts) {\n allAccounts.forEach((a) => {\n pairs.push({\n accountAddress: a.address as ChecksumAddress,\n tokenAddress: ZERO_ADDRESS,\n });\n });\n } else {\n pairs.push({\n accountAddress: selectedAccount,\n tokenAddress: ZERO_ADDRESS,\n });\n }\n\n if (!pairs.length) {\n return [];\n }\n\n // group by account\n const map = new Map<ChecksumAddress, ChecksumAddress[]>();\n pairs.forEach(({ accountAddress, tokenAddress }) => {\n if (!map.has(accountAddress)) {\n map.set(accountAddress, []);\n }\n const tokens = map.get(accountAddress);\n if (tokens) {\n tokens.push(tokenAddress);\n }\n });\n\n return Array.from(map.entries()).map(([accountAddress, tokenAddresses]) => ({\n accountAddress,\n tokenAddresses,\n }));\n}\n"]}
1
+ {"version":3,"file":"rpc-balance-fetcher.cjs","sourceRoot":"","sources":["../../src/rpc-service/rpc-balance-fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Web3Provider } from '@ethersproject/providers';\nimport {\n toChecksumHexAddress,\n safelyExecuteWithTimeout,\n} from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { NetworkClient } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport BN from 'bn.js';\n\nimport { STAKING_CONTRACT_ADDRESS_BY_CHAINID } from '../AssetsContractController';\nimport { getTokenBalancesForMultipleAddresses } from '../multicall';\nimport type { TokensControllerState } from '../TokensController';\n\nconst RPC_TIMEOUT_MS = 30000;\n\nexport type ChainIdHex = Hex;\nexport type ChecksumAddress = Hex;\n\nexport type ProcessedBalance = {\n success: boolean;\n value?: BN;\n account: ChecksumAddress;\n token: ChecksumAddress;\n chainId: ChainIdHex;\n};\n\nexport type BalanceFetchResult = {\n balances: ProcessedBalance[];\n unprocessedChainIds?: ChainIdHex[];\n};\n\nexport type BalanceFetcher = {\n supports(chainId: ChainIdHex): boolean;\n fetch(input: {\n chainIds: ChainIdHex[];\n queryAllAccounts: boolean;\n selectedAccount: ChecksumAddress;\n allAccounts: InternalAccount[];\n }): Promise<BalanceFetchResult>;\n};\n\nconst ZERO_ADDRESS =\n '0x0000000000000000000000000000000000000000' as ChecksumAddress;\n\nconst checksum = (addr: string): ChecksumAddress =>\n toChecksumHexAddress(addr) as ChecksumAddress;\n\nexport class RpcBalanceFetcher implements BalanceFetcher {\n readonly #getProvider: (chainId: ChainIdHex) => Web3Provider;\n\n readonly #getNetworkClient: (chainId: ChainIdHex) => NetworkClient;\n\n readonly #getTokensState: () => {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n };\n\n constructor(\n getProvider: (chainId: ChainIdHex) => Web3Provider,\n getNetworkClient: (chainId: ChainIdHex) => NetworkClient,\n getTokensState: () => {\n allTokens: TokensControllerState['allTokens'];\n allDetectedTokens: TokensControllerState['allDetectedTokens'];\n },\n ) {\n this.#getProvider = getProvider;\n this.#getNetworkClient = getNetworkClient;\n this.#getTokensState = getTokensState;\n }\n\n supports(): boolean {\n return true; // fallback – supports every chain\n }\n\n #getStakingContractAddress(chainId: ChainIdHex): string | undefined {\n return STAKING_CONTRACT_ADDRESS_BY_CHAINID[\n chainId as keyof typeof STAKING_CONTRACT_ADDRESS_BY_CHAINID\n ];\n }\n\n async fetch({\n chainIds,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult> {\n // Process all chains in parallel for better performance\n const chainProcessingPromises = chainIds.map(async (chainId) => {\n const tokensState = this.#getTokensState();\n const accountTokenGroups = buildAccountTokenGroupsStatic(\n chainId,\n queryAllAccounts,\n selectedAccount,\n allAccounts,\n tokensState.allTokens,\n tokensState.allDetectedTokens,\n );\n if (!accountTokenGroups.length) {\n return [];\n }\n\n const provider = this.#getProvider(chainId);\n await this.#ensureFreshBlockData(chainId);\n\n const balanceResult = await safelyExecuteWithTimeout(\n async () => {\n return await getTokenBalancesForMultipleAddresses(\n accountTokenGroups,\n chainId,\n provider,\n true, // include native\n true, // include staked\n );\n },\n true,\n RPC_TIMEOUT_MS,\n );\n\n // If timeout or error occurred, return empty array for this chain\n if (!balanceResult) {\n return [];\n }\n\n const { tokenBalances, stakedBalances } = balanceResult;\n const chainResults: ProcessedBalance[] = [];\n\n // Add native token entries for all addresses being processed\n const allAddressesForNative = new Set<string>();\n accountTokenGroups.forEach((group) => {\n allAddressesForNative.add(group.accountAddress);\n });\n\n // Ensure native token entries exist for all addresses\n allAddressesForNative.forEach((address) => {\n const nativeBalance = tokenBalances[ZERO_ADDRESS]?.[address] || null;\n chainResults.push({\n success: true,\n value: nativeBalance ? (nativeBalance as BN) : new BN('0'),\n account: address as ChecksumAddress,\n token: ZERO_ADDRESS,\n chainId,\n });\n });\n\n // Add other token balances\n Object.entries(tokenBalances).forEach(([tokenAddr, balances]) => {\n // Skip native token since we handled it explicitly above\n if (tokenAddr === ZERO_ADDRESS) {\n return;\n }\n Object.entries(balances).forEach(([acct, bn]) => {\n chainResults.push({\n success: bn !== null,\n value: bn as BN,\n account: acct as ChecksumAddress,\n token: checksum(tokenAddr),\n chainId,\n });\n });\n });\n\n // Add staked balances for all addresses being processed\n const stakingContractAddress = this.#getStakingContractAddress(chainId);\n if (stakingContractAddress) {\n // Get all unique addresses being processed for this chain\n const allAddresses = new Set<string>();\n accountTokenGroups.forEach((group) => {\n allAddresses.add(group.accountAddress);\n });\n\n // Add staked balance entry for each address\n const checksummedStakingAddress = checksum(stakingContractAddress);\n allAddresses.forEach((address) => {\n const stakedBalance = stakedBalances?.[address] || null;\n chainResults.push({\n success: true,\n value: stakedBalance ? (stakedBalance as BN) : new BN('0'),\n account: address as ChecksumAddress,\n token: checksummedStakingAddress,\n chainId,\n });\n });\n }\n\n return chainResults;\n });\n\n // Wait for all chains to complete (or fail) and collect results\n const chainResultsArray = await Promise.allSettled(chainProcessingPromises);\n const results: ProcessedBalance[] = [];\n\n chainResultsArray.forEach((chainResult) => {\n if (chainResult.status === 'fulfilled') {\n results.push(...chainResult.value);\n } else {\n // Log error but continue with other chains\n console.warn('Chain processing failed:', chainResult.reason);\n }\n });\n\n return { balances: results };\n }\n\n /**\n * Ensures that the block tracker has the latest block data before performing multicall operations.\n * This is a temporary fix to ensure that the block number is up to date.\n *\n * @param chainId - The chain id to update block data for.\n */\n async #ensureFreshBlockData(chainId: Hex): Promise<void> {\n // Force fresh block data before multicall\n // TODO: This is a temporary fix to ensure that the block number is up to date.\n // We should remove this once we have a better solution for this on the block tracker controller.\n const networkClient = this.#getNetworkClient(chainId);\n await networkClient.blockTracker?.checkForLatestBlock?.();\n }\n}\n\n/**\n * Merges imported & detected tokens for the requested chain and returns a list\n * of `{ accountAddress, tokenAddresses[] }` suitable for getTokenBalancesForMultipleAddresses.\n *\n * @param chainId - The chain ID to build account token groups for\n * @param queryAllAccounts - Whether to query all accounts or just the selected one\n * @param selectedAccount - The currently selected account\n * @param allAccounts - All available accounts\n * @param allTokens - All tokens from TokensController\n * @param allDetectedTokens - All detected tokens from TokensController\n * @returns Array of account/token groups for multicall\n */\nfunction buildAccountTokenGroupsStatic(\n chainId: ChainIdHex,\n queryAllAccounts: boolean,\n selectedAccount: ChecksumAddress,\n allAccounts: InternalAccount[],\n allTokens: TokensControllerState['allTokens'],\n allDetectedTokens: TokensControllerState['allDetectedTokens'],\n): { accountAddress: ChecksumAddress; tokenAddresses: ChecksumAddress[] }[] {\n const pairs: {\n accountAddress: ChecksumAddress;\n tokenAddress: ChecksumAddress;\n }[] = [];\n\n const add = ([account, tokens]: [string, unknown[]]) => {\n const shouldInclude =\n queryAllAccounts || checksum(account) === checksum(selectedAccount);\n if (!shouldInclude) {\n return;\n }\n (tokens as unknown[]).forEach((t: unknown) =>\n pairs.push({\n accountAddress: account as ChecksumAddress,\n tokenAddress: checksum((t as { address: string }).address),\n }),\n );\n };\n\n Object.entries(allTokens[chainId] ?? {}).forEach(\n add as (entry: [string, unknown]) => void,\n );\n Object.entries(allDetectedTokens[chainId] ?? {}).forEach(\n add as (entry: [string, unknown]) => void,\n );\n\n // Always include native token for relevant accounts\n if (queryAllAccounts) {\n allAccounts.forEach((a) => {\n pairs.push({\n accountAddress: a.address as ChecksumAddress,\n tokenAddress: ZERO_ADDRESS,\n });\n });\n } else {\n pairs.push({\n accountAddress: selectedAccount,\n tokenAddress: ZERO_ADDRESS,\n });\n }\n\n if (!pairs.length) {\n return [];\n }\n\n // group by account\n const map = new Map<ChecksumAddress, ChecksumAddress[]>();\n pairs.forEach(({ accountAddress, tokenAddress }) => {\n if (!map.has(accountAddress)) {\n map.set(accountAddress, []);\n }\n const tokens = map.get(accountAddress);\n if (tokens) {\n tokens.push(tokenAddress);\n }\n });\n\n return Array.from(map.entries()).map(([accountAddress, tokenAddresses]) => ({\n accountAddress,\n tokenAddresses,\n }));\n}\n"]}
@@ -13,6 +13,10 @@ export type ProcessedBalance = {
13
13
  token: ChecksumAddress;
14
14
  chainId: ChainIdHex;
15
15
  };
16
+ export type BalanceFetchResult = {
17
+ balances: ProcessedBalance[];
18
+ unprocessedChainIds?: ChainIdHex[];
19
+ };
16
20
  export type BalanceFetcher = {
17
21
  supports(chainId: ChainIdHex): boolean;
18
22
  fetch(input: {
@@ -20,7 +24,7 @@ export type BalanceFetcher = {
20
24
  queryAllAccounts: boolean;
21
25
  selectedAccount: ChecksumAddress;
22
26
  allAccounts: InternalAccount[];
23
- }): Promise<ProcessedBalance[]>;
27
+ }): Promise<BalanceFetchResult>;
24
28
  };
25
29
  export declare class RpcBalanceFetcher implements BalanceFetcher {
26
30
  #private;
@@ -29,6 +33,6 @@ export declare class RpcBalanceFetcher implements BalanceFetcher {
29
33
  allDetectedTokens: TokensControllerState['allDetectedTokens'];
30
34
  });
31
35
  supports(): boolean;
32
- fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]>;
36
+ fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult>;
33
37
  }
34
38
  //# sourceMappingURL=rpc-balance-fetcher.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-balance-fetcher.d.cts","sourceRoot":"","sources":["../../src/rpc-service/rpc-balance-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAK7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,qCAAqC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,cAAc;AAIvB,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AAIjE,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACjC,CAAC;AAQF,qBAAa,iBAAkB,YAAW,cAAc;;gBAWpD,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,EAClD,gBAAgB,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,aAAa,EACxD,cAAc,EAAE,MAAM;QACpB,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAC9C,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;KAC/D;IAOH,QAAQ,IAAI,OAAO;IAUb,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAmIxE"}
1
+ {"version":3,"file":"rpc-balance-fetcher.d.cts","sourceRoot":"","sources":["../../src/rpc-service/rpc-balance-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAK7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,qCAAqC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,cAAc;AAIvB,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AAIjE,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mBAAmB,CAAC,EAAE,UAAU,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjC,CAAC;AAQF,qBAAa,iBAAkB,YAAW,cAAc;;gBAWpD,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,EAClD,gBAAgB,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,aAAa,EACxD,cAAc,EAAE,MAAM;QACpB,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAC9C,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;KAC/D;IAOH,QAAQ,IAAI,OAAO;IAUb,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAmIxE"}
@@ -13,6 +13,10 @@ export type ProcessedBalance = {
13
13
  token: ChecksumAddress;
14
14
  chainId: ChainIdHex;
15
15
  };
16
+ export type BalanceFetchResult = {
17
+ balances: ProcessedBalance[];
18
+ unprocessedChainIds?: ChainIdHex[];
19
+ };
16
20
  export type BalanceFetcher = {
17
21
  supports(chainId: ChainIdHex): boolean;
18
22
  fetch(input: {
@@ -20,7 +24,7 @@ export type BalanceFetcher = {
20
24
  queryAllAccounts: boolean;
21
25
  selectedAccount: ChecksumAddress;
22
26
  allAccounts: InternalAccount[];
23
- }): Promise<ProcessedBalance[]>;
27
+ }): Promise<BalanceFetchResult>;
24
28
  };
25
29
  export declare class RpcBalanceFetcher implements BalanceFetcher {
26
30
  #private;
@@ -29,6 +33,6 @@ export declare class RpcBalanceFetcher implements BalanceFetcher {
29
33
  allDetectedTokens: TokensControllerState['allDetectedTokens'];
30
34
  });
31
35
  supports(): boolean;
32
- fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<ProcessedBalance[]>;
36
+ fetch({ chainIds, queryAllAccounts, selectedAccount, allAccounts, }: Parameters<BalanceFetcher['fetch']>[0]): Promise<BalanceFetchResult>;
33
37
  }
34
38
  //# sourceMappingURL=rpc-balance-fetcher.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-balance-fetcher.d.mts","sourceRoot":"","sources":["../../src/rpc-service/rpc-balance-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAK7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,qCAAqC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,cAAc;AAIvB,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AAIjE,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACjC,CAAC;AAQF,qBAAa,iBAAkB,YAAW,cAAc;;gBAWpD,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,EAClD,gBAAgB,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,aAAa,EACxD,cAAc,EAAE,MAAM;QACpB,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAC9C,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;KAC/D;IAOH,QAAQ,IAAI,OAAO;IAUb,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAmIxE"}
1
+ {"version":3,"file":"rpc-balance-fetcher.d.mts","sourceRoot":"","sources":["../../src/rpc-service/rpc-balance-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,iCAAiC;AAK7D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,qCAAqC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,cAAc;AAIvB,OAAO,KAAK,EAAE,qBAAqB,EAAE,gCAA4B;AAIjE,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC;AAC7B,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,EAAE,CAAC;IACX,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mBAAmB,CAAC,EAAE,UAAU,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC;IACvC,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,gBAAgB,EAAE,OAAO,CAAC;QAC1B,eAAe,EAAE,eAAe,CAAC;QACjC,WAAW,EAAE,eAAe,EAAE,CAAC;KAChC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjC,CAAC;AAQF,qBAAa,iBAAkB,YAAW,cAAc;;gBAWpD,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,YAAY,EAClD,gBAAgB,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,aAAa,EACxD,cAAc,EAAE,MAAM;QACpB,SAAS,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;QAC9C,iBAAiB,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;KAC/D;IAOH,QAAQ,IAAI,OAAO;IAUb,KAAK,CAAC,EACV,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,WAAW,GACZ,EAAE,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAmIxE"}