@metamask-previews/assets-controller 1.0.0-preview-ee8f1b28b → 2.0.0-preview-33dbba4f3

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 (120) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/dist/AssetsController.cjs +61 -18
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +13 -8
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +13 -8
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +62 -19
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/AccountsApiDataSource.cjs +9 -11
  11. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  12. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
  13. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
  14. package/dist/data-sources/AccountsApiDataSource.mjs +7 -9
  15. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  16. package/dist/data-sources/BackendWebsocketDataSource.cjs +6 -4
  17. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
  18. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
  19. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
  20. package/dist/data-sources/BackendWebsocketDataSource.mjs +6 -4
  21. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
  22. package/dist/data-sources/PriceDataSource.cjs +13 -3
  23. package/dist/data-sources/PriceDataSource.cjs.map +1 -1
  24. package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
  25. package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
  26. package/dist/data-sources/PriceDataSource.mjs +13 -3
  27. package/dist/data-sources/PriceDataSource.mjs.map +1 -1
  28. package/dist/data-sources/RpcDataSource.cjs +80 -10
  29. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  30. package/dist/data-sources/RpcDataSource.d.cts +8 -59
  31. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  32. package/dist/data-sources/RpcDataSource.d.mts +8 -59
  33. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  34. package/dist/data-sources/RpcDataSource.mjs +81 -11
  35. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  36. package/dist/data-sources/SnapDataSource.cjs +16 -4
  37. package/dist/data-sources/SnapDataSource.cjs.map +1 -1
  38. package/dist/data-sources/SnapDataSource.d.cts +2 -1
  39. package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
  40. package/dist/data-sources/SnapDataSource.d.mts +2 -1
  41. package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
  42. package/dist/data-sources/SnapDataSource.mjs +16 -4
  43. package/dist/data-sources/SnapDataSource.mjs.map +1 -1
  44. package/dist/data-sources/StakedBalanceDataSource.cjs +609 -0
  45. package/dist/data-sources/StakedBalanceDataSource.cjs.map +1 -0
  46. package/dist/data-sources/StakedBalanceDataSource.d.cts +72 -0
  47. package/dist/data-sources/StakedBalanceDataSource.d.cts.map +1 -0
  48. package/dist/data-sources/StakedBalanceDataSource.d.mts +72 -0
  49. package/dist/data-sources/StakedBalanceDataSource.d.mts.map +1 -0
  50. package/dist/data-sources/StakedBalanceDataSource.mjs +605 -0
  51. package/dist/data-sources/StakedBalanceDataSource.mjs.map +1 -0
  52. package/dist/data-sources/TokenDataSource.cjs +5 -0
  53. package/dist/data-sources/TokenDataSource.cjs.map +1 -1
  54. package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
  55. package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
  56. package/dist/data-sources/TokenDataSource.mjs +5 -0
  57. package/dist/data-sources/TokenDataSource.mjs.map +1 -1
  58. package/dist/data-sources/evm-rpc-services/index.cjs +5 -1
  59. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
  60. package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
  61. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
  62. package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
  63. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
  64. package/dist/data-sources/evm-rpc-services/index.mjs +1 -1
  65. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
  66. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs +132 -0
  67. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs.map +1 -0
  68. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts +78 -0
  69. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts.map +1 -0
  70. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts +78 -0
  71. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts.map +1 -0
  72. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs +126 -0
  73. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs.map +1 -0
  74. package/dist/data-sources/evm-rpc-services/services/index.cjs +6 -1
  75. package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -1
  76. package/dist/data-sources/evm-rpc-services/services/index.d.cts +1 -0
  77. package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -1
  78. package/dist/data-sources/evm-rpc-services/services/index.d.mts +1 -0
  79. package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -1
  80. package/dist/data-sources/evm-rpc-services/services/index.mjs +1 -0
  81. package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -1
  82. package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -1
  83. package/dist/data-sources/evm-rpc-services/types/state.d.cts +3 -3
  84. package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -1
  85. package/dist/data-sources/evm-rpc-services/types/state.d.mts +3 -3
  86. package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -1
  87. package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -1
  88. package/dist/data-sources/evm-rpc-services/utils/index.cjs +9 -1
  89. package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -1
  90. package/dist/data-sources/evm-rpc-services/utils/index.d.cts +2 -0
  91. package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -1
  92. package/dist/data-sources/evm-rpc-services/utils/index.d.mts +2 -0
  93. package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -1
  94. package/dist/data-sources/evm-rpc-services/utils/index.mjs +2 -0
  95. package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -1
  96. package/dist/data-sources/evm-rpc-services/utils/parsing.cjs +47 -0
  97. package/dist/data-sources/evm-rpc-services/utils/parsing.cjs.map +1 -0
  98. package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts +25 -0
  99. package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts.map +1 -0
  100. package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts +25 -0
  101. package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts.map +1 -0
  102. package/dist/data-sources/evm-rpc-services/utils/parsing.mjs +39 -0
  103. package/dist/data-sources/evm-rpc-services/utils/parsing.mjs.map +1 -0
  104. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs +68 -0
  105. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs.map +1 -0
  106. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts +25 -0
  107. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts.map +1 -0
  108. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts +25 -0
  109. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts.map +1 -0
  110. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs +62 -0
  111. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs.map +1 -0
  112. package/dist/data-sources/index.cjs +3 -1
  113. package/dist/data-sources/index.cjs.map +1 -1
  114. package/dist/data-sources/index.d.cts +1 -0
  115. package/dist/data-sources/index.d.cts.map +1 -1
  116. package/dist/data-sources/index.d.mts +1 -0
  117. package/dist/data-sources/index.d.mts.map +1 -1
  118. package/dist/data-sources/index.mjs +1 -0
  119. package/dist/data-sources/index.mjs.map +1 -1
  120. package/package.json +3 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StakedBalanceDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/StakedBalanceDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { toChecksumAddress } from '@ethereumjs/util';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { NetworkEnablementControllerState } from '@metamask/network-enablement-controller';\nimport {\n isStrictHexString,\n isCaipChainId,\n numberToHex,\n parseCaipChainId,\n} from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport type {\n DataSourceState,\n SubscriptionRequest,\n} from './AbstractDataSource';\nimport { AbstractDataSource } from './AbstractDataSource';\nimport type {\n StakedBalancePollingInput,\n StakedBalanceFetchResult,\n} from './evm-rpc-services';\nimport {\n StakedBalanceFetcher,\n getStakingContractAddress,\n getSupportedStakingChainIds,\n} from './evm-rpc-services';\nimport type { AssetsControllerMessenger } from '../AssetsController';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport type {\n AccountId,\n ChainId,\n Caip19AssetId,\n AssetBalance,\n AssetMetadata,\n DataRequest,\n DataResponse,\n Middleware,\n} from '../types';\n\nconst CONTROLLER_NAME = 'StakedBalanceDataSource';\nconst DEFAULT_POLL_INTERVAL = 180_000; // 3 minutes\n\n/** Metadata for staked ETH (same symbol and decimals as native ETH). */\nconst STAKED_ETH_METADATA: AssetMetadata = {\n type: 'erc20',\n name: 'staked ethereum',\n symbol: 'ETH',\n decimals: 18,\n};\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n/** Optional configuration for StakedBalanceDataSource. */\nexport type StakedBalanceDataSourceConfig = {\n /** Whether staked balance fetching is enabled (default: true). */\n enabled?: boolean;\n /** Polling interval in ms (default: 180s / 3 min). */\n pollInterval?: number;\n};\n\nexport type StakedBalanceDataSourceOptions = StakedBalanceDataSourceConfig & {\n /** The AssetsController messenger (for accessing NetworkController). */\n messenger: AssetsControllerMessenger;\n /** Called when active chains are updated. */\n onActiveChainsUpdated: (\n dataSourceName: string,\n chains: ChainId[],\n previousChains: ChainId[],\n ) => void;\n};\n\n/** Per-account supported chains (same shape as in DataRequest). */\ntype AccountWithSupportedChains = {\n account: InternalAccount;\n supportedChains: ChainId[];\n};\n\n/**\n * Subscription data stored for each active subscription.\n * Stores accountsWithSupportedChains so refresh paths use the same per-account\n * scope as normal subscription setup (avoids querying unsupported chains/accounts).\n */\ntype SubscriptionData = {\n /** Polling tokens from StakedBalanceFetcher. */\n pollingTokens: string[];\n /** Chain IDs being polled (union of all account chains). */\n chains: ChainId[];\n /** Accounts being polled. */\n accounts: InternalAccount[];\n /** Per-account supported chains; used by refreshStakedBalance and transaction handlers. */\n accountsWithSupportedChains: AccountWithSupportedChains[];\n /** Callback to report asset updates. */\n onAssetsUpdate: (response: DataResponse) => void | Promise<void>;\n};\n\n/**\n * Convert CAIP chain ID or hex chain ID to hex chain ID.\n *\n * @param chainId - CAIP chain ID or hex chain ID.\n * @returns Hex chain ID.\n */\nfunction caipChainIdToHex(chainId: string): Hex {\n if (isStrictHexString(chainId)) {\n return chainId;\n }\n\n if (isCaipChainId(chainId)) {\n const ref = parseCaipChainId(chainId).reference;\n return numberToHex(parseInt(ref, 10));\n }\n\n throw new Error('caipChainIdToHex - Failed to provide CAIP-2 or Hex chainId');\n}\n\n/**\n * Build the CAIP-19 asset ID for staked balance (same format as ERC20).\n * Uses the staking contract address (checksummed) so it is consistent with\n * other token assets.\n * Example: \"eip155:1/erc20:0x4fef9d741011476750a243ac70b9789a63dd47df\"\n *\n * @param chainId - CAIP-2 chain ID (e.g. \"eip155:1\").\n * @param contractAddress - Staking contract address (hex).\n * @returns The staked asset CAIP-19 ID with checksummed address.\n */\nfunction stakedAssetId(\n chainId: ChainId,\n contractAddress: string,\n): Caip19AssetId {\n const checksummed = toChecksumAddress(contractAddress);\n return `${chainId}/erc20:${checksummed}` as Caip19AssetId;\n}\n\n/**\n * Data source for fetching staked ETH balances via on-chain staking contracts.\n *\n * Delegates to {@link StakedBalanceFetcher} for the actual RPC calls\n * (getShares + convertToAssets on ERC-4626-style staking contracts).\n * Reports balances as CAIP-19 asset IDs using the ERC20 format with the\n * staking contract address (e.g. \"eip155:1/erc20:0x4fef9d741011476750a243ac70b9789a63dd47df\").\n *\n * Only supports chains with known staking contracts (mainnet, Hoodi).\n * Polling is managed by StakedBalanceFetcher via startPolling/stopPollingByPollingToken.\n */\nexport class StakedBalanceDataSource extends AbstractDataSource<\n typeof CONTROLLER_NAME,\n DataSourceState\n> {\n readonly #messenger: AssetsControllerMessenger;\n\n readonly #onActiveChainsUpdated: (\n dataSourceName: string,\n chains: ChainId[],\n previousChains: ChainId[],\n ) => void;\n\n readonly #pollInterval: number;\n\n readonly #enabled: boolean;\n\n /** The StakedBalanceFetcher that handles polling and RPC calls. */\n readonly #stakedBalanceFetcher: StakedBalanceFetcher;\n\n /** Active subscriptions by ID. */\n readonly #activeSubscriptions: Map<string, SubscriptionData> = new Map();\n\n /** Cache of Web3Provider instances by hex chain ID. */\n readonly #providerCache: Map<Hex, Web3Provider> = new Map();\n\n /** CAIP-2 chain IDs that have known staking contracts. */\n readonly #supportedChainIds: ChainId[];\n\n constructor(options: StakedBalanceDataSourceOptions) {\n super(CONTROLLER_NAME, { activeChains: [] });\n this.#messenger = options.messenger;\n this.#onActiveChainsUpdated = options.onActiveChainsUpdated;\n this.#pollInterval = options.pollInterval ?? DEFAULT_POLL_INTERVAL;\n this.#enabled = options.enabled !== false;\n this.#supportedChainIds = getSupportedStakingChainIds() as ChainId[];\n\n log('Initializing StakedBalanceDataSource', {\n enabled: this.#enabled,\n pollInterval: this.#pollInterval,\n });\n\n // Create StakedBalanceFetcher with provider getter\n this.#stakedBalanceFetcher = new StakedBalanceFetcher({\n pollingInterval: this.#pollInterval,\n getNetworkProvider: (hexChainId): Web3Provider | undefined =>\n this.#getProvider(hexChainId),\n });\n\n // Wire the callback so polling results flow back to subscriptions\n this.#stakedBalanceFetcher.setOnStakedBalanceUpdate(\n this.#handleStakedBalanceUpdate.bind(this),\n );\n\n const unsubConfirmed = this.#messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n this.#onTransactionConfirmed.bind(this),\n );\n this.#unsubscribeTransactionConfirmed =\n typeof unsubConfirmed === 'function' ? unsubConfirmed : undefined;\n\n const unsubIncoming = this.#messenger.subscribe(\n 'TransactionController:incomingTransactionsReceived',\n this.#onIncomingTransactions.bind(this),\n );\n this.#unsubscribeIncomingTransactions =\n typeof unsubIncoming === 'function' ? unsubIncoming : undefined;\n\n const unsubNetwork = this.#messenger.subscribe(\n 'NetworkController:stateChange',\n this.#onNetworkStateChange.bind(this),\n );\n this.#unsubscribeNetworkStateChange =\n typeof unsubNetwork === 'function' ? unsubNetwork : undefined;\n\n const unsubEnablement = this.#messenger.subscribe(\n 'NetworkEnablementController:stateChange',\n this.#onNetworkEnablementControllerStateChange.bind(this),\n );\n this.#unsubscribeNetworkEnablementControllerStateChange =\n typeof unsubEnablement === 'function' ? unsubEnablement : undefined;\n\n this.#initializeActiveChains();\n }\n\n readonly #unsubscribeTransactionConfirmed: (() => void) | undefined =\n undefined;\n\n readonly #unsubscribeIncomingTransactions: (() => void) | undefined =\n undefined;\n\n readonly #unsubscribeNetworkStateChange: (() => void) | undefined = undefined;\n\n readonly #unsubscribeNetworkEnablementControllerStateChange:\n | (() => void)\n | undefined = undefined;\n\n /**\n * When NetworkController state changes (e.g. RPC endpoints or network clients\n * reconfigured), clear the provider cache so subsequent fetches use fresh\n * providers.\n */\n #onNetworkStateChange(): void {\n this.#providerCache.clear();\n log('Provider cache cleared after network state change');\n }\n\n /**\n * When NetworkEnablementController state changes (user enables/disables\n * networks), recompute active chains so we only fetch for enabled staking chains.\n *\n * @param state - The new NetworkEnablementController state.\n */\n #onNetworkEnablementControllerStateChange(\n state: NetworkEnablementControllerState,\n ): void {\n const { enabledNetworkMap } = state ?? {};\n if (!enabledNetworkMap) {\n return;\n }\n this.#initializeActiveChainsFromEnabledMap(enabledNetworkMap);\n }\n\n /**\n * Returns true if the transaction involves the staking contract (from or to)\n * for the payload's chain, so we only refresh staked balance when relevant.\n *\n * @param payload - Transaction payload.\n * @param payload.chainId - Hex chain ID.\n * @param payload.txParams - Optional transaction params.\n * @param payload.txParams.from - Sender address.\n * @param payload.txParams.to - Recipient address.\n * @returns True if txParams.from or txParams.to matches the staking contract address.\n */\n #isTransactionInvolvingStakingContract(payload: {\n chainId?: string;\n txParams?: { from?: string; to?: string };\n }): boolean {\n const hexChainId = payload?.chainId;\n if (!hexChainId) {\n return false;\n }\n const contractAddress = getStakingContractAddress(hexChainId);\n if (!contractAddress) {\n return false;\n }\n const contractLower = contractAddress.toLowerCase();\n const from = payload.txParams?.from?.toLowerCase();\n const to = payload.txParams?.to?.toLowerCase();\n return from === contractLower || to === contractLower;\n }\n\n /**\n * When a transaction is confirmed, refresh staked balance only if the\n * transaction is from or to the staking contract for that chain.\n *\n * @param payload - From TransactionController:transactionConfirmed.\n * @param payload.chainId - Hex chain ID of the transaction.\n * @param payload.txParams - Optional transaction params.\n * @param payload.txParams.from - Sender address.\n * @param payload.txParams.to - Recipient address.\n */\n #onTransactionConfirmed(payload: {\n chainId?: string;\n txParams?: { from?: string; to?: string };\n }): void {\n if (!this.#enabled) {\n return;\n }\n if (!this.#isTransactionInvolvingStakingContract(payload)) {\n return;\n }\n const hexChainId = payload?.chainId;\n if (!hexChainId) {\n return;\n }\n const caipChainId = `eip155:${parseInt(hexChainId, 16)}` as ChainId;\n const toRefresh = this.#getToRefreshForChains([caipChainId]);\n if (toRefresh.length > 0) {\n this.#refreshStakedBalanceAfterTransaction(toRefresh).catch((error) => {\n log('Failed to refresh staked balance after transaction', { error });\n });\n }\n }\n\n /**\n * When incoming transactions are received, refresh staked balance only for\n * chains where at least one transaction is from or to the staking contract.\n *\n * @param payload - From TransactionController:incomingTransactionsReceived (array of { chainId?, txParams? }).\n */\n #onIncomingTransactions(\n payload: { chainId?: string; txParams?: { from?: string; to?: string } }[],\n ): void {\n if (!this.#enabled) {\n return;\n }\n const chainIdsToRefresh = new Set<string>();\n for (const item of payload ?? []) {\n if (!item?.chainId) {\n continue;\n }\n if (this.#isTransactionInvolvingStakingContract(item)) {\n chainIdsToRefresh.add(item.chainId);\n }\n }\n const caipChainIds = [...chainIdsToRefresh].map(\n (hexChainId) => `eip155:${parseInt(hexChainId, 16)}` as ChainId,\n );\n if (caipChainIds.length === 0) {\n return;\n }\n const toRefresh = this.#getToRefreshForChains(caipChainIds);\n if (toRefresh.length > 0) {\n this.#refreshStakedBalanceAfterTransaction(toRefresh).catch((error) => {\n log('Failed to refresh staked balance after incoming transactions', {\n error,\n });\n });\n }\n }\n\n /**\n * Build toRefresh list for subscribed (account, chainId) pairs for the given chains.\n *\n * @param chainIds - CAIP-2 chain IDs to target.\n * @returns Pairs of account and chainId to refresh.\n */\n #getToRefreshForChains(\n chainIds: ChainId[],\n ): { account: InternalAccount; chainId: ChainId }[] {\n const toRefresh: { account: InternalAccount; chainId: ChainId }[] = [];\n const chainSet = new Set(chainIds);\n for (const subscription of this.#activeSubscriptions.values()) {\n for (const {\n account,\n supportedChains,\n } of subscription.accountsWithSupportedChains) {\n for (const chainId of supportedChains) {\n if (chainSet.has(chainId)) {\n toRefresh.push({ account, chainId });\n }\n }\n }\n }\n return toRefresh;\n }\n\n /**\n * Build toRefresh list for all subscribed (account, chainId) pairs.\n *\n * @returns Pairs of account and chainId to refresh.\n */\n #getToRefreshAll(): { account: InternalAccount; chainId: ChainId }[] {\n const toRefresh: { account: InternalAccount; chainId: ChainId }[] = [];\n for (const subscription of this.#activeSubscriptions.values()) {\n for (const {\n account,\n supportedChains,\n } of subscription.accountsWithSupportedChains) {\n for (const chainId of supportedChains) {\n toRefresh.push({ account, chainId });\n }\n }\n }\n return toRefresh;\n }\n\n /**\n * Refresh staked balance for all currently subscribed accounts and chains, then\n * push updates to the controller. Can be called from UI or after transaction events.\n */\n async refreshStakedBalance(): Promise<void> {\n if (!this.#enabled) {\n return;\n }\n const toRefresh = this.#getToRefreshAll();\n if (toRefresh.length > 0) {\n await this.#refreshStakedBalanceAfterTransaction(toRefresh);\n }\n }\n\n /**\n * Fetch staked balance for the given account/chain pairs and push a single\n * DataResponse to all active subscriptions.\n *\n * @param toRefresh - List of { account, chainId } to refresh.\n */\n async #refreshStakedBalanceAfterTransaction(\n toRefresh: { account: InternalAccount; chainId: ChainId }[],\n ): Promise<void> {\n const assetsInfo: Record<Caip19AssetId, AssetMetadata> = {};\n const assetsBalance: Record<\n AccountId,\n Record<Caip19AssetId, AssetBalance>\n > = {};\n\n for (const { account, chainId } of toRefresh) {\n try {\n const hexChainId = caipChainIdToHex(chainId);\n const contractAddress = getStakingContractAddress(hexChainId);\n if (!contractAddress) {\n continue;\n }\n\n const input: StakedBalancePollingInput = {\n chainId: hexChainId,\n accountId: account.id,\n accountAddress: account.address as Hex,\n };\n\n const result =\n await this.#stakedBalanceFetcher.fetchStakedBalance(input);\n const assetId = stakedAssetId(chainId, contractAddress);\n\n assetsInfo[assetId] = STAKED_ETH_METADATA;\n const existing = assetsBalance[account.id];\n assetsBalance[account.id] = {\n ...existing,\n [assetId]: { amount: result.amount },\n };\n } catch (error) {\n log('Failed to fetch staked balance in transaction refresh', {\n chainId,\n accountId: account.id,\n error,\n });\n }\n }\n\n if (Object.keys(assetsBalance).length > 0) {\n const response: DataResponse = { assetsInfo, assetsBalance };\n for (const subscription of this.#activeSubscriptions.values()) {\n subscription.onAssetsUpdate(response)?.catch((error: unknown) => {\n log('Failed to report staked balance update after transaction', {\n error,\n });\n });\n }\n }\n }\n\n /**\n * Set active chains from NetworkEnablementController state.\n * Only staking-supported chains that are enabled in the network enablement map\n * are active (e.g. if mainnet is not selected we do not fetch).\n */\n #initializeActiveChains(): void {\n try {\n const state = this.#messenger.call(\n 'NetworkEnablementController:getState',\n );\n this.#initializeActiveChainsFromEnabledMap(\n state?.enabledNetworkMap ?? {},\n );\n } catch (error) {\n log('Failed to get NetworkEnablementController state', { error });\n this.#initializeActiveChainsFromEnabledMap({});\n }\n }\n\n /**\n * Compute active chains as the intersection of supported staking chains and\n * enabled networks, then update state. Uses the same EIP-155 storage key\n * convention as NetworkEnablementController (hex for eip155).\n *\n * @param enabledNetworkMap - The enabled network map from NetworkEnablementController.\n */\n #initializeActiveChainsFromEnabledMap(\n enabledNetworkMap: Record<string, Record<string, boolean>>,\n ): void {\n if (!this.#enabled) {\n const previous = [...this.state.activeChains];\n this.updateActiveChains([], (updatedChains) =>\n this.#onActiveChainsUpdated(this.getName(), updatedChains, previous),\n );\n return;\n }\n\n const activeChains: ChainId[] = [];\n const eip155Map = enabledNetworkMap.eip155;\n if (eip155Map) {\n for (const caip2 of this.#supportedChainIds) {\n if (!isCaipChainId(caip2)) {\n continue;\n }\n const { reference } = parseCaipChainId(caip2);\n const storageKey = numberToHex(parseInt(reference, 10));\n if (eip155Map[storageKey]) {\n activeChains.push(caip2);\n }\n }\n }\n\n const previous = [...this.state.activeChains];\n this.updateActiveChains(activeChains, (updatedChains) =>\n this.#onActiveChainsUpdated(this.getName(), updatedChains, previous),\n );\n }\n\n /**\n * Get or create a Web3Provider for the given hex chain ID.\n * Uses the same messenger-cast pattern as RpcDataSource.\n *\n * @param hexChainId - The hex chain ID.\n * @returns Web3Provider instance, or undefined if not available.\n */\n #getProvider(hexChainId: Hex): Web3Provider | undefined {\n const cached = this.#providerCache.get(hexChainId);\n if (cached) {\n return cached;\n }\n\n try {\n const networkState = this.#messenger.call('NetworkController:getState');\n\n const { networkConfigurationsByChainId } = networkState;\n if (!networkConfigurationsByChainId) {\n return undefined;\n }\n\n const chainConfig = networkConfigurationsByChainId[hexChainId];\n if (!chainConfig) {\n return undefined;\n }\n\n // Use the network's configured default RPC endpoint (same as RpcDataSource).\n const { rpcEndpoints, defaultRpcEndpointIndex } = chainConfig;\n if (!rpcEndpoints || rpcEndpoints.length === 0) {\n return undefined;\n }\n\n const index =\n typeof defaultRpcEndpointIndex === 'number' &&\n defaultRpcEndpointIndex >= 0 &&\n defaultRpcEndpointIndex < rpcEndpoints.length\n ? defaultRpcEndpointIndex\n : 0;\n const defaultEndpoint = rpcEndpoints[index] as {\n networkClientId?: string;\n };\n const networkClientId = defaultEndpoint?.networkClientId;\n if (!networkClientId) {\n return undefined;\n }\n\n const networkClient = this.#messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n\n if (!networkClient?.provider) {\n return undefined;\n }\n\n const provider = new Web3Provider(networkClient.provider);\n this.#providerCache.set(hexChainId, provider);\n return provider;\n } catch (error) {\n log('Failed to get provider for chain', { hexChainId, error });\n return undefined;\n }\n }\n\n /**\n * Handle a staked balance update from StakedBalanceFetcher.\n * Converts the result into a DataResponse and forwards it to all active\n * subscriptions.\n *\n * @param result - The staked balance fetch result.\n */\n #handleStakedBalanceUpdate(result: StakedBalanceFetchResult): void {\n const contractAddress = getStakingContractAddress(result.chainId);\n if (!contractAddress) {\n return;\n }\n const chainIdDecimal = parseInt(result.chainId, 16);\n const caipChainId = `eip155:${chainIdDecimal}` as ChainId;\n const assetId = stakedAssetId(caipChainId, contractAddress);\n\n const response: DataResponse = {\n assetsInfo: {\n [assetId]: STAKED_ETH_METADATA,\n },\n assetsBalance: {\n [result.accountId]: {\n [assetId]: { amount: result.balance.amount },\n },\n },\n };\n\n log('Staked balance update', {\n accountId: result.accountId,\n chainId: caipChainId,\n amount: result.balance.amount,\n });\n\n for (const subscription of this.#activeSubscriptions.values()) {\n subscription.onAssetsUpdate(response)?.catch((error: unknown) => {\n log('Failed to report staked balance update', { error });\n });\n }\n }\n\n /**\n * Fetch staked balances for all accounts on supported chains.\n *\n * @param request - The data request with accounts and chains.\n * @returns DataResponse with staked balance data.\n */\n async fetch(request: DataRequest): Promise<DataResponse> {\n if (!this.#enabled) {\n return {};\n }\n const response: DataResponse = {};\n const activeChainsSet = new Set(this.state.activeChains);\n\n const chainsToFetch = request.chainIds.filter((chainId) =>\n activeChainsSet.has(chainId),\n );\n\n if (chainsToFetch.length === 0) {\n return response;\n }\n\n const balances: Record<AccountId, Record<Caip19AssetId, AssetBalance>> = {};\n\n for (const {\n account,\n supportedChains: accountChains,\n } of request.accountsWithSupportedChains) {\n const chains = chainsToFetch.filter((chain) =>\n accountChains.includes(chain),\n );\n\n for (const chainId of chains) {\n try {\n const hexChainId = caipChainIdToHex(chainId);\n const contractAddress = getStakingContractAddress(hexChainId);\n if (!contractAddress) {\n continue;\n }\n\n const input: StakedBalancePollingInput = {\n chainId: hexChainId,\n accountId: account.id,\n accountAddress: account.address as Hex,\n };\n\n const result =\n await this.#stakedBalanceFetcher.fetchStakedBalance(input);\n\n // Include zero amounts so merged updates clear prior non-zero state.\n balances[account.id] ??= {};\n const assetId = stakedAssetId(chainId, contractAddress);\n balances[account.id][assetId] = { amount: result.amount };\n } catch (error) {\n log('Failed to fetch staked balance', {\n chainId,\n accountId: account.id,\n error,\n });\n }\n }\n }\n\n if (Object.keys(balances).length > 0) {\n response.assetsBalance = balances;\n // Add metadata for each staked asset ID present in balances\n const assetIds = new Set<Caip19AssetId>();\n for (const accountBalances of Object.values(balances)) {\n for (const assetId of Object.keys(accountBalances)) {\n assetIds.add(assetId as Caip19AssetId);\n }\n }\n response.assetsInfo = {};\n for (const assetId of assetIds) {\n response.assetsInfo[assetId] = STAKED_ETH_METADATA;\n }\n }\n\n return response;\n }\n\n /**\n * Assets middleware for the fetch pipeline.\n * Fetches staked balances and merges them into the response, then passes\n * all chains to the next middleware (staked balance doesn't claim chains).\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return async (context, next) => {\n if (!this.#enabled) {\n return next(context);\n }\n const { request } = context;\n\n if (!request.dataTypes.includes('balance')) {\n return next(context);\n }\n\n if (request.chainIds.length === 0) {\n return next(context);\n }\n\n try {\n const fetchResponse = await this.fetch(request);\n\n if (fetchResponse.assetsInfo) {\n context.response.assetsInfo ??= {};\n Object.assign(context.response.assetsInfo, fetchResponse.assetsInfo);\n }\n if (fetchResponse.assetsBalance) {\n context.response.assetsBalance ??= {};\n for (const [accountId, accountBalances] of Object.entries(\n fetchResponse.assetsBalance,\n )) {\n context.response.assetsBalance[accountId] = {\n ...context.response.assetsBalance[accountId],\n ...accountBalances,\n };\n }\n }\n } catch (error) {\n log('Middleware fetch failed', { error });\n }\n\n // Pass all chains through (staked balance doesn't claim chains)\n return next(context);\n };\n }\n\n /**\n * Subscribe to staked balance updates with polling.\n * Starts polling via StakedBalanceFetcher for each account/chain combination.\n *\n * @param subscriptionRequest - The subscription request details.\n */\n async subscribe(subscriptionRequest: SubscriptionRequest): Promise<void> {\n const { request, subscriptionId, isUpdate } = subscriptionRequest;\n\n const activeChainsSet = new Set(this.state.activeChains);\n const chainsToSubscribe = request.chainIds.filter((chainId) =>\n activeChainsSet.has(chainId),\n );\n\n log('Subscribe requested', {\n subscriptionId,\n isUpdate,\n chainsToSubscribe,\n });\n\n if (chainsToSubscribe.length === 0) {\n log('No staking chains to subscribe');\n return;\n }\n\n // Handle subscription update - restart polling for new chains\n if (isUpdate) {\n const existing = this.#activeSubscriptions.get(subscriptionId);\n if (existing) {\n log('Updating existing subscription - restarting polling', {\n subscriptionId,\n });\n }\n }\n\n // Clean up existing subscription (stops old polling)\n await this.unsubscribe(subscriptionId);\n\n // Build subscription data first so it is available when the first poll runs\n const accountsWithSupportedChains: AccountWithSupportedChains[] =\n request.accountsWithSupportedChains\n .map(({ account, supportedChains }) => ({\n account,\n supportedChains: chainsToSubscribe.filter((chain) =>\n supportedChains.includes(chain),\n ),\n }))\n .filter(({ supportedChains }) => supportedChains.length > 0);\n\n const accounts = accountsWithSupportedChains.map((entry) => entry.account);\n const pollingTokens: string[] = [];\n\n // Store subscription before startPolling so first poll (setTimeout 0) has the callback\n this.#activeSubscriptions.set(subscriptionId, {\n pollingTokens,\n chains: chainsToSubscribe,\n accounts,\n accountsWithSupportedChains,\n onAssetsUpdate: subscriptionRequest.onAssetsUpdate,\n });\n\n this.activeSubscriptions.set(subscriptionId, {\n cleanup: () => {\n for (const token of pollingTokens) {\n this.#stakedBalanceFetcher.stopPollingByPollingToken(token);\n }\n this.#activeSubscriptions.delete(subscriptionId);\n },\n chains: chainsToSubscribe,\n request,\n onAssetsUpdate: subscriptionRequest.onAssetsUpdate,\n });\n\n // Start polling for each account/chain (first poll runs on next tick)\n for (const {\n account,\n supportedChains: accountChains,\n } of request.accountsWithSupportedChains) {\n const chainsForAccount = chainsToSubscribe.filter((chain) =>\n accountChains.includes(chain),\n );\n\n for (const chainId of chainsForAccount) {\n const hexChainId = caipChainIdToHex(chainId);\n\n const input: StakedBalancePollingInput = {\n chainId: hexChainId,\n accountId: account.id,\n accountAddress: account.address as Hex,\n };\n\n const pollingToken = this.#stakedBalanceFetcher.startPolling(input);\n pollingTokens.push(pollingToken);\n }\n }\n\n // Immediate initial fetch so state is updated without waiting for first poll\n try {\n const initialRequest: DataRequest = {\n accountsWithSupportedChains,\n chainIds: chainsToSubscribe,\n dataTypes: ['balance'],\n };\n const initialResponse = await this.fetch(initialRequest);\n if (\n initialResponse.assetsBalance &&\n Object.keys(initialResponse.assetsBalance).length > 0\n ) {\n subscriptionRequest\n .onAssetsUpdate?.(initialResponse)\n ?.catch((error) => {\n log('Initial staked balance update failed', { error });\n });\n }\n } catch (error) {\n log('Initial staked balance fetch failed', { error });\n }\n\n log('Subscription SUCCESS', {\n subscriptionId,\n chains: chainsToSubscribe,\n pollingCount: pollingTokens.length,\n });\n }\n\n /**\n * Unsubscribe from staked balance updates and stop polling.\n *\n * @param subscriptionId - The subscription ID to unsubscribe.\n */\n async unsubscribe(subscriptionId: string): Promise<void> {\n const subscription = this.#activeSubscriptions.get(subscriptionId);\n if (subscription) {\n for (const token of subscription.pollingTokens) {\n this.#stakedBalanceFetcher.stopPollingByPollingToken(token);\n }\n this.#activeSubscriptions.delete(subscriptionId);\n }\n\n await super.unsubscribe(subscriptionId);\n }\n\n /**\n * Destroy the data source and clean up all resources.\n */\n destroy(): void {\n this.#unsubscribeTransactionConfirmed?.();\n this.#unsubscribeIncomingTransactions?.();\n this.#unsubscribeNetworkStateChange?.();\n this.#unsubscribeNetworkEnablementControllerStateChange?.();\n for (const subscription of this.#activeSubscriptions.values()) {\n for (const token of subscription.pollingTokens) {\n this.#stakedBalanceFetcher.stopPollingByPollingToken(token);\n }\n }\n this.#activeSubscriptions.clear();\n this.#providerCache.clear();\n super.destroy();\n }\n}\n"]}
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.TokenDataSource = void 0;
16
16
  const core_backend_1 = require("@metamask/core-backend");
17
17
  const utils_1 = require("@metamask/utils");
18
+ const evm_rpc_services_1 = require("./evm-rpc-services/index.cjs");
18
19
  const logger_1 = require("../logger.cjs");
19
20
  const types_1 = require("../types.cjs");
20
21
  // ============================================================================
@@ -125,6 +126,10 @@ class TokenDataSource {
125
126
  if (existingMetadata?.image) {
126
127
  continue;
127
128
  }
129
+ // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API
130
+ if ((0, evm_rpc_services_1.isStakingContractAssetId)(assetId)) {
131
+ continue;
132
+ }
128
133
  assetIdsNeedingMetadata.add(assetId);
129
134
  }
130
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDataSource.cjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
1
+ {"version":3,"file":"TokenDataSource.cjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { isStakingContractAssetId } from './evm-rpc-services';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API\n if (isStakingContractAssetId(assetId)) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAM3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,CA4EjC;CACF"}
1
+ {"version":3,"file":"TokenDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAiFjC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAM3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,CA4EjC;CACF"}
1
+ {"version":3,"file":"TokenDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EAGV,UAAU,EAEX,qBAAiB;AAclB;;;GAGG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAMlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;CACnC,CAAC;AA2DF;;;;;;;;;GASG;AACH,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,IAAI,qBAAmB;IAEhC,OAAO,IAAI,MAAM;gBAOL,OAAO,EAAE,sBAAsB;IAoD3C;;;;;;;;;;OAUG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAiFjC;CACF"}
@@ -12,6 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
12
12
  var _TokenDataSource_instances, _TokenDataSource_apiClient, _TokenDataSource_getSupportedNetworks, _TokenDataSource_filterAssetsByNetwork;
13
13
  import { ApiPlatformClient } from "@metamask/core-backend";
14
14
  import { parseCaipAssetType } from "@metamask/utils";
15
+ import { isStakingContractAssetId } from "./evm-rpc-services/index.mjs";
15
16
  import { projectLogger, createModuleLogger } from "../logger.mjs";
16
17
  import { forDataTypes } from "../types.mjs";
17
18
  // ============================================================================
@@ -122,6 +123,10 @@ export class TokenDataSource {
122
123
  if (existingMetadata?.image) {
123
124
  continue;
124
125
  }
126
+ // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API
127
+ if (isStakingContractAssetId(assetId)) {
128
+ continue;
129
+ }
125
130
  assetIdsNeedingMetadata.add(assetId);
126
131
  }
127
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TokenDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
1
+ {"version":3,"file":"TokenDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/TokenDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import type { V3AssetResponse } from '@metamask/core-backend';\nimport { ApiPlatformClient } from '@metamask/core-backend';\nimport { parseCaipAssetType } from '@metamask/utils';\nimport type { CaipAssetType } from '@metamask/utils';\n\nimport { isStakingContractAssetId } from './evm-rpc-services';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport { forDataTypes } from '../types';\nimport type {\n Caip19AssetId,\n AssetMetadata,\n Middleware,\n FungibleAssetMetadata,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'TokenDataSource';\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n/**\n * TokenDataSource does not call external messenger actions.\n * It uses ApiPlatformClient directly.\n */\nexport type TokenDataSourceAllowedActions = never;\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type TokenDataSourceOptions = {\n /** ApiPlatformClient for API calls with caching */\n queryApiClient: ApiPlatformClient;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Transform V3 API response to FungibleAssetMetadata for state storage.\n *\n * Mapping:\n * - assetId → used to derive `type` (native/erc20/spl)\n * - iconUrl → image\n * - All other fields map directly\n *\n * @param assetId - CAIP-19 asset ID used to derive token type.\n * @param assetData - V3 API response data.\n * @returns FungibleAssetMetadata for state storage.\n */\nfunction transformV3AssetResponseToMetadata(\n assetId: string,\n assetData: V3AssetResponse,\n): AssetMetadata {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n let tokenType: 'native' | 'erc20' | 'spl' = 'erc20';\n\n if (parsed.assetNamespace === 'slip44') {\n tokenType = 'native';\n } else if (parsed.assetNamespace === 'spl') {\n tokenType = 'spl';\n }\n\n const metadata: FungibleAssetMetadata = {\n // Type derived from assetId\n type: tokenType,\n // BaseAssetMetadata fields\n name: assetData.name,\n symbol: assetData.symbol,\n decimals: assetData.decimals,\n image: assetData.iconUrl,\n // Direct mapping fields\n coingeckoId: assetData.coingeckoId,\n occurrences: assetData.occurrences,\n aggregators: assetData.aggregators,\n labels: assetData.labels,\n erc20Permit: assetData.erc20Permit,\n fees: assetData.fees,\n honeypotStatus: assetData.honeypotStatus,\n storage: assetData.storage,\n isContractVerified: assetData.isContractVerified,\n description: assetData.description,\n };\n\n return metadata;\n}\n\n// ============================================================================\n// TOKEN DATA SOURCE\n// ============================================================================\n\n/**\n * TokenDataSource enriches responses with token metadata from the Tokens API.\n *\n * This middleware-based data source:\n * - Checks detected assets for missing metadata/images\n * - Fetches metadata from Tokens API v3 for assets needing enrichment\n * - Merges fetched metadata into the response\n *\n * Usage: Create with queryApiClient and use assetsMiddleware; no messenger required.\n */\nexport class TokenDataSource {\n readonly name = CONTROLLER_NAME;\n\n getName(): string {\n return this.name;\n }\n\n /** ApiPlatformClient for cached API calls */\n readonly #apiClient: ApiPlatformClient;\n\n constructor(options: TokenDataSourceOptions) {\n this.#apiClient = options.queryApiClient;\n }\n\n /**\n * Gets the supported networks from the API.\n * Caching is handled by ApiPlatformClient.\n *\n * @returns Set of supported chain IDs in CAIP format\n */\n async #getSupportedNetworks(): Promise<Set<string>> {\n try {\n // Use v2/supportedNetworks which returns CAIP chain IDs\n // ApiPlatformClient handles caching\n const response =\n await this.#apiClient.tokens.fetchTokenV2SupportedNetworks();\n\n // Combine full and partial support networks\n const allNetworks = [...response.fullSupport, ...response.partialSupport];\n\n return new Set(allNetworks);\n } catch (error) {\n log('Failed to fetch supported networks', { error });\n return new Set();\n }\n }\n\n /**\n * Filters asset IDs to only include those from supported networks.\n *\n * @param assetIds - Array of CAIP-19 asset IDs\n * @param supportedNetworks - Set of supported chain IDs\n * @returns Array of asset IDs from supported networks\n */\n #filterAssetsByNetwork(\n assetIds: string[],\n supportedNetworks: Set<string>,\n ): string[] {\n return assetIds.filter((assetId) => {\n try {\n const parsed = parseCaipAssetType(assetId as CaipAssetType);\n // chainId is in format \"eip155:1\" or \"tron:728126428\"\n // parsed.chain has namespace and reference properties\n const chainId = `${parsed.chain.namespace}:${parsed.chain.reference}`;\n return supportedNetworks.has(chainId);\n } catch {\n // If we can't parse the asset ID, filter it out\n return false;\n }\n });\n }\n\n /**\n * Get the middleware for enriching responses with token metadata.\n *\n * This middleware:\n * 1. Extracts the response from context\n * 2. Fetches metadata for detected assets (assets without metadata)\n * 3. Enriches the response with fetched metadata\n * 4. Calls next() at the end to continue the middleware chain\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return forDataTypes(['metadata'], async (ctx, next) => {\n // Extract response from context\n const { response } = ctx;\n\n // Only fetch metadata for detected assets (assets without metadata)\n if (!response.detectedAssets) {\n return next(ctx);\n }\n\n const { assetsInfo: stateMetadata } = ctx.getAssetsState();\n const assetIdsNeedingMetadata = new Set<string>();\n\n for (const detectedIds of Object.values(response.detectedAssets)) {\n for (const assetId of detectedIds) {\n // Skip if response already has metadata with image\n const responseMetadata = response.assetsInfo?.[assetId];\n if (responseMetadata?.image) {\n continue;\n }\n\n // Skip if state already has metadata with image\n const existingMetadata = stateMetadata[assetId];\n if (existingMetadata?.image) {\n continue;\n }\n\n // Skip staking contracts; we use built-in metadata and do not fetch from the tokens API\n if (isStakingContractAssetId(assetId)) {\n continue;\n }\n\n assetIdsNeedingMetadata.add(assetId);\n }\n }\n\n if (assetIdsNeedingMetadata.size === 0) {\n return next(ctx);\n }\n\n // Filter asset IDs to only include supported networks\n const supportedNetworks = await this.#getSupportedNetworks();\n const supportedAssetIds = this.#filterAssetsByNetwork(\n [...assetIdsNeedingMetadata],\n supportedNetworks,\n );\n\n if (supportedAssetIds.length === 0) {\n return next(ctx);\n }\n\n try {\n // Use ApiPlatformClient for fetching asset metadata\n // API returns an array with assetId as a property on each item\n const metadataResponse = await this.#apiClient.tokens.fetchV3Assets(\n supportedAssetIds,\n {\n includeIconUrl: true,\n includeMarketData: true,\n includeMetadata: true,\n includeLabels: true,\n includeRwaData: true,\n },\n );\n\n response.assetsInfo ??= {};\n\n for (const assetData of metadataResponse) {\n const caipAssetId = assetData.assetId as Caip19AssetId;\n response.assetsInfo[caipAssetId] = transformV3AssetResponseToMetadata(\n assetData.assetId,\n assetData,\n );\n }\n } catch (error) {\n log('Failed to fetch metadata', { error });\n }\n\n // Call next() at the end to continue the middleware chain\n return next(ctx);\n });\n }\n}\n"]}
@@ -1,11 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.reduceInBatchesSerially = exports.divideIntoBatches = exports.TokenDetector = exports.BalanceFetcher = exports.MulticallClient = void 0;
3
+ exports.reduceInBatchesSerially = exports.divideIntoBatches = exports.isStakingContractAssetId = exports.getStakingContractAddress = exports.getSupportedStakingChainIds = exports.StakedBalanceFetcher = exports.TokenDetector = exports.BalanceFetcher = exports.MulticallClient = void 0;
4
4
  var clients_1 = require("./clients/index.cjs");
5
5
  Object.defineProperty(exports, "MulticallClient", { enumerable: true, get: function () { return clients_1.MulticallClient; } });
6
6
  var services_1 = require("./services/index.cjs");
7
7
  Object.defineProperty(exports, "BalanceFetcher", { enumerable: true, get: function () { return services_1.BalanceFetcher; } });
8
8
  Object.defineProperty(exports, "TokenDetector", { enumerable: true, get: function () { return services_1.TokenDetector; } });
9
+ Object.defineProperty(exports, "StakedBalanceFetcher", { enumerable: true, get: function () { return services_1.StakedBalanceFetcher; } });
10
+ Object.defineProperty(exports, "getSupportedStakingChainIds", { enumerable: true, get: function () { return services_1.getSupportedStakingChainIds; } });
11
+ Object.defineProperty(exports, "getStakingContractAddress", { enumerable: true, get: function () { return services_1.getStakingContractAddress; } });
12
+ Object.defineProperty(exports, "isStakingContractAssetId", { enumerable: true, get: function () { return services_1.isStakingContractAssetId; } });
9
13
  var utils_1 = require("./utils/index.cjs");
10
14
  Object.defineProperty(exports, "divideIntoBatches", { enumerable: true, get: function () { return utils_1.divideIntoBatches; } });
11
15
  Object.defineProperty(exports, "reduceInBatchesSerially", { enumerable: true, get: function () { return utils_1.reduceInBatchesSerially; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":";;;AAYA,+CAAwE;AAA/D,0GAAA,eAAe,OAAA;AACxB,iDAOoB;AANlB,0GAAA,cAAc,OAAA;AACd,yGAAA,aAAa,OAAA;AAMf,2CAAqE;AAA5D,0GAAA,iBAAiB,OAAA;AAAE,gHAAA,uBAAuB,OAAA","sourcesContent":["export type {\n Address,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport { MulticallClient, type MulticallClientConfig } from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n type BalancePollingInput,\n type DetectionPollingInput,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":";;;AAYA,+CAAwE;AAA/D,0GAAA,eAAe,OAAA;AACxB,iDAcoB;AAblB,0GAAA,cAAc,OAAA;AACd,yGAAA,aAAa,OAAA;AACb,gHAAA,oBAAoB,OAAA;AACpB,uHAAA,2BAA2B,OAAA;AAC3B,qHAAA,yBAAyB,OAAA;AACzB,oHAAA,wBAAwB,OAAA;AAS1B,2CAAqE;AAA5D,0GAAA,iBAAiB,OAAA;AAAE,gHAAA,uBAAuB,OAAA","sourcesContent":["export type {\n Address,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport { MulticallClient, type MulticallClientConfig } from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n StakedBalanceFetcher,\n getSupportedStakingChainIds,\n getStakingContractAddress,\n isStakingContractAssetId,\n type BalancePollingInput,\n type DetectionPollingInput,\n type StakedBalancePollingInput,\n type StakedBalanceFetchResult,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n type OnStakedBalanceUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
@@ -1,5 +1,5 @@
1
1
  export type { Address, AssetsBalanceState, ChainId, GetProviderFunction, Provider, BalanceOfRequest, BalanceOfResponse, TokenListState, BalanceFetchResult, TokenDetectionResult, } from "./types/index.cjs";
2
2
  export { MulticallClient, type MulticallClientConfig } from "./clients/index.cjs";
3
- export { BalanceFetcher, TokenDetector, type BalancePollingInput, type DetectionPollingInput, type OnBalanceUpdateCallback, type OnDetectionUpdateCallback, } from "./services/index.cjs";
3
+ export { BalanceFetcher, TokenDetector, StakedBalanceFetcher, getSupportedStakingChainIds, getStakingContractAddress, isStakingContractAssetId, type BalancePollingInput, type DetectionPollingInput, type StakedBalancePollingInput, type StakedBalanceFetchResult, type OnBalanceUpdateCallback, type OnDetectionUpdateCallback, type OnStakedBalanceUpdateCallback, } from "./services/index.cjs";
4
4
  export { divideIntoBatches, reduceInBatchesSerially } from "./utils/index.cjs";
5
5
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,GAC/B,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
@@ -1,5 +1,5 @@
1
1
  export type { Address, AssetsBalanceState, ChainId, GetProviderFunction, Provider, BalanceOfRequest, BalanceOfResponse, TokenListState, BalanceFetchResult, TokenDetectionResult, } from "./types/index.mjs";
2
2
  export { MulticallClient, type MulticallClientConfig } from "./clients/index.mjs";
3
- export { BalanceFetcher, TokenDetector, type BalancePollingInput, type DetectionPollingInput, type OnBalanceUpdateCallback, type OnDetectionUpdateCallback, } from "./services/index.mjs";
3
+ export { BalanceFetcher, TokenDetector, StakedBalanceFetcher, getSupportedStakingChainIds, getStakingContractAddress, isStakingContractAssetId, type BalancePollingInput, type DetectionPollingInput, type StakedBalancePollingInput, type StakedBalanceFetchResult, type OnBalanceUpdateCallback, type OnDetectionUpdateCallback, type OnStakedBalanceUpdateCallback, } from "./services/index.mjs";
4
4
  export { divideIntoBatches, reduceInBatchesSerially } from "./utils/index.mjs";
5
5
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,GAC/B,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,kBAAkB,EAClB,OAAO,EACP,mBAAmB,EACnB,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,0BAAgB;AACjB,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,6BAA6B,GACnC,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB"}
@@ -1,4 +1,4 @@
1
1
  export { MulticallClient } from "./clients/index.mjs";
2
- export { BalanceFetcher, TokenDetector } from "./services/index.mjs";
2
+ export { BalanceFetcher, TokenDetector, StakedBalanceFetcher, getSupportedStakingChainIds, getStakingContractAddress, isStakingContractAssetId } from "./services/index.mjs";
3
3
  export { divideIntoBatches, reduceInBatchesSerially } from "./utils/index.mjs";
4
4
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,eAAe,EAA8B,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EAKd,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB","sourcesContent":["export type {\n Address,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport { MulticallClient, type MulticallClientConfig } from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n type BalancePollingInput,\n type DetectionPollingInput,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/data-sources/evm-rpc-services/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,eAAe,EAA8B,4BAAkB;AACxE,OAAO,EACL,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,EAQzB,6BAAmB;AACpB,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,0BAAgB","sourcesContent":["export type {\n Address,\n AssetsBalanceState,\n ChainId,\n GetProviderFunction,\n Provider,\n BalanceOfRequest,\n BalanceOfResponse,\n TokenListState,\n BalanceFetchResult,\n TokenDetectionResult,\n} from './types';\nexport { MulticallClient, type MulticallClientConfig } from './clients';\nexport {\n BalanceFetcher,\n TokenDetector,\n StakedBalanceFetcher,\n getSupportedStakingChainIds,\n getStakingContractAddress,\n isStakingContractAssetId,\n type BalancePollingInput,\n type DetectionPollingInput,\n type StakedBalancePollingInput,\n type StakedBalanceFetchResult,\n type OnBalanceUpdateCallback,\n type OnDetectionUpdateCallback,\n type OnStakedBalanceUpdateCallback,\n} from './services';\nexport { divideIntoBatches, reduceInBatchesSerially } from './utils';\n"]}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _StakedBalanceFetcher_providerGetter, _StakedBalanceFetcher_onStakedBalanceUpdate;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.StakedBalanceFetcher = exports.isStakingContractAssetId = exports.getSupportedStakingChainIds = exports.getStakingContractAddress = void 0;
16
+ const abi_1 = require("@ethersproject/abi");
17
+ const providers_1 = require("@ethersproject/providers");
18
+ const polling_controller_1 = require("@metamask/polling-controller");
19
+ const utils_1 = require("../utils/index.cjs");
20
+ Object.defineProperty(exports, "getStakingContractAddress", { enumerable: true, get: function () { return utils_1.getStakingContractAddress; } });
21
+ Object.defineProperty(exports, "getSupportedStakingChainIds", { enumerable: true, get: function () { return utils_1.getSupportedStakingChainIds; } });
22
+ Object.defineProperty(exports, "isStakingContractAssetId", { enumerable: true, get: function () { return utils_1.isStakingContractAssetId; } });
23
+ /** Staking contract ABI: getShares(account) and convertToAssets(shares). */
24
+ const STAKING_CONTRACT_ABI = [
25
+ {
26
+ inputs: [{ internalType: 'address', name: 'account', type: 'address' }],
27
+ name: 'getShares',
28
+ outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
29
+ stateMutability: 'view',
30
+ type: 'function',
31
+ },
32
+ {
33
+ inputs: [{ internalType: 'uint256', name: 'shares', type: 'uint256' }],
34
+ name: 'convertToAssets',
35
+ outputs: [{ internalType: 'uint256', name: 'assets', type: 'uint256' }],
36
+ stateMutability: 'view',
37
+ type: 'function',
38
+ },
39
+ ];
40
+ const STAKING_INTERFACE = new abi_1.Interface(STAKING_CONTRACT_ABI);
41
+ const STAKING_DECIMALS = 18;
42
+ const DEFAULT_STAKED_BALANCE_INTERVAL = 180000; // 3 minutes
43
+ class StakedBalanceFetcher extends (0, polling_controller_1.StaticIntervalPollingControllerOnly)() {
44
+ constructor(config) {
45
+ super();
46
+ _StakedBalanceFetcher_providerGetter.set(this, void 0);
47
+ _StakedBalanceFetcher_onStakedBalanceUpdate.set(this, void 0);
48
+ __classPrivateFieldSet(this, _StakedBalanceFetcher_providerGetter, config?.getNetworkProvider, "f");
49
+ this.setIntervalLength(config?.pollingInterval ?? DEFAULT_STAKED_BALANCE_INTERVAL);
50
+ }
51
+ /**
52
+ * Register a callback that is invoked after every successful poll with
53
+ * the staked balance (including zero). Zero is reported so that merged
54
+ * updates can clear prior non-zero state.
55
+ *
56
+ * @param callback - The callback to invoke.
57
+ */
58
+ setOnStakedBalanceUpdate(callback) {
59
+ __classPrivateFieldSet(this, _StakedBalanceFetcher_onStakedBalanceUpdate, callback, "f");
60
+ }
61
+ async _executePoll(input) {
62
+ let result;
63
+ try {
64
+ result = await this.fetchStakedBalance(input);
65
+ }
66
+ catch {
67
+ // Do not push an update on provider/RPC failure; otherwise we would
68
+ // overwrite existing non-zero staked balances with zero in state.
69
+ return;
70
+ }
71
+ if (__classPrivateFieldGet(this, _StakedBalanceFetcher_onStakedBalanceUpdate, "f")) {
72
+ __classPrivateFieldGet(this, _StakedBalanceFetcher_onStakedBalanceUpdate, "f").call(this, {
73
+ accountId: input.accountId,
74
+ chainId: input.chainId,
75
+ balance: result,
76
+ });
77
+ }
78
+ }
79
+ /**
80
+ * Fetches the staked balance for an account on a chain using the same
81
+ * staking contract as AccountTrackerController (getShares then convertToAssets).
82
+ * Returns a human-readable amount string (e.g. "1.5" for 1.5 ETH).
83
+ * Throws when no provider is available or when the RPC/contract call fails, so
84
+ * callers do not persist a false zero and overwrite existing balances.
85
+ *
86
+ * @param input - Chain, account ID, and address to query.
87
+ * @returns Human-readable staked balance (amount string).
88
+ * @throws When provider is missing or when getShares/convertToAssets fails.
89
+ */
90
+ async fetchStakedBalance(input) {
91
+ const { chainId, accountAddress } = input;
92
+ const provider = __classPrivateFieldGet(this, _StakedBalanceFetcher_providerGetter, "f")?.call(this, chainId);
93
+ if (!provider) {
94
+ throw new Error('StakedBalanceFetcher: no provider available for chain');
95
+ }
96
+ const contractAddress = (0, utils_1.getStakingContractAddress)(chainId);
97
+ if (!contractAddress) {
98
+ return { amount: '0' };
99
+ }
100
+ try {
101
+ const sharesCalldata = STAKING_INTERFACE.encodeFunctionData('getShares', [
102
+ accountAddress,
103
+ ]);
104
+ const sharesResult = await provider.call({
105
+ to: contractAddress,
106
+ data: sharesCalldata,
107
+ });
108
+ const sharesRaw = STAKING_INTERFACE.decodeFunctionResult('getShares', sharesResult)[0];
109
+ const sharesBigNum = BigInt(sharesRaw.toString());
110
+ if (sharesBigNum === 0n) {
111
+ return { amount: '0' };
112
+ }
113
+ const assetsCalldata = STAKING_INTERFACE.encodeFunctionData('convertToAssets', [sharesBigNum]);
114
+ const assetsResult = await provider.call({
115
+ to: contractAddress,
116
+ data: assetsCalldata,
117
+ });
118
+ const assetsRaw = STAKING_INTERFACE.decodeFunctionResult('convertToAssets', assetsResult)[0];
119
+ const assetsWei = BigInt(assetsRaw.toString());
120
+ const amount = (0, utils_1.weiToHumanReadable)(assetsWei, STAKING_DECIMALS);
121
+ return { amount };
122
+ }
123
+ catch (error) {
124
+ throw error instanceof Error
125
+ ? error
126
+ : new Error('StakedBalanceFetcher: failed to fetch staked balance');
127
+ }
128
+ }
129
+ }
130
+ exports.StakedBalanceFetcher = StakedBalanceFetcher;
131
+ _StakedBalanceFetcher_providerGetter = new WeakMap(), _StakedBalanceFetcher_onStakedBalanceUpdate = new WeakMap();
132
+ //# sourceMappingURL=StakedBalanceFetcher.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StakedBalanceFetcher.cjs","sourceRoot":"","sources":["../../../../src/data-sources/evm-rpc-services/services/StakedBalanceFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { Web3Provider } from '@ethersproject/providers';\nimport { StaticIntervalPollingControllerOnly } from '@metamask/polling-controller';\n\nimport type { Address, AccountId, ChainId } from '../types';\nimport {\n getStakingContractAddress,\n getSupportedStakingChainIds,\n isStakingContractAssetId,\n weiToHumanReadable,\n} from '../utils';\n\nexport {\n getStakingContractAddress,\n getSupportedStakingChainIds,\n isStakingContractAssetId,\n};\n\nexport type StakedBalancePollingInput = {\n /** Chain ID (hex format, e.g. 0x1) */\n chainId: ChainId;\n /** Account ID */\n accountId: AccountId;\n /** Account address */\n accountAddress: Address;\n};\n\n/** Human-readable staked balance (e.g. \"1.5\" for 1.5 ETH). */\nexport type StakedBalance = {\n amount: string;\n};\n\n/** Result reported via the update callback. */\nexport type StakedBalanceFetchResult = {\n /** Account ID (UUID). */\n accountId: AccountId;\n /** Hex chain ID. */\n chainId: ChainId;\n /** Human-readable staked balance. */\n balance: StakedBalance;\n};\n\n/**\n * Callback type for staked balance updates.\n */\nexport type OnStakedBalanceUpdateCallback = (\n result: StakedBalanceFetchResult,\n) => void;\n\n/** Staking contract ABI: getShares(account) and convertToAssets(shares). */\nconst STAKING_CONTRACT_ABI = [\n {\n inputs: [{ internalType: 'address', name: 'account', type: 'address' }],\n name: 'getShares',\n outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n {\n inputs: [{ internalType: 'uint256', name: 'shares', type: 'uint256' }],\n name: 'convertToAssets',\n outputs: [{ internalType: 'uint256', name: 'assets', type: 'uint256' }],\n stateMutability: 'view',\n type: 'function',\n },\n];\n\nconst STAKING_INTERFACE = new Interface(STAKING_CONTRACT_ABI);\n\nconst STAKING_DECIMALS = 18;\n\nexport type StakedBalanceFetcherConfig = {\n /** Polling interval in ms (default: 180s) */\n pollingInterval?: number;\n /** Returns the network provider for the given chain. Required for fetchStakedBalance. */\n getNetworkProvider?: (chainId: ChainId) => Web3Provider | undefined;\n};\n\nconst DEFAULT_STAKED_BALANCE_INTERVAL = 180_000; // 3 minutes\n\nexport class StakedBalanceFetcher extends StaticIntervalPollingControllerOnly<StakedBalancePollingInput>() {\n readonly #providerGetter?: (chainId: ChainId) => Web3Provider | undefined;\n\n #onStakedBalanceUpdate: OnStakedBalanceUpdateCallback | undefined;\n\n constructor(config?: StakedBalanceFetcherConfig) {\n super();\n this.#providerGetter = config?.getNetworkProvider;\n\n this.setIntervalLength(\n config?.pollingInterval ?? DEFAULT_STAKED_BALANCE_INTERVAL,\n );\n }\n\n /**\n * Register a callback that is invoked after every successful poll with\n * the staked balance (including zero). Zero is reported so that merged\n * updates can clear prior non-zero state.\n *\n * @param callback - The callback to invoke.\n */\n setOnStakedBalanceUpdate(callback: OnStakedBalanceUpdateCallback): void {\n this.#onStakedBalanceUpdate = callback;\n }\n\n async _executePoll(input: StakedBalancePollingInput): Promise<void> {\n let result: StakedBalance;\n try {\n result = await this.fetchStakedBalance(input);\n } catch {\n // Do not push an update on provider/RPC failure; otherwise we would\n // overwrite existing non-zero staked balances with zero in state.\n return;\n }\n\n if (this.#onStakedBalanceUpdate) {\n this.#onStakedBalanceUpdate({\n accountId: input.accountId,\n chainId: input.chainId,\n balance: result,\n });\n }\n }\n\n /**\n * Fetches the staked balance for an account on a chain using the same\n * staking contract as AccountTrackerController (getShares then convertToAssets).\n * Returns a human-readable amount string (e.g. \"1.5\" for 1.5 ETH).\n * Throws when no provider is available or when the RPC/contract call fails, so\n * callers do not persist a false zero and overwrite existing balances.\n *\n * @param input - Chain, account ID, and address to query.\n * @returns Human-readable staked balance (amount string).\n * @throws When provider is missing or when getShares/convertToAssets fails.\n */\n async fetchStakedBalance(\n input: StakedBalancePollingInput,\n ): Promise<StakedBalance> {\n const { chainId, accountAddress } = input;\n const provider = this.#providerGetter?.(chainId);\n if (!provider) {\n throw new Error('StakedBalanceFetcher: no provider available for chain');\n }\n const contractAddress = getStakingContractAddress(chainId);\n\n if (!contractAddress) {\n return { amount: '0' };\n }\n\n try {\n const sharesCalldata = STAKING_INTERFACE.encodeFunctionData('getShares', [\n accountAddress,\n ]);\n const sharesResult = await provider.call({\n to: contractAddress,\n data: sharesCalldata,\n });\n const sharesRaw = STAKING_INTERFACE.decodeFunctionResult(\n 'getShares',\n sharesResult,\n )[0];\n const sharesBigNum = BigInt(sharesRaw.toString());\n\n if (sharesBigNum === 0n) {\n return { amount: '0' };\n }\n\n const assetsCalldata = STAKING_INTERFACE.encodeFunctionData(\n 'convertToAssets',\n [sharesBigNum],\n );\n const assetsResult = await provider.call({\n to: contractAddress,\n data: assetsCalldata,\n });\n const assetsRaw = STAKING_INTERFACE.decodeFunctionResult(\n 'convertToAssets',\n assetsResult,\n )[0];\n const assetsWei = BigInt(assetsRaw.toString());\n\n const amount = weiToHumanReadable(assetsWei, STAKING_DECIMALS);\n return { amount };\n } catch (error) {\n throw error instanceof Error\n ? error\n : new Error('StakedBalanceFetcher: failed to fetch staked balance');\n }\n }\n}\n"]}