@metamask-previews/assets-controller 0.0.0-preview-903db2da → 0.0.0-preview-3ec2a74

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 (250) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/AssetsController.cjs +1028 -61
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +229 -83
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +229 -83
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +1024 -59
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/AbstractDataSource.cjs +103 -0
  11. package/dist/data-sources/AbstractDataSource.cjs.map +1 -0
  12. package/dist/data-sources/AbstractDataSource.d.cts +92 -0
  13. package/dist/data-sources/AbstractDataSource.d.cts.map +1 -0
  14. package/dist/data-sources/AbstractDataSource.d.mts +92 -0
  15. package/dist/data-sources/AbstractDataSource.d.mts.map +1 -0
  16. package/dist/data-sources/AbstractDataSource.mjs +99 -0
  17. package/dist/data-sources/AbstractDataSource.mjs.map +1 -0
  18. package/dist/data-sources/AccountsApiDataSource.cjs +421 -0
  19. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -0
  20. package/dist/data-sources/AccountsApiDataSource.d.cts +103 -0
  21. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -0
  22. package/dist/data-sources/AccountsApiDataSource.d.mts +103 -0
  23. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -0
  24. package/dist/data-sources/AccountsApiDataSource.mjs +416 -0
  25. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -0
  26. package/dist/data-sources/BackendWebsocketDataSource.cjs +388 -0
  27. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -0
  28. package/dist/data-sources/BackendWebsocketDataSource.d.cts +95 -0
  29. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -0
  30. package/dist/data-sources/BackendWebsocketDataSource.d.mts +95 -0
  31. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -0
  32. package/dist/data-sources/BackendWebsocketDataSource.mjs +383 -0
  33. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -0
  34. package/dist/data-sources/PriceDataSource.cjs +350 -0
  35. package/dist/data-sources/PriceDataSource.cjs.map +1 -0
  36. package/dist/data-sources/PriceDataSource.d.cts +153 -0
  37. package/dist/data-sources/PriceDataSource.d.cts.map +1 -0
  38. package/dist/data-sources/PriceDataSource.d.mts +153 -0
  39. package/dist/data-sources/PriceDataSource.d.mts.map +1 -0
  40. package/dist/data-sources/PriceDataSource.mjs +346 -0
  41. package/dist/data-sources/PriceDataSource.mjs.map +1 -0
  42. package/dist/data-sources/RpcDataSource.cjs +410 -0
  43. package/dist/data-sources/RpcDataSource.cjs.map +1 -0
  44. package/dist/data-sources/RpcDataSource.d.cts +154 -0
  45. package/dist/data-sources/RpcDataSource.d.cts.map +1 -0
  46. package/dist/data-sources/RpcDataSource.d.mts +154 -0
  47. package/dist/data-sources/RpcDataSource.d.mts.map +1 -0
  48. package/dist/data-sources/RpcDataSource.mjs +405 -0
  49. package/dist/data-sources/RpcDataSource.mjs.map +1 -0
  50. package/dist/data-sources/SnapDataSource.cjs +734 -0
  51. package/dist/data-sources/SnapDataSource.cjs.map +1 -0
  52. package/dist/data-sources/SnapDataSource.d.cts +217 -0
  53. package/dist/data-sources/SnapDataSource.d.cts.map +1 -0
  54. package/dist/data-sources/SnapDataSource.d.mts +217 -0
  55. package/dist/data-sources/SnapDataSource.d.mts.map +1 -0
  56. package/dist/data-sources/SnapDataSource.mjs +723 -0
  57. package/dist/data-sources/SnapDataSource.mjs.map +1 -0
  58. package/dist/data-sources/TokenDataSource.cjs +179 -0
  59. package/dist/data-sources/TokenDataSource.cjs.map +1 -0
  60. package/dist/data-sources/TokenDataSource.d.cts +62 -0
  61. package/dist/data-sources/TokenDataSource.d.cts.map +1 -0
  62. package/dist/data-sources/TokenDataSource.d.mts +62 -0
  63. package/dist/data-sources/TokenDataSource.d.mts.map +1 -0
  64. package/dist/data-sources/TokenDataSource.mjs +175 -0
  65. package/dist/data-sources/TokenDataSource.mjs.map +1 -0
  66. package/dist/data-sources/index.cjs +62 -0
  67. package/dist/data-sources/index.cjs.map +1 -0
  68. package/dist/data-sources/index.d.cts +9 -0
  69. package/dist/data-sources/index.d.cts.map +1 -0
  70. package/dist/data-sources/index.d.mts +9 -0
  71. package/dist/data-sources/index.d.mts.map +1 -0
  72. package/dist/data-sources/index.mjs +23 -0
  73. package/dist/data-sources/index.mjs.map +1 -0
  74. package/dist/data-sources/initDataSources.cjs +199 -0
  75. package/dist/data-sources/initDataSources.cjs.map +1 -0
  76. package/dist/data-sources/initDataSources.d.cts +123 -0
  77. package/dist/data-sources/initDataSources.d.cts.map +1 -0
  78. package/dist/data-sources/initDataSources.d.mts +123 -0
  79. package/dist/data-sources/initDataSources.d.mts.map +1 -0
  80. package/dist/data-sources/initDataSources.mjs +194 -0
  81. package/dist/data-sources/initDataSources.mjs.map +1 -0
  82. package/dist/data-sources/rpc-datasource/clients/MulticallClient.cjs +638 -0
  83. package/dist/data-sources/rpc-datasource/clients/MulticallClient.cjs.map +1 -0
  84. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.cts +47 -0
  85. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.cts.map +1 -0
  86. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.mts +47 -0
  87. package/dist/data-sources/rpc-datasource/clients/MulticallClient.d.mts.map +1 -0
  88. package/dist/data-sources/rpc-datasource/clients/MulticallClient.mjs +632 -0
  89. package/dist/data-sources/rpc-datasource/clients/MulticallClient.mjs.map +1 -0
  90. package/dist/data-sources/rpc-datasource/clients/index.cjs +8 -0
  91. package/dist/data-sources/rpc-datasource/clients/index.cjs.map +1 -0
  92. package/dist/data-sources/rpc-datasource/clients/index.d.cts +3 -0
  93. package/dist/data-sources/rpc-datasource/clients/index.d.cts.map +1 -0
  94. package/dist/data-sources/rpc-datasource/clients/index.d.mts +3 -0
  95. package/dist/data-sources/rpc-datasource/clients/index.d.mts.map +1 -0
  96. package/dist/data-sources/rpc-datasource/clients/index.mjs +2 -0
  97. package/dist/data-sources/rpc-datasource/clients/index.mjs.map +1 -0
  98. package/dist/data-sources/rpc-datasource/index.cjs +9 -0
  99. package/dist/data-sources/rpc-datasource/index.cjs.map +1 -0
  100. package/dist/data-sources/rpc-datasource/index.d.cts +4 -0
  101. package/dist/data-sources/rpc-datasource/index.d.cts.map +1 -0
  102. package/dist/data-sources/rpc-datasource/index.d.mts +4 -0
  103. package/dist/data-sources/rpc-datasource/index.d.mts.map +1 -0
  104. package/dist/data-sources/rpc-datasource/index.mjs +3 -0
  105. package/dist/data-sources/rpc-datasource/index.mjs.map +1 -0
  106. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.cjs +167 -0
  107. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.cjs.map +1 -0
  108. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.cts +16 -0
  109. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.cts.map +1 -0
  110. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.mts +16 -0
  111. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.d.mts.map +1 -0
  112. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.mjs +163 -0
  113. package/dist/data-sources/rpc-datasource/services/BalanceFetcher.mjs.map +1 -0
  114. package/dist/data-sources/rpc-datasource/services/TokenDetector.cjs +173 -0
  115. package/dist/data-sources/rpc-datasource/services/TokenDetector.cjs.map +1 -0
  116. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.cts +14 -0
  117. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.cts.map +1 -0
  118. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.mts +14 -0
  119. package/dist/data-sources/rpc-datasource/services/TokenDetector.d.mts.map +1 -0
  120. package/dist/data-sources/rpc-datasource/services/TokenDetector.mjs +169 -0
  121. package/dist/data-sources/rpc-datasource/services/TokenDetector.mjs.map +1 -0
  122. package/dist/data-sources/rpc-datasource/services/index.cjs +8 -0
  123. package/dist/data-sources/rpc-datasource/services/index.cjs.map +1 -0
  124. package/dist/data-sources/rpc-datasource/services/index.d.cts +3 -0
  125. package/dist/data-sources/rpc-datasource/services/index.d.cts.map +1 -0
  126. package/dist/data-sources/rpc-datasource/services/index.d.mts +3 -0
  127. package/dist/data-sources/rpc-datasource/services/index.d.mts.map +1 -0
  128. package/dist/data-sources/rpc-datasource/services/index.mjs +3 -0
  129. package/dist/data-sources/rpc-datasource/services/index.mjs.map +1 -0
  130. package/dist/data-sources/rpc-datasource/types/assets.cjs +3 -0
  131. package/dist/data-sources/rpc-datasource/types/assets.cjs.map +1 -0
  132. package/dist/data-sources/rpc-datasource/types/assets.d.cts +53 -0
  133. package/dist/data-sources/rpc-datasource/types/assets.d.cts.map +1 -0
  134. package/dist/data-sources/rpc-datasource/types/assets.d.mts +53 -0
  135. package/dist/data-sources/rpc-datasource/types/assets.d.mts.map +1 -0
  136. package/dist/data-sources/rpc-datasource/types/assets.mjs +2 -0
  137. package/dist/data-sources/rpc-datasource/types/assets.mjs.map +1 -0
  138. package/dist/data-sources/rpc-datasource/types/config.cjs +3 -0
  139. package/dist/data-sources/rpc-datasource/types/config.cjs.map +1 -0
  140. package/dist/data-sources/rpc-datasource/types/config.d.cts +18 -0
  141. package/dist/data-sources/rpc-datasource/types/config.d.cts.map +1 -0
  142. package/dist/data-sources/rpc-datasource/types/config.d.mts +18 -0
  143. package/dist/data-sources/rpc-datasource/types/config.d.mts.map +1 -0
  144. package/dist/data-sources/rpc-datasource/types/config.mjs +2 -0
  145. package/dist/data-sources/rpc-datasource/types/config.mjs.map +1 -0
  146. package/dist/data-sources/rpc-datasource/types/core.cjs +3 -0
  147. package/dist/data-sources/rpc-datasource/types/core.cjs.map +1 -0
  148. package/dist/data-sources/rpc-datasource/types/core.d.cts +19 -0
  149. package/dist/data-sources/rpc-datasource/types/core.d.cts.map +1 -0
  150. package/dist/data-sources/rpc-datasource/types/core.d.mts +19 -0
  151. package/dist/data-sources/rpc-datasource/types/core.d.mts.map +1 -0
  152. package/dist/data-sources/rpc-datasource/types/core.mjs +2 -0
  153. package/dist/data-sources/rpc-datasource/types/core.mjs.map +1 -0
  154. package/dist/data-sources/rpc-datasource/types/index.cjs +3 -0
  155. package/dist/data-sources/rpc-datasource/types/index.cjs.map +1 -0
  156. package/dist/data-sources/rpc-datasource/types/index.d.cts +7 -0
  157. package/dist/data-sources/rpc-datasource/types/index.d.cts.map +1 -0
  158. package/dist/data-sources/rpc-datasource/types/index.d.mts +7 -0
  159. package/dist/data-sources/rpc-datasource/types/index.d.mts.map +1 -0
  160. package/dist/data-sources/rpc-datasource/types/index.mjs +2 -0
  161. package/dist/data-sources/rpc-datasource/types/index.mjs.map +1 -0
  162. package/dist/data-sources/rpc-datasource/types/multicall.cjs +3 -0
  163. package/dist/data-sources/rpc-datasource/types/multicall.cjs.map +1 -0
  164. package/dist/data-sources/rpc-datasource/types/multicall.d.cts +24 -0
  165. package/dist/data-sources/rpc-datasource/types/multicall.d.cts.map +1 -0
  166. package/dist/data-sources/rpc-datasource/types/multicall.d.mts +24 -0
  167. package/dist/data-sources/rpc-datasource/types/multicall.d.mts.map +1 -0
  168. package/dist/data-sources/rpc-datasource/types/multicall.mjs +2 -0
  169. package/dist/data-sources/rpc-datasource/types/multicall.mjs.map +1 -0
  170. package/dist/data-sources/rpc-datasource/types/services.cjs +3 -0
  171. package/dist/data-sources/rpc-datasource/types/services.cjs.map +1 -0
  172. package/dist/data-sources/rpc-datasource/types/services.d.cts +74 -0
  173. package/dist/data-sources/rpc-datasource/types/services.d.cts.map +1 -0
  174. package/dist/data-sources/rpc-datasource/types/services.d.mts +74 -0
  175. package/dist/data-sources/rpc-datasource/types/services.d.mts.map +1 -0
  176. package/dist/data-sources/rpc-datasource/types/services.mjs +2 -0
  177. package/dist/data-sources/rpc-datasource/types/services.mjs.map +1 -0
  178. package/dist/data-sources/rpc-datasource/types/state.cjs +3 -0
  179. package/dist/data-sources/rpc-datasource/types/state.cjs.map +1 -0
  180. package/dist/data-sources/rpc-datasource/types/state.d.cts +67 -0
  181. package/dist/data-sources/rpc-datasource/types/state.d.cts.map +1 -0
  182. package/dist/data-sources/rpc-datasource/types/state.d.mts +67 -0
  183. package/dist/data-sources/rpc-datasource/types/state.d.mts.map +1 -0
  184. package/dist/data-sources/rpc-datasource/types/state.mjs +2 -0
  185. package/dist/data-sources/rpc-datasource/types/state.mjs.map +1 -0
  186. package/dist/data-sources/rpc-datasource/utils/batch.cjs +45 -0
  187. package/dist/data-sources/rpc-datasource/utils/batch.cjs.map +1 -0
  188. package/dist/data-sources/rpc-datasource/utils/batch.d.cts +28 -0
  189. package/dist/data-sources/rpc-datasource/utils/batch.d.cts.map +1 -0
  190. package/dist/data-sources/rpc-datasource/utils/batch.d.mts +28 -0
  191. package/dist/data-sources/rpc-datasource/utils/batch.d.mts.map +1 -0
  192. package/dist/data-sources/rpc-datasource/utils/batch.mjs +40 -0
  193. package/dist/data-sources/rpc-datasource/utils/batch.mjs.map +1 -0
  194. package/dist/data-sources/rpc-datasource/utils/index.cjs +7 -0
  195. package/dist/data-sources/rpc-datasource/utils/index.cjs.map +1 -0
  196. package/dist/data-sources/rpc-datasource/utils/index.d.cts +2 -0
  197. package/dist/data-sources/rpc-datasource/utils/index.d.cts.map +1 -0
  198. package/dist/data-sources/rpc-datasource/utils/index.d.mts +2 -0
  199. package/dist/data-sources/rpc-datasource/utils/index.d.mts.map +1 -0
  200. package/dist/data-sources/rpc-datasource/utils/index.mjs +2 -0
  201. package/dist/data-sources/rpc-datasource/utils/index.mjs.map +1 -0
  202. package/dist/index.cjs +70 -1
  203. package/dist/index.cjs.map +1 -1
  204. package/dist/index.d.cts +19 -1
  205. package/dist/index.d.cts.map +1 -1
  206. package/dist/index.d.mts +19 -1
  207. package/dist/index.d.mts.map +1 -1
  208. package/dist/index.mjs +31 -0
  209. package/dist/index.mjs.map +1 -1
  210. package/dist/logger.cjs +7 -0
  211. package/dist/logger.cjs.map +1 -0
  212. package/dist/logger.d.cts +5 -0
  213. package/dist/logger.d.cts.map +1 -0
  214. package/dist/logger.d.mts +5 -0
  215. package/dist/logger.d.mts.map +1 -0
  216. package/dist/logger.mjs +4 -0
  217. package/dist/logger.mjs.map +1 -0
  218. package/dist/middlewares/DetectionMiddleware.cjs +101 -0
  219. package/dist/middlewares/DetectionMiddleware.cjs.map +1 -0
  220. package/dist/middlewares/DetectionMiddleware.d.cts +54 -0
  221. package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -0
  222. package/dist/middlewares/DetectionMiddleware.d.mts +54 -0
  223. package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -0
  224. package/dist/middlewares/DetectionMiddleware.mjs +97 -0
  225. package/dist/middlewares/DetectionMiddleware.mjs.map +1 -0
  226. package/dist/middlewares/index.cjs +6 -0
  227. package/dist/middlewares/index.cjs.map +1 -0
  228. package/dist/middlewares/index.d.cts +2 -0
  229. package/dist/middlewares/index.d.cts.map +1 -0
  230. package/dist/middlewares/index.d.mts +2 -0
  231. package/dist/middlewares/index.d.mts.map +1 -0
  232. package/dist/middlewares/index.mjs +2 -0
  233. package/dist/middlewares/index.mjs.map +1 -0
  234. package/dist/types.cjs +39 -0
  235. package/dist/types.cjs.map +1 -0
  236. package/dist/types.d.cts +360 -0
  237. package/dist/types.d.cts.map +1 -0
  238. package/dist/types.d.mts +360 -0
  239. package/dist/types.d.mts.map +1 -0
  240. package/dist/types.mjs +35 -0
  241. package/dist/types.mjs.map +1 -0
  242. package/dist/utils.cjs +28 -0
  243. package/dist/utils.cjs.map +1 -0
  244. package/dist/utils.d.cts +13 -0
  245. package/dist/utils.d.cts.map +1 -0
  246. package/dist/utils.d.mts +13 -0
  247. package/dist/utils.d.mts.map +1 -0
  248. package/dist/utils.mjs +24 -0
  249. package/dist/utils.mjs.map +1 -0
  250. package/package.json +15 -2
@@ -0,0 +1,154 @@
1
+ import type { Messenger } from "@metamask/messenger";
2
+ import type { NetworkState, NetworkStatus } from "@metamask/network-controller";
3
+ import { AbstractDataSource } from "./AbstractDataSource.mjs";
4
+ import type { DataSourceState, SubscriptionRequest } from "./AbstractDataSource.mjs";
5
+ import type { ChainId, DataRequest, DataResponse, Middleware } from "../types.mjs";
6
+ declare const CONTROLLER_NAME = "RpcDataSource";
7
+ export type RpcDataSourceGetAssetsMiddlewareAction = {
8
+ type: 'RpcDataSource:getAssetsMiddleware';
9
+ handler: () => Middleware;
10
+ };
11
+ export type RpcDataSourceGetActiveChainsAction = {
12
+ type: 'RpcDataSource:getActiveChains';
13
+ handler: () => Promise<ChainId[]>;
14
+ };
15
+ export type RpcDataSourceFetchAction = {
16
+ type: 'RpcDataSource:fetch';
17
+ handler: (request: DataRequest) => Promise<DataResponse>;
18
+ };
19
+ export type RpcDataSourceSubscribeAction = {
20
+ type: 'RpcDataSource:subscribe';
21
+ handler: (request: SubscriptionRequest) => Promise<void>;
22
+ };
23
+ export type RpcDataSourceUnsubscribeAction = {
24
+ type: 'RpcDataSource:unsubscribe';
25
+ handler: (subscriptionId: string) => Promise<void>;
26
+ };
27
+ export type RpcDataSourceActions = RpcDataSourceGetAssetsMiddlewareAction | RpcDataSourceGetActiveChainsAction | RpcDataSourceFetchAction | RpcDataSourceSubscribeAction | RpcDataSourceUnsubscribeAction;
28
+ export type RpcDataSourceActiveChainsChangedEvent = {
29
+ type: 'RpcDataSource:activeChainsUpdated';
30
+ payload: [ChainId[]];
31
+ };
32
+ export type RpcDataSourceAssetsUpdatedEvent = {
33
+ type: 'RpcDataSource:assetsUpdated';
34
+ payload: [DataResponse, string | undefined];
35
+ };
36
+ export type RpcDataSourceEvents = RpcDataSourceActiveChainsChangedEvent | RpcDataSourceAssetsUpdatedEvent;
37
+ export type NetworkControllerGetStateAction = {
38
+ type: 'NetworkController:getState';
39
+ handler: () => NetworkState;
40
+ };
41
+ export type NetworkControllerGetNetworkClientByIdAction = {
42
+ type: 'NetworkController:getNetworkClientById';
43
+ handler: (networkClientId: string) => NetworkClient;
44
+ };
45
+ export type NetworkClient = {
46
+ provider: EthereumProvider;
47
+ configuration: {
48
+ chainId: string;
49
+ };
50
+ };
51
+ export type EthereumProvider = {
52
+ request: (args: {
53
+ method: string;
54
+ params?: unknown[];
55
+ }) => Promise<unknown>;
56
+ };
57
+ export type NetworkControllerStateChangeEvent = {
58
+ type: 'NetworkController:stateChange';
59
+ payload: [NetworkState, Patch[]];
60
+ };
61
+ type Patch = {
62
+ op: 'add' | 'remove' | 'replace';
63
+ path: string[];
64
+ value?: unknown;
65
+ };
66
+ type AssetsControllerActiveChainsUpdateAction = {
67
+ type: 'AssetsController:activeChainsUpdate';
68
+ handler: (dataSourceId: string, activeChains: ChainId[]) => void;
69
+ };
70
+ type AssetsControllerAssetsUpdateAction = {
71
+ type: 'AssetsController:assetsUpdate';
72
+ handler: (response: DataResponse, sourceId: string) => Promise<void>;
73
+ };
74
+ export type RpcDataSourceAllowedActions = NetworkControllerGetStateAction | NetworkControllerGetNetworkClientByIdAction | AssetsControllerActiveChainsUpdateAction | AssetsControllerAssetsUpdateAction;
75
+ export type RpcDataSourceAllowedEvents = NetworkControllerStateChangeEvent;
76
+ export type RpcDataSourceMessenger = Messenger<typeof CONTROLLER_NAME, RpcDataSourceActions | RpcDataSourceAllowedActions, RpcDataSourceEvents | RpcDataSourceAllowedEvents>;
77
+ /** Network status for each chain */
78
+ export type ChainStatus = {
79
+ chainId: ChainId;
80
+ status: NetworkStatus;
81
+ name: string;
82
+ nativeCurrency: string;
83
+ /** Network client ID for getting the provider */
84
+ networkClientId: string;
85
+ };
86
+ export type RpcDataSourceState = {
87
+ /** Network status for each active chain */
88
+ chainStatuses: Record<ChainId, ChainStatus>;
89
+ } & DataSourceState;
90
+ export type RpcDataSourceOptions = {
91
+ messenger: RpcDataSourceMessenger;
92
+ /** Request timeout in ms */
93
+ timeout?: number;
94
+ /** Polling interval in ms */
95
+ pollInterval?: number;
96
+ state?: Partial<RpcDataSourceState>;
97
+ };
98
+ /**
99
+ * Data source for fetching balances via RPC calls.
100
+ *
101
+ * Used as a fallback when the Accounts API doesn't support a chain.
102
+ *
103
+ * Communicates with AssetsController via Messenger:
104
+ *
105
+ * Actions:
106
+ * - RpcDataSource:getActiveChains
107
+ * - RpcDataSource:fetch
108
+ * - RpcDataSource:subscribe
109
+ * - RpcDataSource:unsubscribe
110
+ *
111
+ * Events:
112
+ * - RpcDataSource:activeChainsUpdated
113
+ * - RpcDataSource:assetsUpdated
114
+ */
115
+ export declare class RpcDataSource extends AbstractDataSource<typeof CONTROLLER_NAME, RpcDataSourceState> {
116
+ #private;
117
+ constructor(options: RpcDataSourceOptions);
118
+ /**
119
+ * Get the status of all configured chains.
120
+ *
121
+ * @returns Record of chain statuses keyed by chain ID.
122
+ */
123
+ getChainStatuses(): Record<ChainId, ChainStatus>;
124
+ /**
125
+ * Get the status of a specific chain.
126
+ *
127
+ * @param chainId - The CAIP-2 chain ID to check.
128
+ * @returns The chain status, or undefined if not configured.
129
+ */
130
+ getChainStatus(chainId: ChainId): ChainStatus | undefined;
131
+ fetch(request: DataRequest): Promise<DataResponse>;
132
+ /**
133
+ * Get the middleware for fetching balances via RPC.
134
+ * This middleware:
135
+ * - Supports multiple accounts in a single request
136
+ * - Filters request to only chains this data source supports
137
+ * - Fetches balances for those chains for all accounts
138
+ * - Merges response into context
139
+ * - Removes handled chains from request for next middleware
140
+ *
141
+ * @returns The middleware function for the assets pipeline.
142
+ */
143
+ get assetsMiddleware(): Middleware;
144
+ subscribe(subscriptionRequest: SubscriptionRequest): Promise<void>;
145
+ }
146
+ /**
147
+ * Creates an RpcDataSource instance.
148
+ *
149
+ * @param options - Configuration options for the data source.
150
+ * @returns A new RpcDataSource instance.
151
+ */
152
+ export declare function createRpcDataSource(options: RpcDataSourceOptions): RpcDataSource;
153
+ export {};
154
+ //# sourceMappingURL=RpcDataSource.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RpcDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/RpcDataSource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,405 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ 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");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
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;
13
+ import { Web3Provider } from "@ethersproject/providers";
14
+ import { AbstractDataSource } from "./AbstractDataSource.mjs";
15
+ import { projectLogger, createModuleLogger } from "../logger.mjs";
16
+ // ============================================================================
17
+ // CONSTANTS
18
+ // ============================================================================
19
+ const CONTROLLER_NAME = 'RpcDataSource';
20
+ const DEFAULT_POLL_INTERVAL = 30000;
21
+ const log = createModuleLogger(projectLogger, CONTROLLER_NAME);
22
+ const defaultState = {
23
+ activeChains: [],
24
+ chainStatuses: {},
25
+ };
26
+ // ============================================================================
27
+ // HELPER FUNCTIONS
28
+ // ============================================================================
29
+ function buildNativeAssetId(chainId) {
30
+ return `${chainId}/slip44:60`;
31
+ }
32
+ // ============================================================================
33
+ // RPC DATA SOURCE
34
+ // ============================================================================
35
+ /**
36
+ * Data source for fetching balances via RPC calls.
37
+ *
38
+ * Used as a fallback when the Accounts API doesn't support a chain.
39
+ *
40
+ * Communicates with AssetsController via Messenger:
41
+ *
42
+ * Actions:
43
+ * - RpcDataSource:getActiveChains
44
+ * - RpcDataSource:fetch
45
+ * - RpcDataSource:subscribe
46
+ * - RpcDataSource:unsubscribe
47
+ *
48
+ * Events:
49
+ * - RpcDataSource:activeChainsUpdated
50
+ * - RpcDataSource:assetsUpdated
51
+ */
52
+ export class RpcDataSource extends AbstractDataSource {
53
+ constructor(options) {
54
+ super(CONTROLLER_NAME, {
55
+ ...defaultState,
56
+ ...options.state,
57
+ });
58
+ _RpcDataSource_instances.add(this);
59
+ _RpcDataSource_messenger.set(this, void 0);
60
+ _RpcDataSource_timeout.set(this, void 0);
61
+ _RpcDataSource_pollInterval.set(this, void 0);
62
+ /** Cache of Web3Provider instances by chainId */
63
+ _RpcDataSource_providerCache.set(this, new Map());
64
+ __classPrivateFieldSet(this, _RpcDataSource_messenger, options.messenger, "f");
65
+ __classPrivateFieldSet(this, _RpcDataSource_timeout, options.timeout ?? 10000, "f");
66
+ __classPrivateFieldSet(this, _RpcDataSource_pollInterval, options.pollInterval ?? DEFAULT_POLL_INTERVAL, "f");
67
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_registerActionHandlers).call(this);
68
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_subscribeToNetworkController).call(this);
69
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_initializeFromNetworkController).call(this);
70
+ }
71
+ // ============================================================================
72
+ // CHAIN STATUS
73
+ // ============================================================================
74
+ /**
75
+ * Get the status of all configured chains.
76
+ *
77
+ * @returns Record of chain statuses keyed by chain ID.
78
+ */
79
+ getChainStatuses() {
80
+ return { ...this.state.chainStatuses };
81
+ }
82
+ /**
83
+ * Get the status of a specific chain.
84
+ *
85
+ * @param chainId - The CAIP-2 chain ID to check.
86
+ * @returns The chain status, or undefined if not configured.
87
+ */
88
+ getChainStatus(chainId) {
89
+ return this.state.chainStatuses[chainId];
90
+ }
91
+ // ============================================================================
92
+ // FETCH
93
+ // ============================================================================
94
+ async fetch(request) {
95
+ const response = {};
96
+ // Filter to active chains
97
+ const chainsToFetch = request.chainIds.filter((chainId) => this.state.activeChains.includes(chainId));
98
+ if (chainsToFetch.length === 0) {
99
+ return response;
100
+ }
101
+ const assetsBalance = {};
102
+ const failedChains = [];
103
+ // Fetch native balance for each chain
104
+ 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
111
+ for (const account of request.accounts) {
112
+ // Check if account supports this chain based on its scopes
113
+ if (!__classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_accountSupportsChain).call(this, account, chainId)) {
114
+ continue;
115
+ }
116
+ const { address, id: accountId } = account;
117
+ 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]);
121
+ if (!assetsBalance[accountId]) {
122
+ assetsBalance[accountId] = {};
123
+ }
124
+ assetsBalance[accountId][assetId] = {
125
+ amount: balance.toString(),
126
+ };
127
+ }
128
+ catch (error) {
129
+ log('Failed to fetch balance', { address, chainId, error });
130
+ if (!assetsBalance[accountId]) {
131
+ assetsBalance[accountId] = {};
132
+ }
133
+ assetsBalance[accountId][assetId] = { amount: '0' };
134
+ if (!failedChains.includes(chainId)) {
135
+ failedChains.push(chainId);
136
+ }
137
+ }
138
+ }
139
+ }
140
+ if (failedChains.length > 0) {
141
+ // Add failed chains to errors so they can fallback to other data sources
142
+ response.errors = {};
143
+ for (const chainId of failedChains) {
144
+ response.errors[chainId] = 'RPC fetch failed';
145
+ }
146
+ }
147
+ response.assetsBalance = assetsBalance;
148
+ return response;
149
+ }
150
+ // ============================================================================
151
+ // MIDDLEWARE
152
+ // ============================================================================
153
+ /**
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
161
+ *
162
+ * @returns The middleware function for the assets pipeline.
163
+ */
164
+ get assetsMiddleware() {
165
+ return async (context, next) => {
166
+ var _a;
167
+ 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
171
+ if (supportedChains.length === 0) {
172
+ return next(context);
173
+ }
174
+ 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
+ }
193
+ }
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
+ }
198
+ catch (error) {
199
+ log('Middleware fetch failed', { error });
200
+ successfullyHandledChains = [];
201
+ }
202
+ // Remove successfully handled chains from request for next middleware
203
+ if (successfullyHandledChains.length > 0) {
204
+ const remainingChains = request.chainIds.filter((chainId) => !successfullyHandledChains.includes(chainId));
205
+ return next({
206
+ ...context,
207
+ request: {
208
+ ...request,
209
+ chainIds: remainingChains,
210
+ },
211
+ });
212
+ }
213
+ // No chains handled - pass context unchanged
214
+ return next(context);
215
+ };
216
+ }
217
+ // ============================================================================
218
+ // SUBSCRIBE
219
+ // ============================================================================
220
+ async subscribe(subscriptionRequest) {
221
+ const { request, subscriptionId, isUpdate } = subscriptionRequest;
222
+ // Filter to active chains
223
+ const chainsToSubscribe = request.chainIds.filter((chainId) => this.state.activeChains.includes(chainId));
224
+ if (chainsToSubscribe.length === 0) {
225
+ return;
226
+ }
227
+ // Handle subscription update - update both chains AND request (for accounts)
228
+ if (isUpdate) {
229
+ const existing = this.activeSubscriptions.get(subscriptionId);
230
+ if (existing) {
231
+ existing.chains = chainsToSubscribe;
232
+ existing.request = request;
233
+ return;
234
+ }
235
+ }
236
+ // Clean up existing subscription
237
+ 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;
245
+ }
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
+ }
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
+ },
267
+ chains: chainsToSubscribe,
268
+ request,
269
+ });
270
+ // Initial fetch
271
+ await pollFn();
272
+ }
273
+ }
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() {
275
+ const getAssetsMiddlewareHandler = () => this.assetsMiddleware;
276
+ const getActiveChainsHandler = async () => this.getActiveChains();
277
+ const fetchHandler = async (request) => this.fetch(request);
278
+ const subscribeHandler = async (request) => this.subscribe(request);
279
+ 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);
285
+ }, _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
288
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_clearProviderCache).call(this);
289
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
290
+ });
291
+ }, _RpcDataSource_initializeFromNetworkController = function _RpcDataSource_initializeFromNetworkController() {
292
+ try {
293
+ const networkState = __classPrivateFieldGet(this, _RpcDataSource_messenger, "f").call('NetworkController:getState');
294
+ __classPrivateFieldGet(this, _RpcDataSource_instances, "m", _RpcDataSource_updateFromNetworkState).call(this, networkState);
295
+ }
296
+ catch (error) {
297
+ log('Failed to initialize from NetworkController', error);
298
+ }
299
+ }, _RpcDataSource_updateFromNetworkState = function _RpcDataSource_updateFromNetworkState(networkState) {
300
+ const { networkConfigurationsByChainId, networksMetadata } = networkState;
301
+ const chainStatuses = {};
302
+ const activeChains = [];
303
+ // Iterate through all configured networks
304
+ for (const [hexChainId, config] of Object.entries(networkConfigurationsByChainId)) {
305
+ // Convert hex chainId to CAIP-2 format (eip155:decimal)
306
+ const decimalChainId = parseInt(hexChainId, 16);
307
+ const caip2ChainId = `eip155:${decimalChainId}`;
308
+ // Get the default RPC endpoint's network client ID
309
+ const defaultRpcEndpoint = config.rpcEndpoints[config.defaultRpcEndpointIndex];
310
+ if (!defaultRpcEndpoint) {
311
+ continue;
312
+ }
313
+ const { networkClientId } = defaultRpcEndpoint;
314
+ const metadata = networksMetadata[networkClientId];
315
+ // Determine status - default to 'unknown' if not in metadata
316
+ const status = metadata?.status ?? 'unknown';
317
+ chainStatuses[caip2ChainId] = {
318
+ chainId: caip2ChainId,
319
+ status,
320
+ name: config.name,
321
+ nativeCurrency: config.nativeCurrency,
322
+ networkClientId,
323
+ };
324
+ // Only include chains that have an available status
325
+ // (not degraded/unavailable/blocked)
326
+ if (status === 'available' || status === 'unknown') {
327
+ activeChains.push(caip2ChainId);
328
+ }
329
+ }
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));
334
+ }, _RpcDataSource_getProvider = function _RpcDataSource_getProvider(chainId) {
335
+ // Check cache first
336
+ const cached = __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").get(chainId);
337
+ if (cached) {
338
+ return cached;
339
+ }
340
+ // Get chain status to find networkClientId
341
+ const chainStatus = this.state.chainStatuses[chainId];
342
+ if (!chainStatus) {
343
+ return undefined;
344
+ }
345
+ 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
349
+ const web3Provider = new Web3Provider(networkClient.provider);
350
+ // Cache for reuse
351
+ __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").set(chainId, web3Provider);
352
+ return web3Provider;
353
+ }
354
+ catch (error) {
355
+ console.error(`[RpcDataSource] Failed to get provider for chain ${chainId}:`, error);
356
+ return undefined;
357
+ }
358
+ }, _RpcDataSource_clearProviderCache = function _RpcDataSource_clearProviderCache() {
359
+ __classPrivateFieldGet(this, _RpcDataSource_providerCache, "f").clear();
360
+ }, _RpcDataSource_accountSupportsChain = function _RpcDataSource_accountSupportsChain(account, chainId) {
361
+ const scopes = account.scopes ?? [];
362
+ // If no scopes defined, assume it supports the chain (backward compatibility)
363
+ if (scopes.length === 0) {
364
+ return true;
365
+ }
366
+ // Extract namespace and reference from chainId (e.g., "eip155:1" -> ["eip155", "1"])
367
+ const [chainNamespace, chainReference] = chainId.split(':');
368
+ for (const scope of scopes) {
369
+ const [scopeNamespace, scopeReference] = scope.split(':');
370
+ // Check if namespaces match
371
+ if (scopeNamespace !== chainNamespace) {
372
+ continue;
373
+ }
374
+ // Wildcard scope (e.g., "eip155:0" means all chains in that namespace)
375
+ if (scopeReference === '0') {
376
+ return true;
377
+ }
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) {
388
+ return true;
389
+ }
390
+ }
391
+ return false;
392
+ };
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
+ export function createRpcDataSource(options) {
403
+ return new RpcDataSource(options);
404
+ }
405
+ //# sourceMappingURL=RpcDataSource.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RpcDataSource.mjs","sourceRoot":"","sources":["../../src/data-sources/RpcDataSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { Web3Provider } from '@ethersproject/providers';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type { NetworkState, NetworkStatus } from '@metamask/network-controller';\n\nimport { AbstractDataSource } from './AbstractDataSource';\nimport type {\n DataSourceState,\n SubscriptionRequest,\n} from './AbstractDataSource';\nimport { projectLogger, createModuleLogger } from '../logger';\nimport type {\n ChainId,\n Caip19AssetId,\n AssetBalance,\n DataRequest,\n DataResponse,\n Middleware,\n} from '../types';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst CONTROLLER_NAME = 'RpcDataSource';\nconst DEFAULT_POLL_INTERVAL = 30_000;\n\nconst log = createModuleLogger(projectLogger, CONTROLLER_NAME);\n\n// ============================================================================\n// MESSENGER TYPES\n// ============================================================================\n\n// Action types\nexport type RpcDataSourceGetAssetsMiddlewareAction = {\n type: 'RpcDataSource:getAssetsMiddleware';\n handler: () => Middleware;\n};\n\nexport type RpcDataSourceGetActiveChainsAction = {\n type: 'RpcDataSource:getActiveChains';\n handler: () => Promise<ChainId[]>;\n};\n\nexport type RpcDataSourceFetchAction = {\n type: 'RpcDataSource:fetch';\n handler: (request: DataRequest) => Promise<DataResponse>;\n};\n\nexport type RpcDataSourceSubscribeAction = {\n type: 'RpcDataSource:subscribe';\n handler: (request: SubscriptionRequest) => Promise<void>;\n};\n\nexport type RpcDataSourceUnsubscribeAction = {\n type: 'RpcDataSource:unsubscribe';\n handler: (subscriptionId: string) => Promise<void>;\n};\n\nexport type RpcDataSourceActions =\n | RpcDataSourceGetAssetsMiddlewareAction\n | RpcDataSourceGetActiveChainsAction\n | RpcDataSourceFetchAction\n | RpcDataSourceSubscribeAction\n | RpcDataSourceUnsubscribeAction;\n\n// Event types\nexport type RpcDataSourceActiveChainsChangedEvent = {\n type: 'RpcDataSource:activeChainsUpdated';\n payload: [ChainId[]];\n};\n\nexport type RpcDataSourceAssetsUpdatedEvent = {\n type: 'RpcDataSource:assetsUpdated';\n payload: [DataResponse, string | undefined];\n};\n\nexport type RpcDataSourceEvents =\n | RpcDataSourceActiveChainsChangedEvent\n | RpcDataSourceAssetsUpdatedEvent;\n\n// NetworkController action to get state\nexport type NetworkControllerGetStateAction = {\n type: 'NetworkController:getState';\n handler: () => NetworkState;\n};\n\n// NetworkController action to get network client by ID\nexport type NetworkControllerGetNetworkClientByIdAction = {\n type: 'NetworkController:getNetworkClientById';\n handler: (networkClientId: string) => NetworkClient;\n};\n\n// Network client returned by NetworkController\nexport type NetworkClient = {\n provider: EthereumProvider;\n configuration: {\n chainId: string;\n };\n};\n\n// Ethereum provider interface\nexport type EthereumProvider = {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n};\n\n// NetworkController state change event\nexport type NetworkControllerStateChangeEvent = {\n type: 'NetworkController:stateChange';\n payload: [NetworkState, Patch[]];\n};\n\n// Patch type for state changes\ntype Patch = {\n op: 'add' | 'remove' | 'replace';\n path: string[];\n value?: unknown;\n};\n\n// Actions to report to AssetsController\ntype AssetsControllerActiveChainsUpdateAction = {\n type: 'AssetsController:activeChainsUpdate';\n handler: (dataSourceId: string, activeChains: ChainId[]) => void;\n};\n\ntype AssetsControllerAssetsUpdateAction = {\n type: 'AssetsController:assetsUpdate';\n handler: (response: DataResponse, sourceId: string) => Promise<void>;\n};\n\n// Allowed actions that RpcDataSource can call\nexport type RpcDataSourceAllowedActions =\n | NetworkControllerGetStateAction\n | NetworkControllerGetNetworkClientByIdAction\n | AssetsControllerActiveChainsUpdateAction\n | AssetsControllerAssetsUpdateAction;\n\n// Allowed events that RpcDataSource can subscribe to\nexport type RpcDataSourceAllowedEvents = NetworkControllerStateChangeEvent;\n\nexport type RpcDataSourceMessenger = Messenger<\n typeof CONTROLLER_NAME,\n RpcDataSourceActions | RpcDataSourceAllowedActions,\n RpcDataSourceEvents | RpcDataSourceAllowedEvents\n>;\n\n// ============================================================================\n// STATE\n// ============================================================================\n\n/** Network status for each chain */\nexport type ChainStatus = {\n chainId: ChainId;\n status: NetworkStatus;\n name: string;\n nativeCurrency: string;\n /** Network client ID for getting the provider */\n networkClientId: string;\n};\n\nexport type RpcDataSourceState = {\n /** Network status for each active chain */\n chainStatuses: Record<ChainId, ChainStatus>;\n} & DataSourceState;\n\nconst defaultState: RpcDataSourceState = {\n activeChains: [],\n chainStatuses: {},\n};\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport type RpcDataSourceOptions = {\n messenger: RpcDataSourceMessenger;\n /** Request timeout in ms */\n timeout?: number;\n /** Polling interval in ms */\n pollInterval?: number;\n state?: Partial<RpcDataSourceState>;\n};\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\nfunction buildNativeAssetId(chainId: ChainId): Caip19AssetId {\n return `${chainId}/slip44:60` as Caip19AssetId;\n}\n\n// ============================================================================\n// RPC DATA SOURCE\n// ============================================================================\n\n/**\n * Data source for fetching balances via RPC calls.\n *\n * Used as a fallback when the Accounts API doesn't support a chain.\n *\n * Communicates with AssetsController via Messenger:\n *\n * Actions:\n * - RpcDataSource:getActiveChains\n * - RpcDataSource:fetch\n * - RpcDataSource:subscribe\n * - RpcDataSource:unsubscribe\n *\n * Events:\n * - RpcDataSource:activeChainsUpdated\n * - RpcDataSource:assetsUpdated\n */\nexport class RpcDataSource extends AbstractDataSource<\n typeof CONTROLLER_NAME,\n RpcDataSourceState\n> {\n readonly #messenger: RpcDataSourceMessenger;\n\n readonly #timeout: number;\n\n readonly #pollInterval: number;\n\n /** Cache of Web3Provider instances by chainId */\n readonly #providerCache: Map<ChainId, Web3Provider> = new Map();\n\n constructor(options: RpcDataSourceOptions) {\n super(CONTROLLER_NAME, {\n ...defaultState,\n ...options.state,\n });\n\n this.#messenger = options.messenger;\n this.#timeout = options.timeout ?? 10_000;\n this.#pollInterval = options.pollInterval ?? DEFAULT_POLL_INTERVAL;\n\n this.#registerActionHandlers();\n this.#subscribeToNetworkController();\n this.#initializeFromNetworkController();\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n #registerActionHandlers(): void {\n const getAssetsMiddlewareHandler: RpcDataSourceGetAssetsMiddlewareAction['handler'] =\n () => this.assetsMiddleware;\n\n const getActiveChainsHandler: RpcDataSourceGetActiveChainsAction['handler'] =\n async () => this.getActiveChains();\n\n const fetchHandler: RpcDataSourceFetchAction['handler'] = async (request) =>\n this.fetch(request);\n\n const subscribeHandler: RpcDataSourceSubscribeAction['handler'] = async (\n request,\n ) => this.subscribe(request);\n\n const unsubscribeHandler: RpcDataSourceUnsubscribeAction['handler'] =\n async (subscriptionId) => this.unsubscribe(subscriptionId);\n\n this.#messenger.registerActionHandler(\n 'RpcDataSource:getAssetsMiddleware',\n getAssetsMiddlewareHandler,\n );\n\n this.#messenger.registerActionHandler(\n 'RpcDataSource:getActiveChains',\n getActiveChainsHandler,\n );\n\n this.#messenger.registerActionHandler('RpcDataSource:fetch', fetchHandler);\n\n this.#messenger.registerActionHandler(\n 'RpcDataSource:subscribe',\n subscribeHandler,\n );\n\n this.#messenger.registerActionHandler(\n 'RpcDataSource:unsubscribe',\n unsubscribeHandler,\n );\n }\n\n /**\n * Subscribe to NetworkController state changes.\n */\n #subscribeToNetworkController(): void {\n this.#messenger.subscribe(\n 'NetworkController:stateChange',\n (networkState: NetworkState) => {\n // Clear provider cache since network configurations may have changed\n this.#clearProviderCache();\n this.#updateFromNetworkState(networkState);\n },\n );\n }\n\n /**\n * Initialize active chains from NetworkController state.\n */\n #initializeFromNetworkController(): void {\n try {\n const networkState = this.#messenger.call('NetworkController:getState');\n this.#updateFromNetworkState(networkState);\n } catch (error) {\n log('Failed to initialize from NetworkController', error);\n }\n }\n\n /**\n * Update active chains and statuses from NetworkController state.\n * Only chains with an available provider are considered active.\n *\n * @param networkState - The current NetworkController state.\n */\n #updateFromNetworkState(networkState: NetworkState): void {\n const { networkConfigurationsByChainId, networksMetadata } = networkState;\n\n const chainStatuses: Record<ChainId, ChainStatus> = {};\n const activeChains: ChainId[] = [];\n\n // Iterate through all configured networks\n for (const [hexChainId, config] of Object.entries(\n networkConfigurationsByChainId,\n )) {\n // Convert hex chainId to CAIP-2 format (eip155:decimal)\n const decimalChainId = parseInt(hexChainId, 16);\n const caip2ChainId = `eip155:${decimalChainId}` as ChainId;\n\n // Get the default RPC endpoint's network client ID\n const defaultRpcEndpoint =\n config.rpcEndpoints[config.defaultRpcEndpointIndex];\n if (!defaultRpcEndpoint) {\n continue;\n }\n\n const { networkClientId } = defaultRpcEndpoint;\n const metadata = networksMetadata[networkClientId];\n\n // Determine status - default to 'unknown' if not in metadata\n const status: NetworkStatus =\n metadata?.status ?? ('unknown' as NetworkStatus);\n\n chainStatuses[caip2ChainId] = {\n chainId: caip2ChainId,\n status,\n name: config.name,\n nativeCurrency: config.nativeCurrency,\n networkClientId,\n };\n\n // Only include chains that have an available status\n // (not degraded/unavailable/blocked)\n if (status === 'available' || status === 'unknown') {\n activeChains.push(caip2ChainId);\n }\n }\n\n // Update state\n this.state.chainStatuses = chainStatuses;\n\n // Update active chains and report to AssetsController\n this.updateActiveChains(activeChains, (chains) =>\n this.#messenger.call(\n 'AssetsController:activeChainsUpdate',\n CONTROLLER_NAME,\n chains,\n ),\n );\n }\n\n // ============================================================================\n // PROVIDER MANAGEMENT\n // ============================================================================\n\n /**\n * Get or create a Web3Provider for a chain.\n * Uses NetworkController to get the underlying provider.\n *\n * @param chainId - The CAIP-2 chain ID.\n * @returns The Web3Provider for the chain, or undefined if not available.\n */\n #getProvider(chainId: ChainId): Web3Provider | undefined {\n // Check cache first\n const cached = this.#providerCache.get(chainId);\n if (cached) {\n return cached;\n }\n\n // Get chain status to find networkClientId\n const chainStatus = this.state.chainStatuses[chainId];\n if (!chainStatus) {\n return undefined;\n }\n\n try {\n // Get network client from NetworkController (like TokenBalancesController)\n const networkClient = this.#messenger.call(\n 'NetworkController:getNetworkClientById',\n chainStatus.networkClientId,\n );\n\n // Create Web3Provider directly\n const web3Provider = new Web3Provider(networkClient.provider);\n\n // Cache for reuse\n this.#providerCache.set(chainId, web3Provider);\n\n return web3Provider;\n } catch (error) {\n console.error(\n `[RpcDataSource] Failed to get provider for chain ${chainId}:`,\n error,\n );\n return undefined;\n }\n }\n\n /**\n * Clear provider cache (e.g., when network configuration changes).\n */\n #clearProviderCache(): void {\n this.#providerCache.clear();\n }\n\n // ============================================================================\n // ACCOUNT SCOPE HELPERS\n // ============================================================================\n\n /**\n * Check if an account supports a specific chain based on its scopes.\n * RpcDataSource only handles EVM chains, so we check for EIP155 scopes.\n *\n * @param account - The account to check\n * @param chainId - The chain ID to check (e.g., \"eip155:1\")\n * @returns True if the account supports the chain\n */\n #accountSupportsChain(account: InternalAccount, chainId: ChainId): boolean {\n const scopes = account.scopes ?? [];\n\n // If no scopes defined, assume it supports the chain (backward compatibility)\n if (scopes.length === 0) {\n return true;\n }\n\n // Extract namespace and reference from chainId (e.g., \"eip155:1\" -> [\"eip155\", \"1\"])\n const [chainNamespace, chainReference] = chainId.split(':');\n\n for (const scope of scopes) {\n const [scopeNamespace, scopeReference] = (scope as string).split(':');\n\n // Check if namespaces match\n if (scopeNamespace !== chainNamespace) {\n continue;\n }\n\n // Wildcard scope (e.g., \"eip155:0\" means all chains in that namespace)\n if (scopeReference === '0') {\n return true;\n }\n\n // Exact match check - normalize hex to decimal for EIP155\n if (chainNamespace === 'eip155') {\n const normalizedScopeRef = scopeReference?.startsWith('0x')\n ? parseInt(scopeReference, 16).toString()\n : scopeReference;\n if (normalizedScopeRef === chainReference) {\n return true;\n }\n } else if (scopeReference === chainReference) {\n return true;\n }\n }\n\n return false;\n }\n\n // ============================================================================\n // CHAIN STATUS\n // ============================================================================\n\n /**\n * Get the status of all configured chains.\n *\n * @returns Record of chain statuses keyed by chain ID.\n */\n getChainStatuses(): Record<ChainId, ChainStatus> {\n return { ...this.state.chainStatuses };\n }\n\n /**\n * Get the status of a specific chain.\n *\n * @param chainId - The CAIP-2 chain ID to check.\n * @returns The chain status, or undefined if not configured.\n */\n getChainStatus(chainId: ChainId): ChainStatus | undefined {\n return this.state.chainStatuses[chainId];\n }\n\n // ============================================================================\n // FETCH\n // ============================================================================\n\n async fetch(request: DataRequest): Promise<DataResponse> {\n const response: DataResponse = {};\n\n // Filter to active chains\n const chainsToFetch = request.chainIds.filter((chainId) =>\n this.state.activeChains.includes(chainId),\n );\n\n if (chainsToFetch.length === 0) {\n return response;\n }\n\n const assetsBalance: Record<\n string,\n Record<Caip19AssetId, AssetBalance>\n > = {};\n const failedChains: ChainId[] = [];\n\n // Fetch native balance for each chain\n for (const chainId of chainsToFetch) {\n const provider = this.#getProvider(chainId);\n\n if (!provider) {\n continue;\n }\n\n const assetId = buildNativeAssetId(chainId);\n\n // Fetch balance for each account that supports this chain\n for (const account of request.accounts) {\n // Check if account supports this chain based on its scopes\n if (!this.#accountSupportsChain(account, chainId)) {\n continue;\n }\n\n const { address, id: accountId } = account;\n\n try {\n const balancePromise = provider.getBalance(address);\n const timeoutPromise = new Promise<never>((_resolve, reject) =>\n setTimeout(() => reject(new Error('RPC timeout')), this.#timeout),\n );\n\n const balance = await Promise.race([balancePromise, timeoutPromise]);\n\n if (!assetsBalance[accountId]) {\n assetsBalance[accountId] = {};\n }\n\n assetsBalance[accountId][assetId] = {\n amount: balance.toString(),\n };\n } catch (error) {\n log('Failed to fetch balance', { address, chainId, error });\n\n if (!assetsBalance[accountId]) {\n assetsBalance[accountId] = {};\n }\n assetsBalance[accountId][assetId] = { amount: '0' };\n\n if (!failedChains.includes(chainId)) {\n failedChains.push(chainId);\n }\n }\n }\n }\n\n if (failedChains.length > 0) {\n // Add failed chains to errors so they can fallback to other data sources\n response.errors = {};\n for (const chainId of failedChains) {\n response.errors[chainId] = 'RPC fetch failed';\n }\n }\n\n response.assetsBalance = assetsBalance;\n\n return response;\n }\n\n // ============================================================================\n // MIDDLEWARE\n // ============================================================================\n\n /**\n * Get the middleware for fetching balances via RPC.\n * This middleware:\n * - Supports multiple accounts in a single request\n * - Filters request to only chains this data source supports\n * - Fetches balances for those chains for all accounts\n * - Merges response into context\n * - Removes handled chains from request for next middleware\n *\n * @returns The middleware function for the assets pipeline.\n */\n get assetsMiddleware(): Middleware {\n return async (context, next) => {\n const { request } = context;\n\n // Filter to chains this data source supports\n const supportedChains = request.chainIds.filter((chainId) =>\n this.state.activeChains.includes(chainId),\n );\n\n // If no supported chains, skip and pass to next middleware\n if (supportedChains.length === 0) {\n return next(context);\n }\n\n let successfullyHandledChains: ChainId[] = [];\n\n try {\n // Fetch for supported chains\n const response = await this.fetch({\n ...request,\n chainIds: supportedChains,\n });\n\n // Merge response into context\n if (response.assetsBalance) {\n context.response.assetsBalance ??= {};\n for (const [accountId, accountBalances] of Object.entries(\n response.assetsBalance,\n )) {\n if (!context.response.assetsBalance[accountId]) {\n context.response.assetsBalance[accountId] = {};\n }\n context.response.assetsBalance[accountId] = {\n ...context.response.assetsBalance[accountId],\n ...accountBalances,\n };\n }\n }\n\n // Determine successfully handled chains (exclude errors)\n const failedChains = new Set(Object.keys(response.errors ?? {}));\n successfullyHandledChains = supportedChains.filter(\n (chainId) => !failedChains.has(chainId),\n );\n } catch (error) {\n log('Middleware fetch failed', { error });\n successfullyHandledChains = [];\n }\n\n // Remove successfully handled chains from request for next middleware\n if (successfullyHandledChains.length > 0) {\n const remainingChains = request.chainIds.filter(\n (chainId) => !successfullyHandledChains.includes(chainId),\n );\n\n return next({\n ...context,\n request: {\n ...request,\n chainIds: remainingChains,\n },\n });\n }\n\n // No chains handled - pass context unchanged\n return next(context);\n };\n }\n\n // ============================================================================\n // SUBSCRIBE\n // ============================================================================\n\n async subscribe(subscriptionRequest: SubscriptionRequest): Promise<void> {\n const { request, subscriptionId, isUpdate } = subscriptionRequest;\n\n // Filter to active chains\n const chainsToSubscribe = request.chainIds.filter((chainId) =>\n this.state.activeChains.includes(chainId),\n );\n\n if (chainsToSubscribe.length === 0) {\n return;\n }\n\n // Handle subscription update - update both chains AND request (for accounts)\n if (isUpdate) {\n const existing = this.activeSubscriptions.get(subscriptionId);\n if (existing) {\n existing.chains = chainsToSubscribe;\n existing.request = request;\n return;\n }\n }\n\n // Clean up existing subscription\n await this.unsubscribe(subscriptionId);\n\n const pollInterval = request.updateInterval ?? this.#pollInterval;\n\n // Create poll function\n const pollFn = async (): Promise<void> => {\n try {\n const subscription = this.activeSubscriptions.get(subscriptionId);\n if (!subscription?.request) {\n return;\n }\n\n // Use stored request (which gets updated on account changes)\n const fetchResponse = await this.fetch({\n ...subscription.request,\n chainIds: subscription.chains,\n });\n\n // Report update to AssetsController\n await this.#messenger.call(\n 'AssetsController:assetsUpdate',\n fetchResponse,\n CONTROLLER_NAME,\n );\n } catch (error) {\n log('Subscription poll failed', { subscriptionId, error });\n }\n };\n\n // Set up polling\n const timer = setInterval(() => {\n pollFn().catch(console.error);\n }, pollInterval);\n\n // Store subscription with request for account updates\n this.activeSubscriptions.set(subscriptionId, {\n cleanup: () => {\n clearInterval(timer);\n },\n chains: chainsToSubscribe,\n request,\n });\n\n // Initial fetch\n await pollFn();\n }\n}\n\n// ============================================================================\n// FACTORY FUNCTION\n// ============================================================================\n\n/**\n * Creates an RpcDataSource instance.\n *\n * @param options - Configuration options for the data source.\n * @returns A new RpcDataSource instance.\n */\nexport function createRpcDataSource(\n options: RpcDataSourceOptions,\n): RpcDataSource {\n return new RpcDataSource(options);\n}\n"]}