@metamask/assets-controller 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +20 -0
  3. package/README.md +15 -0
  4. package/dist/AssetsController.cjs +1057 -0
  5. package/dist/AssetsController.cjs.map +1 -0
  6. package/dist/AssetsController.d.cts +260 -0
  7. package/dist/AssetsController.d.cts.map +1 -0
  8. package/dist/AssetsController.d.mts +260 -0
  9. package/dist/AssetsController.d.mts.map +1 -0
  10. package/dist/AssetsController.mjs +1050 -0
  11. package/dist/AssetsController.mjs.map +1 -0
  12. package/dist/data-sources/AbstractDataSource.cjs +103 -0
  13. package/dist/data-sources/AbstractDataSource.cjs.map +1 -0
  14. package/dist/data-sources/AbstractDataSource.d.cts +92 -0
  15. package/dist/data-sources/AbstractDataSource.d.cts.map +1 -0
  16. package/dist/data-sources/AbstractDataSource.d.mts +92 -0
  17. package/dist/data-sources/AbstractDataSource.d.mts.map +1 -0
  18. package/dist/data-sources/AbstractDataSource.mjs +99 -0
  19. package/dist/data-sources/AbstractDataSource.mjs.map +1 -0
  20. package/dist/data-sources/AccountsApiDataSource.cjs +421 -0
  21. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -0
  22. package/dist/data-sources/AccountsApiDataSource.d.cts +103 -0
  23. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -0
  24. package/dist/data-sources/AccountsApiDataSource.d.mts +103 -0
  25. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -0
  26. package/dist/data-sources/AccountsApiDataSource.mjs +416 -0
  27. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -0
  28. package/dist/data-sources/BackendWebsocketDataSource.cjs +388 -0
  29. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -0
  30. package/dist/data-sources/BackendWebsocketDataSource.d.cts +95 -0
  31. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -0
  32. package/dist/data-sources/BackendWebsocketDataSource.d.mts +95 -0
  33. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -0
  34. package/dist/data-sources/BackendWebsocketDataSource.mjs +383 -0
  35. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -0
  36. package/dist/data-sources/PriceDataSource.cjs +343 -0
  37. package/dist/data-sources/PriceDataSource.cjs.map +1 -0
  38. package/dist/data-sources/PriceDataSource.d.cts +153 -0
  39. package/dist/data-sources/PriceDataSource.d.cts.map +1 -0
  40. package/dist/data-sources/PriceDataSource.d.mts +153 -0
  41. package/dist/data-sources/PriceDataSource.d.mts.map +1 -0
  42. package/dist/data-sources/PriceDataSource.mjs +339 -0
  43. package/dist/data-sources/PriceDataSource.mjs.map +1 -0
  44. package/dist/data-sources/RpcDataSource.cjs +829 -0
  45. package/dist/data-sources/RpcDataSource.cjs.map +1 -0
  46. package/dist/data-sources/RpcDataSource.d.cts +243 -0
  47. package/dist/data-sources/RpcDataSource.d.cts.map +1 -0
  48. package/dist/data-sources/RpcDataSource.d.mts +243 -0
  49. package/dist/data-sources/RpcDataSource.d.mts.map +1 -0
  50. package/dist/data-sources/RpcDataSource.mjs +820 -0
  51. package/dist/data-sources/RpcDataSource.mjs.map +1 -0
  52. package/dist/data-sources/SnapDataSource.cjs +463 -0
  53. package/dist/data-sources/SnapDataSource.cjs.map +1 -0
  54. package/dist/data-sources/SnapDataSource.d.cts +155 -0
  55. package/dist/data-sources/SnapDataSource.d.cts.map +1 -0
  56. package/dist/data-sources/SnapDataSource.d.mts +155 -0
  57. package/dist/data-sources/SnapDataSource.d.mts.map +1 -0
  58. package/dist/data-sources/SnapDataSource.mjs +456 -0
  59. package/dist/data-sources/SnapDataSource.mjs.map +1 -0
  60. package/dist/data-sources/TokenDataSource.cjs +211 -0
  61. package/dist/data-sources/TokenDataSource.cjs.map +1 -0
  62. package/dist/data-sources/TokenDataSource.d.cts +62 -0
  63. package/dist/data-sources/TokenDataSource.d.cts.map +1 -0
  64. package/dist/data-sources/TokenDataSource.d.mts +62 -0
  65. package/dist/data-sources/TokenDataSource.d.mts.map +1 -0
  66. package/dist/data-sources/TokenDataSource.mjs +207 -0
  67. package/dist/data-sources/TokenDataSource.mjs.map +1 -0
  68. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs +638 -0
  69. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.cjs.map +1 -0
  70. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.cts +47 -0
  71. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.cts.map +1 -0
  72. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.mts +47 -0
  73. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.d.mts.map +1 -0
  74. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.mjs +632 -0
  75. package/dist/data-sources/evm-rpc-services/clients/MulticallClient.mjs.map +1 -0
  76. package/dist/data-sources/evm-rpc-services/clients/index.cjs +8 -0
  77. package/dist/data-sources/evm-rpc-services/clients/index.cjs.map +1 -0
  78. package/dist/data-sources/evm-rpc-services/clients/index.d.cts +3 -0
  79. package/dist/data-sources/evm-rpc-services/clients/index.d.cts.map +1 -0
  80. package/dist/data-sources/evm-rpc-services/clients/index.d.mts +3 -0
  81. package/dist/data-sources/evm-rpc-services/clients/index.d.mts.map +1 -0
  82. package/dist/data-sources/evm-rpc-services/clients/index.mjs +2 -0
  83. package/dist/data-sources/evm-rpc-services/clients/index.mjs.map +1 -0
  84. package/dist/data-sources/evm-rpc-services/index.cjs +12 -0
  85. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -0
  86. package/dist/data-sources/evm-rpc-services/index.d.cts +5 -0
  87. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -0
  88. package/dist/data-sources/evm-rpc-services/index.d.mts +5 -0
  89. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -0
  90. package/dist/data-sources/evm-rpc-services/index.mjs +4 -0
  91. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -0
  92. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs +202 -0
  93. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs.map +1 -0
  94. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts +75 -0
  95. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts.map +1 -0
  96. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts +75 -0
  97. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts.map +1 -0
  98. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs +198 -0
  99. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs.map +1 -0
  100. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs +214 -0
  101. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -0
  102. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts +71 -0
  103. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -0
  104. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +71 -0
  105. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -0
  106. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs +210 -0
  107. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -0
  108. package/dist/data-sources/evm-rpc-services/services/index.cjs +8 -0
  109. package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -0
  110. package/dist/data-sources/evm-rpc-services/services/index.d.cts +3 -0
  111. package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -0
  112. package/dist/data-sources/evm-rpc-services/services/index.d.mts +3 -0
  113. package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -0
  114. package/dist/data-sources/evm-rpc-services/services/index.mjs +3 -0
  115. package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -0
  116. package/dist/data-sources/evm-rpc-services/types/assets.cjs +3 -0
  117. package/dist/data-sources/evm-rpc-services/types/assets.cjs.map +1 -0
  118. package/dist/data-sources/evm-rpc-services/types/assets.d.cts +53 -0
  119. package/dist/data-sources/evm-rpc-services/types/assets.d.cts.map +1 -0
  120. package/dist/data-sources/evm-rpc-services/types/assets.d.mts +53 -0
  121. package/dist/data-sources/evm-rpc-services/types/assets.d.mts.map +1 -0
  122. package/dist/data-sources/evm-rpc-services/types/assets.mjs +2 -0
  123. package/dist/data-sources/evm-rpc-services/types/assets.mjs.map +1 -0
  124. package/dist/data-sources/evm-rpc-services/types/config.cjs +3 -0
  125. package/dist/data-sources/evm-rpc-services/types/config.cjs.map +1 -0
  126. package/dist/data-sources/evm-rpc-services/types/config.d.cts +18 -0
  127. package/dist/data-sources/evm-rpc-services/types/config.d.cts.map +1 -0
  128. package/dist/data-sources/evm-rpc-services/types/config.d.mts +18 -0
  129. package/dist/data-sources/evm-rpc-services/types/config.d.mts.map +1 -0
  130. package/dist/data-sources/evm-rpc-services/types/config.mjs +2 -0
  131. package/dist/data-sources/evm-rpc-services/types/config.mjs.map +1 -0
  132. package/dist/data-sources/evm-rpc-services/types/core.cjs +3 -0
  133. package/dist/data-sources/evm-rpc-services/types/core.cjs.map +1 -0
  134. package/dist/data-sources/evm-rpc-services/types/core.d.cts +19 -0
  135. package/dist/data-sources/evm-rpc-services/types/core.d.cts.map +1 -0
  136. package/dist/data-sources/evm-rpc-services/types/core.d.mts +19 -0
  137. package/dist/data-sources/evm-rpc-services/types/core.d.mts.map +1 -0
  138. package/dist/data-sources/evm-rpc-services/types/core.mjs +2 -0
  139. package/dist/data-sources/evm-rpc-services/types/core.mjs.map +1 -0
  140. package/dist/data-sources/evm-rpc-services/types/index.cjs +3 -0
  141. package/dist/data-sources/evm-rpc-services/types/index.cjs.map +1 -0
  142. package/dist/data-sources/evm-rpc-services/types/index.d.cts +7 -0
  143. package/dist/data-sources/evm-rpc-services/types/index.d.cts.map +1 -0
  144. package/dist/data-sources/evm-rpc-services/types/index.d.mts +7 -0
  145. package/dist/data-sources/evm-rpc-services/types/index.d.mts.map +1 -0
  146. package/dist/data-sources/evm-rpc-services/types/index.mjs +2 -0
  147. package/dist/data-sources/evm-rpc-services/types/index.mjs.map +1 -0
  148. package/dist/data-sources/evm-rpc-services/types/multicall.cjs +3 -0
  149. package/dist/data-sources/evm-rpc-services/types/multicall.cjs.map +1 -0
  150. package/dist/data-sources/evm-rpc-services/types/multicall.d.cts +24 -0
  151. package/dist/data-sources/evm-rpc-services/types/multicall.d.cts.map +1 -0
  152. package/dist/data-sources/evm-rpc-services/types/multicall.d.mts +24 -0
  153. package/dist/data-sources/evm-rpc-services/types/multicall.d.mts.map +1 -0
  154. package/dist/data-sources/evm-rpc-services/types/multicall.mjs +2 -0
  155. package/dist/data-sources/evm-rpc-services/types/multicall.mjs.map +1 -0
  156. package/dist/data-sources/evm-rpc-services/types/services.cjs +3 -0
  157. package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -0
  158. package/dist/data-sources/evm-rpc-services/types/services.d.cts +74 -0
  159. package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -0
  160. package/dist/data-sources/evm-rpc-services/types/services.d.mts +74 -0
  161. package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -0
  162. package/dist/data-sources/evm-rpc-services/types/services.mjs +2 -0
  163. package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -0
  164. package/dist/data-sources/evm-rpc-services/types/state.cjs +3 -0
  165. package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -0
  166. package/dist/data-sources/evm-rpc-services/types/state.d.cts +52 -0
  167. package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -0
  168. package/dist/data-sources/evm-rpc-services/types/state.d.mts +52 -0
  169. package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -0
  170. package/dist/data-sources/evm-rpc-services/types/state.mjs +2 -0
  171. package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -0
  172. package/dist/data-sources/evm-rpc-services/utils/batch.cjs +45 -0
  173. package/dist/data-sources/evm-rpc-services/utils/batch.cjs.map +1 -0
  174. package/dist/data-sources/evm-rpc-services/utils/batch.d.cts +28 -0
  175. package/dist/data-sources/evm-rpc-services/utils/batch.d.cts.map +1 -0
  176. package/dist/data-sources/evm-rpc-services/utils/batch.d.mts +28 -0
  177. package/dist/data-sources/evm-rpc-services/utils/batch.d.mts.map +1 -0
  178. package/dist/data-sources/evm-rpc-services/utils/batch.mjs +40 -0
  179. package/dist/data-sources/evm-rpc-services/utils/batch.mjs.map +1 -0
  180. package/dist/data-sources/evm-rpc-services/utils/index.cjs +7 -0
  181. package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -0
  182. package/dist/data-sources/evm-rpc-services/utils/index.d.cts +2 -0
  183. package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -0
  184. package/dist/data-sources/evm-rpc-services/utils/index.d.mts +2 -0
  185. package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -0
  186. package/dist/data-sources/evm-rpc-services/utils/index.mjs +2 -0
  187. package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -0
  188. package/dist/data-sources/index.cjs +33 -0
  189. package/dist/data-sources/index.cjs.map +1 -0
  190. package/dist/data-sources/index.d.cts +9 -0
  191. package/dist/data-sources/index.d.cts.map +1 -0
  192. package/dist/data-sources/index.d.mts +9 -0
  193. package/dist/data-sources/index.d.mts.map +1 -0
  194. package/dist/data-sources/index.mjs +15 -0
  195. package/dist/data-sources/index.mjs.map +1 -0
  196. package/dist/data-sources/initDataSources.cjs +215 -0
  197. package/dist/data-sources/initDataSources.cjs.map +1 -0
  198. package/dist/data-sources/initDataSources.d.cts +140 -0
  199. package/dist/data-sources/initDataSources.d.cts.map +1 -0
  200. package/dist/data-sources/initDataSources.d.mts +140 -0
  201. package/dist/data-sources/initDataSources.d.mts.map +1 -0
  202. package/dist/data-sources/initDataSources.mjs +210 -0
  203. package/dist/data-sources/initDataSources.mjs.map +1 -0
  204. package/dist/index.cjs +47 -0
  205. package/dist/index.cjs.map +1 -0
  206. package/dist/index.d.cts +21 -0
  207. package/dist/index.d.cts.map +1 -0
  208. package/dist/index.d.mts +21 -0
  209. package/dist/index.d.mts.map +1 -0
  210. package/dist/index.mjs +25 -0
  211. package/dist/index.mjs.map +1 -0
  212. package/dist/logger.cjs +7 -0
  213. package/dist/logger.cjs.map +1 -0
  214. package/dist/logger.d.cts +5 -0
  215. package/dist/logger.d.cts.map +1 -0
  216. package/dist/logger.d.mts +5 -0
  217. package/dist/logger.d.mts.map +1 -0
  218. package/dist/logger.mjs +4 -0
  219. package/dist/logger.mjs.map +1 -0
  220. package/dist/middlewares/DetectionMiddleware.cjs +101 -0
  221. package/dist/middlewares/DetectionMiddleware.cjs.map +1 -0
  222. package/dist/middlewares/DetectionMiddleware.d.cts +54 -0
  223. package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -0
  224. package/dist/middlewares/DetectionMiddleware.d.mts +54 -0
  225. package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -0
  226. package/dist/middlewares/DetectionMiddleware.mjs +97 -0
  227. package/dist/middlewares/DetectionMiddleware.mjs.map +1 -0
  228. package/dist/middlewares/index.cjs +6 -0
  229. package/dist/middlewares/index.cjs.map +1 -0
  230. package/dist/middlewares/index.d.cts +2 -0
  231. package/dist/middlewares/index.d.cts.map +1 -0
  232. package/dist/middlewares/index.d.mts +2 -0
  233. package/dist/middlewares/index.d.mts.map +1 -0
  234. package/dist/middlewares/index.mjs +2 -0
  235. package/dist/middlewares/index.mjs.map +1 -0
  236. package/dist/types.cjs +39 -0
  237. package/dist/types.cjs.map +1 -0
  238. package/dist/types.d.cts +433 -0
  239. package/dist/types.d.cts.map +1 -0
  240. package/dist/types.d.mts +433 -0
  241. package/dist/types.d.mts.map +1 -0
  242. package/dist/types.mjs +35 -0
  243. package/dist/types.mjs.map +1 -0
  244. package/dist/utils.cjs +28 -0
  245. package/dist/utils.cjs.map +1 -0
  246. package/dist/utils.d.cts +13 -0
  247. package/dist/utils.d.cts.map +1 -0
  248. package/dist/utils.d.mts +13 -0
  249. package/dist/utils.d.mts.map +1 -0
  250. package/dist/utils.mjs +24 -0
  251. package/dist/utils.mjs.map +1 -0
  252. package/package.json +93 -0
@@ -0,0 +1,829 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _RpcDataSource_instances, _RpcDataSource_timeout, _RpcDataSource_tokenDetectionEnabled, _RpcDataSource_activeChains, _RpcDataSource_chainStatuses, _RpcDataSource_providerCache, _RpcDataSource_activeSubscriptions, _RpcDataSource_multicallClient, _RpcDataSource_balanceFetcher, _RpcDataSource_tokenDetector, _RpcDataSource_convertToHumanReadable, _RpcDataSource_collectMetadataForBalances, _RpcDataSource_handleBalanceUpdate, _RpcDataSource_handleDetectionUpdate, _RpcDataSource_registerActionHandlers, _RpcDataSource_subscribeToNetworkController, _RpcDataSource_initializeFromNetworkController, _RpcDataSource_updateFromNetworkState, _RpcDataSource_getProvider, _RpcDataSource_getMulticallProvider, _RpcDataSource_clearProviderCache, _RpcDataSource_accountSupportsChain, _RpcDataSource_buildNativeAssetId, _RpcDataSource_getExistingAssetsMetadata, _RpcDataSource_getTokenMetadataFromTokenList;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.createRpcDataSource = exports.RpcDataSource = exports.caipChainIdToHex = void 0;
19
+ const providers_1 = require("@ethersproject/providers");
20
+ const base_controller_1 = require("@metamask/base-controller");
21
+ const controller_utils_1 = require("@metamask/controller-utils");
22
+ const utils_1 = require("@metamask/utils");
23
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
24
+ const evm_rpc_services_1 = require("./evm-rpc-services/index.cjs");
25
+ const logger_1 = require("../logger.cjs");
26
+ const CONTROLLER_NAME = 'RpcDataSource';
27
+ const DEFAULT_BALANCE_INTERVAL = 30000; // 30 seconds
28
+ const DEFAULT_DETECTION_INTERVAL = 180000; // 3 minutes
29
+ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, CONTROLLER_NAME);
30
+ /**
31
+ * Convert CAIP chain ID or hex chain ID to hex chain ID.
32
+ *
33
+ * @param chainId - CAIP chain ID or hex chain ID.
34
+ * @returns Hex chain ID.
35
+ */
36
+ const caipChainIdToHex = (chainId) => {
37
+ if ((0, utils_1.isStrictHexString)(chainId)) {
38
+ return chainId;
39
+ }
40
+ if ((0, utils_1.isCaipChainId)(chainId)) {
41
+ return (0, controller_utils_1.toHex)((0, utils_1.parseCaipChainId)(chainId).reference);
42
+ }
43
+ throw new Error('caipChainIdToHex - Failed to provide CAIP-2 or Hex chainId');
44
+ };
45
+ exports.caipChainIdToHex = caipChainIdToHex;
46
+ /**
47
+ * Data source for fetching balances via RPC calls.
48
+ *
49
+ * Orchestrates polling through BalanceFetcher and TokenDetector,
50
+ * each of which handle their own polling intervals.
51
+ *
52
+ * Communicates with AssetsController via Messenger:
53
+ *
54
+ * Actions:
55
+ * - RpcDataSource:getActiveChains
56
+ * - RpcDataSource:fetch
57
+ * - RpcDataSource:subscribe
58
+ * - RpcDataSource:unsubscribe
59
+ *
60
+ * Events:
61
+ * - RpcDataSource:activeChainsUpdated
62
+ * - RpcDataSource:assetsUpdated
63
+ */
64
+ class RpcDataSource extends base_controller_1.BaseController {
65
+ constructor(options) {
66
+ super({
67
+ name: CONTROLLER_NAME,
68
+ metadata: {},
69
+ state: {},
70
+ messenger: options.messenger,
71
+ });
72
+ _RpcDataSource_instances.add(this);
73
+ _RpcDataSource_timeout.set(this, void 0);
74
+ _RpcDataSource_tokenDetectionEnabled.set(this, void 0);
75
+ /** Currently active chains */
76
+ _RpcDataSource_activeChains.set(this, []);
77
+ /** Network status for each active chain */
78
+ _RpcDataSource_chainStatuses.set(this, {});
79
+ /** Cache of Web3Provider instances by chainId */
80
+ _RpcDataSource_providerCache.set(this, new Map());
81
+ /** Active subscriptions by ID */
82
+ _RpcDataSource_activeSubscriptions.set(this, new Map());
83
+ // Rpc-datasource components
84
+ _RpcDataSource_multicallClient.set(this, void 0);
85
+ _RpcDataSource_balanceFetcher.set(this, void 0);
86
+ _RpcDataSource_tokenDetector.set(this, void 0);
87
+ __classPrivateFieldSet(this, _RpcDataSource_timeout, options.timeout ?? 10000, "f");
88
+ __classPrivateFieldSet(this, _RpcDataSource_tokenDetectionEnabled, options.tokenDetectionEnabled ?? false, "f");
89
+ const balanceInterval = options.balanceInterval ?? DEFAULT_BALANCE_INTERVAL;
90
+ const detectionInterval = options.detectionInterval ?? DEFAULT_DETECTION_INTERVAL;
91
+ log('Initializing RpcDataSource', {
92
+ timeout: __classPrivateFieldGet(this, _RpcDataSource_timeout, "f"),
93
+ balanceInterval,
94
+ detectionInterval,
95
+ tokenDetectionEnabled: __classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f"),
96
+ });
97
+ // Initialize MulticallClient with a provider getter
98
+ __classPrivateFieldSet(this, _RpcDataSource_multicallClient, new evm_rpc_services_1.MulticallClient((hexChainId) => {
99
+ return __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getMulticallProvider).call(this, hexChainId);
100
+ }), "f");
101
+ // Create messenger adapters for BalanceFetcher and TokenDetector
102
+ const balanceFetcherMessenger = {
103
+ call: (_action) => {
104
+ const state = this.messenger.call('AssetsController:getState');
105
+ return {
106
+ assetsBalance: (state.assetsBalance ?? {}),
107
+ };
108
+ },
109
+ };
110
+ const tokenDetectorMessenger = {
111
+ call: (_action) => {
112
+ return this.messenger.call('TokenListController:getState');
113
+ },
114
+ };
115
+ // Initialize BalanceFetcher with polling interval
116
+ __classPrivateFieldSet(this, _RpcDataSource_balanceFetcher, new evm_rpc_services_1.BalanceFetcher(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), balanceFetcherMessenger, { pollingInterval: balanceInterval }), "f");
117
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").setOnBalanceUpdate(__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_handleBalanceUpdate).bind(this));
118
+ // Initialize TokenDetector with polling interval
119
+ __classPrivateFieldSet(this, _RpcDataSource_tokenDetector, new evm_rpc_services_1.TokenDetector(__classPrivateFieldGet(this, _RpcDataSource_multicallClient, "f"), tokenDetectorMessenger, { pollingInterval: detectionInterval }), "f");
120
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").setOnDetectionUpdate(__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_handleDetectionUpdate).bind(this));
121
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_registerActionHandlers).call(this);
122
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_subscribeToNetworkController).call(this);
123
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_initializeFromNetworkController).call(this);
124
+ }
125
+ /**
126
+ * Get the data source name.
127
+ *
128
+ * @returns The name of this data source.
129
+ */
130
+ getName() {
131
+ return this.name;
132
+ }
133
+ /**
134
+ * Get currently active chains.
135
+ *
136
+ * @returns Promise resolving to array of active chain IDs.
137
+ */
138
+ async getActiveChains() {
139
+ return __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f");
140
+ }
141
+ /**
142
+ * Get the status of all configured chains.
143
+ *
144
+ * @returns Record of chain statuses keyed by chain ID.
145
+ */
146
+ getChainStatuses() {
147
+ return { ...__classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f") };
148
+ }
149
+ /**
150
+ * Get the status of a specific chain.
151
+ *
152
+ * @param chainId - The chain ID to get status for.
153
+ * @returns The chain status or undefined if not found.
154
+ */
155
+ getChainStatus(chainId) {
156
+ return __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
157
+ }
158
+ /**
159
+ * Set the balance polling interval.
160
+ *
161
+ * @param interval - The polling interval in milliseconds.
162
+ */
163
+ setBalancePollingInterval(interval) {
164
+ log('Setting balance polling interval', { interval });
165
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").setIntervalLength(interval);
166
+ }
167
+ /**
168
+ * Get the current balance polling interval.
169
+ *
170
+ * @returns The polling interval in milliseconds, or undefined if not set.
171
+ */
172
+ getBalancePollingInterval() {
173
+ return __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").getIntervalLength();
174
+ }
175
+ /**
176
+ * Set the token detection polling interval.
177
+ *
178
+ * @param interval - The polling interval in milliseconds.
179
+ */
180
+ setDetectionPollingInterval(interval) {
181
+ log('Setting detection polling interval', { interval });
182
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").setIntervalLength(interval);
183
+ }
184
+ /**
185
+ * Get the current token detection polling interval.
186
+ *
187
+ * @returns The polling interval in milliseconds, or undefined if not set.
188
+ */
189
+ getDetectionPollingInterval() {
190
+ return __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").getIntervalLength();
191
+ }
192
+ async fetch(request) {
193
+ const response = {};
194
+ const chainsToFetch = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
195
+ log('Fetch requested', {
196
+ accounts: request.accounts.map((a) => a.id),
197
+ requestedChains: request.chainIds,
198
+ chainsToFetch,
199
+ });
200
+ if (chainsToFetch.length === 0) {
201
+ log('No active chains to fetch');
202
+ return response;
203
+ }
204
+ const assetsBalance = {};
205
+ const assetsMetadata = {};
206
+ const failedChains = [];
207
+ // Fetch balances for each chain using BalanceFetcher
208
+ for (const chainId of chainsToFetch) {
209
+ const hexChainId = (0, exports.caipChainIdToHex)(chainId);
210
+ for (const account of request.accounts) {
211
+ if (!__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_accountSupportsChain).call(this, account, chainId)) {
212
+ continue;
213
+ }
214
+ const { address, id: accountId } = account;
215
+ try {
216
+ // Use BalanceFetcher for batched balance fetching
217
+ const result = await __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").fetchBalancesForTokens(hexChainId, accountId, address, [], // Empty array means just native token
218
+ { includeNative: true });
219
+ if (!assetsBalance[accountId]) {
220
+ assetsBalance[accountId] = {};
221
+ }
222
+ // Collect metadata for all balances
223
+ const balanceMetadata = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_collectMetadataForBalances).call(this, result.balances, chainId);
224
+ Object.assign(assetsMetadata, balanceMetadata);
225
+ // Convert balances to human-readable format
226
+ for (const balance of result.balances) {
227
+ const metadata = assetsMetadata[balance.assetId];
228
+ // Default to 18 decimals (ERC20 standard) for consistent human-readable format
229
+ const decimals = metadata?.decimals ?? 18;
230
+ const humanReadableAmount = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_convertToHumanReadable).call(this, balance.balance, decimals);
231
+ assetsBalance[accountId][balance.assetId] = {
232
+ amount: humanReadableAmount,
233
+ };
234
+ }
235
+ }
236
+ catch (error) {
237
+ log('Failed to fetch balance', { address, chainId, error });
238
+ if (!assetsBalance[accountId]) {
239
+ assetsBalance[accountId] = {};
240
+ }
241
+ const nativeAssetId = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_buildNativeAssetId).call(this, chainId);
242
+ assetsBalance[accountId][nativeAssetId] = { amount: '0' };
243
+ // Even on error, include native token metadata
244
+ const chainStatus = __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
245
+ if (chainStatus) {
246
+ assetsMetadata[nativeAssetId] = {
247
+ type: 'native',
248
+ symbol: chainStatus.nativeCurrency,
249
+ name: chainStatus.nativeCurrency,
250
+ decimals: 18,
251
+ };
252
+ }
253
+ if (!failedChains.includes(chainId)) {
254
+ failedChains.push(chainId);
255
+ }
256
+ }
257
+ }
258
+ }
259
+ if (failedChains.length > 0) {
260
+ log('Fetch PARTIAL - some chains failed', {
261
+ successChains: chainsToFetch.filter((chain) => !failedChains.includes(chain)),
262
+ failedChains,
263
+ });
264
+ response.errors = {};
265
+ for (const chainId of failedChains) {
266
+ response.errors[chainId] = 'RPC fetch failed';
267
+ }
268
+ }
269
+ else {
270
+ log('Fetch SUCCESS', {
271
+ chains: chainsToFetch,
272
+ accountCount: Object.keys(assetsBalance).length,
273
+ });
274
+ }
275
+ response.assetsBalance = assetsBalance;
276
+ // Include metadata for native tokens if we have any
277
+ if (Object.keys(assetsMetadata).length > 0) {
278
+ response.assetsMetadata = assetsMetadata;
279
+ }
280
+ return response;
281
+ }
282
+ /**
283
+ * Run token detection for an account on a chain.
284
+ *
285
+ * @param chainId - The chain ID to detect tokens on.
286
+ * @param account - The account to detect tokens for.
287
+ * @returns Promise resolving to a DataResponse with detected assets.
288
+ */
289
+ async detectTokens(chainId, account) {
290
+ if (!__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f")) {
291
+ return {};
292
+ }
293
+ const hexChainId = (0, exports.caipChainIdToHex)(chainId);
294
+ const { address, id: accountId } = account;
295
+ log('Running token detection', { chainId, accountId });
296
+ try {
297
+ const result = await __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").detectTokens(hexChainId, accountId, address);
298
+ if (result.detectedAssets.length === 0) {
299
+ log('No new tokens detected');
300
+ return {};
301
+ }
302
+ log('Detected new tokens', {
303
+ count: result.detectedAssets.length,
304
+ chainId,
305
+ accountId,
306
+ });
307
+ // Convert detected assets to DataResponse format
308
+ const balances = {};
309
+ const assetsMetadata = {};
310
+ // Build metadata from detected assets
311
+ for (const asset of result.detectedAssets) {
312
+ if (asset.symbol && asset.decimals !== undefined) {
313
+ assetsMetadata[asset.assetId] = {
314
+ type: 'erc20',
315
+ symbol: asset.symbol,
316
+ name: asset.name ?? asset.symbol,
317
+ decimals: asset.decimals,
318
+ image: asset.image,
319
+ };
320
+ }
321
+ }
322
+ // Add balances for detected tokens (converted to human-readable format)
323
+ for (const balance of result.detectedBalances) {
324
+ const detectedAsset = result.detectedAssets.find((asset) => asset.assetId === balance.assetId);
325
+ // Default to 18 decimals (ERC20 standard) for consistent human-readable format
326
+ const decimals = detectedAsset?.decimals ?? 18;
327
+ const humanReadableAmount = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_convertToHumanReadable).call(this, balance.balance, decimals);
328
+ balances[balance.assetId] = {
329
+ amount: humanReadableAmount,
330
+ };
331
+ }
332
+ const response = {
333
+ detectedAssets: {
334
+ [accountId]: result.detectedAssets.map((asset) => asset.assetId),
335
+ },
336
+ assetsBalance: {
337
+ [accountId]: balances,
338
+ },
339
+ };
340
+ // Include metadata if we have any
341
+ if (Object.keys(assetsMetadata).length > 0) {
342
+ response.assetsMetadata = assetsMetadata;
343
+ }
344
+ return response;
345
+ }
346
+ catch (error) {
347
+ log('Token detection failed', { chainId, accountId, error });
348
+ return {};
349
+ }
350
+ }
351
+ get assetsMiddleware() {
352
+ return async (context, next) => {
353
+ var _a, _b, _c;
354
+ const { request } = context;
355
+ const supportedChains = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
356
+ if (supportedChains.length === 0) {
357
+ return next(context);
358
+ }
359
+ let successfullyHandledChains = [];
360
+ log('Middleware fetching', {
361
+ chains: supportedChains,
362
+ accounts: request.accounts.map((a) => a.id),
363
+ });
364
+ const response = await this.fetch({
365
+ ...request,
366
+ chainIds: supportedChains,
367
+ });
368
+ if (response.assetsBalance) {
369
+ (_a = context.response).assetsBalance ?? (_a.assetsBalance = {});
370
+ for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
371
+ (_b = context.response.assetsBalance)[accountId] ?? (_b[accountId] = {});
372
+ context.response.assetsBalance[accountId] = {
373
+ ...context.response.assetsBalance[accountId],
374
+ ...accountBalances,
375
+ };
376
+ }
377
+ }
378
+ if (response.assetsMetadata) {
379
+ (_c = context.response).assetsMetadata ?? (_c.assetsMetadata = {});
380
+ context.response.assetsMetadata = {
381
+ ...context.response.assetsMetadata,
382
+ ...response.assetsMetadata,
383
+ };
384
+ }
385
+ const failedChains = new Set(Object.keys(response.errors ?? {}));
386
+ successfullyHandledChains = supportedChains.filter((chainId) => !failedChains.has(chainId));
387
+ if (successfullyHandledChains.length > 0) {
388
+ const remainingChains = request.chainIds.filter((chainId) => !successfullyHandledChains.includes(chainId));
389
+ return next({
390
+ ...context,
391
+ request: {
392
+ ...request,
393
+ chainIds: remainingChains,
394
+ },
395
+ });
396
+ }
397
+ return next(context);
398
+ };
399
+ }
400
+ /**
401
+ * Subscribe to updates for the given request.
402
+ * Starts polling through BalanceFetcher and TokenDetector.
403
+ *
404
+ * @param subscriptionRequest - The subscription request details.
405
+ */
406
+ async subscribe(subscriptionRequest) {
407
+ const { request, subscriptionId, isUpdate } = subscriptionRequest;
408
+ const chainsToSubscribe = request.chainIds.filter((chainId) => __classPrivateFieldGet(this, _RpcDataSource_activeChains, "f").includes(chainId));
409
+ log('Subscribe requested', {
410
+ subscriptionId,
411
+ isUpdate,
412
+ accounts: request.accounts.map((a) => a.id),
413
+ chainsToSubscribe,
414
+ });
415
+ if (chainsToSubscribe.length === 0) {
416
+ log('No active chains to subscribe');
417
+ return;
418
+ }
419
+ // Handle subscription update - restart polling for new chains
420
+ if (isUpdate) {
421
+ const existing = __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").get(subscriptionId);
422
+ if (existing) {
423
+ log('Updating existing subscription - restarting polling', {
424
+ subscriptionId,
425
+ existingChains: existing.chains,
426
+ newChains: chainsToSubscribe,
427
+ });
428
+ // Don't return early - continue to unsubscribe and restart polling
429
+ }
430
+ }
431
+ // Clean up existing subscription (stops old polling)
432
+ await this.unsubscribe(subscriptionId);
433
+ // Start polling through BalanceFetcher and TokenDetector
434
+ const balancePollingTokens = [];
435
+ const detectionPollingTokens = [];
436
+ for (const chainId of chainsToSubscribe) {
437
+ const hexChainId = (0, exports.caipChainIdToHex)(chainId);
438
+ for (const account of request.accounts) {
439
+ if (!__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_accountSupportsChain).call(this, account, chainId)) {
440
+ continue;
441
+ }
442
+ const { address, id: accountId } = account;
443
+ // Start balance polling
444
+ const balanceInput = {
445
+ chainId: hexChainId,
446
+ accountId,
447
+ accountAddress: address,
448
+ };
449
+ const balanceToken = __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").startPolling(balanceInput);
450
+ balancePollingTokens.push(balanceToken);
451
+ // Start detection polling if enabled
452
+ if (__classPrivateFieldGet(this, _RpcDataSource_tokenDetectionEnabled, "f")) {
453
+ const detectionInput = {
454
+ chainId: hexChainId,
455
+ accountId,
456
+ accountAddress: address,
457
+ };
458
+ const detectionToken = __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").startPolling(detectionInput);
459
+ detectionPollingTokens.push(detectionToken);
460
+ }
461
+ }
462
+ }
463
+ // Store subscription data
464
+ __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").set(subscriptionId, {
465
+ balancePollingTokens,
466
+ detectionPollingTokens,
467
+ chains: chainsToSubscribe,
468
+ accounts: request.accounts,
469
+ });
470
+ log('Subscription SUCCESS', {
471
+ subscriptionId,
472
+ chains: chainsToSubscribe,
473
+ balancePollingCount: balancePollingTokens.length,
474
+ detectionPollingCount: detectionPollingTokens.length,
475
+ });
476
+ }
477
+ /**
478
+ * Unsubscribe from updates and stop polling.
479
+ *
480
+ * @param subscriptionId - The subscription ID to unsubscribe.
481
+ */
482
+ async unsubscribe(subscriptionId) {
483
+ const subscription = __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").get(subscriptionId);
484
+ if (subscription) {
485
+ // Stop balance polling
486
+ for (const token of subscription.balancePollingTokens) {
487
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").stopPollingByPollingToken(token);
488
+ }
489
+ // Stop detection polling
490
+ for (const token of subscription.detectionPollingTokens) {
491
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").stopPollingByPollingToken(token);
492
+ }
493
+ __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").delete(subscriptionId);
494
+ log('Unsubscribed and stopped polling', { subscriptionId });
495
+ }
496
+ }
497
+ /**
498
+ * Destroy the data source and clean up resources.
499
+ */
500
+ destroy() {
501
+ log('Destroying RpcDataSource');
502
+ // Stop all polling
503
+ __classPrivateFieldGet(this, _RpcDataSource_balanceFetcher, "f").stopAllPolling();
504
+ __classPrivateFieldGet(this, _RpcDataSource_tokenDetector, "f").stopAllPolling();
505
+ // Clear subscriptions
506
+ __classPrivateFieldGet(this, _RpcDataSource_activeSubscriptions, "f").clear();
507
+ // Clear caches
508
+ __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
509
+ }
510
+ }
511
+ exports.RpcDataSource = RpcDataSource;
512
+ _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_convertToHumanReadable = function _RpcDataSource_convertToHumanReadable(rawBalance, decimals) {
513
+ const rawAmount = new bignumber_js_1.default(rawBalance);
514
+ const divisor = new bignumber_js_1.default(10).pow(decimals);
515
+ return rawAmount.dividedBy(divisor).toString();
516
+ }, _RpcDataSource_collectMetadataForBalances = function _RpcDataSource_collectMetadataForBalances(balances, chainId) {
517
+ const assetsMetadata = {};
518
+ const existingMetadata = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getExistingAssetsMetadata).call(this);
519
+ for (const balance of balances) {
520
+ const isNative = balance.assetId.includes('/slip44:');
521
+ if (isNative) {
522
+ const chainStatus = __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
523
+ if (chainStatus) {
524
+ assetsMetadata[balance.assetId] = {
525
+ type: 'native',
526
+ symbol: chainStatus.nativeCurrency,
527
+ name: chainStatus.nativeCurrency,
528
+ decimals: 18,
529
+ };
530
+ }
531
+ }
532
+ else {
533
+ // For ERC20 tokens, try existing metadata from state first
534
+ const existingMeta = existingMetadata[balance.assetId];
535
+ if (existingMeta) {
536
+ assetsMetadata[balance.assetId] = existingMeta;
537
+ }
538
+ else {
539
+ // Fallback to token list if not in state
540
+ const tokenListMeta = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getTokenMetadataFromTokenList).call(this, balance.assetId);
541
+ if (tokenListMeta) {
542
+ assetsMetadata[balance.assetId] = tokenListMeta;
543
+ }
544
+ else {
545
+ // Default metadata for unknown ERC20 tokens.
546
+ // Use 18 decimals (the standard for most ERC20 tokens)
547
+ // to ensure consistent human-readable balance format.
548
+ assetsMetadata[balance.assetId] = {
549
+ type: 'erc20',
550
+ symbol: '',
551
+ name: '',
552
+ decimals: 18,
553
+ };
554
+ }
555
+ }
556
+ }
557
+ }
558
+ return assetsMetadata;
559
+ }, _RpcDataSource_handleBalanceUpdate = function _RpcDataSource_handleBalanceUpdate(result) {
560
+ const newBalances = {};
561
+ // Convert hex chain ID to CAIP-2 format
562
+ const chainIdDecimal = parseInt(result.chainId, 16);
563
+ const caipChainId = `eip155:${chainIdDecimal}`;
564
+ // Collect metadata for all balances
565
+ const assetsMetadata = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_collectMetadataForBalances).call(this, result.balances, caipChainId);
566
+ // Convert balances to human-readable format using metadata
567
+ for (const balance of result.balances) {
568
+ const metadata = assetsMetadata[balance.assetId];
569
+ // Default to 18 decimals (ERC20 standard) for consistent human-readable format
570
+ const decimals = metadata?.decimals ?? 18;
571
+ const humanReadableAmount = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_convertToHumanReadable).call(this, balance.balance, decimals);
572
+ newBalances[balance.assetId] = {
573
+ amount: humanReadableAmount,
574
+ };
575
+ }
576
+ // Only send new data to AssetsController - it handles merging atomically
577
+ // to avoid race conditions when concurrent updates occur for the same account
578
+ const response = {
579
+ assetsBalance: {
580
+ [result.accountId]: newBalances,
581
+ },
582
+ assetsMetadata,
583
+ };
584
+ log('Balance update response', {
585
+ accountId: result.accountId,
586
+ newBalanceCount: Object.keys(newBalances).length,
587
+ });
588
+ this.messenger
589
+ .call('AssetsController:assetsUpdate', response, CONTROLLER_NAME)
590
+ .catch((error) => {
591
+ log('Failed to update assets', { error });
592
+ });
593
+ }, _RpcDataSource_handleDetectionUpdate = function _RpcDataSource_handleDetectionUpdate(result) {
594
+ log('Detected new tokens', {
595
+ count: result.detectedAssets.length,
596
+ });
597
+ // Build new metadata from detected assets
598
+ const newMetadata = {};
599
+ if (result.detectedAssets.length > 0) {
600
+ for (const asset of result.detectedAssets) {
601
+ // Only include if we have metadata (symbol and decimals at minimum)
602
+ if (asset.symbol && asset.decimals !== undefined) {
603
+ newMetadata[asset.assetId] = {
604
+ type: 'erc20',
605
+ symbol: asset.symbol,
606
+ name: asset.name ?? asset.symbol,
607
+ decimals: asset.decimals,
608
+ image: asset.image,
609
+ };
610
+ }
611
+ }
612
+ }
613
+ // Build new balances from detected tokens
614
+ const newBalances = {};
615
+ if (result.detectedBalances.length > 0) {
616
+ for (const balance of result.detectedBalances) {
617
+ // Get decimals from the detected asset metadata
618
+ const detectedAsset = result.detectedAssets.find((asset) => asset.assetId === balance.assetId);
619
+ // Default to 18 decimals (ERC20 standard) for consistent human-readable format
620
+ const decimals = detectedAsset?.decimals ?? 18;
621
+ const humanReadableAmount = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_convertToHumanReadable).call(this, balance.balance, decimals);
622
+ newBalances[balance.assetId] = {
623
+ amount: humanReadableAmount,
624
+ };
625
+ }
626
+ }
627
+ // Only send new data to AssetsController - it handles merging atomically
628
+ // to avoid race conditions when concurrent updates occur for the same account
629
+ const response = {
630
+ detectedAssets: {
631
+ [result.accountId]: result.detectedAssets.map((asset) => asset.assetId),
632
+ },
633
+ assetsMetadata: newMetadata,
634
+ assetsBalance: {
635
+ [result.accountId]: newBalances,
636
+ },
637
+ };
638
+ this.messenger
639
+ .call('AssetsController:assetsUpdate', response, CONTROLLER_NAME)
640
+ .catch((error) => {
641
+ log('Failed to update detected assets', { error });
642
+ });
643
+ }, _RpcDataSource_registerActionHandlers = function _RpcDataSource_registerActionHandlers() {
644
+ const getAssetsMiddlewareHandler = () => this.assetsMiddleware;
645
+ const getActiveChainsHandler = async () => this.getActiveChains();
646
+ const fetchHandler = async (request) => this.fetch(request);
647
+ const subscribeHandler = async (request) => this.subscribe(request);
648
+ const unsubscribeHandler = async (subscriptionId) => this.unsubscribe(subscriptionId);
649
+ this.messenger.registerActionHandler('RpcDataSource:getAssetsMiddleware', getAssetsMiddlewareHandler);
650
+ this.messenger.registerActionHandler('RpcDataSource:getActiveChains', getActiveChainsHandler);
651
+ this.messenger.registerActionHandler('RpcDataSource:fetch', fetchHandler);
652
+ this.messenger.registerActionHandler('RpcDataSource:subscribe', subscribeHandler);
653
+ this.messenger.registerActionHandler('RpcDataSource:unsubscribe', unsubscribeHandler);
654
+ }, _RpcDataSource_subscribeToNetworkController = function _RpcDataSource_subscribeToNetworkController() {
655
+ this.messenger.subscribe('NetworkController:stateChange', (networkState) => {
656
+ log('NetworkController state changed');
657
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_clearProviderCache).call(this);
658
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
659
+ });
660
+ }, _RpcDataSource_initializeFromNetworkController = function _RpcDataSource_initializeFromNetworkController() {
661
+ log('Initializing from NetworkController');
662
+ try {
663
+ const networkState = this.messenger.call('NetworkController:getState');
664
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
665
+ }
666
+ catch (error) {
667
+ log('Failed to initialize from NetworkController', error);
668
+ }
669
+ }, _RpcDataSource_updateFromNetworkState = function _RpcDataSource_updateFromNetworkState(networkState) {
670
+ const { networkConfigurationsByChainId, networksMetadata } = networkState;
671
+ const chainStatuses = {};
672
+ const activeChains = [];
673
+ for (const [hexChainId, config] of Object.entries(networkConfigurationsByChainId)) {
674
+ const decimalChainId = parseInt(hexChainId, 16);
675
+ const caip2ChainId = `eip155:${decimalChainId}`;
676
+ const defaultRpcEndpoint = config.rpcEndpoints[config.defaultRpcEndpointIndex];
677
+ if (!defaultRpcEndpoint) {
678
+ continue;
679
+ }
680
+ const { networkClientId } = defaultRpcEndpoint;
681
+ const metadata = networksMetadata[networkClientId];
682
+ const status = metadata?.status ?? 'unknown';
683
+ chainStatuses[caip2ChainId] = {
684
+ chainId: caip2ChainId,
685
+ status,
686
+ name: config.name,
687
+ nativeCurrency: config.nativeCurrency,
688
+ networkClientId,
689
+ };
690
+ if (status === 'available' || status === 'unknown') {
691
+ activeChains.push(caip2ChainId);
692
+ }
693
+ }
694
+ log('Network state updated', {
695
+ configuredChains: Object.keys(chainStatuses),
696
+ activeChains,
697
+ });
698
+ // Check if chains changed
699
+ const previousChains = new Set(__classPrivateFieldGet(this, _RpcDataSource_activeChains, "f"));
700
+ const hasChanges = previousChains.size !== activeChains.length ||
701
+ activeChains.some((chain) => !previousChains.has(chain));
702
+ // Update internal state
703
+ __classPrivateFieldSet(this, _RpcDataSource_chainStatuses, chainStatuses, "f");
704
+ __classPrivateFieldSet(this, _RpcDataSource_activeChains, activeChains, "f");
705
+ if (hasChanges) {
706
+ this.messenger.call('AssetsController:activeChainsUpdate', CONTROLLER_NAME, activeChains);
707
+ }
708
+ }, _RpcDataSource_getProvider = function _RpcDataSource_getProvider(chainId) {
709
+ const cached = __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").get(chainId);
710
+ if (cached) {
711
+ return cached;
712
+ }
713
+ const chainStatus = __classPrivateFieldGet(this, _RpcDataSource_chainStatuses, "f")[chainId];
714
+ if (!chainStatus) {
715
+ return undefined;
716
+ }
717
+ try {
718
+ const networkClient = this.messenger.call('NetworkController:getNetworkClientById', chainStatus.networkClientId);
719
+ const web3Provider = new providers_1.Web3Provider(networkClient.provider);
720
+ __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").set(chainId, web3Provider);
721
+ return web3Provider;
722
+ }
723
+ catch (error) {
724
+ log('Failed to get provider for chain', { chainId, error });
725
+ return undefined;
726
+ }
727
+ }, _RpcDataSource_getMulticallProvider = function _RpcDataSource_getMulticallProvider(hexChainId) {
728
+ const decimalChainId = parseInt(hexChainId, 16);
729
+ const caip2ChainId = `eip155:${decimalChainId}`;
730
+ const web3Provider = __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_getProvider).call(this, caip2ChainId);
731
+ if (!web3Provider) {
732
+ throw new Error(`No provider available for chain ${hexChainId}`);
733
+ }
734
+ return {
735
+ call: async (params) => {
736
+ return web3Provider.call({
737
+ to: params.to,
738
+ data: params.data,
739
+ });
740
+ },
741
+ getBalance: async (address) => {
742
+ const balance = await web3Provider.getBalance(address);
743
+ return balance;
744
+ },
745
+ };
746
+ }, _RpcDataSource_clearProviderCache = function _RpcDataSource_clearProviderCache() {
747
+ __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
748
+ }, _RpcDataSource_accountSupportsChain = function _RpcDataSource_accountSupportsChain(account, chainId) {
749
+ const scopes = account.scopes ?? [];
750
+ if (scopes.length === 0) {
751
+ return true;
752
+ }
753
+ const [chainNamespace, chainReference] = chainId.split(':');
754
+ for (const scope of scopes) {
755
+ const [scopeNamespace, scopeReference] = scope.split(':');
756
+ if (scopeNamespace !== chainNamespace) {
757
+ continue;
758
+ }
759
+ // Wildcard scope (e.g., eip155:0) matches all chains in the namespace
760
+ if (scopeReference === '0') {
761
+ return true;
762
+ }
763
+ // RpcDataSource only handles eip155 (EVM) chains
764
+ // Normalize hex chain references (e.g., 0x1 -> 1) for comparison
765
+ const normalizedScopeRef = scopeReference?.startsWith('0x')
766
+ ? parseInt(scopeReference, 16).toString()
767
+ : scopeReference;
768
+ if (normalizedScopeRef === chainReference) {
769
+ return true;
770
+ }
771
+ }
772
+ return false;
773
+ }, _RpcDataSource_buildNativeAssetId = function _RpcDataSource_buildNativeAssetId(chainId) {
774
+ const { nativeAssetIdentifiers } = this.messenger.call('NetworkEnablementController:getState');
775
+ return (nativeAssetIdentifiers[chainId] ??
776
+ `${chainId}/slip44:60`);
777
+ }, _RpcDataSource_getExistingAssetsMetadata = function _RpcDataSource_getExistingAssetsMetadata() {
778
+ try {
779
+ const state = this.messenger.call('AssetsController:getState');
780
+ return (state.assetsMetadata ?? {});
781
+ }
782
+ catch {
783
+ // If AssetsController:getState fails, return empty metadata
784
+ return {};
785
+ }
786
+ }, _RpcDataSource_getTokenMetadataFromTokenList = function _RpcDataSource_getTokenMetadataFromTokenList(assetId) {
787
+ try {
788
+ // Parse asset ID to get chain and token address
789
+ // Format: eip155:{chainId}/erc20:{address}
790
+ const [chainPart, assetPart] = assetId.split('/');
791
+ if (!assetPart?.startsWith('erc20:')) {
792
+ return undefined;
793
+ }
794
+ const tokenAddress = assetPart.slice(6); // Remove 'erc20:' prefix
795
+ const chainIdDecimal = chainPart.split(':')[1];
796
+ const hexChainId = `0x${parseInt(chainIdDecimal, 10).toString(16)}`;
797
+ const tokenListState = this.messenger.call('TokenListController:getState');
798
+ const chainCacheEntry = tokenListState.tokensChainsCache[hexChainId];
799
+ const chainTokenList = chainCacheEntry?.data;
800
+ if (!chainTokenList) {
801
+ return undefined;
802
+ }
803
+ // Look up token by address (case-insensitive)
804
+ const lowerAddress = tokenAddress.toLowerCase();
805
+ for (const [address, tokenData] of Object.entries(chainTokenList)) {
806
+ if (address.toLowerCase() === lowerAddress) {
807
+ const token = tokenData;
808
+ if (token.symbol && token.decimals !== undefined) {
809
+ return {
810
+ type: 'erc20',
811
+ symbol: token.symbol,
812
+ name: token.name ?? token.symbol,
813
+ decimals: token.decimals,
814
+ image: token.iconUrl,
815
+ };
816
+ }
817
+ }
818
+ }
819
+ return undefined;
820
+ }
821
+ catch {
822
+ return undefined;
823
+ }
824
+ };
825
+ function createRpcDataSource(options) {
826
+ return new RpcDataSource(options);
827
+ }
828
+ exports.createRpcDataSource = createRpcDataSource;
829
+ //# sourceMappingURL=RpcDataSource.cjs.map