@metamask-previews/assets-controller 0.2.0-preview-429bf064c → 1.0.0-preview-7aeef9dd1

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 (72) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/dist/AssetsController.cjs +80 -161
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +9 -15
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +9 -15
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +80 -161
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/AbstractDataSource.cjs +8 -0
  11. package/dist/data-sources/AbstractDataSource.cjs.map +1 -1
  12. package/dist/data-sources/AbstractDataSource.d.cts +6 -0
  13. package/dist/data-sources/AbstractDataSource.d.cts.map +1 -1
  14. package/dist/data-sources/AbstractDataSource.d.mts +6 -0
  15. package/dist/data-sources/AbstractDataSource.d.mts.map +1 -1
  16. package/dist/data-sources/AbstractDataSource.mjs +8 -0
  17. package/dist/data-sources/AbstractDataSource.mjs.map +1 -1
  18. package/dist/data-sources/AccountsApiDataSource.cjs +4 -2
  19. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  20. package/dist/data-sources/AccountsApiDataSource.d.cts +2 -2
  21. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
  22. package/dist/data-sources/AccountsApiDataSource.d.mts +2 -2
  23. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
  24. package/dist/data-sources/AccountsApiDataSource.mjs +4 -2
  25. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  26. package/dist/data-sources/BackendWebsocketDataSource.cjs +6 -3
  27. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
  28. package/dist/data-sources/BackendWebsocketDataSource.d.cts +2 -2
  29. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
  30. package/dist/data-sources/BackendWebsocketDataSource.d.mts +2 -2
  31. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
  32. package/dist/data-sources/BackendWebsocketDataSource.mjs +6 -3
  33. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
  34. package/dist/data-sources/RpcDataSource.cjs +9 -6
  35. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  36. package/dist/data-sources/RpcDataSource.d.cts +2 -2
  37. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  38. package/dist/data-sources/RpcDataSource.d.mts +2 -2
  39. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  40. package/dist/data-sources/RpcDataSource.mjs +9 -6
  41. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  42. package/dist/data-sources/SnapDataSource.cjs +4 -2
  43. package/dist/data-sources/SnapDataSource.cjs.map +1 -1
  44. package/dist/data-sources/SnapDataSource.d.cts +2 -2
  45. package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
  46. package/dist/data-sources/SnapDataSource.d.mts +2 -2
  47. package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
  48. package/dist/data-sources/SnapDataSource.mjs +4 -2
  49. package/dist/data-sources/SnapDataSource.mjs.map +1 -1
  50. package/dist/index.cjs +6 -1
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +3 -1
  53. package/dist/index.d.cts.map +1 -1
  54. package/dist/index.d.mts +3 -1
  55. package/dist/index.d.mts.map +1 -1
  56. package/dist/index.mjs +2 -0
  57. package/dist/index.mjs.map +1 -1
  58. package/dist/selectors/balance.cjs +306 -0
  59. package/dist/selectors/balance.cjs.map +1 -0
  60. package/dist/selectors/balance.d.cts +22 -0
  61. package/dist/selectors/balance.d.cts.map +1 -0
  62. package/dist/selectors/balance.d.mts +22 -0
  63. package/dist/selectors/balance.d.mts.map +1 -0
  64. package/dist/selectors/balance.mjs +297 -0
  65. package/dist/selectors/balance.mjs.map +1 -0
  66. package/dist/types.cjs.map +1 -1
  67. package/dist/types.d.cts +1 -15
  68. package/dist/types.d.cts.map +1 -1
  69. package/dist/types.d.mts +1 -15
  70. package/dist/types.d.mts.map +1 -1
  71. package/dist/types.mjs.map +1 -1
  72. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Changed
11
+
12
+ - Bump `@metamask/keyring-api` from `^21.0.0` to `^21.5.0` ([#7857](https://github.com/MetaMask/core/pull/7857))
13
+ - Bump `@metamask/keyring-internal-api` from `^9.0.0` to `^10.0.0` ([#7857](https://github.com/MetaMask/core/pull/7857))
14
+
15
+ ## [1.0.0]
16
+
17
+ ### Added
18
+
19
+ - Add balance selectors `getAggregatedBalanceForAccount`, `getGroupIdForAccount`, and `getInternalAccountsForGroup` with types `AggregatedBalanceEntry`, `AggregatedBalanceForAccount`, `EnabledNetworkMap`, and `AccountsById` for aggregated portfolio balance (optionally by account group), fiat total, and portfolio-weighted 1d price change ([#7864](https://github.com/MetaMask/core/pull/7864))
20
+
21
+ ### Changed
22
+
23
+ - **BREAKING:** Require `previousChains` in `handleActiveChainsUpdate(dataSourceId, activeChains, previousChains)` and in the `onActiveChainsUpdated` callback used by data sources; the third parameter is no longer optional. Callers and data sources must pass the previous chain list for correct added/removed chain diff computation ([#7867](https://github.com/MetaMask/core/pull/7867))
24
+ - Bump `@metamask/account-tree-controller` from `^4.0.0` to `^4.1.0` ([#7869](https://github.com/MetaMask/core/pull/7869))
25
+
10
26
  ### Removed
11
27
 
12
28
  - **BREAKING:** Remove `initDataSources` and related exports (`InitDataSourcesOptions`, `DataSources`, `DataSourceActions`, `DataSourceEvents`, `DataSourceAllowedActions`, `DataSourceAllowedEvents`, `RootMessenger`). Initialize assets by creating `AssetsController` with `queryApiClient`; the controller instantiates all data sources internally ([#7859](https://github.com/MetaMask/core/pull/7859))
@@ -48,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
48
64
  - Refactor `RpcDataSource` to delegate polling to `BalanceFetcher` and `TokenDetector` services ([#7709](https://github.com/MetaMask/core/pull/7709))
49
65
  - Refactor `BalanceFetcher` and `TokenDetector` to extend `StaticIntervalPollingControllerOnly` for independent polling management ([#7709](https://github.com/MetaMask/core/pull/7709))
50
66
 
51
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@0.2.0...HEAD
67
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@1.0.0...HEAD
68
+ [1.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@0.2.0...@metamask/assets-controller@1.0.0
52
69
  [0.2.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@0.1.0...@metamask/assets-controller@0.2.0
53
70
  [0.1.0]: https://github.com/MetaMask/core/releases/tag/@metamask/assets-controller@0.1.0
@@ -1,19 +1,19 @@
1
1
  "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ 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");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
2
7
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
8
  if (kind === "m") throw new TypeError("Private method is not writable");
4
9
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
11
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
12
  };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
- var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_defaultUpdateInterval, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_dataSources, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_getBalanceDataSource, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_registerActionHandlers, _AssetsController_executeMiddlewares, _AssetsController_assignChainsToDataSources, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeToDataSources, _AssetsController_subscribeAssetsBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_getAccountsForChains, _AssetsController_subscribeToDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
16
+ var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_defaultUpdateInterval, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_subscriptionBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_registerActionHandlers, _AssetsController_executeMiddlewares, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.AssetsController = exports.getDefaultAssetsControllerState = void 0;
19
19
  const base_controller_1 = require("@metamask/base-controller");
@@ -207,12 +207,6 @@ class AssetsController extends base_controller_1.BaseController {
207
207
  _AssetsController_activeSubscriptions.set(this, new Map());
208
208
  /** Currently enabled chains from NetworkEnablementController */
209
209
  _AssetsController_enabledChains.set(this, new Set());
210
- /**
211
- * Registered data sources with their available chains.
212
- * Updated continuously and independently from subscription flows.
213
- * Key: sourceId, Value: Set of currently available chainIds
214
- */
215
- _AssetsController_dataSources.set(this, new Map());
216
210
  _AssetsController_backendWebsocketDataSource.set(this, void 0);
217
211
  _AssetsController_accountsApiDataSource.set(this, void 0);
218
212
  _AssetsController_snapDataSource.set(this, void 0);
@@ -223,24 +217,23 @@ class AssetsController extends base_controller_1.BaseController {
223
217
  __classPrivateFieldSet(this, _AssetsController_isEnabled, isEnabled(), "f");
224
218
  __classPrivateFieldSet(this, _AssetsController_defaultUpdateInterval, defaultUpdateInterval, "f");
225
219
  const rpcConfig = rpcDataSourceConfig ?? {};
220
+ const onActiveChainsUpdated = (dataSourceName, chains, previousChains) => this.handleActiveChainsUpdate(dataSourceName, chains, previousChains);
226
221
  __classPrivateFieldSet(this, _AssetsController_backendWebsocketDataSource, new BackendWebsocketDataSource_1.BackendWebsocketDataSource({
227
222
  messenger: this.messenger,
228
223
  queryApiClient,
229
- onActiveChainsUpdated: (chains) => this.handleActiveChainsUpdate('BackendWebsocketDataSource', chains),
224
+ onActiveChainsUpdated,
230
225
  }), "f");
231
226
  __classPrivateFieldSet(this, _AssetsController_accountsApiDataSource, new AccountsApiDataSource_1.AccountsApiDataSource({
232
227
  queryApiClient,
233
- onActiveChainsUpdated: (chains) => {
234
- this.handleActiveChainsUpdate('AccountsApiDataSource', chains);
235
- },
228
+ onActiveChainsUpdated,
236
229
  }), "f");
237
230
  __classPrivateFieldSet(this, _AssetsController_snapDataSource, new SnapDataSource_1.SnapDataSource({
238
231
  messenger: this.messenger,
239
- onActiveChainsUpdated: (chains) => this.handleActiveChainsUpdate('SnapDataSource', chains),
232
+ onActiveChainsUpdated,
240
233
  }), "f");
241
234
  __classPrivateFieldSet(this, _AssetsController_rpcDataSource, new RpcDataSource_1.RpcDataSource({
242
235
  messenger: this.messenger,
243
- onActiveChainsUpdated: (chains) => this.handleActiveChainsUpdate('RpcDataSource', chains),
236
+ onActiveChainsUpdated,
244
237
  ...rpcConfig,
245
238
  }), "f");
246
239
  __classPrivateFieldSet(this, _AssetsController_tokenDataSource, new TokenDataSource_1.TokenDataSource({
@@ -250,10 +243,6 @@ class AssetsController extends base_controller_1.BaseController {
250
243
  queryApiClient,
251
244
  }), "f");
252
245
  __classPrivateFieldSet(this, _AssetsController_detectionMiddleware, new DetectionMiddleware_1.DetectionMiddleware(), "f");
253
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").set('BackendWebsocketDataSource', new Set());
254
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").set('AccountsApiDataSource', new Set());
255
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").set('SnapDataSource', new Set());
256
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").set('RpcDataSource', new Set());
257
246
  if (!__classPrivateFieldGet(this, _AssetsController_isEnabled, "f")) {
258
247
  log('AssetsController is disabled, skipping initialization');
259
248
  return;
@@ -266,56 +255,34 @@ class AssetsController extends base_controller_1.BaseController {
266
255
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_registerActionHandlers).call(this);
267
256
  }
268
257
  // ============================================================================
269
- // DATA SOURCE MANAGEMENT
270
- // ============================================================================
271
- /**
272
- * Register data sources with the controller.
273
- * Order of the array determines subscription order.
274
- *
275
- * Data sources report chain changes via the onActiveChainsUpdated callback passed at construction.
276
- *
277
- * @param dataSourceIds - Array of data source identifiers to register.
278
- */
279
- registerDataSources(dataSourceIds) {
280
- for (const id of dataSourceIds) {
281
- log('Registering data source', { id });
282
- // Initialize available chains tracking for this source
283
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").set(id, new Set());
284
- }
285
- }
286
- // ============================================================================
287
258
  // DATA SOURCE CHAIN MANAGEMENT
288
259
  // ============================================================================
289
260
  /**
290
- * Handle when a data source's active chains change.
291
- * Active chains are chains that are both supported AND available.
292
- * Updates centralized chain tracking and triggers re-selection if needed.
261
+ * Handle when a data source's supported chains change.
262
+ * Used to refresh balance subscriptions and run a one-time fetch when a new chain is supported.
293
263
  *
294
- * Called from the onActiveChainsUpdated callbacks passed to data sources at construction.
264
+ * - On any add/remove: re-subscribes to data sources so chain assignment stays correct.
265
+ * - When chains are added: fetches balances for the new chains (for selected accounts on enabled networks).
266
+ *
267
+ * Controller does not store chains; sources report via this callback. previousChains is required for diff.
295
268
  *
296
269
  * @param dataSourceId - The identifier of the data source reporting the change.
297
- * @param activeChains - Array of currently active chain IDs for this source.
270
+ * @param activeChains - Currently active (supported and available) chain IDs for this source.
271
+ * @param previousChains - Previous chains; used to compute added/removed.
298
272
  */
299
- handleActiveChainsUpdate(dataSourceId, activeChains) {
273
+ handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
300
274
  log('Data source active chains changed', {
301
275
  dataSourceId,
302
276
  chainCount: activeChains.length,
303
277
  chains: activeChains,
304
278
  });
305
- // When BackendWebsocketDataSource is updated via AccountsApiDataSource callback, sync its state
306
- if (dataSourceId === 'BackendWebsocketDataSource') {
307
- __classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f").setActiveChainsFromAccountsApi(activeChains);
308
- }
309
- const previousChains = __classPrivateFieldGet(this, _AssetsController_dataSources, "f").get(dataSourceId) ?? new Set();
310
- const newChains = new Set(activeChains);
311
- // Update centralized available chains tracking
312
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").set(dataSourceId, newChains);
313
- // Check for changes
314
- const addedChains = activeChains.filter((chain) => !previousChains.has(chain));
315
- const removedChains = Array.from(previousChains).filter((chain) => !newChains.has(chain));
279
+ const previous = previousChains;
280
+ const previousSet = new Set(previous);
281
+ const addedChains = activeChains.filter((ch) => !previousSet.has(ch));
282
+ const removedChains = previous.filter((ch) => !activeChains.includes(ch));
316
283
  if (addedChains.length > 0 || removedChains.length > 0) {
317
284
  // Refresh subscriptions to use updated data source availability
318
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToDataSources).call(this);
285
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
319
286
  }
320
287
  // If chains were added and we have selected accounts, do one-time fetch
321
288
  if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
@@ -512,6 +479,9 @@ class AssetsController extends base_controller_1.BaseController {
512
479
  }
513
480
  });
514
481
  }
482
+ // ============================================================================
483
+ // SUBSCRIPTIONS
484
+ // ============================================================================
515
485
  /**
516
486
  * Subscribe to price updates for all assets held by the given accounts.
517
487
  * Polls PriceDataSource which fetches prices from balance state.
@@ -594,7 +564,7 @@ class AssetsController extends base_controller_1.BaseController {
594
564
  // ============================================================================
595
565
  destroy() {
596
566
  log('Destroying AssetsController', {
597
- dataSourceCount: __classPrivateFieldGet(this, _AssetsController_dataSources, "f").size,
567
+ dataSourceCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_subscriptionBalanceDataSources_get).length,
598
568
  subscriptionCount: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size,
599
569
  });
600
570
  // Destroy instantiated data sources
@@ -607,8 +577,6 @@ class AssetsController extends base_controller_1.BaseController {
607
577
  'function') {
608
578
  __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f").destroy();
609
579
  }
610
- // Clear data sources
611
- __classPrivateFieldGet(this, _AssetsController_dataSources, "f").clear();
612
580
  // Stop all active subscriptions
613
581
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
614
582
  // Unregister action handlers
@@ -624,21 +592,15 @@ class AssetsController extends base_controller_1.BaseController {
624
592
  }
625
593
  }
626
594
  exports.AssetsController = AssetsController;
627
- _AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_dataSources = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_selectedAccounts_get = function _AssetsController_selectedAccounts_get() {
595
+ _AssetsController_isEnabled = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_selectedAccounts_get = function _AssetsController_selectedAccounts_get() {
628
596
  return this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
629
- }, _AssetsController_getBalanceDataSource = function _AssetsController_getBalanceDataSource(sourceId) {
630
- switch (sourceId) {
631
- case 'BackendWebsocketDataSource':
632
- return __classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f");
633
- case 'AccountsApiDataSource':
634
- return __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f");
635
- case 'SnapDataSource':
636
- return __classPrivateFieldGet(this, _AssetsController_snapDataSource, "f");
637
- case 'RpcDataSource':
638
- return __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f");
639
- default:
640
- return undefined;
641
- }
597
+ }, _AssetsController_subscriptionBalanceDataSources_get = function _AssetsController_subscriptionBalanceDataSources_get() {
598
+ return [
599
+ __classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f"),
600
+ __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
601
+ __classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"),
602
+ __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
603
+ ];
642
604
  }, _AssetsController_initializeState = function _AssetsController_initializeState() {
643
605
  const { enabledNetworkMap } = this.messenger.call('NetworkEnablementController:getState');
644
606
  __classPrivateFieldSet(this, _AssetsController_enabledChains, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_extractEnabledChains).call(this, enabledNetworkMap), "f");
@@ -713,32 +675,6 @@ async function _AssetsController_executeMiddlewares(middlewares, request, initia
713
675
  getAssetsState: () => this.state,
714
676
  });
715
677
  return result.response;
716
- }, _AssetsController_assignChainsToDataSources = function _AssetsController_assignChainsToDataSources(requestedChains) {
717
- const assignment = new Map();
718
- const remainingChains = new Set(requestedChains);
719
- for (const sourceId of __classPrivateFieldGet(this, _AssetsController_dataSources, "f").keys()) {
720
- // Get available chains for this data source
721
- const availableChains = __classPrivateFieldGet(this, _AssetsController_dataSources, "f").get(sourceId);
722
- if (!availableChains || availableChains.size === 0) {
723
- continue;
724
- }
725
- const chainsForThisSource = [];
726
- for (const chainId of remainingChains) {
727
- // Check if this chain is available on this source
728
- if (availableChains.has(chainId)) {
729
- chainsForThisSource.push(chainId);
730
- remainingChains.delete(chainId);
731
- }
732
- }
733
- if (chainsForThisSource.length > 0) {
734
- assignment.set(sourceId, chainsForThisSource);
735
- log('Assigned chains to data source', {
736
- sourceId,
737
- chains: chainsForThisSource,
738
- });
739
- }
740
- }
741
- return assignment;
742
678
  }, _AssetsController_updateState =
743
679
  // ============================================================================
744
680
  // STATE MANAGEMENT
@@ -932,7 +868,7 @@ async function _AssetsController_updateState(response) {
932
868
  selectedAccountCount: __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length,
933
869
  enabledChainCount: __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size,
934
870
  });
935
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToDataSources).call(this);
871
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
936
872
  if (__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
937
873
  this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
938
874
  chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
@@ -953,77 +889,67 @@ async function _AssetsController_updateState(response) {
953
889
  // Convert to array first to avoid modifying map during iteration
954
890
  const subscriptionKeys = [...__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").keys()];
955
891
  for (const subscriptionKey of subscriptionKeys) {
956
- // Extract sourceId from subscription key (format: "ds:${sourceId}")
957
892
  if (subscriptionKey.startsWith('ds:')) {
958
893
  const sourceId = subscriptionKey.slice(3);
959
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, sourceId);
894
+ const source = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_subscriptionBalanceDataSources_get).find((ds) => ds.getName() === sourceId);
895
+ if (source) {
896
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
897
+ }
960
898
  }
961
899
  }
962
900
  __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").clear();
963
- }, _AssetsController_subscribeToDataSources = function _AssetsController_subscribeToDataSources() {
901
+ }, _AssetsController_subscribeAssets = function _AssetsController_subscribeAssets() {
964
902
  if (__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length === 0) {
965
903
  return;
966
904
  }
967
905
  // Subscribe to balance updates (batched by data source)
968
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this);
906
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [
907
+ ...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
908
+ ]);
969
909
  // Subscribe to price updates for all assets held by selected accounts
970
910
  this.subscribeAssetsPrice(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
971
- }, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance() {
972
- // Step 1: Build chain -> accounts mapping based on account scopes and enabled networks
973
- const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
974
- // Step 2: Split by data source active chains (ordered by priority)
975
- // Get all chains that need to be subscribed
911
+ }, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance(accounts, chainIds) {
912
+ const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
976
913
  const remainingChains = new Set(chainToAccounts.keys());
977
- // Assign chains to data sources based on availability (ordered by priority)
978
- const chainAssignment = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_assignChainsToDataSources).call(this, Array.from(remainingChains));
979
- log('Subscribe - chain assignment', {
980
- totalChains: remainingChains.size,
981
- dataSourceAssignments: Array.from(chainAssignment.entries()).map(([sourceId, chains]) => ({ sourceId, chainCount: chains.length })),
982
- });
983
- // Subscribe to each data source with its assigned chains and relevant accounts
984
- for (const sourceId of __classPrivateFieldGet(this, _AssetsController_dataSources, "f").keys()) {
985
- const assignedChains = chainAssignment.get(sourceId);
986
- if (!assignedChains || assignedChains.length === 0) {
987
- // Unsubscribe from data sources with no assigned chains
988
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, sourceId);
989
- continue;
914
+ for (const source of __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_subscriptionBalanceDataSources_get)) {
915
+ const availableChains = new Set(source.getActiveChainsSync());
916
+ const assignedChains = [];
917
+ for (const chainId of remainingChains) {
918
+ if (availableChains.has(chainId)) {
919
+ assignedChains.push(chainId);
920
+ remainingChains.delete(chainId);
921
+ }
990
922
  }
991
- // Collect unique accounts that need any of the assigned chains
992
- const accountsForSource = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAccountsForChains).call(this, assignedChains, chainToAccounts);
993
- if (accountsForSource.length === 0) {
923
+ if (assignedChains.length === 0) {
924
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
994
925
  continue;
995
926
  }
996
- // Subscribe with ONE call per data source
997
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToDataSource).call(this, sourceId, accountsForSource, assignedChains);
927
+ const seenIds = new Set();
928
+ const accountsForSource = assignedChains
929
+ .flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
930
+ .filter((account) => !seenIds.has(account.id) && (seenIds.add(account.id), true));
931
+ if (accountsForSource.length > 0) {
932
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains);
933
+ }
998
934
  }
999
935
  }, _AssetsController_buildChainToAccountsMap = function _AssetsController_buildChainToAccountsMap(accounts, chainsToSubscribe) {
1000
936
  const chainToAccounts = new Map();
1001
937
  for (const account of accounts) {
1002
- const accountChains = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account);
1003
- for (const chainId of accountChains) {
938
+ for (const chainId of __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account)) {
1004
939
  if (!chainsToSubscribe.has(chainId)) {
1005
940
  continue;
1006
941
  }
1007
- const existingAccounts = chainToAccounts.get(chainId) ?? [];
1008
- existingAccounts.push(account);
1009
- chainToAccounts.set(chainId, existingAccounts);
1010
- }
1011
- }
1012
- return chainToAccounts;
1013
- }, _AssetsController_getAccountsForChains = function _AssetsController_getAccountsForChains(chains, chainToAccounts) {
1014
- const accountIds = new Set();
1015
- const accounts = [];
1016
- for (const chainId of chains) {
1017
- const chainAccounts = chainToAccounts.get(chainId) ?? [];
1018
- for (const account of chainAccounts) {
1019
- if (!accountIds.has(account.id)) {
1020
- accountIds.add(account.id);
1021
- accounts.push(account);
942
+ let list = chainToAccounts.get(chainId);
943
+ if (!list) {
944
+ list = [];
945
+ chainToAccounts.set(chainId, list);
1022
946
  }
947
+ list.push(account);
1023
948
  }
1024
949
  }
1025
- return accounts;
1026
- }, _AssetsController_subscribeToDataSource = function _AssetsController_subscribeToDataSource(sourceId, accounts, chains) {
950
+ return chainToAccounts;
951
+ }, _AssetsController_subscribeDataSource = function _AssetsController_subscribeDataSource(source, accounts, chains) {
952
+ const sourceId = source.getName();
1027
953
  const subscriptionKey = `ds:${sourceId}`;
1028
954
  const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
1029
955
  const isUpdate = existingSubscription !== undefined;
@@ -1045,11 +971,7 @@ async function _AssetsController_updateState(response) {
1045
971
  onAssetsUpdate: (response) => this.handleAssetsUpdate(response, sourceId),
1046
972
  getAssetsState: () => this.state,
1047
973
  };
1048
- const balanceDs = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getBalanceDataSource).call(this, sourceId);
1049
- if (!balanceDs) {
1050
- return;
1051
- }
1052
- balanceDs.subscribe(subscribeReq).catch((error) => {
974
+ source.subscribe(subscribeReq).catch((error) => {
1053
975
  console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
1054
976
  });
1055
977
  // Track subscription
@@ -1063,14 +985,11 @@ async function _AssetsController_updateState(response) {
1063
985
  },
1064
986
  };
1065
987
  __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").set(subscriptionKey, subscription);
1066
- }, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(sourceId) {
1067
- const subscriptionKey = `ds:${sourceId}`;
988
+ }, _AssetsController_unsubscribeDataSource = function _AssetsController_unsubscribeDataSource(source) {
989
+ const subscriptionKey = `ds:${source.getName()}`;
1068
990
  const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
1069
991
  if (existingSubscription) {
1070
- const balanceDs = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getBalanceDataSource).call(this, sourceId);
1071
- if (balanceDs) {
1072
- balanceDs.unsubscribe(subscriptionKey).catch(() => undefined);
1073
- }
992
+ source.unsubscribe(subscriptionKey).catch(() => undefined);
1074
993
  existingSubscription.unsubscribe();
1075
994
  }
1076
995
  }, _AssetsController_buildDataRequest = function _AssetsController_buildDataRequest(accounts, chainIds, partial = {}) {
@@ -1118,7 +1037,7 @@ async function _AssetsController_handleAccountGroupChanged() {
1118
1037
  accountIds: accounts.map((a) => a.id),
1119
1038
  });
1120
1039
  // Subscribe and fetch for the new account group
1121
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToDataSources).call(this);
1040
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
1122
1041
  if (accounts.length > 0) {
1123
1042
  await this.getAssets(accounts, {
1124
1043
  chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
@@ -1152,7 +1071,7 @@ async function _AssetsController_handleAccountGroupChanged() {
1152
1071
  // Users may want to see historical balances even if the network is currently disabled.
1153
1072
  // The data will simply not be updated until the network is re-enabled.
1154
1073
  // Refresh subscriptions for new chain set
1155
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeToDataSources).call(this);
1074
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
1156
1075
  // Do one-time fetch for newly enabled chains
1157
1076
  if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
1158
1077
  await this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {