@metamask/assets-controller 0.2.0 → 2.0.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 (202) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/dist/AssetsController-method-action-types.cjs +7 -0
  3. package/dist/AssetsController-method-action-types.cjs.map +1 -0
  4. package/dist/AssetsController-method-action-types.d.cts +78 -0
  5. package/dist/AssetsController-method-action-types.d.cts.map +1 -0
  6. package/dist/AssetsController-method-action-types.d.mts +78 -0
  7. package/dist/AssetsController-method-action-types.d.mts.map +1 -0
  8. package/dist/AssetsController-method-action-types.mjs +6 -0
  9. package/dist/AssetsController-method-action-types.mjs.map +1 -0
  10. package/dist/AssetsController.cjs +346 -271
  11. package/dist/AssetsController.cjs.map +1 -1
  12. package/dist/AssetsController.d.cts +92 -96
  13. package/dist/AssetsController.d.cts.map +1 -1
  14. package/dist/AssetsController.d.mts +92 -96
  15. package/dist/AssetsController.d.mts.map +1 -1
  16. package/dist/AssetsController.mjs +347 -272
  17. package/dist/AssetsController.mjs.map +1 -1
  18. package/dist/data-sources/AbstractDataSource.cjs +8 -0
  19. package/dist/data-sources/AbstractDataSource.cjs.map +1 -1
  20. package/dist/data-sources/AbstractDataSource.d.cts +16 -1
  21. package/dist/data-sources/AbstractDataSource.d.cts.map +1 -1
  22. package/dist/data-sources/AbstractDataSource.d.mts +16 -1
  23. package/dist/data-sources/AbstractDataSource.d.mts.map +1 -1
  24. package/dist/data-sources/AbstractDataSource.mjs +8 -0
  25. package/dist/data-sources/AbstractDataSource.mjs.map +1 -1
  26. package/dist/data-sources/AccountsApiDataSource.cjs +92 -111
  27. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  28. package/dist/data-sources/AccountsApiDataSource.d.cts +27 -70
  29. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
  30. package/dist/data-sources/AccountsApiDataSource.d.mts +27 -70
  31. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
  32. package/dist/data-sources/AccountsApiDataSource.mjs +88 -107
  33. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  34. package/dist/data-sources/BackendWebsocketDataSource.cjs +141 -46
  35. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
  36. package/dist/data-sources/BackendWebsocketDataSource.d.cts +19 -66
  37. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
  38. package/dist/data-sources/BackendWebsocketDataSource.d.mts +19 -66
  39. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
  40. package/dist/data-sources/BackendWebsocketDataSource.mjs +141 -46
  41. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
  42. package/dist/data-sources/PriceDataSource.cjs +39 -48
  43. package/dist/data-sources/PriceDataSource.cjs.map +1 -1
  44. package/dist/data-sources/PriceDataSource.d.cts +13 -92
  45. package/dist/data-sources/PriceDataSource.d.cts.map +1 -1
  46. package/dist/data-sources/PriceDataSource.d.mts +13 -92
  47. package/dist/data-sources/PriceDataSource.d.mts.map +1 -1
  48. package/dist/data-sources/PriceDataSource.mjs +39 -48
  49. package/dist/data-sources/PriceDataSource.mjs.map +1 -1
  50. package/dist/data-sources/RpcDataSource.cjs +184 -142
  51. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  52. package/dist/data-sources/RpcDataSource.d.cts +29 -114
  53. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  54. package/dist/data-sources/RpcDataSource.d.mts +29 -114
  55. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  56. package/dist/data-sources/RpcDataSource.mjs +185 -143
  57. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  58. package/dist/data-sources/SnapDataSource.cjs +53 -39
  59. package/dist/data-sources/SnapDataSource.cjs.map +1 -1
  60. package/dist/data-sources/SnapDataSource.d.cts +9 -45
  61. package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
  62. package/dist/data-sources/SnapDataSource.d.mts +9 -45
  63. package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
  64. package/dist/data-sources/SnapDataSource.mjs +53 -39
  65. package/dist/data-sources/SnapDataSource.mjs.map +1 -1
  66. package/dist/data-sources/StakedBalanceDataSource.cjs +609 -0
  67. package/dist/data-sources/StakedBalanceDataSource.cjs.map +1 -0
  68. package/dist/data-sources/StakedBalanceDataSource.d.cts +72 -0
  69. package/dist/data-sources/StakedBalanceDataSource.d.cts.map +1 -0
  70. package/dist/data-sources/StakedBalanceDataSource.d.mts +72 -0
  71. package/dist/data-sources/StakedBalanceDataSource.d.mts.map +1 -0
  72. package/dist/data-sources/StakedBalanceDataSource.mjs +605 -0
  73. package/dist/data-sources/StakedBalanceDataSource.mjs.map +1 -0
  74. package/dist/data-sources/TokenDataSource.cjs +15 -21
  75. package/dist/data-sources/TokenDataSource.cjs.map +1 -1
  76. package/dist/data-sources/TokenDataSource.d.cts +3 -25
  77. package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
  78. package/dist/data-sources/TokenDataSource.d.mts +3 -25
  79. package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
  80. package/dist/data-sources/TokenDataSource.mjs +15 -21
  81. package/dist/data-sources/TokenDataSource.mjs.map +1 -1
  82. package/dist/data-sources/evm-rpc-services/index.cjs +5 -1
  83. package/dist/data-sources/evm-rpc-services/index.cjs.map +1 -1
  84. package/dist/data-sources/evm-rpc-services/index.d.cts +1 -1
  85. package/dist/data-sources/evm-rpc-services/index.d.cts.map +1 -1
  86. package/dist/data-sources/evm-rpc-services/index.d.mts +1 -1
  87. package/dist/data-sources/evm-rpc-services/index.d.mts.map +1 -1
  88. package/dist/data-sources/evm-rpc-services/index.mjs +1 -1
  89. package/dist/data-sources/evm-rpc-services/index.mjs.map +1 -1
  90. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs +132 -0
  91. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.cjs.map +1 -0
  92. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts +78 -0
  93. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.cts.map +1 -0
  94. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts +78 -0
  95. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.d.mts.map +1 -0
  96. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs +126 -0
  97. package/dist/data-sources/evm-rpc-services/services/StakedBalanceFetcher.mjs.map +1 -0
  98. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs +16 -0
  99. package/dist/data-sources/evm-rpc-services/services/TokenDetector.cjs.map +1 -1
  100. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts +5 -1
  101. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.cts.map +1 -1
  102. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts +5 -1
  103. package/dist/data-sources/evm-rpc-services/services/TokenDetector.d.mts.map +1 -1
  104. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs +16 -0
  105. package/dist/data-sources/evm-rpc-services/services/TokenDetector.mjs.map +1 -1
  106. package/dist/data-sources/evm-rpc-services/services/index.cjs +6 -1
  107. package/dist/data-sources/evm-rpc-services/services/index.cjs.map +1 -1
  108. package/dist/data-sources/evm-rpc-services/services/index.d.cts +1 -0
  109. package/dist/data-sources/evm-rpc-services/services/index.d.cts.map +1 -1
  110. package/dist/data-sources/evm-rpc-services/services/index.d.mts +1 -0
  111. package/dist/data-sources/evm-rpc-services/services/index.d.mts.map +1 -1
  112. package/dist/data-sources/evm-rpc-services/services/index.mjs +1 -0
  113. package/dist/data-sources/evm-rpc-services/services/index.mjs.map +1 -1
  114. package/dist/data-sources/evm-rpc-services/types/services.cjs.map +1 -1
  115. package/dist/data-sources/evm-rpc-services/types/services.d.cts +4 -0
  116. package/dist/data-sources/evm-rpc-services/types/services.d.cts.map +1 -1
  117. package/dist/data-sources/evm-rpc-services/types/services.d.mts +4 -0
  118. package/dist/data-sources/evm-rpc-services/types/services.d.mts.map +1 -1
  119. package/dist/data-sources/evm-rpc-services/types/services.mjs.map +1 -1
  120. package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -1
  121. package/dist/data-sources/evm-rpc-services/types/state.d.cts +3 -3
  122. package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -1
  123. package/dist/data-sources/evm-rpc-services/types/state.d.mts +3 -3
  124. package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -1
  125. package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -1
  126. package/dist/data-sources/evm-rpc-services/utils/index.cjs +9 -1
  127. package/dist/data-sources/evm-rpc-services/utils/index.cjs.map +1 -1
  128. package/dist/data-sources/evm-rpc-services/utils/index.d.cts +2 -0
  129. package/dist/data-sources/evm-rpc-services/utils/index.d.cts.map +1 -1
  130. package/dist/data-sources/evm-rpc-services/utils/index.d.mts +2 -0
  131. package/dist/data-sources/evm-rpc-services/utils/index.d.mts.map +1 -1
  132. package/dist/data-sources/evm-rpc-services/utils/index.mjs +2 -0
  133. package/dist/data-sources/evm-rpc-services/utils/index.mjs.map +1 -1
  134. package/dist/data-sources/evm-rpc-services/utils/parsing.cjs +47 -0
  135. package/dist/data-sources/evm-rpc-services/utils/parsing.cjs.map +1 -0
  136. package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts +25 -0
  137. package/dist/data-sources/evm-rpc-services/utils/parsing.d.cts.map +1 -0
  138. package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts +25 -0
  139. package/dist/data-sources/evm-rpc-services/utils/parsing.d.mts.map +1 -0
  140. package/dist/data-sources/evm-rpc-services/utils/parsing.mjs +39 -0
  141. package/dist/data-sources/evm-rpc-services/utils/parsing.mjs.map +1 -0
  142. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs +68 -0
  143. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.cjs.map +1 -0
  144. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts +25 -0
  145. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.cts.map +1 -0
  146. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts +25 -0
  147. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.d.mts.map +1 -0
  148. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs +62 -0
  149. package/dist/data-sources/evm-rpc-services/utils/staking-contracts.mjs.map +1 -0
  150. package/dist/data-sources/index.cjs +3 -6
  151. package/dist/data-sources/index.cjs.map +1 -1
  152. package/dist/data-sources/index.d.cts +7 -7
  153. package/dist/data-sources/index.d.cts.map +1 -1
  154. package/dist/data-sources/index.d.mts +7 -7
  155. package/dist/data-sources/index.d.mts.map +1 -1
  156. package/dist/data-sources/index.mjs +2 -3
  157. package/dist/data-sources/index.mjs.map +1 -1
  158. package/dist/index.cjs +6 -6
  159. package/dist/index.cjs.map +1 -1
  160. package/dist/index.d.cts +11 -11
  161. package/dist/index.d.cts.map +1 -1
  162. package/dist/index.d.mts +11 -11
  163. package/dist/index.d.mts.map +1 -1
  164. package/dist/index.mjs +3 -3
  165. package/dist/index.mjs.map +1 -1
  166. package/dist/middlewares/DetectionMiddleware.cjs +8 -28
  167. package/dist/middlewares/DetectionMiddleware.cjs.map +1 -1
  168. package/dist/middlewares/DetectionMiddleware.d.cts +4 -26
  169. package/dist/middlewares/DetectionMiddleware.d.cts.map +1 -1
  170. package/dist/middlewares/DetectionMiddleware.d.mts +4 -26
  171. package/dist/middlewares/DetectionMiddleware.d.mts.map +1 -1
  172. package/dist/middlewares/DetectionMiddleware.mjs +8 -28
  173. package/dist/middlewares/DetectionMiddleware.mjs.map +1 -1
  174. package/dist/middlewares/index.cjs.map +1 -1
  175. package/dist/middlewares/index.d.cts +1 -1
  176. package/dist/middlewares/index.d.cts.map +1 -1
  177. package/dist/middlewares/index.d.mts +1 -1
  178. package/dist/middlewares/index.d.mts.map +1 -1
  179. package/dist/middlewares/index.mjs.map +1 -1
  180. package/dist/selectors/balance.cjs +306 -0
  181. package/dist/selectors/balance.cjs.map +1 -0
  182. package/dist/selectors/balance.d.cts +22 -0
  183. package/dist/selectors/balance.d.cts.map +1 -0
  184. package/dist/selectors/balance.d.mts +22 -0
  185. package/dist/selectors/balance.d.mts.map +1 -0
  186. package/dist/selectors/balance.mjs +297 -0
  187. package/dist/selectors/balance.mjs.map +1 -0
  188. package/dist/types.cjs.map +1 -1
  189. package/dist/types.d.cts +56 -21
  190. package/dist/types.d.cts.map +1 -1
  191. package/dist/types.d.mts +56 -21
  192. package/dist/types.d.mts.map +1 -1
  193. package/dist/types.mjs.map +1 -1
  194. package/package.json +13 -10
  195. package/dist/data-sources/initDataSources.cjs +0 -215
  196. package/dist/data-sources/initDataSources.cjs.map +0 -1
  197. package/dist/data-sources/initDataSources.d.cts +0 -140
  198. package/dist/data-sources/initDataSources.d.cts.map +0 -1
  199. package/dist/data-sources/initDataSources.d.mts +0 -140
  200. package/dist/data-sources/initDataSources.d.mts.map +0 -1
  201. package/dist/data-sources/initDataSources.mjs +0 -210
  202. package/dist/data-sources/initDataSources.mjs.map +0 -1
@@ -1,78 +1,42 @@
1
1
  import { ApiPlatformClient } from "@metamask/core-backend";
2
- import type { Messenger } from "@metamask/messenger";
3
2
  import type { DataSourceState, SubscriptionRequest } from "./AbstractDataSource.cjs";
4
3
  import { AbstractDataSource } from "./AbstractDataSource.cjs";
5
- import type { ChainId, DataRequest, DataResponse, Middleware } from "../types.cjs";
4
+ import type { ChainId, DataRequest, DataResponse, Middleware, AssetsControllerStateInternal } from "../types.cjs";
6
5
  declare const CONTROLLER_NAME = "AccountsApiDataSource";
7
- export type AccountsApiDataSourceGetAssetsMiddlewareAction = {
8
- type: 'AccountsApiDataSource:getAssetsMiddleware';
9
- handler: () => Middleware;
10
- };
11
- export type AccountsApiDataSourceGetActiveChainsAction = {
12
- type: 'AccountsApiDataSource:getActiveChains';
13
- handler: () => Promise<ChainId[]>;
14
- };
15
- export type AccountsApiDataSourceFetchAction = {
16
- type: 'AccountsApiDataSource:fetch';
17
- handler: (request: DataRequest) => Promise<DataResponse>;
18
- };
19
- export type AccountsApiDataSourceSubscribeAction = {
20
- type: 'AccountsApiDataSource:subscribe';
21
- handler: (request: SubscriptionRequest) => Promise<void>;
22
- };
23
- export type AccountsApiDataSourceUnsubscribeAction = {
24
- type: 'AccountsApiDataSource:unsubscribe';
25
- handler: (subscriptionId: string) => Promise<void>;
26
- };
27
- export type AccountsApiDataSourceActions = AccountsApiDataSourceGetAssetsMiddlewareAction | AccountsApiDataSourceGetActiveChainsAction | AccountsApiDataSourceFetchAction | AccountsApiDataSourceSubscribeAction | AccountsApiDataSourceUnsubscribeAction;
28
- export type AccountsApiDataSourceActiveChainsChangedEvent = {
29
- type: 'AccountsApiDataSource:activeChainsUpdated';
30
- payload: [ChainId[]];
31
- };
32
- export type AccountsApiDataSourceAssetsUpdatedEvent = {
33
- type: 'AccountsApiDataSource:assetsUpdated';
34
- payload: [DataResponse, string | undefined];
35
- };
36
- export type AccountsApiDataSourceEvents = AccountsApiDataSourceActiveChainsChangedEvent | AccountsApiDataSourceAssetsUpdatedEvent;
37
- type AssetsControllerActiveChainsUpdateAction = {
38
- type: 'AssetsController:activeChainsUpdate';
39
- handler: (dataSourceId: string, activeChains: ChainId[]) => void;
40
- };
41
- type AssetsControllerAssetsUpdateAction = {
42
- type: 'AssetsController:assetsUpdate';
43
- handler: (response: DataResponse, sourceId: string) => Promise<void>;
44
- };
45
- export type AccountsApiDataSourceAllowedActions = AssetsControllerActiveChainsUpdateAction | AssetsControllerAssetsUpdateAction;
46
- export type AccountsApiDataSourceMessenger = Messenger<typeof CONTROLLER_NAME, AccountsApiDataSourceActions | AccountsApiDataSourceAllowedActions, AccountsApiDataSourceEvents>;
6
+ export type AccountsApiDataSourceAllowedActions = never;
47
7
  export type AccountsApiDataSourceState = DataSourceState;
48
- export type AccountsApiDataSourceOptions = {
49
- messenger: AccountsApiDataSourceMessenger;
8
+ /** Optional configuration for AccountsApiDataSource. */
9
+ export type AccountsApiDataSourceConfig = {
10
+ /** Polling interval in ms (default: 30000) */
11
+ pollInterval?: number;
12
+ /**
13
+ * Function returning whether token detection is enabled (default: () => true).
14
+ * When it returns false, balances are only returned for tokens already in state.
15
+ * Using a getter avoids stale values when the user toggles the preference at runtime.
16
+ */
17
+ tokenDetectionEnabled?: () => boolean;
18
+ };
19
+ export type AccountsApiDataSourceOptions = AccountsApiDataSourceConfig & {
50
20
  /** ApiPlatformClient for API calls with caching */
51
21
  queryApiClient: ApiPlatformClient;
52
- pollInterval?: number;
22
+ /** Called when active chains are updated. Pass dataSourceName so the controller knows the source. */
23
+ onActiveChainsUpdated: (dataSourceName: string, chains: ChainId[], previousChains: ChainId[]) => void;
53
24
  state?: Partial<AccountsApiDataSourceState>;
54
25
  };
55
26
  /**
56
- * Data source for fetching balances from the MetaMask Accounts API.
27
+ * Filter a response to only include balances for assets already in state.
28
+ * Used when tokenDetectionEnabled is false to prevent adding new tokens.
57
29
  *
58
- * Uses Messenger pattern for all interactions:
59
- * - Calls BackendApiClient methods via messenger actions
60
- * - Exposes its own actions for AssetsController to call
61
- * - Publishes events for AssetsController to subscribe to
62
- *
63
- * Actions exposed:
64
- * - AccountsApiDataSource:getActiveChains
65
- * - AccountsApiDataSource:fetch
66
- * - AccountsApiDataSource:subscribe
67
- * - AccountsApiDataSource:unsubscribe
68
- *
69
- * Events published:
70
- * - AccountsApiDataSource:activeChainsUpdated
71
- * - AccountsApiDataSource:assetsUpdated
30
+ * @param response - The fetch response to filter.
31
+ * @param assetsState - Current assets controller state to check existing balances against.
32
+ * @returns A new response with only known asset balances.
33
+ */
34
+ export declare function filterResponseToKnownAssets(response: DataResponse, assetsState: AssetsControllerStateInternal): DataResponse;
35
+ /**
36
+ * Data source for fetching balances from the MetaMask Accounts API.
72
37
  *
73
- * Actions called (from BackendApiClient):
74
- * - BackendApiClient:Accounts:getV2SupportedNetworks
75
- * - BackendApiClient:Accounts:getV5MultiAccountBalances
38
+ * Uses ApiPlatformClient (queryApiClient) for all API calls. Does not use the
39
+ * messenger. Reports active chains via onActiveChainsUpdated callback.
76
40
  */
77
41
  export declare class AccountsApiDataSource extends AbstractDataSource<typeof CONTROLLER_NAME, AccountsApiDataSourceState> {
78
42
  #private;
@@ -92,12 +56,5 @@ export declare class AccountsApiDataSource extends AbstractDataSource<typeof CON
92
56
  subscribe(subscriptionRequest: SubscriptionRequest): Promise<void>;
93
57
  destroy(): void;
94
58
  }
95
- /**
96
- * Creates an AccountsApiDataSource instance.
97
- *
98
- * @param options - Configuration options for the data source.
99
- * @returns A new AccountsApiDataSource instance.
100
- */
101
- export declare function createAccountsApiDataSource(options: AccountsApiDataSourceOptions): AccountsApiDataSource;
102
59
  export {};
103
60
  //# sourceMappingURL=AccountsApiDataSource.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccountsApiDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/AccountsApiDataSource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountsApiDataSource.d.cts","sourceRoot":"","sources":["../../src/data-sources/AccountsApiDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,iCAA6B;AAC9B,OAAO,EAAE,kBAAkB,EAAE,iCAA6B;AAE1D,OAAO,KAAK,EACV,OAAO,EAGP,WAAW,EACX,YAAY,EACZ,UAAU,EACV,6BAA6B,EAC9B,qBAAiB;AAOlB,QAAA,MAAM,eAAe,0BAA0B,CAAC;AAWhD,MAAM,MAAM,mCAAmC,GAAG,KAAK,CAAC;AAMxD,MAAM,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAUzD,wDAAwD;AACxD,MAAM,MAAM,2BAA2B,GAAG;IACxC,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,2BAA2B,GAAG;IACvE,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;IAClC,qGAAqG;IACrG,qBAAqB,EAAE,CACrB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,OAAO,EAAE,EACjB,cAAc,EAAE,OAAO,EAAE,KACtB,IAAI,CAAC;IACV,KAAK,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC7C,CAAC;AAgCF;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,6BAA6B,GACzC,YAAY,CAqCd;AAMD;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,kBAAkB,CAC3D,OAAO,eAAe,EACtB,0BAA0B,CAC3B;;gBAqBa,OAAO,EAAE,4BAA4B;IA6E3C,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAkJxD;;;;;;;;;OASG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAkEjC;IAMK,SAAS,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0ExE,OAAO,IAAI,IAAI;CAShB"}
@@ -1,78 +1,42 @@
1
1
  import { ApiPlatformClient } from "@metamask/core-backend";
2
- import type { Messenger } from "@metamask/messenger";
3
2
  import type { DataSourceState, SubscriptionRequest } from "./AbstractDataSource.mjs";
4
3
  import { AbstractDataSource } from "./AbstractDataSource.mjs";
5
- import type { ChainId, DataRequest, DataResponse, Middleware } from "../types.mjs";
4
+ import type { ChainId, DataRequest, DataResponse, Middleware, AssetsControllerStateInternal } from "../types.mjs";
6
5
  declare const CONTROLLER_NAME = "AccountsApiDataSource";
7
- export type AccountsApiDataSourceGetAssetsMiddlewareAction = {
8
- type: 'AccountsApiDataSource:getAssetsMiddleware';
9
- handler: () => Middleware;
10
- };
11
- export type AccountsApiDataSourceGetActiveChainsAction = {
12
- type: 'AccountsApiDataSource:getActiveChains';
13
- handler: () => Promise<ChainId[]>;
14
- };
15
- export type AccountsApiDataSourceFetchAction = {
16
- type: 'AccountsApiDataSource:fetch';
17
- handler: (request: DataRequest) => Promise<DataResponse>;
18
- };
19
- export type AccountsApiDataSourceSubscribeAction = {
20
- type: 'AccountsApiDataSource:subscribe';
21
- handler: (request: SubscriptionRequest) => Promise<void>;
22
- };
23
- export type AccountsApiDataSourceUnsubscribeAction = {
24
- type: 'AccountsApiDataSource:unsubscribe';
25
- handler: (subscriptionId: string) => Promise<void>;
26
- };
27
- export type AccountsApiDataSourceActions = AccountsApiDataSourceGetAssetsMiddlewareAction | AccountsApiDataSourceGetActiveChainsAction | AccountsApiDataSourceFetchAction | AccountsApiDataSourceSubscribeAction | AccountsApiDataSourceUnsubscribeAction;
28
- export type AccountsApiDataSourceActiveChainsChangedEvent = {
29
- type: 'AccountsApiDataSource:activeChainsUpdated';
30
- payload: [ChainId[]];
31
- };
32
- export type AccountsApiDataSourceAssetsUpdatedEvent = {
33
- type: 'AccountsApiDataSource:assetsUpdated';
34
- payload: [DataResponse, string | undefined];
35
- };
36
- export type AccountsApiDataSourceEvents = AccountsApiDataSourceActiveChainsChangedEvent | AccountsApiDataSourceAssetsUpdatedEvent;
37
- type AssetsControllerActiveChainsUpdateAction = {
38
- type: 'AssetsController:activeChainsUpdate';
39
- handler: (dataSourceId: string, activeChains: ChainId[]) => void;
40
- };
41
- type AssetsControllerAssetsUpdateAction = {
42
- type: 'AssetsController:assetsUpdate';
43
- handler: (response: DataResponse, sourceId: string) => Promise<void>;
44
- };
45
- export type AccountsApiDataSourceAllowedActions = AssetsControllerActiveChainsUpdateAction | AssetsControllerAssetsUpdateAction;
46
- export type AccountsApiDataSourceMessenger = Messenger<typeof CONTROLLER_NAME, AccountsApiDataSourceActions | AccountsApiDataSourceAllowedActions, AccountsApiDataSourceEvents>;
6
+ export type AccountsApiDataSourceAllowedActions = never;
47
7
  export type AccountsApiDataSourceState = DataSourceState;
48
- export type AccountsApiDataSourceOptions = {
49
- messenger: AccountsApiDataSourceMessenger;
8
+ /** Optional configuration for AccountsApiDataSource. */
9
+ export type AccountsApiDataSourceConfig = {
10
+ /** Polling interval in ms (default: 30000) */
11
+ pollInterval?: number;
12
+ /**
13
+ * Function returning whether token detection is enabled (default: () => true).
14
+ * When it returns false, balances are only returned for tokens already in state.
15
+ * Using a getter avoids stale values when the user toggles the preference at runtime.
16
+ */
17
+ tokenDetectionEnabled?: () => boolean;
18
+ };
19
+ export type AccountsApiDataSourceOptions = AccountsApiDataSourceConfig & {
50
20
  /** ApiPlatformClient for API calls with caching */
51
21
  queryApiClient: ApiPlatformClient;
52
- pollInterval?: number;
22
+ /** Called when active chains are updated. Pass dataSourceName so the controller knows the source. */
23
+ onActiveChainsUpdated: (dataSourceName: string, chains: ChainId[], previousChains: ChainId[]) => void;
53
24
  state?: Partial<AccountsApiDataSourceState>;
54
25
  };
55
26
  /**
56
- * Data source for fetching balances from the MetaMask Accounts API.
27
+ * Filter a response to only include balances for assets already in state.
28
+ * Used when tokenDetectionEnabled is false to prevent adding new tokens.
57
29
  *
58
- * Uses Messenger pattern for all interactions:
59
- * - Calls BackendApiClient methods via messenger actions
60
- * - Exposes its own actions for AssetsController to call
61
- * - Publishes events for AssetsController to subscribe to
62
- *
63
- * Actions exposed:
64
- * - AccountsApiDataSource:getActiveChains
65
- * - AccountsApiDataSource:fetch
66
- * - AccountsApiDataSource:subscribe
67
- * - AccountsApiDataSource:unsubscribe
68
- *
69
- * Events published:
70
- * - AccountsApiDataSource:activeChainsUpdated
71
- * - AccountsApiDataSource:assetsUpdated
30
+ * @param response - The fetch response to filter.
31
+ * @param assetsState - Current assets controller state to check existing balances against.
32
+ * @returns A new response with only known asset balances.
33
+ */
34
+ export declare function filterResponseToKnownAssets(response: DataResponse, assetsState: AssetsControllerStateInternal): DataResponse;
35
+ /**
36
+ * Data source for fetching balances from the MetaMask Accounts API.
72
37
  *
73
- * Actions called (from BackendApiClient):
74
- * - BackendApiClient:Accounts:getV2SupportedNetworks
75
- * - BackendApiClient:Accounts:getV5MultiAccountBalances
38
+ * Uses ApiPlatformClient (queryApiClient) for all API calls. Does not use the
39
+ * messenger. Reports active chains via onActiveChainsUpdated callback.
76
40
  */
77
41
  export declare class AccountsApiDataSource extends AbstractDataSource<typeof CONTROLLER_NAME, AccountsApiDataSourceState> {
78
42
  #private;
@@ -92,12 +56,5 @@ export declare class AccountsApiDataSource extends AbstractDataSource<typeof CON
92
56
  subscribe(subscriptionRequest: SubscriptionRequest): Promise<void>;
93
57
  destroy(): void;
94
58
  }
95
- /**
96
- * Creates an AccountsApiDataSource instance.
97
- *
98
- * @param options - Configuration options for the data source.
99
- * @returns A new AccountsApiDataSource instance.
100
- */
101
- export declare function createAccountsApiDataSource(options: AccountsApiDataSourceOptions): AccountsApiDataSource;
102
59
  export {};
103
60
  //# sourceMappingURL=AccountsApiDataSource.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccountsApiDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/AccountsApiDataSource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountsApiDataSource.d.mts","sourceRoot":"","sources":["../../src/data-sources/AccountsApiDataSource.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,+BAA+B;AAO3D,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,iCAA6B;AAC9B,OAAO,EAAE,kBAAkB,EAAE,iCAA6B;AAE1D,OAAO,KAAK,EACV,OAAO,EAGP,WAAW,EACX,YAAY,EACZ,UAAU,EACV,6BAA6B,EAC9B,qBAAiB;AAOlB,QAAA,MAAM,eAAe,0BAA0B,CAAC;AAWhD,MAAM,MAAM,mCAAmC,GAAG,KAAK,CAAC;AAMxD,MAAM,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAUzD,wDAAwD;AACxD,MAAM,MAAM,2BAA2B,GAAG;IACxC,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,2BAA2B,GAAG;IACvE,mDAAmD;IACnD,cAAc,EAAE,iBAAiB,CAAC;IAClC,qGAAqG;IACrG,qBAAqB,EAAE,CACrB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,OAAO,EAAE,EACjB,cAAc,EAAE,OAAO,EAAE,KACtB,IAAI,CAAC;IACV,KAAK,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC7C,CAAC;AAgCF;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,6BAA6B,GACzC,YAAY,CAqCd;AAMD;;;;;GAKG;AACH,qBAAa,qBAAsB,SAAQ,kBAAkB,CAC3D,OAAO,eAAe,EACtB,0BAA0B,CAC3B;;gBAqBa,OAAO,EAAE,4BAA4B;IA6E3C,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAkJxD;;;;;;;;;OASG;IACH,IAAI,gBAAgB,IAAI,UAAU,CAkEjC;IAMK,SAAS,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0ExE,OAAO,IAAI,IAAI;CAShB"}
@@ -9,8 +9,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _AccountsApiDataSource_instances, _AccountsApiDataSource_messenger, _AccountsApiDataSource_pollInterval, _AccountsApiDataSource_apiClient, _AccountsApiDataSource_chainsRefreshTimer, _AccountsApiDataSource_registerActionHandlers, _AccountsApiDataSource_initializeActiveChains, _AccountsApiDataSource_refreshActiveChains, _AccountsApiDataSource_fetchActiveChains, _AccountsApiDataSource_accountSupportsChain, _AccountsApiDataSource_processV5Balances;
12
+ var _AccountsApiDataSource_instances, _AccountsApiDataSource_onActiveChainsUpdated, _AccountsApiDataSource_pollInterval, _AccountsApiDataSource_tokenDetectionEnabled, _AccountsApiDataSource_apiClient, _AccountsApiDataSource_chainsRefreshTimer, _AccountsApiDataSource_getAssetsState, _AccountsApiDataSource_initializeActiveChains, _AccountsApiDataSource_refreshActiveChains, _AccountsApiDataSource_fetchActiveChains, _AccountsApiDataSource_processV5Balances;
13
13
  import { ApiPlatformClient } from "@metamask/core-backend";
14
+ import { isCaipChainId, KnownCaipNamespace, toCaipChainId } from "@metamask/utils";
14
15
  import { AbstractDataSource } from "./AbstractDataSource.mjs";
15
16
  import { projectLogger, createModuleLogger } from "../logger.mjs";
16
17
  import { normalizeAssetId } from "../utils.mjs";
@@ -29,29 +30,61 @@ const defaultState = {
29
30
  function decimalToChainId(decimalChainId) {
30
31
  // Handle both decimal numbers and already-formatted CAIP chain IDs
31
32
  if (typeof decimalChainId === 'string') {
32
- // If already a CAIP chain ID (e.g., "eip155:1"), return as-is
33
- if (decimalChainId.startsWith('eip155:')) {
33
+ if (isCaipChainId(decimalChainId)) {
34
34
  return decimalChainId;
35
35
  }
36
- // If it's a string number, convert
37
- return `eip155:${decimalChainId}`;
36
+ return toCaipChainId(KnownCaipNamespace.Eip155, decimalChainId);
38
37
  }
39
- return `eip155:${decimalChainId}`;
38
+ return toCaipChainId(KnownCaipNamespace.Eip155, String(decimalChainId));
40
39
  }
41
40
  /**
42
41
  * Convert a CAIP-2 chain ID from the API response to our ChainId type.
43
42
  * Handles both formats: "eip155:1" or just "1" (decimal).
43
+ * Uses @metamask/utils for CAIP parsing.
44
44
  *
45
45
  * @param chainIdStr - The chain ID string to convert.
46
46
  * @returns The normalized ChainId.
47
47
  */
48
48
  function caipChainIdToChainId(chainIdStr) {
49
- // If already in CAIP-2 format, return as-is
50
- if (chainIdStr.includes(':')) {
49
+ if (isCaipChainId(chainIdStr)) {
51
50
  return chainIdStr;
52
51
  }
53
- // If decimal number, convert to CAIP-2
54
- return `eip155:${chainIdStr}`;
52
+ return toCaipChainId(KnownCaipNamespace.Eip155, chainIdStr);
53
+ }
54
+ /**
55
+ * Filter a response to only include balances for assets already in state.
56
+ * Used when tokenDetectionEnabled is false to prevent adding new tokens.
57
+ *
58
+ * @param response - The fetch response to filter.
59
+ * @param assetsState - Current assets controller state to check existing balances against.
60
+ * @returns A new response with only known asset balances.
61
+ */
62
+ export function filterResponseToKnownAssets(response, assetsState) {
63
+ if (!response.assetsBalance) {
64
+ return response;
65
+ }
66
+ const filteredBalance = {};
67
+ for (const [accountId, accountBalances] of Object.entries(response.assetsBalance)) {
68
+ const existingBalances = assetsState.assetsBalance[accountId];
69
+ if (!existingBalances) {
70
+ // Account has no balances in state yet — skip all its tokens
71
+ continue;
72
+ }
73
+ const filtered = {};
74
+ for (const [assetId, balance] of Object.entries(accountBalances)) {
75
+ // Only include assets already tracked in state
76
+ if (assetId in existingBalances) {
77
+ filtered[assetId] = balance;
78
+ }
79
+ }
80
+ if (Object.keys(filtered).length > 0) {
81
+ filteredBalance[accountId] = filtered;
82
+ }
83
+ }
84
+ return {
85
+ ...response,
86
+ assetsBalance: Object.keys(filteredBalance).length > 0 ? filteredBalance : undefined,
87
+ };
55
88
  }
56
89
  // ============================================================================
57
90
  // ACCOUNTS API DATA SOURCE
@@ -59,24 +92,8 @@ function caipChainIdToChainId(chainIdStr) {
59
92
  /**
60
93
  * Data source for fetching balances from the MetaMask Accounts API.
61
94
  *
62
- * Uses Messenger pattern for all interactions:
63
- * - Calls BackendApiClient methods via messenger actions
64
- * - Exposes its own actions for AssetsController to call
65
- * - Publishes events for AssetsController to subscribe to
66
- *
67
- * Actions exposed:
68
- * - AccountsApiDataSource:getActiveChains
69
- * - AccountsApiDataSource:fetch
70
- * - AccountsApiDataSource:subscribe
71
- * - AccountsApiDataSource:unsubscribe
72
- *
73
- * Events published:
74
- * - AccountsApiDataSource:activeChainsUpdated
75
- * - AccountsApiDataSource:assetsUpdated
76
- *
77
- * Actions called (from BackendApiClient):
78
- * - BackendApiClient:Accounts:getV2SupportedNetworks
79
- * - BackendApiClient:Accounts:getV5MultiAccountBalances
95
+ * Uses ApiPlatformClient (queryApiClient) for all API calls. Does not use the
96
+ * messenger. Reports active chains via onActiveChainsUpdated callback.
80
97
  */
81
98
  export class AccountsApiDataSource extends AbstractDataSource {
82
99
  constructor(options) {
@@ -85,23 +102,30 @@ export class AccountsApiDataSource extends AbstractDataSource {
85
102
  ...options.state,
86
103
  });
87
104
  _AccountsApiDataSource_instances.add(this);
88
- _AccountsApiDataSource_messenger.set(this, void 0);
105
+ _AccountsApiDataSource_onActiveChainsUpdated.set(this, void 0);
89
106
  _AccountsApiDataSource_pollInterval.set(this, void 0);
107
+ /** Getter avoids stale value when user toggles token detection at runtime. */
108
+ _AccountsApiDataSource_tokenDetectionEnabled.set(this, void 0);
90
109
  /** ApiPlatformClient for cached API calls */
91
110
  _AccountsApiDataSource_apiClient.set(this, void 0);
92
111
  /** Chains refresh timer */
93
112
  _AccountsApiDataSource_chainsRefreshTimer.set(this, null);
94
- __classPrivateFieldSet(this, _AccountsApiDataSource_messenger, options.messenger, "f");
113
+ /** State accessor from subscriptions (for filtering when tokenDetectionEnabled is false) */
114
+ _AccountsApiDataSource_getAssetsState.set(this, void 0);
115
+ __classPrivateFieldSet(this, _AccountsApiDataSource_onActiveChainsUpdated, options.onActiveChainsUpdated, "f");
95
116
  __classPrivateFieldSet(this, _AccountsApiDataSource_pollInterval, options.pollInterval ?? DEFAULT_POLL_INTERVAL, "f");
117
+ __classPrivateFieldSet(this, _AccountsApiDataSource_tokenDetectionEnabled, options.tokenDetectionEnabled ?? (() => true), "f");
96
118
  __classPrivateFieldSet(this, _AccountsApiDataSource_apiClient, options.queryApiClient, "f");
97
- __classPrivateFieldGet(this, _AccountsApiDataSource_instances, "m", _AccountsApiDataSource_registerActionHandlers).call(this);
98
119
  __classPrivateFieldGet(this, _AccountsApiDataSource_instances, "m", _AccountsApiDataSource_initializeActiveChains).call(this).catch(console.error);
99
120
  }
100
121
  // ============================================================================
122
+ // ACCOUNT SCOPE HELPERS
123
+ // ============================================================================
124
+ // ============================================================================
101
125
  // FETCH
102
126
  // ============================================================================
103
127
  async fetch(request) {
104
- const response = {};
128
+ let response = {};
105
129
  // Filter to only chains supported by Accounts API
106
130
  const supportedChains = new Set(this.state.activeChains);
107
131
  const chainsToFetch = request.chainIds.filter((chainId) => supportedChains.has(chainId));
@@ -117,10 +141,9 @@ export class AccountsApiDataSource extends AbstractDataSource {
117
141
  }
118
142
  try {
119
143
  // Build CAIP-10 account IDs (e.g., "eip155:1:0x1234...")
120
- // Only include account-chain combinations where the account's scopes
121
- // overlap with the chains being fetched
122
- const accountIds = request.accounts.flatMap((account) => chainsToFetch
123
- .filter((chainId) => __classPrivateFieldGet(this, _AccountsApiDataSource_instances, "m", _AccountsApiDataSource_accountSupportsChain).call(this, account, chainId))
144
+ // Use pre-computed supportedChains per account from the request
145
+ const accountIds = request.accountsWithSupportedChains.flatMap(({ account, supportedChains: accountChains }) => chainsToFetch
146
+ .filter((chainId) => accountChains.includes(chainId))
124
147
  .map((chainId) => `${chainId}:${account.address}`));
125
148
  // Skip API call if no valid account-chain combinations
126
149
  if (accountIds.length === 0) {
@@ -155,6 +178,10 @@ export class AccountsApiDataSource extends AbstractDataSource {
155
178
  response.errors[chainId] = 'Chain not supported by Accounts API';
156
179
  }
157
180
  }
181
+ // When token detection is disabled, filter out tokens not already in state
182
+ if (!__classPrivateFieldGet(this, _AccountsApiDataSource_tokenDetectionEnabled, "f").call(this) && __classPrivateFieldGet(this, _AccountsApiDataSource_getAssetsState, "f")) {
183
+ response = filterResponseToKnownAssets(response, __classPrivateFieldGet(this, _AccountsApiDataSource_getAssetsState, "f").call(this));
184
+ }
158
185
  return response;
159
186
  }
160
187
  // ============================================================================
@@ -194,6 +221,14 @@ export class AccountsApiDataSource extends AbstractDataSource {
194
221
  // Determine successfully handled chains (exclude unprocessed/error chains)
195
222
  const unprocessedChains = new Set(Object.keys(response.errors ?? {}));
196
223
  successfullyHandledChains = request.chainIds.filter((chainId) => !unprocessedChains.has(chainId));
224
+ // When token detection is off and we filtered out all balance data (e.g. new
225
+ // account with empty state), do not claim any chain as handled so that RPC
226
+ // middleware can still process them and fetch native balances (ETH, MATIC, etc.).
227
+ if (!__classPrivateFieldGet(this, _AccountsApiDataSource_tokenDetectionEnabled, "f").call(this) &&
228
+ (!response.assetsBalance ||
229
+ Object.keys(response.assetsBalance).length === 0)) {
230
+ successfullyHandledChains = [];
231
+ }
197
232
  }
198
233
  catch (error) {
199
234
  log('Middleware fetch failed', { error });
@@ -219,6 +254,10 @@ export class AccountsApiDataSource extends AbstractDataSource {
219
254
  // ============================================================================
220
255
  async subscribe(subscriptionRequest) {
221
256
  const { request, subscriptionId, isUpdate } = subscriptionRequest;
257
+ // Store state accessor for filtering when tokenDetectionEnabled is false
258
+ if (subscriptionRequest.getAssetsState) {
259
+ __classPrivateFieldSet(this, _AccountsApiDataSource_getAssetsState, subscriptionRequest.getAssetsState, "f");
260
+ }
222
261
  // Try all requested chains - API will handle unsupported ones via unprocessedNetworks
223
262
  const chainsToSubscribe = request.chainIds;
224
263
  if (chainsToSubscribe.length === 0) {
@@ -248,8 +287,8 @@ export class AccountsApiDataSource extends AbstractDataSource {
248
287
  ...subscription.request,
249
288
  chainIds: subscription.chains,
250
289
  });
251
- // Report update to AssetsController
252
- await __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").call('AssetsController:assetsUpdate', fetchResponse, CONTROLLER_NAME);
290
+ // Report update to AssetsController via callback
291
+ await subscription.onAssetsUpdate(fetchResponse);
253
292
  }
254
293
  catch (error) {
255
294
  log('Subscription poll failed', { subscriptionId, error });
@@ -266,6 +305,7 @@ export class AccountsApiDataSource extends AbstractDataSource {
266
305
  },
267
306
  chains: chainsToSubscribe,
268
307
  request,
308
+ onAssetsUpdate: subscriptionRequest.onAssetsUpdate,
269
309
  });
270
310
  // Initial fetch
271
311
  await pollFn();
@@ -282,27 +322,15 @@ export class AccountsApiDataSource extends AbstractDataSource {
282
322
  super.destroy();
283
323
  }
284
324
  }
285
- _AccountsApiDataSource_messenger = new WeakMap(), _AccountsApiDataSource_pollInterval = new WeakMap(), _AccountsApiDataSource_apiClient = new WeakMap(), _AccountsApiDataSource_chainsRefreshTimer = new WeakMap(), _AccountsApiDataSource_instances = new WeakSet(), _AccountsApiDataSource_registerActionHandlers = function _AccountsApiDataSource_registerActionHandlers() {
286
- // Define strongly-typed handlers
287
- const getAssetsMiddlewareHandler = () => this.assetsMiddleware;
288
- const getActiveChainsHandler = async () => this.getActiveChains();
289
- const fetchHandler = async (request) => this.fetch(request);
290
- const subscribeHandler = async (request) => this.subscribe(request);
291
- const unsubscribeHandler = async (subscriptionId) => this.unsubscribe(subscriptionId);
292
- // Register handlers
293
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").registerActionHandler('AccountsApiDataSource:getAssetsMiddleware', getAssetsMiddlewareHandler);
294
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").registerActionHandler('AccountsApiDataSource:getActiveChains', getActiveChainsHandler);
295
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").registerActionHandler('AccountsApiDataSource:fetch', fetchHandler);
296
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").registerActionHandler('AccountsApiDataSource:subscribe', subscribeHandler);
297
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").registerActionHandler('AccountsApiDataSource:unsubscribe', unsubscribeHandler);
298
- }, _AccountsApiDataSource_initializeActiveChains = async function _AccountsApiDataSource_initializeActiveChains() {
325
+ _AccountsApiDataSource_onActiveChainsUpdated = new WeakMap(), _AccountsApiDataSource_pollInterval = new WeakMap(), _AccountsApiDataSource_tokenDetectionEnabled = new WeakMap(), _AccountsApiDataSource_apiClient = new WeakMap(), _AccountsApiDataSource_chainsRefreshTimer = new WeakMap(), _AccountsApiDataSource_getAssetsState = new WeakMap(), _AccountsApiDataSource_instances = new WeakSet(), _AccountsApiDataSource_initializeActiveChains =
326
+ // ============================================================================
327
+ // INITIALIZATION
328
+ // ============================================================================
329
+ async function _AccountsApiDataSource_initializeActiveChains() {
299
330
  try {
300
331
  const chains = await __classPrivateFieldGet(this, _AccountsApiDataSource_instances, "m", _AccountsApiDataSource_fetchActiveChains).call(this);
301
- this.updateActiveChains(chains, (updatedChains) => {
302
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', CONTROLLER_NAME, updatedChains);
303
- // Also publish event for BackendWebsocketDataSource to sync
304
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").publish('AccountsApiDataSource:activeChainsUpdated', updatedChains);
305
- });
332
+ const previous = [...this.state.activeChains];
333
+ this.updateActiveChains(chains, (updatedChains) => __classPrivateFieldGet(this, _AccountsApiDataSource_onActiveChainsUpdated, "f").call(this, this.getName(), updatedChains, previous));
306
334
  // Periodically refresh active chains (every 20 minutes)
307
335
  __classPrivateFieldSet(this, _AccountsApiDataSource_chainsRefreshTimer, setInterval(() => {
308
336
  __classPrivateFieldGet(this, _AccountsApiDataSource_instances, "m", _AccountsApiDataSource_refreshActiveChains).call(this).catch(console.error);
@@ -320,11 +348,8 @@ _AccountsApiDataSource_messenger = new WeakMap(), _AccountsApiDataSource_pollInt
320
348
  const added = chains.filter((chain) => !previousChains.has(chain));
321
349
  const removed = Array.from(previousChains).filter((chain) => !newChains.has(chain));
322
350
  if (added.length > 0 || removed.length > 0) {
323
- this.updateActiveChains(chains, (updatedChains) => {
324
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").call('AssetsController:activeChainsUpdate', CONTROLLER_NAME, updatedChains);
325
- // Also publish event for BackendWebsocketDataSource to sync
326
- __classPrivateFieldGet(this, _AccountsApiDataSource_messenger, "f").publish('AccountsApiDataSource:activeChainsUpdated', updatedChains);
327
- });
351
+ const previous = [...this.state.activeChains];
352
+ this.updateActiveChains(chains, (updatedChains) => __classPrivateFieldGet(this, _AccountsApiDataSource_onActiveChainsUpdated, "f").call(this, this.getName(), updatedChains, previous));
328
353
  }
329
354
  }
330
355
  catch (error) {
@@ -334,43 +359,11 @@ _AccountsApiDataSource_messenger = new WeakMap(), _AccountsApiDataSource_pollInt
334
359
  const response = await __classPrivateFieldGet(this, _AccountsApiDataSource_apiClient, "f").accounts.fetchV2SupportedNetworks();
335
360
  // Use fullSupport networks as active chains
336
361
  return response.fullSupport.map(decimalToChainId);
337
- }, _AccountsApiDataSource_accountSupportsChain = function _AccountsApiDataSource_accountSupportsChain(account, chainId) {
338
- const scopes = account.scopes ?? [];
339
- // If no scopes defined, assume it supports the chain (backward compatibility)
340
- if (scopes.length === 0) {
341
- return true;
342
- }
343
- // Extract namespace and reference from chainId (e.g., "eip155:1" -> ["eip155", "1"])
344
- const [chainNamespace, chainReference] = chainId.split(':');
345
- for (const scope of scopes) {
346
- const [scopeNamespace, scopeReference] = scope.split(':');
347
- // Check if namespaces match
348
- if (scopeNamespace !== chainNamespace) {
349
- continue;
350
- }
351
- // Wildcard scope (e.g., "eip155:0" means all chains in that namespace)
352
- if (scopeReference === '0') {
353
- return true;
354
- }
355
- // Exact match check - normalize hex to decimal for EIP155
356
- if (chainNamespace === 'eip155') {
357
- const normalizedScopeRef = scopeReference?.startsWith('0x')
358
- ? parseInt(scopeReference, 16).toString()
359
- : scopeReference;
360
- if (normalizedScopeRef === chainReference) {
361
- return true;
362
- }
363
- }
364
- else if (scopeReference === chainReference) {
365
- return true;
366
- }
367
- }
368
- return false;
369
362
  }, _AccountsApiDataSource_processV5Balances = function _AccountsApiDataSource_processV5Balances(balances, request) {
370
363
  const assetsBalance = {};
371
364
  // Build a map of lowercase addresses to account IDs for efficient lookup
372
365
  const addressToAccountId = new Map();
373
- for (const account of request.accounts) {
366
+ for (const { account } of request.accountsWithSupportedChains) {
374
367
  if (account.address) {
375
368
  addressToAccountId.set(account.address.toLowerCase(), account.id);
376
369
  }
@@ -401,16 +394,4 @@ _AccountsApiDataSource_messenger = new WeakMap(), _AccountsApiDataSource_pollInt
401
394
  }
402
395
  return { assetsBalance };
403
396
  };
404
- // ============================================================================
405
- // FACTORY FUNCTION
406
- // ============================================================================
407
- /**
408
- * Creates an AccountsApiDataSource instance.
409
- *
410
- * @param options - Configuration options for the data source.
411
- * @returns A new AccountsApiDataSource instance.
412
- */
413
- export function createAccountsApiDataSource(options) {
414
- return new AccountsApiDataSource(options);
415
- }
416
397
  //# sourceMappingURL=AccountsApiDataSource.mjs.map