@metamask-previews/assets-controller 0.0.0-preview-3ec2a74 → 0.0.0-preview-6ae8a59c

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 (206) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/data-sources/RpcDataSource.cjs +415 -186
  3. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  4. package/dist/data-sources/RpcDataSource.d.cts +115 -30
  5. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  6. package/dist/data-sources/RpcDataSource.d.mts +115 -30
  7. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  8. package/dist/data-sources/RpcDataSource.mjs +413 -185
  9. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  10. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs.map +1 -0
  11. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.cts.map +1 -0
  12. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.mts.map +1 -0
  13. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.mjs.map +1 -0
  14. package/dist/data-sources/evm-rpc-services/clients/index.cjs.map +1 -0
  15. package/dist/data-sources/evm-rpc-services/clients/index.d.cts.map +1 -0
  16. package/dist/data-sources/evm-rpc-services/clients/index.d.mts.map +1 -0
  17. package/dist/data-sources/evm-rpc-services/clients/index.mjs.map +1 -0
  18. package/dist/data-sources/{rpc-datasource → evm-rpc-services}/index.cjs +4 -1
  19. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -0
  20. package/dist/data-sources/evm-rpc-services/index.d.cts +5 -0
  21. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -0
  22. package/dist/data-sources/evm-rpc-services/index.d.mts +5 -0
  23. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -0
  24. package/dist/data-sources/{rpc-datasource → evm-rpc-services}/index.mjs +1 -0
  25. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -0
  26. package/dist/data-sources/{rpc-datasource → evm-rpc-services}/services/BalanceFetcher.cjs +33 -3
  27. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs.map +1 -0
  28. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts +68 -0
  29. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts.map +1 -0
  30. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts +68 -0
  31. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts.map +1 -0
  32. package/dist/data-sources/{rpc-datasource → evm-rpc-services}/services/BalanceFetcher.mjs +33 -3
  33. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs.map +1 -0
  34. package/dist/data-sources/{rpc-datasource → evm-rpc-services}/services/TokenDetector.cjs +33 -3
  35. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -0
  36. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts +66 -0
  37. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -0
  38. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +66 -0
  39. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -0
  40. package/dist/data-sources/{rpc-datasource → evm-rpc-services}/services/TokenDetector.mjs +33 -3
  41. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -0
  42. package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -0
  43. package/dist/data-sources/evm-rpc-services/services/index.d.cts +3 -0
  44. package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -0
  45. package/dist/data-sources/evm-rpc-services/services/index.d.mts +3 -0
  46. package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -0
  47. package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -0
  48. package/dist/data-sources/evm-rpc-services/types/assets.cjs.map +1 -0
  49. package/dist/data-sources/evm-rpc-services/types/assets.d.cts.map +1 -0
  50. package/dist/data-sources/evm-rpc-services/types/assets.d.mts.map +1 -0
  51. package/dist/data-sources/evm-rpc-services/types/assets.mjs.map +1 -0
  52. package/dist/data-sources/evm-rpc-services/types/config.cjs.map +1 -0
  53. package/dist/data-sources/evm-rpc-services/types/config.d.cts.map +1 -0
  54. package/dist/data-sources/evm-rpc-services/types/config.d.mts.map +1 -0
  55. package/dist/data-sources/evm-rpc-services/types/config.mjs.map +1 -0
  56. package/dist/data-sources/evm-rpc-services/types/core.cjs.map +1 -0
  57. package/dist/data-sources/evm-rpc-services/types/core.d.cts.map +1 -0
  58. package/dist/data-sources/evm-rpc-services/types/core.d.mts.map +1 -0
  59. package/dist/data-sources/evm-rpc-services/types/core.mjs.map +1 -0
  60. package/dist/data-sources/evm-rpc-services/types/index.cjs.map +1 -0
  61. package/dist/data-sources/evm-rpc-services/types/index.d.cts.map +1 -0
  62. package/dist/data-sources/evm-rpc-services/types/index.d.mts.map +1 -0
  63. package/dist/data-sources/evm-rpc-services/types/index.mjs.map +1 -0
  64. package/dist/data-sources/evm-rpc-services/types/multicall.cjs.map +1 -0
  65. package/dist/data-sources/evm-rpc-services/types/multicall.d.cts.map +1 -0
  66. package/dist/data-sources/evm-rpc-services/types/multicall.d.mts.map +1 -0
  67. package/dist/data-sources/evm-rpc-services/types/multicall.mjs.map +1 -0
  68. package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -0
  69. package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -0
  70. package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -0
  71. package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -0
  72. package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -0
  73. package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -0
  74. package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -0
  75. package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -0
  76. package/dist/data-sources/evm-rpc-services/utils/batch.cjs.map +1 -0
  77. package/dist/data-sources/evm-rpc-services/utils/batch.d.cts.map +1 -0
  78. package/dist/data-sources/evm-rpc-services/utils/batch.d.mts.map +1 -0
  79. package/dist/data-sources/evm-rpc-services/utils/batch.mjs.map +1 -0
  80. package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -0
  81. package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -0
  82. package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -0
  83. package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -0
  84. package/dist/data-sources/initDataSources.cjs +5 -1
  85. package/dist/data-sources/initDataSources.cjs.map +1 -1
  86. package/dist/data-sources/initDataSources.d.cts +15 -0
  87. package/dist/data-sources/initDataSources.d.cts.map +1 -1
  88. package/dist/data-sources/initDataSources.d.mts +15 -0
  89. package/dist/data-sources/initDataSources.d.mts.map +1 -1
  90. package/dist/data-sources/initDataSources.mjs +5 -1
  91. package/dist/data-sources/initDataSources.mjs.map +1 -1
  92. package/package.json +5 -2
  93. package/dist/data-sources/rpc-datasource/clients/MulticallClient.cjs.map +0 -1
  94. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.cts.map +0 -1
  95. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.mts.map +0 -1
  96. package/dist/data-sources/rpc-datasource/clients/MulticallClient.mjs.map +0 -1
  97. package/dist/data-sources/rpc-datasource/clients/index.cjs.map +0 -1
  98. package/dist/data-sources/rpc-datasource/clients/index.d.cts.map +0 -1
  99. package/dist/data-sources/rpc-datasource/clients/index.d.mts.map +0 -1
  100. package/dist/data-sources/rpc-datasource/clients/index.mjs.map +0 -1
  101. package/dist/data-sources/rpc-datasource/index.cjs.map +0 -1
  102. package/dist/data-sources/rpc-datasource/index.d.cts +0 -4
  103. package/dist/data-sources/rpc-datasource/index.d.cts.map +0 -1
  104. package/dist/data-sources/rpc-datasource/index.d.mts +0 -4
  105. package/dist/data-sources/rpc-datasource/index.d.mts.map +0 -1
  106. package/dist/data-sources/rpc-datasource/index.mjs.map +0 -1
  107. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.cjs.map +0 -1
  108. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.cts +0 -16
  109. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.cts.map +0 -1
  110. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.mts +0 -16
  111. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.mts.map +0 -1
  112. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.mjs.map +0 -1
  113. package/dist/data-sources/rpc-datasource/services/TokenDetector.cjs.map +0 -1
  114. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.cts +0 -14
  115. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.cts.map +0 -1
  116. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.mts +0 -14
  117. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.mts.map +0 -1
  118. package/dist/data-sources/rpc-datasource/services/TokenDetector.mjs.map +0 -1
  119. package/dist/data-sources/rpc-datasource/services/index.cjs.map +0 -1
  120. package/dist/data-sources/rpc-datasource/services/index.d.cts +0 -3
  121. package/dist/data-sources/rpc-datasource/services/index.d.cts.map +0 -1
  122. package/dist/data-sources/rpc-datasource/services/index.d.mts +0 -3
  123. package/dist/data-sources/rpc-datasource/services/index.d.mts.map +0 -1
  124. package/dist/data-sources/rpc-datasource/services/index.mjs.map +0 -1
  125. package/dist/data-sources/rpc-datasource/types/assets.cjs.map +0 -1
  126. package/dist/data-sources/rpc-datasource/types/assets.d.cts.map +0 -1
  127. package/dist/data-sources/rpc-datasource/types/assets.d.mts.map +0 -1
  128. package/dist/data-sources/rpc-datasource/types/assets.mjs.map +0 -1
  129. package/dist/data-sources/rpc-datasource/types/config.cjs.map +0 -1
  130. package/dist/data-sources/rpc-datasource/types/config.d.cts.map +0 -1
  131. package/dist/data-sources/rpc-datasource/types/config.d.mts.map +0 -1
  132. package/dist/data-sources/rpc-datasource/types/config.mjs.map +0 -1
  133. package/dist/data-sources/rpc-datasource/types/core.cjs.map +0 -1
  134. package/dist/data-sources/rpc-datasource/types/core.d.cts.map +0 -1
  135. package/dist/data-sources/rpc-datasource/types/core.d.mts.map +0 -1
  136. package/dist/data-sources/rpc-datasource/types/core.mjs.map +0 -1
  137. package/dist/data-sources/rpc-datasource/types/index.cjs.map +0 -1
  138. package/dist/data-sources/rpc-datasource/types/index.d.cts.map +0 -1
  139. package/dist/data-sources/rpc-datasource/types/index.d.mts.map +0 -1
  140. package/dist/data-sources/rpc-datasource/types/index.mjs.map +0 -1
  141. package/dist/data-sources/rpc-datasource/types/multicall.cjs.map +0 -1
  142. package/dist/data-sources/rpc-datasource/types/multicall.d.cts.map +0 -1
  143. package/dist/data-sources/rpc-datasource/types/multicall.d.mts.map +0 -1
  144. package/dist/data-sources/rpc-datasource/types/multicall.mjs.map +0 -1
  145. package/dist/data-sources/rpc-datasource/types/services.cjs.map +0 -1
  146. package/dist/data-sources/rpc-datasource/types/services.d.cts.map +0 -1
  147. package/dist/data-sources/rpc-datasource/types/services.d.mts.map +0 -1
  148. package/dist/data-sources/rpc-datasource/types/services.mjs.map +0 -1
  149. package/dist/data-sources/rpc-datasource/types/state.cjs.map +0 -1
  150. package/dist/data-sources/rpc-datasource/types/state.d.cts.map +0 -1
  151. package/dist/data-sources/rpc-datasource/types/state.d.mts.map +0 -1
  152. package/dist/data-sources/rpc-datasource/types/state.mjs.map +0 -1
  153. package/dist/data-sources/rpc-datasource/utils/batch.cjs.map +0 -1
  154. package/dist/data-sources/rpc-datasource/utils/batch.d.cts.map +0 -1
  155. package/dist/data-sources/rpc-datasource/utils/batch.d.mts.map +0 -1
  156. package/dist/data-sources/rpc-datasource/utils/batch.mjs.map +0 -1
  157. package/dist/data-sources/rpc-datasource/utils/index.cjs.map +0 -1
  158. package/dist/data-sources/rpc-datasource/utils/index.d.cts.map +0 -1
  159. package/dist/data-sources/rpc-datasource/utils/index.d.mts.map +0 -1
  160. package/dist/data-sources/rpc-datasource/utils/index.mjs.map +0 -1
  161. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/MulticallClient.cjs +0 -0
  162. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/MulticallClient.d.cts +0 -0
  163. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/MulticallClient.d.mts +0 -0
  164. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/MulticallClient.mjs +0 -0
  165. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/index.cjs +0 -0
  166. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/index.d.cts +0 -0
  167. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/index.d.mts +0 -0
  168. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/clients/index.mjs +0 -0
  169. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/services/index.cjs +0 -0
  170. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/services/index.mjs +0 -0
  171. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/assets.cjs +0 -0
  172. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/assets.d.cts +0 -0
  173. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/assets.d.mts +0 -0
  174. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/assets.mjs +0 -0
  175. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/config.cjs +0 -0
  176. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/config.d.cts +0 -0
  177. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/config.d.mts +0 -0
  178. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/config.mjs +0 -0
  179. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/core.cjs +0 -0
  180. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/core.d.cts +0 -0
  181. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/core.d.mts +0 -0
  182. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/core.mjs +0 -0
  183. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/index.cjs +0 -0
  184. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/index.d.cts +0 -0
  185. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/index.d.mts +0 -0
  186. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/index.mjs +0 -0
  187. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/multicall.cjs +0 -0
  188. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/multicall.d.cts +0 -0
  189. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/multicall.d.mts +0 -0
  190. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/multicall.mjs +0 -0
  191. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/services.cjs +0 -0
  192. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/services.d.cts +0 -0
  193. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/services.d.mts +0 -0
  194. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/services.mjs +0 -0
  195. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/state.cjs +0 -0
  196. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/state.d.cts +0 -0
  197. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/state.d.mts +0 -0
  198. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/types/state.mjs +0 -0
  199. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/batch.cjs +0 -0
  200. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/batch.d.cts +0 -0
  201. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/batch.d.mts +0 -0
  202. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/batch.mjs +0 -0
  203. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/index.cjs +0 -0
  204. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/index.d.cts +0 -0
  205. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/index.d.mts +0 -0
  206. /package/dist/data-sources/{rpc-datasource → evm-rpc-services}/utils/index.mjs +0 -0
@@ -9,33 +9,37 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _RpcDataSource_instances, _RpcDataSource_messenger, _RpcDataSource_timeout, _RpcDataSource_pollInterval, _RpcDataSource_providerCache, _RpcDataSource_registerActionHandlers, _RpcDataSource_subscribeToNetworkController, _RpcDataSource_initializeFromNetworkController, _RpcDataSource_updateFromNetworkState, _RpcDataSource_getProvider, _RpcDataSource_clearProviderCache, _RpcDataSource_accountSupportsChain;
12
+ var _RpcDataSource_instances, _RpcDataSource_timeout, _RpcDataSource_tokenDetectionEnabled, _RpcDataSource_activeChains, _RpcDataSource_chainStatuses, _RpcDataSource_providerCache, _RpcDataSource_activeSubscriptions, _RpcDataSource_multicallClient, _RpcDataSource_balanceFetcher, _RpcDataSource_tokenDetector, _RpcDataSource_handleBalanceUpdate, _RpcDataSource_handleDetectionUpdate, _RpcDataSource_registerActionHandlers, _RpcDataSource_subscribeToNetworkController, _RpcDataSource_initializeFromNetworkController, _RpcDataSource_updateFromNetworkState, _RpcDataSource_getProvider, _RpcDataSource_getMulticallProvider, _RpcDataSource_clearProviderCache, _RpcDataSource_accountSupportsChain, _RpcDataSource_buildNativeAssetId;
13
13
  import { Web3Provider } from "@ethersproject/providers";
14
- import { AbstractDataSource } from "./AbstractDataSource.mjs";
14
+ import { BaseController } from "@metamask/base-controller";
15
+ import { toHex } from "@metamask/controller-utils";
16
+ import { isStrictHexString, isCaipChainId, parseCaipChainId } from "@metamask/utils";
17
+ import { BalanceFetcher, MulticallClient, TokenDetector } from "./evm-rpc-services/index.mjs";
15
18
  import { projectLogger, createModuleLogger } from "../logger.mjs";
16
- // ============================================================================
17
- // CONSTANTS
18
- // ============================================================================
19
19
  const CONTROLLER_NAME = 'RpcDataSource';
20
- const DEFAULT_POLL_INTERVAL = 30000;
20
+ const DEFAULT_BALANCE_INTERVAL = 30000; // 30 seconds
21
+ const DEFAULT_DETECTION_INTERVAL = 180000; // 3 minutes
21
22
  const log = createModuleLogger(projectLogger, CONTROLLER_NAME);
22
- const defaultState = {
23
- activeChains: [],
24
- chainStatuses: {},
23
+ /**
24
+ * Convert CAIP chain ID or hex chain ID to hex chain ID.
25
+ *
26
+ * @param chainId - CAIP chain ID or hex chain ID.
27
+ * @returns Hex chain ID.
28
+ */
29
+ export const caipChainIdToHex = (chainId) => {
30
+ if (isStrictHexString(chainId)) {
31
+ return chainId;
32
+ }
33
+ if (isCaipChainId(chainId)) {
34
+ return toHex(parseCaipChainId(chainId).reference);
35
+ }
36
+ throw new Error('caipChainIdToHex - Failed to provide CAIP-2 or Hex chainId');
25
37
  };
26
- // ============================================================================
27
- // HELPER FUNCTIONS
28
- // ============================================================================
29
- function buildNativeAssetId(chainId) {
30
- return `${chainId}/slip44:60`;
31
- }
32
- // ============================================================================
33
- // RPC DATA SOURCE
34
- // ============================================================================
35
38
  /**
36
39
  * Data source for fetching balances via RPC calls.
37
40
  *
38
- * Used as a fallback when the Accounts API doesn't support a chain.
41
+ * Orchestrates polling through BalanceFetcher and TokenDetector,
42
+ * each of which handle their own polling intervals.
39
43
  *
40
44
  * Communicates with AssetsController via Messenger:
41
45
  *
@@ -49,88 +53,176 @@ function buildNativeAssetId(chainId) {
49
53
  * - RpcDataSource:activeChainsUpdated
50
54
  * - RpcDataSource:assetsUpdated
51
55
  */
52
- export class RpcDataSource extends AbstractDataSource {
56
+ export class RpcDataSource extends BaseController {
53
57
  constructor(options) {
54
- super(CONTROLLER_NAME, {
55
- ...defaultState,
56
- ...options.state,
58
+ super({
59
+ name: CONTROLLER_NAME,
60
+ metadata: {},
61
+ state: {},
62
+ messenger: options.messenger,
57
63
  });
58
64
  _RpcDataSource_instances.add(this);
59
- _RpcDataSource_messenger.set(this, void 0);
60
65
  _RpcDataSource_timeout.set(this, void 0);
61
- _RpcDataSource_pollInterval.set(this, void 0);
66
+ _RpcDataSource_tokenDetectionEnabled.set(this, void 0);
67
+ /** Currently active chains */
68
+ _RpcDataSource_activeChains.set(this, []);
69
+ /** Network status for each active chain */
70
+ _RpcDataSource_chainStatuses.set(this, {});
62
71
  /** Cache of Web3Provider instances by chainId */
63
72
  _RpcDataSource_providerCache.set(this, new Map());
64
- __classPrivateFieldSet(this, _RpcDataSource_messenger, options.messenger, "f");
73
+ /** Active subscriptions by ID */
74
+ _RpcDataSource_activeSubscriptions.set(this, new Map());
75
+ // Rpc-datasource components
76
+ _RpcDataSource_multicallClient.set(this, void 0);
77
+ _RpcDataSource_balanceFetcher.set(this, void 0);
78
+ _RpcDataSource_tokenDetector.set(this, void 0);
65
79
  __classPrivateFieldSet(this, _RpcDataSource_timeout, options.timeout ?? 10000, "f");
66
- __classPrivateFieldSet(this, _RpcDataSource_pollInterval, options.pollInterval ?? DEFAULT_POLL_INTERVAL, "f");
80
+ __classPrivateFieldSet(this, _RpcDataSource_tokenDetectionEnabled, options.tokenDetectionEnabled ?? false, "f");
81
+ const balanceInterval = options.balanceInterval ?? DEFAULT_BALANCE_INTERVAL;
82
+ const detectionInterval = options.detectionInterval ?? DEFAULT_DETECTION_INTERVAL;
83
+ log('Initializing RpcDataSource', {
84
+ timeout: __classPrivateFieldGet(this, _RpcDataSource_timeout, "f"),
85
+ balanceInterval,
86
+ detectionInterval,
87
+ tokenDetectionEnabled: __classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f"),
88
+ });
89
+ // Initialize MulticallClient with a provider getter
90
+ __classPrivateFieldSet(this, _RpcDataSource_multicallClient, new MulticallClient((hexChainId) => {
91
+ return __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getMulticallProvider).call(this, hexChainId);
92
+ }), "f");
93
+ // Create state getters using messenger
94
+ const getTokenListState = () => {
95
+ return this.messenger.call('TokenListController:getState');
96
+ };
97
+ const getUserTokensState = () => {
98
+ return this.messenger.call('AssetsController:getState');
99
+ };
100
+ // Initialize BalanceFetcher with polling interval
101
+ __classPrivateFieldSet(this, _RpcDataSource_balanceFetcher, new BalanceFetcher(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), {
102
+ pollingInterval: balanceInterval,
103
+ }), "f");
104
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").setUserTokensStateGetter(getUserTokensState);
105
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").setOnBalanceUpdate(__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_handleBalanceUpdate).bind(this));
106
+ // Initialize TokenDetector with polling interval
107
+ __classPrivateFieldSet(this, _RpcDataSource_tokenDetector, new TokenDetector(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), {
108
+ pollingInterval: detectionInterval,
109
+ }), "f");
110
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").setTokenListStateGetter(getTokenListState);
111
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").setOnDetectionUpdate(__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_handleDetectionUpdate).bind(this));
67
112
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_registerActionHandlers).call(this);
68
113
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_subscribeToNetworkController).call(this);
69
114
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_initializeFromNetworkController).call(this);
70
115
  }
71
- // ============================================================================
72
- // CHAIN STATUS
73
- // ============================================================================
116
+ /**
117
+ * Get the data source name.
118
+ *
119
+ * @returns The name of this data source.
120
+ */
121
+ getName() {
122
+ return this.name;
123
+ }
124
+ /**
125
+ * Get currently active chains.
126
+ *
127
+ * @returns Promise resolving to array of active chain IDs.
128
+ */
129
+ async getActiveChains() {
130
+ return __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f");
131
+ }
74
132
  /**
75
133
  * Get the status of all configured chains.
76
134
  *
77
135
  * @returns Record of chain statuses keyed by chain ID.
78
136
  */
79
137
  getChainStatuses() {
80
- return { ...this.state.chainStatuses };
138
+ return { ...__classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f") };
81
139
  }
82
140
  /**
83
141
  * Get the status of a specific chain.
84
142
  *
85
- * @param chainId - The CAIP-2 chain ID to check.
86
- * @returns The chain status, or undefined if not configured.
143
+ * @param chainId - The chain ID to get status for.
144
+ * @returns The chain status or undefined if not found.
87
145
  */
88
146
  getChainStatus(chainId) {
89
- return this.state.chainStatuses[chainId];
147
+ return __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
148
+ }
149
+ /**
150
+ * Set the balance polling interval.
151
+ *
152
+ * @param interval - The polling interval in milliseconds.
153
+ */
154
+ setBalancePollingInterval(interval) {
155
+ log('Setting balance polling interval', { interval });
156
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").setIntervalLength(interval);
157
+ }
158
+ /**
159
+ * Get the current balance polling interval.
160
+ *
161
+ * @returns The polling interval in milliseconds, or undefined if not set.
162
+ */
163
+ getBalancePollingInterval() {
164
+ return __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").getIntervalLength();
165
+ }
166
+ /**
167
+ * Set the token detection polling interval.
168
+ *
169
+ * @param interval - The polling interval in milliseconds.
170
+ */
171
+ setDetectionPollingInterval(interval) {
172
+ log('Setting detection polling interval', { interval });
173
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").setIntervalLength(interval);
174
+ }
175
+ /**
176
+ * Get the current token detection polling interval.
177
+ *
178
+ * @returns The polling interval in milliseconds, or undefined if not set.
179
+ */
180
+ getDetectionPollingInterval() {
181
+ return __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").getIntervalLength();
90
182
  }
91
- // ============================================================================
92
- // FETCH
93
- // ============================================================================
94
183
  async fetch(request) {
95
184
  const response = {};
96
- // Filter to active chains
97
- const chainsToFetch = request.chainIds.filter((chainId) => this.state.activeChains.includes(chainId));
185
+ const chainsToFetch = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
186
+ log('Fetch requested', {
187
+ accounts: request.accounts.map((a) => a.id),
188
+ requestedChains: request.chainIds,
189
+ chainsToFetch,
190
+ });
98
191
  if (chainsToFetch.length === 0) {
192
+ log('No active chains to fetch');
99
193
  return response;
100
194
  }
101
195
  const assetsBalance = {};
102
196
  const failedChains = [];
103
- // Fetch native balance for each chain
197
+ // Fetch balances for each chain using BalanceFetcher
104
198
  for (const chainId of chainsToFetch) {
105
- const provider = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getProvider).call(this, chainId);
106
- if (!provider) {
107
- continue;
108
- }
109
- const assetId = buildNativeAssetId(chainId);
110
- // Fetch balance for each account that supports this chain
199
+ const hexChainId = caipChainIdToHex(chainId);
111
200
  for (const account of request.accounts) {
112
- // Check if account supports this chain based on its scopes
113
201
  if (!__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_accountSupportsChain).call(this, account, chainId)) {
114
202
  continue;
115
203
  }
116
204
  const { address, id: accountId } = account;
117
205
  try {
118
- const balancePromise = provider.getBalance(address);
119
- const timeoutPromise = new Promise((_resolve, reject) => setTimeout(() => reject(new Error('RPC timeout')), __classPrivateFieldGet(this, _RpcDataSource_timeout, "f")));
120
- const balance = await Promise.race([balancePromise, timeoutPromise]);
206
+ // Use BalanceFetcher for batched balance fetching
207
+ const result = await __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").fetchBalancesForTokens(hexChainId, accountId, address, [], // Empty array means just native token
208
+ { includeNative: true });
121
209
  if (!assetsBalance[accountId]) {
122
210
  assetsBalance[accountId] = {};
123
211
  }
124
- assetsBalance[accountId][assetId] = {
125
- amount: balance.toString(),
126
- };
212
+ // Convert balances to response format
213
+ for (const balance of result.balances) {
214
+ assetsBalance[accountId][balance.assetId] = {
215
+ amount: balance.balance,
216
+ };
217
+ }
127
218
  }
128
219
  catch (error) {
129
220
  log('Failed to fetch balance', { address, chainId, error });
130
221
  if (!assetsBalance[accountId]) {
131
222
  assetsBalance[accountId] = {};
132
223
  }
133
- assetsBalance[accountId][assetId] = { amount: '0' };
224
+ const nativeAssetId = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_buildNativeAssetId).call(this, chainId);
225
+ assetsBalance[accountId][nativeAssetId] = { amount: '0' };
134
226
  if (!failedChains.includes(chainId)) {
135
227
  failedChains.push(chainId);
136
228
  }
@@ -138,68 +230,101 @@ export class RpcDataSource extends AbstractDataSource {
138
230
  }
139
231
  }
140
232
  if (failedChains.length > 0) {
141
- // Add failed chains to errors so they can fallback to other data sources
233
+ log('Fetch PARTIAL - some chains failed', {
234
+ successChains: chainsToFetch.filter((chain) => !failedChains.includes(chain)),
235
+ failedChains,
236
+ });
142
237
  response.errors = {};
143
238
  for (const chainId of failedChains) {
144
239
  response.errors[chainId] = 'RPC fetch failed';
145
240
  }
146
241
  }
242
+ else {
243
+ log('Fetch SUCCESS', {
244
+ chains: chainsToFetch,
245
+ accountCount: Object.keys(assetsBalance).length,
246
+ });
247
+ }
147
248
  response.assetsBalance = assetsBalance;
148
249
  return response;
149
250
  }
150
- // ============================================================================
151
- // MIDDLEWARE
152
- // ============================================================================
153
251
  /**
154
- * Get the middleware for fetching balances via RPC.
155
- * This middleware:
156
- * - Supports multiple accounts in a single request
157
- * - Filters request to only chains this data source supports
158
- * - Fetches balances for those chains for all accounts
159
- * - Merges response into context
160
- * - Removes handled chains from request for next middleware
252
+ * Run token detection for an account on a chain.
161
253
  *
162
- * @returns The middleware function for the assets pipeline.
254
+ * @param chainId - The chain ID to detect tokens on.
255
+ * @param account - The account to detect tokens for.
256
+ * @returns Promise resolving to a DataResponse with detected assets.
163
257
  */
258
+ async detectTokens(chainId, account) {
259
+ if (!__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f")) {
260
+ return {};
261
+ }
262
+ const hexChainId = caipChainIdToHex(chainId);
263
+ const { address, id: accountId } = account;
264
+ log('Running token detection', { chainId, accountId });
265
+ try {
266
+ const result = await __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").detectTokens(hexChainId, accountId, address);
267
+ if (result.detectedAssets.length === 0) {
268
+ log('No new tokens detected');
269
+ return {};
270
+ }
271
+ log('Detected new tokens', {
272
+ count: result.detectedAssets.length,
273
+ chainId,
274
+ accountId,
275
+ });
276
+ // Convert detected assets to DataResponse format
277
+ const balances = {};
278
+ // Add balances for detected tokens
279
+ for (const balance of result.detectedBalances) {
280
+ balances[balance.assetId] = {
281
+ amount: balance.balance,
282
+ };
283
+ }
284
+ const response = {
285
+ detectedAssets: {
286
+ [accountId]: result.detectedAssets.map((asset) => asset.assetId),
287
+ },
288
+ assetsBalance: {
289
+ [accountId]: balances,
290
+ },
291
+ };
292
+ return response;
293
+ }
294
+ catch (error) {
295
+ log('Token detection failed', { chainId, accountId, error });
296
+ return {};
297
+ }
298
+ }
164
299
  get assetsMiddleware() {
165
300
  return async (context, next) => {
166
- var _a;
301
+ var _a, _b;
167
302
  const { request } = context;
168
- // Filter to chains this data source supports
169
- const supportedChains = request.chainIds.filter((chainId) => this.state.activeChains.includes(chainId));
170
- // If no supported chains, skip and pass to next middleware
303
+ const supportedChains = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
171
304
  if (supportedChains.length === 0) {
172
305
  return next(context);
173
306
  }
174
307
  let successfullyHandledChains = [];
175
- try {
176
- // Fetch for supported chains
177
- const response = await this.fetch({
178
- ...request,
179
- chainIds: supportedChains,
180
- });
181
- // Merge response into context
182
- if (response.assetsBalance) {
183
- (_a = context.response).assetsBalance ?? (_a.assetsBalance = {});
184
- for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
185
- if (!context.response.assetsBalance[accountId]) {
186
- context.response.assetsBalance[accountId] = {};
187
- }
188
- context.response.assetsBalance[accountId] = {
189
- ...context.response.assetsBalance[accountId],
190
- ...accountBalances,
191
- };
192
- }
308
+ log('Middleware fetching', {
309
+ chains: supportedChains,
310
+ accounts: request.accounts.map((a) => a.id),
311
+ });
312
+ const response = await this.fetch({
313
+ ...request,
314
+ chainIds: supportedChains,
315
+ });
316
+ if (response.assetsBalance) {
317
+ (_a = context.response).assetsBalance ?? (_a.assetsBalance = {});
318
+ for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
319
+ (_b = context.response.assetsBalance)[accountId] ?? (_b[accountId] = {});
320
+ context.response.assetsBalance[accountId] = {
321
+ ...context.response.assetsBalance[accountId],
322
+ ...accountBalances,
323
+ };
193
324
  }
194
- // Determine successfully handled chains (exclude errors)
195
- const failedChains = new Set(Object.keys(response.errors ?? {}));
196
- successfullyHandledChains = supportedChains.filter((chainId) => !failedChains.has(chainId));
197
325
  }
198
- catch (error) {
199
- log('Middleware fetch failed', { error });
200
- successfullyHandledChains = [];
201
- }
202
- // Remove successfully handled chains from request for next middleware
326
+ const failedChains = new Set(Object.keys(response.errors ?? {}));
327
+ successfullyHandledChains = supportedChains.filter((chainId) => !failedChains.has(chainId));
203
328
  if (successfullyHandledChains.length > 0) {
204
329
  const remainingChains = request.chainIds.filter((chainId) => !successfullyHandledChains.includes(chainId));
205
330
  return next({
@@ -210,87 +335,184 @@ export class RpcDataSource extends AbstractDataSource {
210
335
  },
211
336
  });
212
337
  }
213
- // No chains handled - pass context unchanged
214
338
  return next(context);
215
339
  };
216
340
  }
217
- // ============================================================================
218
- // SUBSCRIBE
219
- // ============================================================================
341
+ /**
342
+ * Subscribe to updates for the given request.
343
+ * Starts polling through BalanceFetcher and TokenDetector.
344
+ *
345
+ * @param subscriptionRequest - The subscription request details.
346
+ */
220
347
  async subscribe(subscriptionRequest) {
221
348
  const { request, subscriptionId, isUpdate } = subscriptionRequest;
222
- // Filter to active chains
223
- const chainsToSubscribe = request.chainIds.filter((chainId) => this.state.activeChains.includes(chainId));
349
+ const chainsToSubscribe = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
350
+ log('Subscribe requested', {
351
+ subscriptionId,
352
+ isUpdate,
353
+ accounts: request.accounts.map((a) => a.id),
354
+ chainsToSubscribe,
355
+ });
224
356
  if (chainsToSubscribe.length === 0) {
357
+ log('No active chains to subscribe');
225
358
  return;
226
359
  }
227
- // Handle subscription update - update both chains AND request (for accounts)
360
+ // Handle subscription update
228
361
  if (isUpdate) {
229
- const existing = this.activeSubscriptions.get(subscriptionId);
362
+ const existing = __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").get(subscriptionId);
230
363
  if (existing) {
364
+ log('Updating existing subscription', {
365
+ subscriptionId,
366
+ chainsToSubscribe,
367
+ });
231
368
  existing.chains = chainsToSubscribe;
232
- existing.request = request;
369
+ existing.accounts = request.accounts;
233
370
  return;
234
371
  }
235
372
  }
236
373
  // Clean up existing subscription
237
374
  await this.unsubscribe(subscriptionId);
238
- const pollInterval = request.updateInterval ?? __classPrivateFieldGet(this, _RpcDataSource_pollInterval, "f");
239
- // Create poll function
240
- const pollFn = async () => {
241
- try {
242
- const subscription = this.activeSubscriptions.get(subscriptionId);
243
- if (!subscription?.request) {
244
- return;
375
+ // Start polling through BalanceFetcher and TokenDetector
376
+ const balancePollingTokens = [];
377
+ const detectionPollingTokens = [];
378
+ for (const chainId of chainsToSubscribe) {
379
+ const hexChainId = caipChainIdToHex(chainId);
380
+ for (const account of request.accounts) {
381
+ if (!__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_accountSupportsChain).call(this, account, chainId)) {
382
+ continue;
383
+ }
384
+ const { address, id: accountId } = account;
385
+ // Start balance polling
386
+ const balanceInput = {
387
+ chainId: hexChainId,
388
+ accountId,
389
+ accountAddress: address,
390
+ };
391
+ const balanceToken = __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").startPolling(balanceInput);
392
+ balancePollingTokens.push(balanceToken);
393
+ // Start detection polling if enabled
394
+ if (__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f")) {
395
+ const detectionInput = {
396
+ chainId: hexChainId,
397
+ accountId,
398
+ accountAddress: address,
399
+ };
400
+ const detectionToken = __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").startPolling(detectionInput);
401
+ detectionPollingTokens.push(detectionToken);
245
402
  }
246
- // Use stored request (which gets updated on account changes)
247
- const fetchResponse = await this.fetch({
248
- ...subscription.request,
249
- chainIds: subscription.chains,
250
- });
251
- // Report update to AssetsController
252
- await __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('AssetsController:assetsUpdate', fetchResponse, CONTROLLER_NAME);
253
- }
254
- catch (error) {
255
- log('Subscription poll failed', { subscriptionId, error });
256
403
  }
257
- };
258
- // Set up polling
259
- const timer = setInterval(() => {
260
- pollFn().catch(console.error);
261
- }, pollInterval);
262
- // Store subscription with request for account updates
263
- this.activeSubscriptions.set(subscriptionId, {
264
- cleanup: () => {
265
- clearInterval(timer);
266
- },
404
+ }
405
+ // Store subscription data
406
+ __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").set(subscriptionId, {
407
+ balancePollingTokens,
408
+ detectionPollingTokens,
409
+ chains: chainsToSubscribe,
410
+ accounts: request.accounts,
411
+ });
412
+ log('Subscription SUCCESS', {
413
+ subscriptionId,
267
414
  chains: chainsToSubscribe,
268
- request,
415
+ balancePollingCount: balancePollingTokens.length,
416
+ detectionPollingCount: detectionPollingTokens.length,
269
417
  });
270
- // Initial fetch
271
- await pollFn();
418
+ }
419
+ /**
420
+ * Unsubscribe from updates and stop polling.
421
+ *
422
+ * @param subscriptionId - The subscription ID to unsubscribe.
423
+ */
424
+ async unsubscribe(subscriptionId) {
425
+ const subscription = __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").get(subscriptionId);
426
+ if (subscription) {
427
+ // Stop balance polling
428
+ for (const token of subscription.balancePollingTokens) {
429
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").stopPollingByPollingToken(token);
430
+ }
431
+ // Stop detection polling
432
+ for (const token of subscription.detectionPollingTokens) {
433
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").stopPollingByPollingToken(token);
434
+ }
435
+ __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").delete(subscriptionId);
436
+ log('Unsubscribed and stopped polling', { subscriptionId });
437
+ }
438
+ }
439
+ /**
440
+ * Destroy the data source and clean up resources.
441
+ */
442
+ destroy() {
443
+ log('Destroying RpcDataSource');
444
+ // Stop all polling
445
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").stopAllPolling();
446
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").stopAllPolling();
447
+ // Clear subscriptions
448
+ __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").clear();
449
+ // Clear caches
450
+ __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
272
451
  }
273
452
  }
274
- _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_timeout = new WeakMap(), _RpcDataSource_pollInterval = new WeakMap(), _RpcDataSource_providerCache = new WeakMap(), _RpcDataSource_instances = new WeakSet(), _RpcDataSource_registerActionHandlers = function _RpcDataSource_registerActionHandlers() {
453
+ _RpcDataSource_timeout = new WeakMap(), _RpcDataSource_tokenDetectionEnabled = new WeakMap(), _RpcDataSource_activeChains = new WeakMap(), _RpcDataSource_chainStatuses = new WeakMap(), _RpcDataSource_providerCache = new WeakMap(), _RpcDataSource_activeSubscriptions = new WeakMap(), _RpcDataSource_multicallClient = new WeakMap(), _RpcDataSource_balanceFetcher = new WeakMap(), _RpcDataSource_tokenDetector = new WeakMap(), _RpcDataSource_instances = new WeakSet(), _RpcDataSource_handleBalanceUpdate = function _RpcDataSource_handleBalanceUpdate(result) {
454
+ const accountBalances = {};
455
+ for (const balance of result.balances) {
456
+ accountBalances[balance.assetId] = {
457
+ amount: balance.balance,
458
+ };
459
+ }
460
+ const response = {
461
+ assetsBalance: {
462
+ [result.accountId]: accountBalances,
463
+ },
464
+ };
465
+ this.messenger
466
+ .call('AssetsController:assetsUpdate', response, CONTROLLER_NAME)
467
+ .catch((error) => {
468
+ log('Failed to update assets', { error });
469
+ });
470
+ }, _RpcDataSource_handleDetectionUpdate = function _RpcDataSource_handleDetectionUpdate(result) {
471
+ log('Detected new tokens', {
472
+ count: result.detectedAssets.length,
473
+ });
474
+ const response = {
475
+ detectedAssets: {
476
+ [result.accountId]: result.detectedAssets.map((asset) => asset.assetId),
477
+ },
478
+ };
479
+ // Add balances for detected tokens
480
+ if (result.detectedBalances.length > 0) {
481
+ response.assetsBalance = {
482
+ [result.accountId]: {},
483
+ };
484
+ for (const balance of result.detectedBalances) {
485
+ response.assetsBalance[result.accountId][balance.assetId] = {
486
+ amount: balance.balance,
487
+ };
488
+ }
489
+ }
490
+ this.messenger
491
+ .call('AssetsController:assetsUpdate', response, CONTROLLER_NAME)
492
+ .catch((error) => {
493
+ log('Failed to update detected assets', { error });
494
+ });
495
+ }, _RpcDataSource_registerActionHandlers = function _RpcDataSource_registerActionHandlers() {
275
496
  const getAssetsMiddlewareHandler = () => this.assetsMiddleware;
276
497
  const getActiveChainsHandler = async () => this.getActiveChains();
277
498
  const fetchHandler = async (request) => this.fetch(request);
278
499
  const subscribeHandler = async (request) => this.subscribe(request);
279
500
  const unsubscribeHandler = async (subscriptionId) => this.unsubscribe(subscriptionId);
280
- __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").registerActionHandler('RpcDataSource:getAssetsMiddleware', getAssetsMiddlewareHandler);
281
- __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").registerActionHandler('RpcDataSource:getActiveChains', getActiveChainsHandler);
282
- __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").registerActionHandler('RpcDataSource:fetch', fetchHandler);
283
- __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").registerActionHandler('RpcDataSource:subscribe', subscribeHandler);
284
- __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").registerActionHandler('RpcDataSource:unsubscribe', unsubscribeHandler);
501
+ this.messenger.registerActionHandler('RpcDataSource:getAssetsMiddleware', getAssetsMiddlewareHandler);
502
+ this.messenger.registerActionHandler('RpcDataSource:getActiveChains', getActiveChainsHandler);
503
+ this.messenger.registerActionHandler('RpcDataSource:fetch', fetchHandler);
504
+ this.messenger.registerActionHandler('RpcDataSource:subscribe', subscribeHandler);
505
+ this.messenger.registerActionHandler('RpcDataSource:unsubscribe', unsubscribeHandler);
285
506
  }, _RpcDataSource_subscribeToNetworkController = function _RpcDataSource_subscribeToNetworkController() {
286
- __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").subscribe('NetworkController:stateChange', (networkState) => {
287
- // Clear provider cache since network configurations may have changed
507
+ this.messenger.subscribe('NetworkController:stateChange', (networkState) => {
508
+ log('NetworkController state changed');
288
509
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_clearProviderCache).call(this);
289
510
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
290
511
  });
291
512
  }, _RpcDataSource_initializeFromNetworkController = function _RpcDataSource_initializeFromNetworkController() {
513
+ log('Initializing from NetworkController');
292
514
  try {
293
- const networkState = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('NetworkController:getState');
515
+ const networkState = this.messenger.call('NetworkController:getState');
294
516
  __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
295
517
  }
296
518
  catch (error) {
@@ -300,19 +522,15 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_timeout = new WeakMap()
300
522
  const { networkConfigurationsByChainId, networksMetadata } = networkState;
301
523
  const chainStatuses = {};
302
524
  const activeChains = [];
303
- // Iterate through all configured networks
304
525
  for (const [hexChainId, config] of Object.entries(networkConfigurationsByChainId)) {
305
- // Convert hex chainId to CAIP-2 format (eip155:decimal)
306
526
  const decimalChainId = parseInt(hexChainId, 16);
307
527
  const caip2ChainId = `eip155:${decimalChainId}`;
308
- // Get the default RPC endpoint's network client ID
309
528
  const defaultRpcEndpoint = config.rpcEndpoints[config.defaultRpcEndpointIndex];
310
529
  if (!defaultRpcEndpoint) {
311
530
  continue;
312
531
  }
313
532
  const { networkClientId } = defaultRpcEndpoint;
314
533
  const metadata = networksMetadata[networkClientId];
315
- // Determine status - default to 'unknown' if not in metadata
316
534
  const status = metadata?.status ?? 'unknown';
317
535
  chainStatuses[caip2ChainId] = {
318
536
  chainId: caip2ChainId,
@@ -321,84 +539,94 @@ _RpcDataSource_messenger = new WeakMap(), _RpcDataSource_timeout = new WeakMap()
321
539
  nativeCurrency: config.nativeCurrency,
322
540
  networkClientId,
323
541
  };
324
- // Only include chains that have an available status
325
- // (not degraded/unavailable/blocked)
326
542
  if (status === 'available' || status === 'unknown') {
327
543
  activeChains.push(caip2ChainId);
328
544
  }
329
545
  }
330
- // Update state
331
- this.state.chainStatuses = chainStatuses;
332
- // Update active chains and report to AssetsController
333
- this.updateActiveChains(activeChains, (chains) => __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', CONTROLLER_NAME, chains));
546
+ log('Network state updated', {
547
+ configuredChains: Object.keys(chainStatuses),
548
+ activeChains,
549
+ });
550
+ // Check if chains changed
551
+ const previousChains = new Set(__classPrivateFieldGet(this, _RpcDataSource_activeChains, "f"));
552
+ const hasChanges = previousChains.size !== activeChains.length ||
553
+ activeChains.some((chain) => !previousChains.has(chain));
554
+ // Update internal state
555
+ __classPrivateFieldSet(this, _RpcDataSource_chainStatuses, chainStatuses, "f");
556
+ __classPrivateFieldSet(this, _RpcDataSource_activeChains, activeChains, "f");
557
+ if (hasChanges) {
558
+ this.messenger.call('AssetsController:activeChainsUpdate', CONTROLLER_NAME, activeChains);
559
+ }
334
560
  }, _RpcDataSource_getProvider = function _RpcDataSource_getProvider(chainId) {
335
- // Check cache first
336
561
  const cached = __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").get(chainId);
337
562
  if (cached) {
338
563
  return cached;
339
564
  }
340
- // Get chain status to find networkClientId
341
- const chainStatus = this.state.chainStatuses[chainId];
565
+ const chainStatus = __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
342
566
  if (!chainStatus) {
343
567
  return undefined;
344
568
  }
345
569
  try {
346
- // Get network client from NetworkController (like TokenBalancesController)
347
- const networkClient = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('NetworkController:getNetworkClientById', chainStatus.networkClientId);
348
- // Create Web3Provider directly
570
+ const networkClient = this.messenger.call('NetworkController:getNetworkClientById', chainStatus.networkClientId);
349
571
  const web3Provider = new Web3Provider(networkClient.provider);
350
- // Cache for reuse
351
572
  __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").set(chainId, web3Provider);
352
573
  return web3Provider;
353
574
  }
354
575
  catch (error) {
355
- console.error(`[RpcDataSource] Failed to get provider for chain ${chainId}:`, error);
576
+ log('Failed to get provider for chain', { chainId, error });
356
577
  return undefined;
357
578
  }
579
+ }, _RpcDataSource_getMulticallProvider = function _RpcDataSource_getMulticallProvider(hexChainId) {
580
+ const decimalChainId = parseInt(hexChainId, 16);
581
+ const caip2ChainId = `eip155:${decimalChainId}`;
582
+ const web3Provider = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getProvider).call(this, caip2ChainId);
583
+ if (!web3Provider) {
584
+ throw new Error(`No provider available for chain ${hexChainId}`);
585
+ }
586
+ return {
587
+ call: async (params) => {
588
+ return web3Provider.call({
589
+ to: params.to,
590
+ data: params.data,
591
+ });
592
+ },
593
+ getBalance: async (address) => {
594
+ const balance = await web3Provider.getBalance(address);
595
+ return balance;
596
+ },
597
+ };
358
598
  }, _RpcDataSource_clearProviderCache = function _RpcDataSource_clearProviderCache() {
359
599
  __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
360
600
  }, _RpcDataSource_accountSupportsChain = function _RpcDataSource_accountSupportsChain(account, chainId) {
361
601
  const scopes = account.scopes ?? [];
362
- // If no scopes defined, assume it supports the chain (backward compatibility)
363
602
  if (scopes.length === 0) {
364
603
  return true;
365
604
  }
366
- // Extract namespace and reference from chainId (e.g., "eip155:1" -> ["eip155", "1"])
367
605
  const [chainNamespace, chainReference] = chainId.split(':');
368
606
  for (const scope of scopes) {
369
607
  const [scopeNamespace, scopeReference] = scope.split(':');
370
- // Check if namespaces match
371
608
  if (scopeNamespace !== chainNamespace) {
372
609
  continue;
373
610
  }
374
- // Wildcard scope (e.g., "eip155:0" means all chains in that namespace)
611
+ // Wildcard scope (e.g., eip155:0) matches all chains in the namespace
375
612
  if (scopeReference === '0') {
376
613
  return true;
377
614
  }
378
- // Exact match check - normalize hex to decimal for EIP155
379
- if (chainNamespace === 'eip155') {
380
- const normalizedScopeRef = scopeReference?.startsWith('0x')
381
- ? parseInt(scopeReference, 16).toString()
382
- : scopeReference;
383
- if (normalizedScopeRef === chainReference) {
384
- return true;
385
- }
386
- }
387
- else if (scopeReference === chainReference) {
615
+ // RpcDataSource only handles eip155 (EVM) chains
616
+ // Normalize hex chain references (e.g., 0x1 -> 1) for comparison
617
+ const normalizedScopeRef = scopeReference?.startsWith('0x')
618
+ ? parseInt(scopeReference, 16).toString()
619
+ : scopeReference;
620
+ if (normalizedScopeRef === chainReference) {
388
621
  return true;
389
622
  }
390
623
  }
391
624
  return false;
625
+ }, _RpcDataSource_buildNativeAssetId = function _RpcDataSource_buildNativeAssetId(chainId) {
626
+ const { nativeAssetIdentifiers } = this.messenger.call('NetworkEnablementController:getState');
627
+ return (nativeAssetIdentifiers[chainId] ??
628
+ `${chainId}/slip44:60`);
392
629
  };
393
- // ============================================================================
394
- // FACTORY FUNCTION
395
- // ============================================================================
396
- /**
397
- * Creates an RpcDataSource instance.
398
- *
399
- * @param options - Configuration options for the data source.
400
- * @returns A new RpcDataSource instance.
401
- */
402
630
  export function createRpcDataSource(options) {
403
631
  return new RpcDataSource(options);
404
632
  }