@metamask-previews/assets-controller 15.0.0-preview-d8fceeabc → 15.0.0-preview-b123e43e2

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 (74) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/AssetsController.cjs +631 -275
  3. package/dist/AssetsController.cjs.map +1 -1
  4. package/dist/AssetsController.d.cts +7 -3
  5. package/dist/AssetsController.d.cts.map +1 -1
  6. package/dist/AssetsController.d.mts +7 -3
  7. package/dist/AssetsController.d.mts.map +1 -1
  8. package/dist/AssetsController.mjs +632 -276
  9. package/dist/AssetsController.mjs.map +1 -1
  10. package/dist/data-sources/AbstractDataSource.cjs +23 -0
  11. package/dist/data-sources/AbstractDataSource.cjs.map +1 -1
  12. package/dist/data-sources/AbstractDataSource.d.cts +13 -1
  13. package/dist/data-sources/AbstractDataSource.d.cts.map +1 -1
  14. package/dist/data-sources/AbstractDataSource.d.mts +13 -1
  15. package/dist/data-sources/AbstractDataSource.d.mts.map +1 -1
  16. package/dist/data-sources/AbstractDataSource.mjs +23 -0
  17. package/dist/data-sources/AbstractDataSource.mjs.map +1 -1
  18. package/dist/data-sources/AccountActivityDataSource.cjs +2 -0
  19. package/dist/data-sources/AccountActivityDataSource.cjs.map +1 -1
  20. package/dist/data-sources/AccountActivityDataSource.d.cts.map +1 -1
  21. package/dist/data-sources/AccountActivityDataSource.d.mts.map +1 -1
  22. package/dist/data-sources/AccountActivityDataSource.mjs +2 -0
  23. package/dist/data-sources/AccountActivityDataSource.mjs.map +1 -1
  24. package/dist/data-sources/AccountsApiDataSource.cjs +143 -22
  25. package/dist/data-sources/AccountsApiDataSource.cjs.map +1 -1
  26. package/dist/data-sources/AccountsApiDataSource.d.cts +18 -2
  27. package/dist/data-sources/AccountsApiDataSource.d.cts.map +1 -1
  28. package/dist/data-sources/AccountsApiDataSource.d.mts +18 -2
  29. package/dist/data-sources/AccountsApiDataSource.d.mts.map +1 -1
  30. package/dist/data-sources/AccountsApiDataSource.mjs +144 -23
  31. package/dist/data-sources/AccountsApiDataSource.mjs.map +1 -1
  32. package/dist/data-sources/RpcDataSource.cjs +163 -24
  33. package/dist/data-sources/RpcDataSource.cjs.map +1 -1
  34. package/dist/data-sources/RpcDataSource.d.cts +17 -0
  35. package/dist/data-sources/RpcDataSource.d.cts.map +1 -1
  36. package/dist/data-sources/RpcDataSource.d.mts +17 -0
  37. package/dist/data-sources/RpcDataSource.d.mts.map +1 -1
  38. package/dist/data-sources/RpcDataSource.mjs +164 -25
  39. package/dist/data-sources/RpcDataSource.mjs.map +1 -1
  40. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs +21 -12
  41. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.cjs.map +1 -1
  42. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts +7 -2
  43. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.cts.map +1 -1
  44. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts +7 -2
  45. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.d.mts.map +1 -1
  46. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs +21 -12
  47. package/dist/data-sources/evm-rpc-services/services/BalanceFetcher.mjs.map +1 -1
  48. package/dist/data-sources/evm-rpc-services/types/state.cjs.map +1 -1
  49. package/dist/data-sources/evm-rpc-services/types/state.d.cts +3 -2
  50. package/dist/data-sources/evm-rpc-services/types/state.d.cts.map +1 -1
  51. package/dist/data-sources/evm-rpc-services/types/state.d.mts +3 -2
  52. package/dist/data-sources/evm-rpc-services/types/state.d.mts.map +1 -1
  53. package/dist/data-sources/evm-rpc-services/types/state.mjs.map +1 -1
  54. package/dist/middlewares/ParallelMiddleware.cjs +9 -0
  55. package/dist/middlewares/ParallelMiddleware.cjs.map +1 -1
  56. package/dist/middlewares/ParallelMiddleware.d.cts.map +1 -1
  57. package/dist/middlewares/ParallelMiddleware.d.mts.map +1 -1
  58. package/dist/middlewares/ParallelMiddleware.mjs +9 -0
  59. package/dist/middlewares/ParallelMiddleware.mjs.map +1 -1
  60. package/dist/middlewares/RpcFallbackMiddleware.cjs +158 -128
  61. package/dist/middlewares/RpcFallbackMiddleware.cjs.map +1 -1
  62. package/dist/middlewares/RpcFallbackMiddleware.d.cts +10 -14
  63. package/dist/middlewares/RpcFallbackMiddleware.d.cts.map +1 -1
  64. package/dist/middlewares/RpcFallbackMiddleware.d.mts +10 -14
  65. package/dist/middlewares/RpcFallbackMiddleware.d.mts.map +1 -1
  66. package/dist/middlewares/RpcFallbackMiddleware.mjs +158 -128
  67. package/dist/middlewares/RpcFallbackMiddleware.mjs.map +1 -1
  68. package/dist/types.cjs.map +1 -1
  69. package/dist/types.d.cts +28 -18
  70. package/dist/types.d.cts.map +1 -1
  71. package/dist/types.d.mts +28 -18
  72. package/dist/types.d.mts.map +1 -1
  73. package/dist/types.mjs.map +1 -1
  74. package/package.json +2 -2
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
9
9
  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");
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
- var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitStateSizeTrace, _AssetsController_controllerMutex, _AssetsController_accountRefreshMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_getSelectedAccounts, _AssetsController_isAccountTreeInitialized, _AssetsController_isUiOpen, _AssetsController_isKeyringUnlocked, _AssetsController_accountActivityDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_customAssetGraduationMiddleware, _AssetsController_rpcFallbackMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_queryApiClient, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeNativeAssetsMap, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_refreshAssetsForTransaction, _AssetsController_runSpamCleanup, _AssetsController_updateActive, _AssetsController_runStartupRefresh, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_assertNonEmptyAccountId, _AssetsController_normalizeAssetIdOrThrow, _AssetsController_fetchMissingPricesWithoutCache, _AssetsController_getNativeAssetMap, _AssetsController_isNativeAsset, _AssetsController_getAssetType, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_getSlowPipelineChainIds, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_ensureDefaultTrackedAssetsSeeded, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_getAssetFromState, _AssetsController_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeRpcCustomAssetsSupplement, _AssetsController_unsubscribeBySubscriptionKey, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged, _AssetsController_handleNetworkAdded, _AssetsController_refreshActiveChainsOnNetworkSwitch, _AssetsController_getSelectedEvmChainIdFromNetworkState, _AssetsController_handleNetworkDidChange, _AssetsController_refreshAssetsAfterNetworkChange, _AssetsController_refreshAssetsAfterNetworkAdded;
12
+ var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitStateSizeTrace, _AssetsController_controllerMutex, _AssetsController_accountRefreshMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_getSelectedAccounts, _AssetsController_isAccountTreeInitialized, _AssetsController_isUiOpen, _AssetsController_isKeyringUnlocked, _AssetsController_accountActivityDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_customAssetGraduationMiddleware, _AssetsController_rpcFallbackMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_queryApiClient, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeNativeAssetsMap, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_refreshAssetsForTransaction, _AssetsController_runSpamCleanup, _AssetsController_updateActive, _AssetsController_runStartupRefresh, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_buildForceUpdateRequestV5, _AssetsController_buildForceUpdateRequestV6, _AssetsController_forceUpdateAssetsV5, _AssetsController_forceUpdateAssetsV6, _AssetsController_runFastFetchV5, _AssetsController_runFastFetchV6, _AssetsController_runBackgroundFetch, _AssetsController_emitFastFetchTraces, _AssetsController_assertNonEmptyAccountId, _AssetsController_normalizeAssetIdOrThrow, _AssetsController_getHiddenAssetIds, _AssetsController_getVisibleCustomAssets, _AssetsController_isBalanceV6Enabled, _AssetsController_fetchMissingPricesWithoutCache, _AssetsController_getNativeAssetMap, _AssetsController_isNativeAsset, _AssetsController_getAssetType, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_getDefaultTrackedAssetIdsForAccount, _AssetsController_getSlowPipelineChainIds, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_ensureDefaultTrackedAssetsSeeded, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_getAssetFromState, _AssetsController_shouldHideNativeToken, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeAssetsBalanceV5, _AssetsController_subscribeAssetsBalanceV6, _AssetsController_subscribeRpcCustomAssetsSupplement, _AssetsController_unsubscribeBySubscriptionKey, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged, _AssetsController_handleNetworkAdded, _AssetsController_refreshActiveChainsOnNetworkSwitch, _AssetsController_getSelectedEvmChainIdFromNetworkState, _AssetsController_handleNetworkDidChange, _AssetsController_refreshAssetsAfterNetworkChange, _AssetsController_refreshAssetsAfterNetworkAdded, _AssetsController_handleAssetsUpdateV5, _AssetsController_handleAssetsUpdateV6, _AssetsController_getUpdatePipelineRequest, _AssetsController_getUpdateTraceData, _AssetsController_emitUpdateTrace;
13
13
  import { BaseController } from "@metamask/base-controller";
14
14
  import { clientControllerSelectors } from "@metamask/client-controller";
15
15
  import { isCaipChainId, isStrictHexString, KnownCaipNamespace, parseCaipAssetType, parseCaipChainId } from "@metamask/utils";
@@ -26,7 +26,7 @@ import { RpcDataSource } from "./data-sources/RpcDataSource.mjs";
26
26
  import { SnapDataSource } from "./data-sources/SnapDataSource.mjs";
27
27
  import { StakedBalanceDataSource } from "./data-sources/StakedBalanceDataSource.mjs";
28
28
  import { CaipAssetNamespace, TokenDataSource } from "./data-sources/TokenDataSource.mjs";
29
- import { CHAINS_WITH_DEFAULT_TRACKED_ASSETS, DEFAULT_TRACKED_ASSETS_BY_CHAIN, buildDefaultAssetsInfo, getDefaultAssetMetadata } from "./defaults.mjs";
29
+ import { CHAINS_WITH_DEFAULT_TRACKED_ASSETS, DEFAULT_TRACKED_ASSETS_BY_CHAIN, buildDefaultAssetsInfo, getDefaultAssetMetadata, getDefaultTrackedAssetsForChain } from "./defaults.mjs";
30
30
  import { AssetsDataSourceError } from "./errors.mjs";
31
31
  import { projectLogger, createModuleLogger } from "./logger.mjs";
32
32
  import { CustomAssetGraduationMiddleware } from "./middlewares/CustomAssetGraduationMiddleware.mjs";
@@ -202,6 +202,10 @@ function normalizeResponse(response) {
202
202
  if (response.replaceCoveredChainBalances) {
203
203
  normalized.replaceCoveredChainBalances = true;
204
204
  }
205
+ if (response.unprocessedCustomAssets &&
206
+ response.unprocessedCustomAssets.length > 0) {
207
+ normalized.unprocessedCustomAssets = response.unprocessedCustomAssets.map((assetId) => normalizeAssetId(assetId));
208
+ }
205
209
  return normalized;
206
210
  }
207
211
  /**
@@ -209,12 +213,13 @@ function normalizeResponse(response) {
209
213
  *
210
214
  * @param previousBalances - Balances already in state for this account.
211
215
  * @param accountBalances - Balances from the incoming response.
212
- * @param customAssetIds - Custom assets to preserve when replacing covered chains.
213
- * @param replaceCoveredChains - When true, drop prior balances on chains present
214
- * in the response before applying it (authoritative chain slice).
216
+ * @param customAssetIds - Custom assets to preserve when replacing covered chains
217
+ * on the Accounts API v5 path (`replaceCoveredChainBalances`).
218
+ * @param replaceCoveredChains - When true (v5 force refresh), drop prior balances
219
+ * on chains present in the response before applying it, then restore custom assets.
215
220
  * @returns The merged balance map for the account.
216
221
  */
217
- function mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains) {
222
+ function mergeAccountBalancesV5(previousBalances, accountBalances, customAssetIds = [], replaceCoveredChains = false) {
218
223
  if (!replaceCoveredChains) {
219
224
  return { ...previousBalances, ...accountBalances };
220
225
  }
@@ -228,8 +233,8 @@ function mergeAccountBalances(previousBalances, accountBalances, customAssetIds,
228
233
  Object.assign(next, accountBalances);
229
234
  for (const customId of customAssetIds) {
230
235
  if (!Object.prototype.hasOwnProperty.call(next, customId)) {
231
- const prev = previousBalances[customId];
232
- next[customId] = prev ?? { amount: '0' };
236
+ const previous = previousBalances[customId];
237
+ next[customId] = previous ?? { amount: '0' };
233
238
  }
234
239
  }
235
240
  // Staked vault balances are owned by StakedBalanceDataSource. When an
@@ -243,6 +248,38 @@ function mergeAccountBalances(previousBalances, accountBalances, customAssetIds,
243
248
  }
244
249
  return next;
245
250
  }
251
+ /**
252
+ * Apply an Accounts API v6 authoritative chain snapshot.
253
+ *
254
+ * @param previousBalances - Balances already in state for this account.
255
+ * @param accountBalances - Balances from the incoming response.
256
+ * @param unprocessedCustomAssets - Pins that v6 and RPC could not resolve.
257
+ * @returns The merged balance map for the account.
258
+ */
259
+ function mergeAccountBalancesV6(previousBalances, accountBalances, unprocessedCustomAssets = []) {
260
+ const coveredChains = new Set(Object.keys(accountBalances).map((assetId) => assetId.split('/')[0]));
261
+ const next = {};
262
+ for (const [assetId, balance] of Object.entries(previousBalances)) {
263
+ if (!coveredChains.has(assetId.split('/')[0])) {
264
+ next[assetId] = balance;
265
+ }
266
+ }
267
+ Object.assign(next, accountBalances);
268
+ const unprocessedSet = new Set(unprocessedCustomAssets.map((assetId) => normalizeAssetId(assetId)));
269
+ for (const [assetId, balance] of Object.entries(previousBalances)) {
270
+ if (unprocessedSet.has(normalizeAssetId(assetId)) &&
271
+ !Object.prototype.hasOwnProperty.call(next, assetId)) {
272
+ next[assetId] = balance;
273
+ }
274
+ }
275
+ for (const [assetId, balance] of Object.entries(previousBalances)) {
276
+ if (isStakingContractAssetId(assetId) &&
277
+ !Object.prototype.hasOwnProperty.call(next, assetId)) {
278
+ next[assetId] = balance;
279
+ }
280
+ }
281
+ return next;
282
+ }
246
283
  // ============================================================================
247
284
  // CONTROLLER IMPLEMENTATION
248
285
  // ============================================================================
@@ -363,6 +400,7 @@ export class AssetsController extends BaseController {
363
400
  queryApiClient,
364
401
  onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
365
402
  ...accountsApiDataSourceConfig,
403
+ isBalanceV6Enabled: () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this),
366
404
  }), "f");
367
405
  __classPrivateFieldSet(this, _AssetsController_snapDataSource, new SnapDataSource({
368
406
  messenger: this.messenger,
@@ -382,6 +420,7 @@ export class AssetsController extends BaseController {
382
420
  ...rpcConfig,
383
421
  isOnboarded: rpcConfig.isOnboarded ?? isOnboarded,
384
422
  getAssetType: (assetId) => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetType).call(this, assetId),
423
+ isBalanceV6Enabled: () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this),
385
424
  }), "f");
386
425
  __classPrivateFieldSet(this, _AssetsController_stakedBalanceDataSource, new StakedBalanceDataSource({
387
426
  messenger: this.messenger,
@@ -414,6 +453,7 @@ export class AssetsController extends BaseController {
414
453
  }), "f");
415
454
  __classPrivateFieldSet(this, _AssetsController_rpcFallbackMiddleware, new RpcFallbackMiddleware({
416
455
  rpcDataSource: __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f"),
456
+ isBalanceV6Enabled: () => __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this),
417
457
  }), "f");
418
458
  log('Initializing AssetsController', {
419
459
  defaultUpdateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
@@ -450,147 +490,35 @@ export class AssetsController extends BaseController {
450
490
  if (accounts.length === 0 || chainIds.length === 0) {
451
491
  return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
452
492
  }
453
- // Collect custom assets for all requested accounts
454
- const customAssets = [];
455
- for (const account of accounts) {
456
- const accountCustomAssets = this.getCustomAssets(account.id);
457
- customAssets.push(...accountCustomAssets);
458
- }
459
493
  if (options?.forceUpdate) {
460
- // Pipeline spans only on unlock/first-init fetch; later forceUpdates pass
461
- // `undefined` so `emitTrace` / `withTrace` no-op without call-site if/else.
462
494
  const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
463
495
  ? undefined
464
496
  : __classPrivateFieldGet(this, _AssetsController_trace, "f");
465
- const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
497
+ const requestOptions = {
466
498
  assetTypes,
467
499
  dataTypes,
468
- customAssets: customAssets.length > 0 ? customAssets : undefined,
469
500
  forceUpdate: true,
470
501
  bypassServerCache: options?.bypassServerCache,
471
502
  assetsForPriceUpdate: options?.assetsForPriceUpdate,
472
- });
473
- // Fast pipeline: accountsApi + stakedBalance → detection → token + price.
474
- // Snap and RPC are excluded here due to their latency (snap triggers account
475
- // creation, RPC is slow on many chains). Results are committed to state
476
- // immediately so the UI can display balances without waiting for them.
477
- //
478
- // Fast/slow pipelines use merge so partial API snapshots cannot wipe
479
- // tokens missing from the response (e.g. USDC when only native balance
480
- // is returned). Balances present in the response are still refreshed.
481
- const fastSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
482
- ? [
483
- createParallelBalanceMiddleware([
484
- __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
485
- __classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
486
- ]),
487
- // Graduation must run BEFORE the RPC fallback so it only sees
488
- // AccountsApi/Websocket balances. RPC intentionally carries
489
- // custom assets and must never trigger graduation.
490
- __classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f"),
491
- __classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f"),
492
- __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
493
- createParallelMiddleware([
494
- __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
495
- __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
496
- ]),
497
- ]
498
- : [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
499
- const { response } = await withTrace({
500
- name: TRACE_FETCH_PIPELINE,
501
- trace: pipelineTrace,
502
- data: {
503
- chain_count: chainIds.length,
504
- account_count: accounts.length,
505
- basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
506
- },
507
- fn: async (parentContext) => {
508
- const startTime = performance.now();
509
- const result = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
510
- sources: fastSources,
511
- request,
512
- parentContext,
513
- trace: pipelineTrace,
514
- });
515
- await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
516
- ...result.response,
517
- updateMode: 'merge',
518
- replaceCoveredChainBalances: true,
519
- });
520
- const durationMs = performance.now() - startTime;
521
- // Summary fields for Assets Health (nested under the parent span).
522
- emitTrace({
523
- name: TRACE_FULL_FETCH,
524
- trace: pipelineTrace,
525
- data: {
526
- duration_ms: durationMs,
527
- chain_count: chainIds.length,
528
- account_count: accounts.length,
529
- basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
530
- asset_count: result.response.assetsBalance
531
- ? Object.values(result.response.assetsBalance).reduce((sum, acct) => sum + Object.keys(acct).length, 0)
532
- : 0,
533
- price_count: result.response.assetsPrice
534
- ? Object.keys(result.response.assetsPrice).length
535
- : 0,
536
- ...result.durationByDataSource,
537
- },
538
- parentContext,
539
- });
540
- emitTrace({
541
- name: TRACE_FIRST_INIT_FETCH,
542
- trace: pipelineTrace,
543
- data: {
544
- duration_ms: durationMs,
545
- chain_ids: JSON.stringify(chainIds),
546
- ...result.durationByDataSource,
547
- },
548
- parentContext,
549
- });
550
- return result;
551
- },
552
- });
553
- // Mark after the unlock/first forceUpdate so later polls skip pipeline spans.
554
- __classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
555
- // Background (slow) lane — flattened sibling of the fast lane (not nested
556
- // inside its withTrace callback). Still fire-and-forget so UI is not blocked.
557
- const slowPipelineChainIds = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSlowPipelineChainIds).call(this, chainIds, response);
558
- if (slowPipelineChainIds.length > 0) {
559
- const slowSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
560
- ? [__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")]
561
- : [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
562
- const slowRequest = { ...request, chainIds: slowPipelineChainIds };
563
- withTrace({
564
- name: TRACE_BACKGROUND_FETCH,
565
- trace: pipelineTrace,
566
- data: {
567
- chain_count: slowPipelineChainIds.length,
568
- account_count: accounts.length,
569
- },
570
- fn: async (slowParentContext) => {
571
- const { response: slowResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
572
- sources: [
573
- createParallelBalanceMiddleware(slowSources),
574
- __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
575
- ...(__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
576
- ? [
577
- createParallelMiddleware([
578
- __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
579
- __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
580
- ]),
581
- ]
582
- : []),
583
- ],
584
- request: slowRequest,
585
- parentContext: slowParentContext,
586
- trace: pipelineTrace,
587
- });
588
- await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
589
- ...slowResponse,
590
- updateMode: 'merge',
591
- });
592
- },
593
- }).catch((error) => log('Background pipeline failed', { error }));
503
+ };
504
+ if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this)) {
505
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_forceUpdateAssetsV6).call(this, {
506
+ accounts,
507
+ chainIds,
508
+ request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildForceUpdateRequestV6).call(this, accounts, chainIds, {
509
+ ...requestOptions,
510
+ customAssetsOverride: options?.customAssets,
511
+ }),
512
+ pipelineTrace,
513
+ });
514
+ }
515
+ else {
516
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_forceUpdateAssetsV5).call(this, {
517
+ accounts,
518
+ chainIds,
519
+ request: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildForceUpdateRequestV5).call(this, accounts, chainIds, requestOptions),
520
+ pipelineTrace,
521
+ });
594
522
  }
595
523
  }
596
524
  const result = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
@@ -837,20 +765,28 @@ export class AssetsController extends BaseController {
837
765
  balances[accountId] ?? (balances[accountId] = {});
838
766
  (_a = balances[accountId])[normalizedAssetId] ?? (_a[normalizedAssetId] = { amount: '0' });
839
767
  });
840
- // Fetch data for the newly added custom asset (merge to preserve other chains)
841
768
  const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
842
769
  if (account) {
843
770
  const chainId = extractChainId(normalizedAssetId);
844
- await this.getAssets([account], {
845
- chainIds: [chainId],
846
- dataTypes: ['balance', 'metadata', 'price'],
847
- assetTypes: ['fungible'],
848
- forceUpdate: true,
849
- updateMode: 'merge',
850
- });
771
+ if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this)) {
772
+ await this.getAssets([account], {
773
+ chainIds: [chainId],
774
+ dataTypes: ['balance', 'metadata', 'price'],
775
+ assetTypes: ['fungible'],
776
+ forceUpdate: true,
777
+ customAssets: [normalizedAssetId],
778
+ });
779
+ }
780
+ else {
781
+ await this.getAssets([account], {
782
+ chainIds: [chainId],
783
+ dataTypes: ['balance', 'metadata', 'price'],
784
+ assetTypes: ['fungible'],
785
+ forceUpdate: true,
786
+ });
787
+ }
851
788
  }
852
- // Re-evaluate subscriptions so the supplemental RPC poll picks up the
853
- // new customAsset on chains another data source already owns.
789
+ // Re-evaluate subscriptions so polls pick up the new pin.
854
790
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
855
791
  }
856
792
  /**
@@ -871,8 +807,7 @@ export class AssetsController extends BaseController {
871
807
  }
872
808
  }
873
809
  });
874
- // Re-evaluate subscriptions so the supplemental RPC poll for that chain
875
- // is torn down when no more customAssets remain there.
810
+ // Re-evaluate subscriptions so polls drop the removed pin.
876
811
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
877
812
  }
878
813
  /**
@@ -903,6 +838,8 @@ export class AssetsController extends BaseController {
903
838
  }
904
839
  state.assetPreferences[normalizedAssetId].hidden = true;
905
840
  });
841
+ // Re-evaluate subscriptions so polls exclude the newly hidden asset.
842
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
906
843
  }
907
844
  /**
908
845
  * Unhide an asset globally.
@@ -921,6 +858,8 @@ export class AssetsController extends BaseController {
921
858
  }
922
859
  }
923
860
  });
861
+ // Re-evaluate subscriptions so polls stop excluding the asset.
862
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
924
863
  }
925
864
  // ============================================================================
926
865
  // CURRENT CURRENCY MANAGEMENT
@@ -1032,101 +971,14 @@ export class AssetsController extends BaseController {
1032
971
  async handleAssetsUpdate(response, sourceId, request) {
1033
972
  log('Assets updated from data source', {
1034
973
  sourceId,
1035
- hasBalance: Boolean(response.assetsBalance),
1036
- hasPrice: Boolean(response.assetsPrice),
1037
- });
1038
- // Enrichment spans only before unlock/first-init fetch completes.
1039
- const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
1040
- ? undefined
1041
- : __classPrivateFieldGet(this, _AssetsController_trace, "f");
1042
- await withTrace({
1043
- name: TRACE_UPDATE_PARENT,
1044
- trace: pipelineTrace,
1045
- data: {
1046
- source: sourceId,
1047
- has_balance: Boolean(response.assetsBalance),
1048
- has_price: Boolean(response.assetsPrice),
1049
- balance_account_count: response.assetsBalance
1050
- ? Object.keys(response.assetsBalance).length
1051
- : 0,
1052
- },
1053
- fn: async (parentContext) => {
1054
- const updateStart = performance.now();
1055
- const resolvedRequest = request ?? {
1056
- accountsWithSupportedChains: [],
1057
- chainIds: [],
1058
- dataTypes: ['balance', 'metadata', 'price'],
1059
- };
1060
- // RPC-only mode (basic functionality off): never run token/price APIs. Strip
1061
- // those data types so downstream middleware cannot treat them as requested.
1062
- const pipelineRequest = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
1063
- ? resolvedRequest
1064
- : {
1065
- ...resolvedRequest,
1066
- dataTypes: resolvedRequest.dataTypes.filter((dt) => dt !== 'metadata' && dt !== 'price'),
1067
- };
1068
- // Graduate custom assets only when AccountsAPI / AccountActivity reports
1069
- // them. RPC already fetches custom assets on purpose, and Snap handles
1070
- // non-EVM chains the rule does not apply to, so skip the middleware for
1071
- // those.
1072
- const shouldGraduateCustomAssets = sourceId === 'AccountsApiDataSource' ||
1073
- sourceId === 'AccountActivityDataSource';
1074
- // Websocket updates can carry brand-new spam airdrops: enrich them
1075
- // with Token API occurrences and drop below-floor tokens BEFORE
1076
- // detection, so spam is never detected, enriched, priced or persisted.
1077
- const shouldFilterOccurrences = sourceId === 'AccountActivityDataSource' &&
1078
- __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
1079
- const shouldRunRpcFallback = sourceId === 'AccountsApiDataSource';
1080
- const enrichmentSources = [
1081
- ...(shouldGraduateCustomAssets
1082
- ? [__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f")]
1083
- : []),
1084
- ...(shouldFilterOccurrences
1085
- ? [
1086
- {
1087
- getName: () => 'OccurrenceFloorFilter',
1088
- assetsMiddleware: __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f").occurrenceFilterMiddleware,
1089
- },
1090
- ]
1091
- : []),
1092
- ...(shouldRunRpcFallback ? [__classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f")] : []),
1093
- __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
1094
- ];
1095
- if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
1096
- enrichmentSources.push(createParallelMiddleware([
1097
- __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
1098
- __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
1099
- ]));
1100
- }
1101
- const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
1102
- sources: enrichmentSources,
1103
- request: pipelineRequest,
1104
- initialResponse: response,
1105
- parentContext,
1106
- trace: pipelineTrace,
1107
- });
1108
- await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
1109
- ...enrichedResponse,
1110
- replaceCoveredChainBalances: response.replaceCoveredChainBalances,
1111
- });
1112
- // Summary fields for Assets Health (nested under the parent span).
1113
- emitTrace({
1114
- name: TRACE_UPDATE_PIPELINE,
1115
- trace: pipelineTrace,
1116
- data: {
1117
- source: sourceId,
1118
- duration_ms: performance.now() - updateStart,
1119
- has_balance: Boolean(response.assetsBalance),
1120
- has_price: Boolean(response.assetsPrice),
1121
- has_metadata: Boolean(enrichedResponse.assetsInfo),
1122
- balance_account_count: response.assetsBalance
1123
- ? Object.keys(response.assetsBalance).length
1124
- : 0,
1125
- },
1126
- parentContext,
1127
- });
1128
- },
974
+ assetsBalance: response.assetsBalance,
975
+ assetsPrice: response.assetsPrice,
1129
976
  });
977
+ if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this)) {
978
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAssetsUpdateV6).call(this, response, sourceId, request);
979
+ return;
980
+ }
981
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_handleAssetsUpdateV5).call(this, response, sourceId, request);
1130
982
  }
1131
983
  // ============================================================================
1132
984
  // CLEANUP
@@ -1577,6 +1429,239 @@ async function _AssetsController_executeMiddlewares(params) {
1577
1429
  });
1578
1430
  }
1579
1431
  return { response: result.response, durationByDataSource };
1432
+ }, _AssetsController_buildForceUpdateRequestV5 = function _AssetsController_buildForceUpdateRequestV5(accounts, chainIds, requestOptions) {
1433
+ const customAssets = [];
1434
+ for (const account of accounts) {
1435
+ customAssets.push(...__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getVisibleCustomAssets).call(this, account.id));
1436
+ }
1437
+ return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
1438
+ ...requestOptions,
1439
+ customAssets: customAssets.length > 0 ? customAssets : undefined,
1440
+ });
1441
+ }, _AssetsController_buildForceUpdateRequestV6 = function _AssetsController_buildForceUpdateRequestV6(accounts, chainIds, requestOptions) {
1442
+ const requestedChains = new Set(chainIds);
1443
+ const candidateCustomAssets = requestOptions.customAssetsOverride ??
1444
+ accounts.flatMap((account) => this.getCustomAssets(account.id));
1445
+ const customAssetsSet = new Set();
1446
+ for (const assetId of candidateCustomAssets) {
1447
+ try {
1448
+ const normalizedAssetId = normalizeAssetId(assetId);
1449
+ if (requestedChains.has(parseCaipAssetType(normalizedAssetId).chainId) &&
1450
+ !this.state.assetPreferences[normalizedAssetId]?.hidden) {
1451
+ customAssetsSet.add(normalizedAssetId);
1452
+ }
1453
+ }
1454
+ catch {
1455
+ // Skip unparseable asset IDs
1456
+ }
1457
+ }
1458
+ const customAssets = [...customAssetsSet];
1459
+ const hiddenAssets = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getHiddenAssetIds).call(this);
1460
+ return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
1461
+ assetTypes: requestOptions.assetTypes,
1462
+ dataTypes: requestOptions.dataTypes,
1463
+ forceUpdate: requestOptions.forceUpdate,
1464
+ bypassServerCache: requestOptions.bypassServerCache,
1465
+ assetsForPriceUpdate: requestOptions.assetsForPriceUpdate,
1466
+ customAssets: customAssets.length > 0 ? customAssets : undefined,
1467
+ excludeAssetIds: hiddenAssets.length > 0 ? hiddenAssets : undefined,
1468
+ });
1469
+ }, _AssetsController_forceUpdateAssetsV5 = async function _AssetsController_forceUpdateAssetsV5({ accounts, chainIds, request, pipelineTrace, }) {
1470
+ const isBasicFunctionality = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
1471
+ const fastSources = isBasicFunctionality
1472
+ ? [
1473
+ createParallelBalanceMiddleware([
1474
+ __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
1475
+ __classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
1476
+ ]),
1477
+ __classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f"),
1478
+ __classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f"),
1479
+ __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
1480
+ createParallelMiddleware([
1481
+ __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
1482
+ __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
1483
+ ]),
1484
+ ]
1485
+ : [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
1486
+ const fastResponse = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runFastFetchV5).call(this, {
1487
+ accounts,
1488
+ chainIds,
1489
+ request,
1490
+ pipelineTrace,
1491
+ fastSources,
1492
+ isBasicFunctionality,
1493
+ });
1494
+ __classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
1495
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runBackgroundFetch).call(this, {
1496
+ accounts,
1497
+ request,
1498
+ pipelineTrace,
1499
+ chainIds: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSlowPipelineChainIds).call(this, chainIds, fastResponse),
1500
+ isBasicFunctionality,
1501
+ });
1502
+ }, _AssetsController_forceUpdateAssetsV6 = async function _AssetsController_forceUpdateAssetsV6({ accounts, chainIds, request, pipelineTrace, }) {
1503
+ const isBasicFunctionality = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
1504
+ const fastSources = isBasicFunctionality
1505
+ ? [
1506
+ createParallelBalanceMiddleware([
1507
+ __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f"),
1508
+ __classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"),
1509
+ ]),
1510
+ __classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f"),
1511
+ __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
1512
+ createParallelMiddleware([
1513
+ __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
1514
+ __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
1515
+ ]),
1516
+ ]
1517
+ : [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
1518
+ const fastResponse = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runFastFetchV6).call(this, {
1519
+ accounts,
1520
+ chainIds,
1521
+ request,
1522
+ pipelineTrace,
1523
+ fastSources,
1524
+ isBasicFunctionality,
1525
+ });
1526
+ __classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
1527
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_runBackgroundFetch).call(this, {
1528
+ accounts,
1529
+ request,
1530
+ pipelineTrace,
1531
+ chainIds: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSlowPipelineChainIds).call(this, chainIds, fastResponse),
1532
+ isBasicFunctionality,
1533
+ });
1534
+ }, _AssetsController_runFastFetchV5 = async function _AssetsController_runFastFetchV5({ accounts, chainIds, request, pipelineTrace, fastSources, isBasicFunctionality, }) {
1535
+ const { response } = await withTrace({
1536
+ name: TRACE_FETCH_PIPELINE,
1537
+ trace: pipelineTrace,
1538
+ data: {
1539
+ chain_count: chainIds.length,
1540
+ account_count: accounts.length,
1541
+ basic_functionality: isBasicFunctionality,
1542
+ },
1543
+ fn: async (parentContext) => {
1544
+ const startTime = performance.now();
1545
+ const result = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
1546
+ sources: fastSources,
1547
+ request,
1548
+ parentContext,
1549
+ trace: pipelineTrace,
1550
+ });
1551
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
1552
+ ...result.response,
1553
+ updateMode: 'merge',
1554
+ replaceCoveredChainBalances: true,
1555
+ });
1556
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitFastFetchTraces).call(this, {
1557
+ accounts,
1558
+ chainIds,
1559
+ result,
1560
+ durationMs: performance.now() - startTime,
1561
+ isBasicFunctionality,
1562
+ parentContext,
1563
+ pipelineTrace,
1564
+ });
1565
+ return result;
1566
+ },
1567
+ });
1568
+ return response;
1569
+ }, _AssetsController_runFastFetchV6 = async function _AssetsController_runFastFetchV6({ accounts, chainIds, request, pipelineTrace, fastSources, isBasicFunctionality, }) {
1570
+ const { response } = await withTrace({
1571
+ name: TRACE_FETCH_PIPELINE,
1572
+ trace: pipelineTrace,
1573
+ data: {
1574
+ chain_count: chainIds.length,
1575
+ account_count: accounts.length,
1576
+ basic_functionality: isBasicFunctionality,
1577
+ },
1578
+ fn: async (parentContext) => {
1579
+ const startTime = performance.now();
1580
+ const result = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
1581
+ sources: fastSources,
1582
+ request,
1583
+ parentContext,
1584
+ trace: pipelineTrace,
1585
+ });
1586
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, result.response);
1587
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitFastFetchTraces).call(this, {
1588
+ accounts,
1589
+ chainIds,
1590
+ result,
1591
+ durationMs: performance.now() - startTime,
1592
+ isBasicFunctionality,
1593
+ parentContext,
1594
+ pipelineTrace,
1595
+ });
1596
+ return result;
1597
+ },
1598
+ });
1599
+ return response;
1600
+ }, _AssetsController_runBackgroundFetch = function _AssetsController_runBackgroundFetch({ accounts, chainIds, request, pipelineTrace, isBasicFunctionality, }) {
1601
+ if (chainIds.length === 0) {
1602
+ return;
1603
+ }
1604
+ const slowSources = isBasicFunctionality
1605
+ ? [__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")]
1606
+ : [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
1607
+ const slowRequest = { ...request, chainIds };
1608
+ withTrace({
1609
+ name: TRACE_BACKGROUND_FETCH,
1610
+ trace: pipelineTrace,
1611
+ data: {
1612
+ chain_count: chainIds.length,
1613
+ account_count: accounts.length,
1614
+ },
1615
+ fn: async (parentContext) => {
1616
+ const { response } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
1617
+ sources: [
1618
+ createParallelBalanceMiddleware(slowSources),
1619
+ __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
1620
+ ...(isBasicFunctionality
1621
+ ? [
1622
+ createParallelMiddleware([
1623
+ __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
1624
+ __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
1625
+ ]),
1626
+ ]
1627
+ : []),
1628
+ ],
1629
+ request: slowRequest,
1630
+ parentContext,
1631
+ trace: pipelineTrace,
1632
+ });
1633
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, { ...response, updateMode: 'merge' });
1634
+ },
1635
+ }).catch((error) => log('Background pipeline failed', { error }));
1636
+ }, _AssetsController_emitFastFetchTraces = function _AssetsController_emitFastFetchTraces({ accounts, chainIds, result, durationMs, isBasicFunctionality, parentContext, pipelineTrace, }) {
1637
+ emitTrace({
1638
+ name: TRACE_FULL_FETCH,
1639
+ trace: pipelineTrace,
1640
+ data: {
1641
+ duration_ms: durationMs,
1642
+ chain_count: chainIds.length,
1643
+ account_count: accounts.length,
1644
+ basic_functionality: isBasicFunctionality,
1645
+ asset_count: result.response.assetsBalance
1646
+ ? Object.values(result.response.assetsBalance).reduce((sum, account) => sum + Object.keys(account).length, 0)
1647
+ : 0,
1648
+ price_count: result.response.assetsPrice
1649
+ ? Object.keys(result.response.assetsPrice).length
1650
+ : 0,
1651
+ ...result.durationByDataSource,
1652
+ },
1653
+ parentContext,
1654
+ });
1655
+ emitTrace({
1656
+ name: TRACE_FIRST_INIT_FETCH,
1657
+ trace: pipelineTrace,
1658
+ data: {
1659
+ duration_ms: durationMs,
1660
+ chain_ids: JSON.stringify(chainIds),
1661
+ ...result.durationByDataSource,
1662
+ },
1663
+ parentContext,
1664
+ });
1580
1665
  }, _AssetsController_assertNonEmptyAccountId = function _AssetsController_assertNonEmptyAccountId(accountId, methodName) {
1581
1666
  if (typeof accountId !== 'string' || accountId.length === 0) {
1582
1667
  throw new Error(`AssetsController.${methodName}: accountId must be a non-empty string`);
@@ -1588,6 +1673,27 @@ async function _AssetsController_executeMiddlewares(params) {
1588
1673
  catch {
1589
1674
  throw new Error(`AssetsController.${methodName}: invalid CAIP-19 assetId "${assetId}"`);
1590
1675
  }
1676
+ }, _AssetsController_getHiddenAssetIds = function _AssetsController_getHiddenAssetIds() {
1677
+ const hidden = [];
1678
+ for (const [assetId, prefs] of Object.entries(this.state.assetPreferences)) {
1679
+ if (prefs.hidden) {
1680
+ hidden.push(assetId);
1681
+ }
1682
+ }
1683
+ return hidden;
1684
+ }, _AssetsController_getVisibleCustomAssets = function _AssetsController_getVisibleCustomAssets(accountId) {
1685
+ return this.getCustomAssets(accountId).filter((assetId) => !this.state.assetPreferences[assetId]?.hidden);
1686
+ }, _AssetsController_isBalanceV6Enabled = function _AssetsController_isBalanceV6Enabled() {
1687
+ try {
1688
+ const { remoteFeatureFlags } = this.messenger.call('RemoteFeatureFlagController:getState');
1689
+ const flag = remoteFeatureFlags?.assetsAccountsApiV6;
1690
+ return (typeof flag === 'object' &&
1691
+ flag !== null &&
1692
+ Boolean(flag.value));
1693
+ }
1694
+ catch {
1695
+ return false;
1696
+ }
1591
1697
  }, _AssetsController_fetchMissingPricesWithoutCache = function _AssetsController_fetchMissingPricesWithoutCache(accounts, chainIds) {
1592
1698
  if (!__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this) || accounts.length === 0) {
1593
1699
  return;
@@ -1667,12 +1773,24 @@ async function _AssetsController_executeMiddlewares(params) {
1667
1773
  return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_enabledChains, "f"));
1668
1774
  }, _AssetsController_getNativeAssetIdsForAccount = function _AssetsController_getNativeAssetIdsForAccount(account) {
1669
1775
  return __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_resolveNativeAssetIds).call(this, __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account));
1776
+ }, _AssetsController_getDefaultTrackedAssetIdsForAccount = function _AssetsController_getDefaultTrackedAssetIdsForAccount(account) {
1777
+ const ids = [];
1778
+ for (const chainId of __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getEnabledChainsForAccount).call(this, account)) {
1779
+ ids.push(...getDefaultTrackedAssetsForChain(chainId));
1780
+ }
1781
+ return ids;
1670
1782
  }, _AssetsController_getSlowPipelineChainIds = function _AssetsController_getSlowPipelineChainIds(chainIds, fastResponse) {
1671
1783
  const accountsApiChains = new Set(__classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f").getActiveChainsSync());
1784
+ // Chains whose pins went unresolved (`unprocessedCustomAssets`): route
1785
+ // them to the slow pipeline so RPC fetches the pins.
1786
+ const unprocessedCustomAssetChains = new Set((fastResponse.unprocessedCustomAssets ?? []).map((assetId) => assetId.split('/')[0]));
1672
1787
  return chainIds.filter((chainId) => {
1673
1788
  if (fastResponse.errors?.[chainId]) {
1674
1789
  return true;
1675
1790
  }
1791
+ if (unprocessedCustomAssetChains.has(chainId)) {
1792
+ return true;
1793
+ }
1676
1794
  if (!accountsApiChains.has(chainId)) {
1677
1795
  return true;
1678
1796
  }
@@ -1812,9 +1930,9 @@ async function _AssetsController_executeMiddlewares(params) {
1812
1930
  for (const [accountId, accountBalances] of Object.entries(normalizedResponse.assetsBalance)) {
1813
1931
  const previousBalances = previousState.assetsBalance[accountId] ?? {};
1814
1932
  const customAssetIds = state.customAssets[accountId] ?? [];
1815
- const replaceCoveredChains = mode === 'full' ||
1816
- normalizedResponse.replaceCoveredChainBalances === true;
1817
- const effective = mergeAccountBalances(previousBalances, accountBalances, customAssetIds, replaceCoveredChains);
1933
+ const effective = mode === 'full'
1934
+ ? mergeAccountBalancesV6(previousBalances, accountBalances, normalizedResponse.unprocessedCustomAssets ?? [])
1935
+ : mergeAccountBalancesV5(previousBalances, accountBalances, customAssetIds, normalizedResponse.replaceCoveredChainBalances === true);
1818
1936
  // Ensure native tokens have an entry (0 if missing) for chains this account supports
1819
1937
  const account = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this).find((a) => a.id === accountId);
1820
1938
  const nativeAssetIdsForAccount = account
@@ -1825,6 +1943,19 @@ async function _AssetsController_executeMiddlewares(params) {
1825
1943
  effective[nativeAssetId] = { amount: '0' };
1826
1944
  }
1827
1945
  }
1946
+ // Default tracked assets (mUSD) are controller-managed and, like
1947
+ // natives, must render at zero balance. An authoritative
1948
+ // chain-slice replace omits them whenever the account holds none,
1949
+ // so re-assert them here — otherwise a force refresh (e.g. the
1950
+ // "Refresh list" action) would drop mUSD from the token list.
1951
+ const defaultTrackedAssetIdsForAccount = account
1952
+ ? __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getDefaultTrackedAssetIdsForAccount).call(this, account)
1953
+ : [];
1954
+ for (const defaultAssetId of defaultTrackedAssetIdsForAccount) {
1955
+ if (!Object.prototype.hasOwnProperty.call(effective, defaultAssetId)) {
1956
+ effective[defaultAssetId] = { amount: '0' };
1957
+ }
1958
+ }
1828
1959
  for (const [assetId, balance] of Object.entries(effective)) {
1829
1960
  const previousBalance = previousBalances[assetId];
1830
1961
  // Coerce amounts (e.g. "1e-18" from a data source stringifying
@@ -1838,10 +1969,11 @@ async function _AssetsController_executeMiddlewares(params) {
1838
1969
  const newAmount = normalizeAmountString(balance.amount, assetDecimals);
1839
1970
  effective[assetId] = { ...balance, amount: newAmount };
1840
1971
  const oldAmount = previousBalance?.amount;
1841
- const isNewDefaultNativeZero = oldAmount === undefined &&
1972
+ const isNewSeededZero = oldAmount === undefined &&
1842
1973
  newAmount === '0' &&
1843
- nativeAssetIdsForAccount.includes(assetId);
1844
- if (oldAmount !== newAmount && !isNewDefaultNativeZero) {
1974
+ (nativeAssetIdsForAccount.includes(assetId) ||
1975
+ defaultTrackedAssetIdsForAccount.includes(assetId));
1976
+ if (oldAmount !== newAmount && !isNewSeededZero) {
1845
1977
  changedBalances.push({
1846
1978
  accountId,
1847
1979
  assetId,
@@ -1871,10 +2003,8 @@ async function _AssetsController_executeMiddlewares(params) {
1871
2003
  changedPriceAssets.length > 0) {
1872
2004
  log('State updated', {
1873
2005
  changedBalances: changedBalances.length > 0 ? changedBalances : undefined,
1874
- changedMetadataCount: changedMetadata.length > 0 ? changedMetadata.length : undefined,
1875
- changedPricesCount: changedPriceAssets.length > 0
1876
- ? changedPriceAssets.length
1877
- : undefined,
2006
+ changedMetadata: changedMetadata.length > 0 ? changedMetadata : undefined,
2007
+ changedPrices: changedPriceAssets.length > 0 ? changedPriceAssets : undefined,
1878
2008
  newAssets: Object.keys(detectedAssets).length > 0
1879
2009
  ? Object.entries(detectedAssets).map(([accountId, assets]) => ({
1880
2010
  accountId,
@@ -2047,16 +2177,10 @@ async function _AssetsController_executeMiddlewares(params) {
2047
2177
  if (!subscriptionKey.startsWith('ds:')) {
2048
2178
  continue;
2049
2179
  }
2050
- // Subscription keys take the form `ds:<SourceName>` for the regular
2051
- // subscription or `ds:<SourceName>:<suffix>` for supplemental
2052
- // subscriptions (e.g. `ds:RpcDataSource:custom`). Split on `:` and
2053
- // pick the source-name segment so both shapes resolve correctly.
2180
+ // Subscription keys take the form `ds:<SourceName>`.
2054
2181
  const [, sourceId] = subscriptionKey.split(':');
2055
2182
  const source = allSources.find((ds) => ds.getName() === sourceId);
2056
2183
  if (source) {
2057
- // Unsubscribe by the actual key — `#unsubscribeDataSource` only
2058
- // knows the regular `ds:<SourceName>` shape and would miss
2059
- // supplemental subscriptions, leaking their polling timers.
2060
2184
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeBySubscriptionKey).call(this, source, subscriptionKey);
2061
2185
  }
2062
2186
  }
@@ -2074,12 +2198,15 @@ async function _AssetsController_executeMiddlewares(params) {
2074
2198
  // Subscribe to price updates for all assets held by selected accounts
2075
2199
  this.subscribeAssetsPrice(accounts, enabledChains);
2076
2200
  }, _AssetsController_subscribeAssetsBalance = function _AssetsController_subscribeAssetsBalance(accounts, chainIds, options) {
2201
+ if (__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_isBalanceV6Enabled).call(this)) {
2202
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalanceV6).call(this, accounts, chainIds, options);
2203
+ return;
2204
+ }
2205
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssetsBalanceV5).call(this, accounts, chainIds, options);
2206
+ }, _AssetsController_subscribeAssetsBalanceV5 = function _AssetsController_subscribeAssetsBalanceV5(accounts, chainIds, options) {
2077
2207
  const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
2078
2208
  const remainingChains = new Set(chainToAccounts.keys());
2079
- // When basic functionality is on, use all balance data sources; when off,
2080
- // RPC only.
2081
- const isBasicFunctionality = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
2082
- const balanceDataSources = isBasicFunctionality
2209
+ const balanceDataSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
2083
2210
  ? __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get)
2084
2211
  : [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
2085
2212
  let rpcAssignedChains = new Set();
@@ -2118,19 +2245,94 @@ async function _AssetsController_executeMiddlewares(params) {
2118
2245
  });
2119
2246
  }
2120
2247
  }
2121
- // Supplemental RPC subscription for customAssets on chains another data
2122
- // source claimed during regular handoff. RPC is the sole balance fetcher
2123
- // for customAssets, so we must always poll them — even when (e.g.)
2124
- // AccountsApi is already covering the chain for normal balances. The
2125
- // supplemental subscription runs in `customAssetsOnly` mode so it does
2126
- // NOT double-poll the regular tracked balances.
2127
2248
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeRpcCustomAssetsSupplement).call(this, accounts, chainToAccounts, rpcAssignedChains);
2249
+ }, _AssetsController_subscribeAssetsBalanceV6 = function _AssetsController_subscribeAssetsBalanceV6(accounts, chainIds, options) {
2250
+ const chainToAccounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildChainToAccountsMap).call(this, accounts, new Set(chainIds));
2251
+ const remainingChains = new Set(chainToAccounts.keys());
2252
+ const remainingCustomAssets = new Set();
2253
+ for (const account of accounts) {
2254
+ for (const assetId of __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getVisibleCustomAssets).call(this, account.id)) {
2255
+ try {
2256
+ if (remainingChains.has(parseCaipAssetType(assetId).chainId)) {
2257
+ remainingCustomAssets.add(assetId);
2258
+ }
2259
+ }
2260
+ catch {
2261
+ // Skip unparseable asset IDs
2262
+ }
2263
+ }
2264
+ }
2265
+ const balanceDataSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
2266
+ ? __classPrivateFieldGet(this, _AssetsController_instances, "a", _AssetsController_allBalanceDataSources_get)
2267
+ : [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
2268
+ for (const source of balanceDataSources) {
2269
+ const availableChains = new Set(source.getActiveChainsSync());
2270
+ const assignedChains = [];
2271
+ for (const chainId of remainingChains) {
2272
+ if (availableChains.has(chainId)) {
2273
+ assignedChains.push(chainId);
2274
+ remainingChains.delete(chainId);
2275
+ }
2276
+ }
2277
+ const claimedAssets = source.claimCustomAssets([...remainingCustomAssets], assignedChains);
2278
+ for (const assetId of claimedAssets) {
2279
+ remainingCustomAssets.delete(assetId);
2280
+ }
2281
+ if (assignedChains.length === 0 && claimedAssets.length === 0) {
2282
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
2283
+ continue;
2284
+ }
2285
+ const claimedAssetsSet = new Set(claimedAssets);
2286
+ const seenIds = new Set();
2287
+ const accountsForSource = assignedChains
2288
+ .flatMap((chainId) => chainToAccounts.get(chainId) ?? [])
2289
+ .filter((account) => {
2290
+ if (seenIds.has(account.id)) {
2291
+ return false;
2292
+ }
2293
+ seenIds.add(account.id);
2294
+ return true;
2295
+ });
2296
+ for (const account of accounts) {
2297
+ if (!seenIds.has(account.id) &&
2298
+ this.getCustomAssets(account.id).some((assetId) => claimedAssetsSet.has(assetId))) {
2299
+ seenIds.add(account.id);
2300
+ accountsForSource.push(account);
2301
+ }
2302
+ }
2303
+ if (accountsForSource.length > 0) {
2304
+ const hiddenAssets = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getHiddenAssetIds).call(this);
2305
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeDataSource).call(this, source, accountsForSource, assignedChains, {
2306
+ customAssets: claimedAssets,
2307
+ excludeAssetIds: hiddenAssets.length > 0 ? hiddenAssets : undefined,
2308
+ ...(options?.skipInitialFetch &&
2309
+ source === __classPrivateFieldGet(this, _AssetsController_accountsApiDataSource, "f")
2310
+ ? { skipInitialFetch: true }
2311
+ : {}),
2312
+ });
2313
+ }
2314
+ else {
2315
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_unsubscribeDataSource).call(this, source);
2316
+ }
2317
+ }
2318
+ if (remainingCustomAssets.size > 0) {
2319
+ log('Custom assets unclaimed by any data source', {
2320
+ assetIds: [...remainingCustomAssets],
2321
+ });
2322
+ }
2128
2323
  }, _AssetsController_subscribeRpcCustomAssetsSupplement = function _AssetsController_subscribeRpcCustomAssetsSupplement(accounts, chainToAccounts, rpcAssignedChains) {
2129
2324
  const rpc = __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f");
2130
2325
  const supplementalKey = `ds:${rpc.getName()}:custom`;
2326
+ const visibleCustomAssetsByAccount = {};
2327
+ for (const account of accounts) {
2328
+ const visibleCustomAssets = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getVisibleCustomAssets).call(this, account.id);
2329
+ if (visibleCustomAssets.length > 0) {
2330
+ visibleCustomAssetsByAccount[account.id] = visibleCustomAssets;
2331
+ }
2332
+ }
2131
2333
  const decision = pickRpcCustomAssetsSupplement({
2132
2334
  accountIds: accounts.map((account) => account.id),
2133
- customAssetsByAccount: this.state.customAssets,
2335
+ customAssetsByAccount: visibleCustomAssetsByAccount,
2134
2336
  rpcAssignedChains,
2135
2337
  rpcAvailableChains: new Set(rpc.getActiveChainsSync()),
2136
2338
  enabledChains: new Set(chainToAccounts.keys()),
@@ -2187,12 +2389,14 @@ async function _AssetsController_executeMiddlewares(params) {
2187
2389
  const subscriptionKey = options.subscriptionKey ?? `ds:${sourceId}`;
2188
2390
  const existingSubscription = __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").get(subscriptionKey);
2189
2391
  const isUpdate = existingSubscription !== undefined;
2392
+ const customAssets = options.customAssets ?? [];
2190
2393
  log('Subscribe to data source', {
2191
2394
  sourceId,
2192
2395
  subscriptionKey,
2193
2396
  isUpdate,
2194
2397
  accountCount: accounts.length,
2195
2398
  chainCount: chains.length,
2399
+ customAssetCount: customAssets.length,
2196
2400
  customAssetsOnly: options.customAssetsOnly === true,
2197
2401
  skipInitialFetch: options.skipInitialFetch === true,
2198
2402
  });
@@ -2201,6 +2405,10 @@ async function _AssetsController_executeMiddlewares(params) {
2201
2405
  assetTypes: ['fungible'],
2202
2406
  dataTypes: ['balance'],
2203
2407
  updateInterval: __classPrivateFieldGet(this, _AssetsController_defaultUpdateInterval, "f"),
2408
+ customAssets: customAssets.length > 0 ? customAssets : undefined,
2409
+ excludeAssetIds: options.excludeAssetIds && options.excludeAssetIds.length > 0
2410
+ ? options.excludeAssetIds
2411
+ : undefined,
2204
2412
  ...(options.customAssetsOnly === true
2205
2413
  ? { customAssetsOnly: true }
2206
2414
  : {}),
@@ -2364,13 +2572,13 @@ async function _AssetsController_handleAccountGroupChanged(groupId, previousGrou
2364
2572
  // The data will simply not be updated until the network is re-enabled.
2365
2573
  // Refresh subscriptions for new chain set
2366
2574
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_subscribeAssets).call(this);
2367
- // Do one-time fetch for newly enabled chains; merge so we keep existing chain balances
2575
+ // One-time fetch for newly enabled chains. v6 `full` replace is scoped to
2576
+ // those chains; existing balances on other chains are left untouched.
2368
2577
  const accounts = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSelectedAccounts).call(this);
2369
2578
  if (addedChains.length > 0 && accounts.length > 0) {
2370
2579
  await this.getAssets(accounts, {
2371
2580
  chainIds: addedChains,
2372
2581
  forceUpdate: true,
2373
- updateMode: 'merge',
2374
2582
  });
2375
2583
  }
2376
2584
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
@@ -2493,5 +2701,153 @@ async function _AssetsController_refreshAssetsAfterNetworkAdded(hexChainId) {
2493
2701
  });
2494
2702
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_ensureNativeBalancesDefaultZero).call(this);
2495
2703
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_fetchMissingPricesWithoutCache).call(this, accounts, [caipChainId]);
2704
+ }, _AssetsController_handleAssetsUpdateV5 = async function _AssetsController_handleAssetsUpdateV5(response, sourceId, request) {
2705
+ const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
2706
+ ? undefined
2707
+ : __classPrivateFieldGet(this, _AssetsController_trace, "f");
2708
+ await withTrace({
2709
+ name: TRACE_UPDATE_PARENT,
2710
+ trace: pipelineTrace,
2711
+ data: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getUpdateTraceData).call(this, response, sourceId),
2712
+ fn: async (parentContext) => {
2713
+ const updateStart = performance.now();
2714
+ const pipelineRequest = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getUpdatePipelineRequest).call(this, request);
2715
+ const shouldGraduateCustomAssets = sourceId === 'AccountsApiDataSource' ||
2716
+ sourceId === 'AccountActivityDataSource';
2717
+ const shouldFilterOccurrences = sourceId === 'AccountActivityDataSource' &&
2718
+ __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
2719
+ const shouldRunRpcFallback = sourceId === 'AccountsApiDataSource';
2720
+ const enrichmentSources = [
2721
+ ...(shouldGraduateCustomAssets
2722
+ ? [__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f")]
2723
+ : []),
2724
+ ...(shouldFilterOccurrences
2725
+ ? [
2726
+ {
2727
+ getName: () => 'OccurrenceFloorFilter',
2728
+ assetsMiddleware: __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f").occurrenceFilterMiddleware,
2729
+ },
2730
+ ]
2731
+ : []),
2732
+ ...(shouldRunRpcFallback ? [__classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f")] : []),
2733
+ __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
2734
+ ];
2735
+ enrichmentSources.push(__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"));
2736
+ if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
2737
+ enrichmentSources.push(createParallelMiddleware([
2738
+ __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
2739
+ __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
2740
+ ]));
2741
+ }
2742
+ const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
2743
+ sources: enrichmentSources,
2744
+ request: pipelineRequest,
2745
+ initialResponse: response,
2746
+ parentContext,
2747
+ trace: pipelineTrace,
2748
+ });
2749
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
2750
+ ...enrichedResponse,
2751
+ replaceCoveredChainBalances: response.replaceCoveredChainBalances,
2752
+ });
2753
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitUpdateTrace).call(this, {
2754
+ response,
2755
+ sourceId,
2756
+ enrichedResponse,
2757
+ updateStart,
2758
+ pipelineTrace,
2759
+ parentContext,
2760
+ });
2761
+ },
2762
+ });
2763
+ }, _AssetsController_handleAssetsUpdateV6 = async function _AssetsController_handleAssetsUpdateV6(response, sourceId, request) {
2764
+ const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
2765
+ ? undefined
2766
+ : __classPrivateFieldGet(this, _AssetsController_trace, "f");
2767
+ await withTrace({
2768
+ name: TRACE_UPDATE_PARENT,
2769
+ trace: pipelineTrace,
2770
+ data: __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getUpdateTraceData).call(this, response, sourceId),
2771
+ fn: async (parentContext) => {
2772
+ const updateStart = performance.now();
2773
+ const pipelineRequest = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getUpdatePipelineRequest).call(this, request);
2774
+ const shouldFilterOccurrences = sourceId === 'AccountActivityDataSource' &&
2775
+ __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this);
2776
+ const enrichmentSources = [
2777
+ ...(shouldFilterOccurrences
2778
+ ? [
2779
+ {
2780
+ getName: () => 'OccurrenceFloorFilter',
2781
+ assetsMiddleware: __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f").occurrenceFilterMiddleware,
2782
+ },
2783
+ ]
2784
+ : []),
2785
+ ];
2786
+ if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
2787
+ enrichmentSources.push(__classPrivateFieldGet(this, _AssetsController_rpcFallbackMiddleware, "f"));
2788
+ }
2789
+ enrichmentSources.push(__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"));
2790
+ if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
2791
+ enrichmentSources.push(createParallelMiddleware([
2792
+ __classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
2793
+ __classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
2794
+ ]));
2795
+ }
2796
+ const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
2797
+ sources: enrichmentSources,
2798
+ request: pipelineRequest,
2799
+ initialResponse: response,
2800
+ parentContext,
2801
+ trace: pipelineTrace,
2802
+ });
2803
+ await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
2804
+ __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitUpdateTrace).call(this, {
2805
+ response,
2806
+ sourceId,
2807
+ enrichedResponse,
2808
+ updateStart,
2809
+ pipelineTrace,
2810
+ parentContext,
2811
+ });
2812
+ },
2813
+ });
2814
+ }, _AssetsController_getUpdatePipelineRequest = function _AssetsController_getUpdatePipelineRequest(request) {
2815
+ const resolvedRequest = request ?? {
2816
+ accountsWithSupportedChains: [],
2817
+ chainIds: [],
2818
+ dataTypes: ['balance', 'metadata', 'price'],
2819
+ };
2820
+ if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
2821
+ return resolvedRequest;
2822
+ }
2823
+ return {
2824
+ ...resolvedRequest,
2825
+ dataTypes: resolvedRequest.dataTypes.filter((dataType) => dataType !== 'metadata' && dataType !== 'price'),
2826
+ };
2827
+ }, _AssetsController_getUpdateTraceData = function _AssetsController_getUpdateTraceData(response, sourceId) {
2828
+ return {
2829
+ source: sourceId,
2830
+ has_balance: Boolean(response.assetsBalance),
2831
+ has_price: Boolean(response.assetsPrice),
2832
+ balance_account_count: response.assetsBalance
2833
+ ? Object.keys(response.assetsBalance).length
2834
+ : 0,
2835
+ };
2836
+ }, _AssetsController_emitUpdateTrace = function _AssetsController_emitUpdateTrace({ response, sourceId, enrichedResponse, updateStart, pipelineTrace, parentContext, }) {
2837
+ emitTrace({
2838
+ name: TRACE_UPDATE_PIPELINE,
2839
+ trace: pipelineTrace,
2840
+ data: {
2841
+ source: sourceId,
2842
+ duration_ms: performance.now() - updateStart,
2843
+ has_balance: Boolean(response.assetsBalance),
2844
+ has_price: Boolean(response.assetsPrice),
2845
+ has_metadata: Boolean(enrichedResponse.assetsInfo),
2846
+ balance_account_count: response.assetsBalance
2847
+ ? Object.keys(response.assetsBalance).length
2848
+ : 0,
2849
+ },
2850
+ parentContext,
2851
+ });
2496
2852
  };
2497
2853
  //# sourceMappingURL=AssetsController.mjs.map