@metamask-previews/assets-controller 5.0.0-preview-d9d1316f5 → 5.0.0-preview-d5ac72227

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 (30) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/AssetsController.cjs +76 -29
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +10 -2
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +10 -2
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +76 -29
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/BackendWebsocketDataSource.cjs +45 -29
  11. package/dist/data-sources/BackendWebsocketDataSource.cjs.map +1 -1
  12. package/dist/data-sources/BackendWebsocketDataSource.d.cts.map +1 -1
  13. package/dist/data-sources/BackendWebsocketDataSource.d.mts.map +1 -1
  14. package/dist/data-sources/BackendWebsocketDataSource.mjs +45 -29
  15. package/dist/data-sources/BackendWebsocketDataSource.mjs.map +1 -1
  16. package/dist/data-sources/RpcDataSource.cjs +12 -2
  17. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  18. package/dist/data-sources/RpcDataSource.d.cts +4 -0
  19. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  20. package/dist/data-sources/RpcDataSource.d.mts +4 -0
  21. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  22. package/dist/data-sources/RpcDataSource.mjs +12 -2
  23. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  24. package/dist/data-sources/TokenDataSource.cjs +12 -3
  25. package/dist/data-sources/TokenDataSource.cjs.map +1 -1
  26. package/dist/data-sources/TokenDataSource.d.cts.map +1 -1
  27. package/dist/data-sources/TokenDataSource.d.mts.map +1 -1
  28. package/dist/data-sources/TokenDataSource.mjs +12 -3
  29. package/dist/data-sources/TokenDataSource.mjs.map +1 -1
  30. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -7,12 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+
12
+ - Added `isOnboarded` option to `AssetsControllerOptions` and `RpcDataSourceConfig` ([#8430](https://github.com/MetaMask/core/pull/8430))
13
+ - When `isOnboarded` returns `false`, `RpcDataSource` skips `fetch` and `subscribe` calls, preventing on-chain RPC calls before onboarding is complete.
14
+ - Defaults to `() => true` so existing consumers are unaffected.
15
+
10
16
  ### Changed
11
17
 
12
18
  - Bump `@metamask/transaction-controller` from `^64.0.0` to `^64.1.0` ([#8432](https://github.com/MetaMask/core/pull/8432))
13
19
 
14
20
  ### Fixed
15
21
 
22
+ - `AssetsController` now re-subscribes to all data sources when `AccountTreeController` state changes after initial startup, ensuring snap accounts and their chains are included ([#8430](https://github.com/MetaMask/core/pull/8430))
23
+ - Previously, `#start()` would create subscriptions before snap accounts were available, and its idempotency guard prevented re-subscription when the full account list arrived.
24
+ - Added `#handleAccountTreeStateChange()` which forces a full re-subscription and re-fetch when the account tree updates, picking up all accounts including snaps.
25
+ - Added `AccountsController:getSelectedAccount` as a fallback in `#getSelectedAccounts()` for when the account tree is not yet initialized.
26
+ - `TokenDataSource` no longer filters out user-imported custom assets with the `MIN_TOKEN_OCCURRENCES` spam filter or Blockaid bulk scan ([#8430](https://github.com/MetaMask/core/pull/8430))
27
+ - Tokens present in `customAssets` state now bypass the EVM occurrence threshold and non-EVM Blockaid scan, ensuring manually imported assets always appear.
28
+ - `BackendWebsocketDataSource` now properly releases chains to `AccountsApiDataSource` when the websocket is disconnected or disabled ([#8430](https://github.com/MetaMask/core/pull/8430))
29
+ - Previously, `BackendWebsocketDataSource` eagerly claimed all supported chains on initialization regardless of connection state, preventing `AccountsApiDataSource` from polling.
30
+ - Chains are now only claimed when the websocket is connected. On disconnect, chains are released so the chain-claiming loop assigns them to `AccountsApiDataSource` for polling fallback. On reconnect, chains are reclaimed.
16
31
  - `AssetsController` no longer silently skips asset fetching on startup for returning users ([#8412](https://github.com/MetaMask/core/pull/8412))
17
32
  - Previously, `#start()` was called at keyring unlock before `AccountTreeController.init()` had built the account tree, causing `#selectedAccounts` to return an empty array and all subscriptions and fetches to be skipped. `selectedAccountGroupChange` does not fire when the persisted selected group is unchanged, leaving the controller idle.
18
33
  - Now subscribes to `AccountTreeController:stateChange` (the base-controller event guaranteed to fire when `init()` calls `this.update()`), so the controller re-evaluates its active state once accounts are available.
@@ -13,7 +13,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
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_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitTrace, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_updateActive, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
16
+ var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitTrace, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_lastKnownAccountIds, _AssetsController_getSelectedAccounts, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_updateActive, _AssetsController_handleAccountTreeStateChange, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeStakedBalance, _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");
@@ -210,7 +210,7 @@ function normalizeResponse(response) {
210
210
  * - The controller does NOT manage polling - it simply receives pushed updates
211
211
  */
212
212
  class AssetsController extends base_controller_1.BaseController {
213
- constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, isBasicFunctionality, subscribeToBasicFunctionalityChange, queryApiClient, rpcDataSourceConfig, trace, accountsApiDataSourceConfig, priceDataSourceConfig, stakedBalanceDataSourceConfig, }) {
213
+ constructor({ messenger, state = {}, defaultUpdateInterval = DEFAULT_POLLING_INTERVAL_MS, isEnabled = () => true, isBasicFunctionality, subscribeToBasicFunctionalityChange, queryApiClient, rpcDataSourceConfig, trace, accountsApiDataSourceConfig, priceDataSourceConfig, stakedBalanceDataSourceConfig, isOnboarded, }) {
214
214
  super({
215
215
  name: CONTROLLER_NAME,
216
216
  messenger,
@@ -247,6 +247,12 @@ class AssetsController extends base_controller_1.BaseController {
247
247
  _AssetsController_activeSubscriptions.set(this, new Map());
248
248
  /** Currently enabled chains from NetworkEnablementController */
249
249
  _AssetsController_enabledChains.set(this, new Set());
250
+ /**
251
+ * Snapshot of account IDs that were active when the last subscription/fetch
252
+ * cycle ran. Used by #handleAccountTreeStateChange to skip redundant
253
+ * re-subscriptions when the account set hasn't actually changed.
254
+ */
255
+ _AssetsController_lastKnownAccountIds.set(this, new Set());
250
256
  _AssetsController_backendWebsocketDataSource.set(this, void 0);
251
257
  _AssetsController_accountsApiDataSource.set(this, void 0);
252
258
  _AssetsController_snapDataSource.set(this, void 0);
@@ -291,6 +297,7 @@ class AssetsController extends base_controller_1.BaseController {
291
297
  messenger: this.messenger,
292
298
  onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
293
299
  ...rpcConfig,
300
+ isOnboarded: rpcConfig.isOnboarded ?? isOnboarded,
294
301
  }), "f");
295
302
  __classPrivateFieldSet(this, _AssetsController_stakedBalanceDataSource, new StakedBalanceDataSource_1.StakedBalanceDataSource({
296
303
  messenger: this.messenger,
@@ -508,7 +515,7 @@ class AssetsController extends base_controller_1.BaseController {
508
515
  * @returns Legacy-compatible state for transaction-pay-controller.
509
516
  */
510
517
  getStateForTransactionPay() {
511
- const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get);
518
+ const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
512
519
  const { nativeAssetIdentifiers } = this.messenger.call('NetworkEnablementController:getState');
513
520
  const { networkConfigurationsByChainId } = this.messenger.call('NetworkController:getState');
514
521
  return (0, utils_2.formatStateForTransactionPay)({
@@ -581,7 +588,7 @@ class AssetsController extends base_controller_1.BaseController {
581
588
  }
582
589
  });
583
590
  // Fetch data for the newly added custom asset (merge to preserve other chains)
584
- const account = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).find((a) => a.id === accountId);
591
+ const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
585
592
  if (account) {
586
593
  const chainId = extractChainId(normalizedAssetId);
587
594
  await this.getAssets([account], {
@@ -680,7 +687,7 @@ class AssetsController extends base_controller_1.BaseController {
680
687
  if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
681
688
  return;
682
689
  }
683
- this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
690
+ this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this), {
684
691
  forceUpdate: true,
685
692
  dataTypes: ['price'],
686
693
  assetsForPriceUpdate: Object.values(this.state.assetsBalance).flatMap((balances) => Object.keys(balances)),
@@ -705,10 +712,11 @@ class AssetsController extends base_controller_1.BaseController {
705
712
  const subscriptionKey = 'ds:PriceDataSource';
706
713
  const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
707
714
  const isUpdate = existingSubscription !== undefined;
715
+ const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
716
+ dataTypes: ['price'],
717
+ });
708
718
  const subscribeReq = {
709
- request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
710
- dataTypes: ['price'],
711
- }),
719
+ request,
712
720
  subscriptionId: subscriptionKey,
713
721
  isUpdate,
714
722
  onAssetsUpdate: (response) => this.handleAssetsUpdate(response, 'PriceDataSource'),
@@ -836,7 +844,7 @@ class AssetsController extends base_controller_1.BaseController {
836
844
  }
837
845
  }
838
846
  exports.AssetsController = AssetsController;
839
- _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = 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_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_emitTrace = function _AssetsController_emitTrace(name, data, tags = {
847
+ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_lastKnownAccountIds = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_emitTrace = function _AssetsController_emitTrace(name, data, tags = {
840
848
  controller: 'AssetsController',
841
849
  }) {
842
850
  if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
@@ -882,8 +890,16 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
882
890
  price_entries: Object.keys(assetsPrice).length,
883
891
  custom_asset_entries: customAssetEntries,
884
892
  });
885
- }, _AssetsController_selectedAccounts_get = function _AssetsController_selectedAccounts_get() {
886
- return this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
893
+ }, _AssetsController_getSelectedAccounts = function _AssetsController_getSelectedAccounts() {
894
+ const accounts = this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
895
+ if (accounts.length > 0) {
896
+ return accounts;
897
+ }
898
+ const selectedAccount = this.messenger.call('AccountsController:getSelectedAccount');
899
+ if (selectedAccount) {
900
+ return [selectedAccount];
901
+ }
902
+ return [];
887
903
  }, _AssetsController_allBalanceDataSources_get = function _AssetsController_allBalanceDataSources_get() {
888
904
  return [
889
905
  __classPrivateFieldGet(this, _AssetsController_backendWebsocketDataSource, "f"),
@@ -936,7 +952,7 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
936
952
  // when init() calls this.update(). #start() is idempotent so
937
953
  // repeated fires are safe.
938
954
  this.messenger.subscribe('AccountTreeController:stateChange', () => {
939
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateActive).call(this);
955
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAccountTreeStateChange).call(this);
940
956
  });
941
957
  // Subscribe to network enablement changes (only enabledNetworkMap)
942
958
  this.messenger.subscribe('NetworkEnablementController:stateChange', ({ enabledNetworkMap }) => {
@@ -963,6 +979,36 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
963
979
  else {
964
980
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_stop).call(this);
965
981
  }
982
+ }, _AssetsController_handleAccountTreeStateChange = function _AssetsController_handleAccountTreeStateChange() {
983
+ const shouldRun = __classPrivateFieldGet(this, _AssetsController_uiOpen, "f") && __classPrivateFieldGet(this, _AssetsController_keyringUnlocked, "f");
984
+ if (!shouldRun) {
985
+ return;
986
+ }
987
+ if (__classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").size > 0) {
988
+ const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
989
+ const currentIds = new Set(accounts.map((a) => a.id));
990
+ const accountsChanged = currentIds.size !== __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size ||
991
+ [...currentIds].some((id) => !__classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").has(id));
992
+ if (!accountsChanged) {
993
+ return;
994
+ }
995
+ log('Account tree changed with new accounts, re-subscribing', {
996
+ previousCount: __classPrivateFieldGet(this, _AssetsController_lastKnownAccountIds, "f").size,
997
+ currentCount: currentIds.size,
998
+ });
999
+ __classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, currentIds, "f");
1000
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
1001
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
1002
+ this.getAssets(accounts, {
1003
+ chainIds: [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")],
1004
+ forceUpdate: true,
1005
+ }).catch((error) => {
1006
+ log('Failed to fetch assets after tree change', error);
1007
+ });
1008
+ }
1009
+ else {
1010
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_start).call(this);
1011
+ }
966
1012
  }, _AssetsController_registerActionHandlers = function _AssetsController_registerActionHandlers() {
967
1013
  this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
968
1014
  }, _AssetsController_handleActiveChainsUpdate = function _AssetsController_handleActiveChainsUpdate(dataSourceId, activeChains, previousChains) {
@@ -983,11 +1029,11 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
983
1029
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
984
1030
  }
985
1031
  // If chains were added and we have selected accounts, do one-time fetch
986
- if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
1032
+ if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).length > 0) {
987
1033
  const addedEnabledChains = addedChains.filter((chain) => __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").has(chain));
988
1034
  if (addedEnabledChains.length > 0) {
989
1035
  log('Fetching balances for newly added chains', { addedEnabledChains });
990
- this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
1036
+ this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this), {
991
1037
  chainIds: addedEnabledChains,
992
1038
  forceUpdate: true,
993
1039
  updateMode: 'merge',
@@ -1086,7 +1132,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1086
1132
  }, _AssetsController_getNativeAssetIdsForAccount = function _AssetsController_getNativeAssetIdsForAccount(account) {
1087
1133
  return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account));
1088
1134
  }, _AssetsController_ensureNativeBalancesDefaultZero = function _AssetsController_ensureNativeBalancesDefaultZero() {
1089
- const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get);
1135
+ const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
1090
1136
  if (accounts.length === 0) {
1091
1137
  return;
1092
1138
  }
@@ -1175,7 +1221,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1175
1221
  return next;
1176
1222
  })();
1177
1223
  // Ensure native tokens have an entry (0 if missing) for chains this account supports
1178
- const account = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).find((a) => a.id === accountId);
1224
+ const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
1179
1225
  const nativeAssetIdsForAccount = account
1180
1226
  ? __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForAccount).call(this, account)
1181
1227
  : __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getNativeAssetIdsForEnabledChains).call(this);
@@ -1353,7 +1399,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1353
1399
  return 'fungible';
1354
1400
  }
1355
1401
  }, _AssetsController_start = function _AssetsController_start() {
1356
- const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get);
1402
+ const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
1357
1403
  const chainIds = [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")];
1358
1404
  if (accounts.length === 0 || chainIds.length === 0) {
1359
1405
  return;
@@ -1365,6 +1411,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1365
1411
  selectedAccountCount: accounts.length,
1366
1412
  enabledChainCount: chainIds.length,
1367
1413
  });
1414
+ __classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
1368
1415
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
1369
1416
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
1370
1417
  this.getAssets(accounts, {
@@ -1380,6 +1427,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1380
1427
  });
1381
1428
  __classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, false, "f");
1382
1429
  __classPrivateFieldSet(this, _AssetsController_stateSizeReported, false, "f");
1430
+ __classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(), "f");
1383
1431
  // Stop price subscription first (uses direct messenger call)
1384
1432
  this.unsubscribeAssetsPrice();
1385
1433
  // Stop balance subscriptions by properly notifying data sources via messenger
@@ -1402,23 +1450,21 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1402
1450
  }
1403
1451
  __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").clear();
1404
1452
  }, _AssetsController_subscribeAssets = function _AssetsController_subscribeAssets() {
1405
- if (__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length === 0 || __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size === 0) {
1453
+ const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
1454
+ const enabledChains = [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")];
1455
+ if (accounts.length === 0 || enabledChains.length === 0) {
1406
1456
  return;
1407
1457
  }
1408
1458
  // Subscribe to balance updates (batched by data source)
1409
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [
1410
- ...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
1411
- ]);
1459
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalance).call(this, accounts, enabledChains);
1412
1460
  // Subscribe to staked balance updates (separate from regular balance chain-claiming)
1413
- __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeStakedBalance).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [
1414
- ...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f"),
1415
- ]);
1461
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeStakedBalance).call(this, accounts, enabledChains);
1416
1462
  // Subscribe to price updates for all assets held by selected accounts
1417
- this.subscribeAssetsPrice(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), [...__classPrivateFieldGet(this, _AssetsController_enabledChains, "f")]);
1463
+ this.subscribeAssetsPrice(accounts, enabledChains);
1418
1464
  }, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance(accounts, chainIds) {
1419
1465
  const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
1420
1466
  const remainingChains = new Set(chainToAccounts.keys());
1421
- // When basic functionality is on (getter true), use all balance data sources; when off (getter false), RPC only.
1467
+ // When basic functionality is on, use all balance data sources; when off, RPC only.
1422
1468
  const balanceDataSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
1423
1469
  ? __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get)
1424
1470
  : [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
@@ -1566,11 +1612,12 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
1566
1612
  // EVENT HANDLERS
1567
1613
  // ============================================================================
1568
1614
  async function _AssetsController_handleAccountGroupChanged() {
1569
- const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get);
1615
+ const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
1570
1616
  log('Account group changed', {
1571
1617
  accountCount: accounts.length,
1572
1618
  accountIds: accounts.map((a) => a.id),
1573
1619
  });
1620
+ __classPrivateFieldSet(this, _AssetsController_lastKnownAccountIds, new Set(accounts.map((a) => a.id)), "f");
1574
1621
  // Subscribe and fetch for the new account group
1575
1622
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
1576
1623
  if (accounts.length > 0) {
@@ -1609,8 +1656,8 @@ async function _AssetsController_handleAccountGroupChanged() {
1609
1656
  // Refresh subscriptions for new chain set
1610
1657
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
1611
1658
  // Do one-time fetch for newly enabled chains; merge so we keep existing chain balances
1612
- if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get).length > 0) {
1613
- await this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_selectedAccounts_get), {
1659
+ if (addedChains.length > 0 && __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).length > 0) {
1660
+ await this.getAssets(__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this), {
1614
1661
  chainIds: addedChains,
1615
1662
  forceUpdate: true,
1616
1663
  updateMode: 'merge',