@metamask-previews/assets-controller 11.2.1-preview-6cd1bb2f5 → 11.3.0-preview-2296abeaf
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.
- package/CHANGELOG.md +28 -1
- package/dist/AssetsController.cjs +238 -133
- package/dist/AssetsController.cjs.map +1 -1
- package/dist/AssetsController.d.cts.map +1 -1
- package/dist/AssetsController.d.mts.map +1 -1
- package/dist/AssetsController.mjs +238 -133
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/data-sources/SnapDataSource.cjs +10 -49
- package/dist/data-sources/SnapDataSource.cjs.map +1 -1
- package/dist/data-sources/SnapDataSource.d.cts +8 -0
- package/dist/data-sources/SnapDataSource.d.cts.map +1 -1
- package/dist/data-sources/SnapDataSource.d.mts +8 -0
- package/dist/data-sources/SnapDataSource.d.mts.map +1 -1
- package/dist/data-sources/SnapDataSource.mjs +10 -49
- package/dist/data-sources/SnapDataSource.mjs.map +1 -1
- package/dist/selectors/balance.cjs +53 -35
- package/dist/selectors/balance.cjs.map +1 -1
- package/dist/selectors/balance.d.cts.map +1 -1
- package/dist/selectors/balance.d.mts.map +1 -1
- package/dist/selectors/balance.mjs +53 -35
- package/dist/selectors/balance.mjs.map +1 -1
- package/dist/utils/trace.cjs +120 -0
- package/dist/utils/trace.cjs.map +1 -0
- package/dist/utils/trace.d.cts +52 -0
- package/dist/utils/trace.d.cts.map +1 -0
- package/dist/utils/trace.d.mts +52 -0
- package/dist/utils/trace.d.mts.map +1 -0
- package/dist/utils/trace.mjs +115 -0
- package/dist/utils/trace.mjs.map +1 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [11.3.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `SnapDataSource` now preserves optional balance `metadata` from snap keyrings into `assetsBalance` when handling `AccountsController:accountBalancesUpdated` and `getAccountBalances` results ([#9564](https://github.com/MetaMask/core/pull/9564))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Bump `@metamask/assets-controllers` from `^110.0.0` to `^110.0.1` ([#9693](https://github.com/MetaMask/core/pull/9693))
|
|
19
|
+
- Bump `@metamask/core-backend` from `^7.0.0` to `^8.0.0` ([#9693](https://github.com/MetaMask/core/pull/9693))
|
|
20
|
+
- Bump `@metamask/transaction-controller` from `^69.2.1` to `^69.3.0` ([#9693](https://github.com/MetaMask/core/pull/9693))
|
|
21
|
+
- Nest AssetsController Sentry spans (`AssetsDataSourceTiming`, `AssetsDataSourceError`, `AssetsControllerFirstInitFetch`, pipeline summaries) as subspans under parent `AssetsFullFetch` / `AssetsUpdatePipeline` / `AssetsBackgroundFetch` traces, and emit a single `AggregatedBalanceSelector` span for `calculateBalanceForAllWallets` instead of one root span per account group, to avoid Sentry rate limits ([#9672](https://github.com/MetaMask/core/pull/9672))
|
|
22
|
+
- Pipeline / data-source / update enrichment spans emit only on the unlock (first-init) fetch per session; later polls, force updates, and subscription enrichment skip tracing.
|
|
23
|
+
- Tracing helpers live in `utils/trace.ts` (`emitTrace` / `withTrace`); omit `trace` to no-op so call sites stay free of gating `if`s. Fast and background fetch lanes are sibling `withTrace` calls (not nested).
|
|
24
|
+
- Dashboard-facing spans (`AssetsFullFetch`, `AssetsUpdatePipeline`, `AggregatedBalanceSelector`, etc.) record `duration_ms` as a Sentry measurement (and backdate `startTime`) so Spans widgets charting `p95(duration_ms)` receive data. Nesting parents use `AssetsFetchPipeline` / `AssetsUpdateEnrichment` / `AssetsBackgroundFetch` / `AggregatedBalance`.
|
|
25
|
+
- `AggregatedBalanceSelector` is nested under an `AggregatedBalance` parent span via `parentContext`.
|
|
26
|
+
- Bump `@metamask/keyring-api` from `^23.5.0` to `^23.7.0` ([#9676](https://github.com/MetaMask/core/pull/9676))
|
|
27
|
+
- Bump `@metamask/keyring-internal-api` from `^11.0.1` to `^11.0.2` ([#9676](https://github.com/MetaMask/core/pull/9676))
|
|
28
|
+
- Bump `@metamask/keyring-snap-client` from `^9.2.0` to `^9.2.1` ([#9676](https://github.com/MetaMask/core/pull/9676))
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- `withTrace` treats a rejected parent `trace` promise as best-effort (like `emitTrace`), so Sentry/adapter failures cannot fail full fetches or `handleAssetsUpdate` enrichment ([#9672](https://github.com/MetaMask/core/pull/9672))
|
|
33
|
+
- `SnapDataSource` now delivers snap-sourced balance updates directly to `AssetsController` via a constructor-supplied `onAssetsUpdate` callback instead of fanning out to `activeSubscriptions`, so updates (e.g. Tron energy/bandwidth) are no longer dropped when no active subscription is tracked for the chain in the SnapDataSource ([#9656](https://github.com/MetaMask/core/pull/9656))
|
|
34
|
+
- Balance aggregation selectors (`getAggregatedBalanceForAccount`, `getAggregatedBalanceForAccountIds`, `calculateBalanceForAllWallets`, `calculateBalanceChangeForAccountGroup`) no longer rescale balances whose amount is greater than or equal to `10^decimals`. Amounts in `assetsBalance` state are always human-readable, so the removed raw-vs-human magnitude heuristic corrupted legitimately large balances (e.g. 54.06B tokens with 9 decimals were divided by `10^9`), excluding them from aggregated fiat totals ([#9653](https://github.com/MetaMask/core/pull/9653))
|
|
35
|
+
|
|
10
36
|
## [11.2.1]
|
|
11
37
|
|
|
12
38
|
### Fixed
|
|
@@ -783,7 +809,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
783
809
|
- Refactor `RpcDataSource` to delegate polling to `BalanceFetcher` and `TokenDetector` services ([#7709](https://github.com/MetaMask/core/pull/7709))
|
|
784
810
|
- Refactor `BalanceFetcher` and `TokenDetector` to extend `StaticIntervalPollingControllerOnly` for independent polling management ([#7709](https://github.com/MetaMask/core/pull/7709))
|
|
785
811
|
|
|
786
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@11.
|
|
812
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@11.3.0...HEAD
|
|
813
|
+
[11.3.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@11.2.1...@metamask/assets-controller@11.3.0
|
|
787
814
|
[11.2.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@11.2.0...@metamask/assets-controller@11.2.1
|
|
788
815
|
[11.2.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@11.1.1...@metamask/assets-controller@11.2.0
|
|
789
816
|
[11.1.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@11.1.0...@metamask/assets-controller@11.1.1
|
|
@@ -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_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported,
|
|
16
|
+
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_captureException, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_accountRefreshMutex, _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_customAssetGraduationMiddleware, _AssetsController_rpcFallbackMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_queryApiClient, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeNativeAssetsMap, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_onUnapprovedTransactionAdded, _AssetsController_onTransactionConfirmed, _AssetsController_onAccountActivityBalanceUpdated, _AssetsController_updateActive, _AssetsController_handleAccountTreeStateChange, _AssetsController_runAccountTreeRefresh, _AssetsController_runStartupRefresh, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _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;
|
|
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");
|
|
@@ -42,6 +42,7 @@ const constants_js_1 = require("./utils/constants.cjs");
|
|
|
42
42
|
const customAssetsRpcSupplement_js_1 = require("./utils/customAssetsRpcSupplement.cjs");
|
|
43
43
|
const index_js_1 = require("./utils/index.cjs");
|
|
44
44
|
const processAccountActivityBalanceUpdates_js_1 = require("./utils/processAccountActivityBalanceUpdates.cjs");
|
|
45
|
+
const trace_js_1 = require("./utils/trace.cjs");
|
|
45
46
|
const NATIVE_ASSETS_QUERY_KEY = ['nativeAssets'];
|
|
46
47
|
/** Stable empty map so memoized formatters are not busted by `?? {}` identity churn. */
|
|
47
48
|
const EMPTY_NATIVE_ASSET_MAP = {};
|
|
@@ -72,9 +73,14 @@ const DEFAULT_POLLING_INTERVAL_MS = 30000;
|
|
|
72
73
|
// ============================================================================
|
|
73
74
|
const TRACE_FIRST_INIT_FETCH = 'AssetsControllerFirstInitFetch';
|
|
74
75
|
const TRACE_FULL_FETCH = 'AssetsFullFetch';
|
|
76
|
+
/** Parent span that nests per-source timings; dashboard charts {@link TRACE_FULL_FETCH}. */
|
|
77
|
+
const TRACE_FETCH_PIPELINE = 'AssetsFetchPipeline';
|
|
78
|
+
const TRACE_BACKGROUND_FETCH = 'AssetsBackgroundFetch';
|
|
75
79
|
const TRACE_DATA_SOURCE_TIMING = 'AssetsDataSourceTiming';
|
|
76
80
|
const TRACE_DATA_SOURCE_ERROR = 'AssetsDataSourceError';
|
|
77
81
|
const TRACE_UPDATE_PIPELINE = 'AssetsUpdatePipeline';
|
|
82
|
+
/** Parent span that nests update enrichment; dashboard charts {@link TRACE_UPDATE_PIPELINE}. */
|
|
83
|
+
const TRACE_UPDATE_PARENT = 'AssetsUpdateEnrichment';
|
|
78
84
|
const TRACE_SUBSCRIPTION_ERROR = 'AssetsSubscriptionError';
|
|
79
85
|
const TRACE_STATE_SIZE = 'AssetsStateSize';
|
|
80
86
|
const log = (0, logger_js_1.createModuleLogger)(logger_js_1.projectLogger, CONTROLLER_NAME);
|
|
@@ -366,6 +372,7 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
366
372
|
__classPrivateFieldSet(this, _AssetsController_snapDataSource, new SnapDataSource_js_1.SnapDataSource({
|
|
367
373
|
messenger: this.messenger,
|
|
368
374
|
onActiveChainsUpdated: __classPrivateFieldGet(this, _AssetsController_onActiveChainsUpdated, "f"),
|
|
375
|
+
onAssetsUpdate: (response) => this.handleAssetsUpdate(response, 'SnapDataSource'),
|
|
369
376
|
}), "f");
|
|
370
377
|
__classPrivateFieldSet(this, _AssetsController_rpcDataSource, new RpcDataSource_js_1.RpcDataSource({
|
|
371
378
|
messenger: this.messenger,
|
|
@@ -455,7 +462,11 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
455
462
|
customAssets.push(...accountCustomAssets);
|
|
456
463
|
}
|
|
457
464
|
if (options?.forceUpdate) {
|
|
458
|
-
|
|
465
|
+
// Pipeline spans only on unlock/first-init fetch; later forceUpdates pass
|
|
466
|
+
// `undefined` so `emitTrace` / `withTrace` no-op without call-site if/else.
|
|
467
|
+
const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
|
|
468
|
+
? undefined
|
|
469
|
+
: __classPrivateFieldGet(this, _AssetsController_trace, "f");
|
|
459
470
|
const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
|
|
460
471
|
assetTypes,
|
|
461
472
|
dataTypes,
|
|
@@ -489,59 +500,101 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
489
500
|
]),
|
|
490
501
|
]
|
|
491
502
|
: [__classPrivateFieldGet(this, _AssetsController_stakedBalanceDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f")];
|
|
492
|
-
const { response
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
503
|
+
const { response } = await (0, trace_js_1.withTrace)({
|
|
504
|
+
name: TRACE_FETCH_PIPELINE,
|
|
505
|
+
trace: pipelineTrace,
|
|
506
|
+
data: {
|
|
507
|
+
chain_count: chainIds.length,
|
|
508
|
+
account_count: accounts.length,
|
|
509
|
+
basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
|
|
510
|
+
},
|
|
511
|
+
fn: async (parentContext) => {
|
|
512
|
+
const startTime = performance.now();
|
|
513
|
+
const result = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
|
|
514
|
+
sources: fastSources,
|
|
515
|
+
request,
|
|
516
|
+
parentContext,
|
|
517
|
+
trace: pipelineTrace,
|
|
518
|
+
});
|
|
519
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
520
|
+
...result.response,
|
|
521
|
+
updateMode: 'merge',
|
|
522
|
+
replaceCoveredChainBalances: true,
|
|
523
|
+
});
|
|
524
|
+
const durationMs = performance.now() - startTime;
|
|
525
|
+
// Summary fields for Assets Health (nested under the parent span).
|
|
526
|
+
(0, trace_js_1.emitTrace)({
|
|
527
|
+
name: TRACE_FULL_FETCH,
|
|
528
|
+
trace: pipelineTrace,
|
|
529
|
+
data: {
|
|
530
|
+
duration_ms: durationMs,
|
|
531
|
+
chain_count: chainIds.length,
|
|
532
|
+
account_count: accounts.length,
|
|
533
|
+
basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
|
|
534
|
+
asset_count: result.response.assetsBalance
|
|
535
|
+
? Object.values(result.response.assetsBalance).reduce((sum, acct) => sum + Object.keys(acct).length, 0)
|
|
536
|
+
: 0,
|
|
537
|
+
price_count: result.response.assetsPrice
|
|
538
|
+
? Object.keys(result.response.assetsPrice).length
|
|
539
|
+
: 0,
|
|
540
|
+
...result.durationByDataSource,
|
|
541
|
+
},
|
|
542
|
+
parentContext,
|
|
543
|
+
});
|
|
544
|
+
(0, trace_js_1.emitTrace)({
|
|
545
|
+
name: TRACE_FIRST_INIT_FETCH,
|
|
546
|
+
trace: pipelineTrace,
|
|
547
|
+
data: {
|
|
548
|
+
duration_ms: durationMs,
|
|
549
|
+
chain_ids: JSON.stringify(chainIds),
|
|
550
|
+
...result.durationByDataSource,
|
|
551
|
+
},
|
|
552
|
+
parentContext,
|
|
553
|
+
});
|
|
554
|
+
return result;
|
|
555
|
+
},
|
|
497
556
|
});
|
|
498
|
-
//
|
|
499
|
-
|
|
500
|
-
//
|
|
501
|
-
//
|
|
557
|
+
// Mark after the unlock/first forceUpdate so later polls skip pipeline spans.
|
|
558
|
+
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
|
|
559
|
+
// Background (slow) lane — flattened sibling of the fast lane (not nested
|
|
560
|
+
// inside its withTrace callback). Still fire-and-forget so UI is not blocked.
|
|
502
561
|
const slowPipelineChainIds = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getSlowPipelineChainIds).call(this, chainIds, response);
|
|
503
562
|
if (slowPipelineChainIds.length > 0) {
|
|
504
563
|
const slowSources = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
505
564
|
? [__classPrivateFieldGet(this, _AssetsController_snapDataSource, "f"), __classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")]
|
|
506
565
|
: [__classPrivateFieldGet(this, _AssetsController_rpcDataSource, "f")];
|
|
507
566
|
const slowRequest = { ...request, chainIds: slowPipelineChainIds };
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
|
|
540
|
-
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_FIRST_INIT_FETCH, {
|
|
541
|
-
duration_ms: durationMs,
|
|
542
|
-
chain_ids: JSON.stringify(chainIds),
|
|
543
|
-
...durationByDataSource,
|
|
544
|
-
});
|
|
567
|
+
(0, trace_js_1.withTrace)({
|
|
568
|
+
name: TRACE_BACKGROUND_FETCH,
|
|
569
|
+
trace: pipelineTrace,
|
|
570
|
+
data: {
|
|
571
|
+
chain_count: slowPipelineChainIds.length,
|
|
572
|
+
account_count: accounts.length,
|
|
573
|
+
},
|
|
574
|
+
fn: async (slowParentContext) => {
|
|
575
|
+
const { response: slowResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
|
|
576
|
+
sources: [
|
|
577
|
+
(0, ParallelMiddleware_js_1.createParallelBalanceMiddleware)(slowSources),
|
|
578
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
579
|
+
...(__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
580
|
+
? [
|
|
581
|
+
(0, ParallelMiddleware_js_1.createParallelMiddleware)([
|
|
582
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
583
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
584
|
+
]),
|
|
585
|
+
]
|
|
586
|
+
: []),
|
|
587
|
+
],
|
|
588
|
+
request: slowRequest,
|
|
589
|
+
parentContext: slowParentContext,
|
|
590
|
+
trace: pipelineTrace,
|
|
591
|
+
});
|
|
592
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
593
|
+
...slowResponse,
|
|
594
|
+
updateMode: 'merge',
|
|
595
|
+
});
|
|
596
|
+
},
|
|
597
|
+
}).catch((error) => log('Background pipeline failed', { error }));
|
|
545
598
|
}
|
|
546
599
|
}
|
|
547
600
|
const result = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
|
|
@@ -921,57 +974,87 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
921
974
|
* @param request - Optional original request for context when enriching
|
|
922
975
|
*/
|
|
923
976
|
async handleAssetsUpdate(response, sourceId, request) {
|
|
924
|
-
const updateStart = performance.now();
|
|
925
977
|
log('Assets updated from data source', {
|
|
926
978
|
sourceId,
|
|
927
979
|
hasBalance: Boolean(response.assetsBalance),
|
|
928
980
|
hasPrice: Boolean(response.assetsPrice),
|
|
929
981
|
});
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
:
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
982
|
+
// Enrichment spans only before unlock/first-init fetch completes.
|
|
983
|
+
const pipelineTrace = __classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")
|
|
984
|
+
? undefined
|
|
985
|
+
: __classPrivateFieldGet(this, _AssetsController_trace, "f");
|
|
986
|
+
await (0, trace_js_1.withTrace)({
|
|
987
|
+
name: TRACE_UPDATE_PARENT,
|
|
988
|
+
trace: pipelineTrace,
|
|
989
|
+
data: {
|
|
990
|
+
source: sourceId,
|
|
991
|
+
has_balance: Boolean(response.assetsBalance),
|
|
992
|
+
has_price: Boolean(response.assetsPrice),
|
|
993
|
+
balance_account_count: response.assetsBalance
|
|
994
|
+
? Object.keys(response.assetsBalance).length
|
|
995
|
+
: 0,
|
|
996
|
+
},
|
|
997
|
+
fn: async (parentContext) => {
|
|
998
|
+
const updateStart = performance.now();
|
|
999
|
+
const resolvedRequest = request ?? {
|
|
1000
|
+
accountsWithSupportedChains: [],
|
|
1001
|
+
chainIds: [],
|
|
1002
|
+
dataTypes: ['balance', 'metadata', 'price'],
|
|
1003
|
+
};
|
|
1004
|
+
// RPC-only mode (basic functionality off): never run token/price APIs. Strip
|
|
1005
|
+
// those data types so downstream middleware cannot treat them as requested.
|
|
1006
|
+
const pipelineRequest = __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)
|
|
1007
|
+
? resolvedRequest
|
|
1008
|
+
: {
|
|
1009
|
+
...resolvedRequest,
|
|
1010
|
+
dataTypes: resolvedRequest.dataTypes.filter((dt) => dt !== 'metadata' && dt !== 'price'),
|
|
1011
|
+
};
|
|
1012
|
+
// Graduate custom assets only when AccountsAPI / Websocket reports them.
|
|
1013
|
+
// RPC already fetches custom assets on purpose, and Snap handles non-EVM
|
|
1014
|
+
// chains the rule does not apply to, so skip the middleware for those.
|
|
1015
|
+
const shouldGraduateCustomAssets = sourceId === 'AccountsApiDataSource' ||
|
|
1016
|
+
sourceId === 'BackendWebsocketDataSource' ||
|
|
1017
|
+
sourceId === 'AccountActivityService';
|
|
1018
|
+
const enrichmentSources = [
|
|
1019
|
+
...(shouldGraduateCustomAssets
|
|
1020
|
+
? [__classPrivateFieldGet(this, _AssetsController_customAssetGraduationMiddleware, "f")]
|
|
1021
|
+
: []),
|
|
1022
|
+
__classPrivateFieldGet(this, _AssetsController_detectionMiddleware, "f"),
|
|
1023
|
+
];
|
|
1024
|
+
if (__classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this)) {
|
|
1025
|
+
enrichmentSources.push((0, ParallelMiddleware_js_1.createParallelMiddleware)([
|
|
1026
|
+
__classPrivateFieldGet(this, _AssetsController_tokenDataSource, "f"),
|
|
1027
|
+
__classPrivateFieldGet(this, _AssetsController_priceDataSource, "f"),
|
|
1028
|
+
]));
|
|
1029
|
+
}
|
|
1030
|
+
const { response: enrichedResponse } = await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_executeMiddlewares).call(this, {
|
|
1031
|
+
sources: enrichmentSources,
|
|
1032
|
+
request: pipelineRequest,
|
|
1033
|
+
initialResponse: response,
|
|
1034
|
+
parentContext,
|
|
1035
|
+
trace: pipelineTrace,
|
|
1036
|
+
});
|
|
1037
|
+
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, {
|
|
1038
|
+
...enrichedResponse,
|
|
1039
|
+
replaceCoveredChainBalances: response.replaceCoveredChainBalances,
|
|
1040
|
+
});
|
|
1041
|
+
// Summary fields for Assets Health (nested under the parent span).
|
|
1042
|
+
(0, trace_js_1.emitTrace)({
|
|
1043
|
+
name: TRACE_UPDATE_PIPELINE,
|
|
1044
|
+
trace: pipelineTrace,
|
|
1045
|
+
data: {
|
|
1046
|
+
source: sourceId,
|
|
1047
|
+
duration_ms: performance.now() - updateStart,
|
|
1048
|
+
has_balance: Boolean(response.assetsBalance),
|
|
1049
|
+
has_price: Boolean(response.assetsPrice),
|
|
1050
|
+
has_metadata: Boolean(enrichedResponse.assetsInfo),
|
|
1051
|
+
balance_account_count: response.assetsBalance
|
|
1052
|
+
? Object.keys(response.assetsBalance).length
|
|
1053
|
+
: 0,
|
|
1054
|
+
},
|
|
1055
|
+
parentContext,
|
|
1056
|
+
});
|
|
1057
|
+
},
|
|
975
1058
|
});
|
|
976
1059
|
}
|
|
977
1060
|
// ============================================================================
|
|
@@ -1011,16 +1094,7 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
1011
1094
|
}
|
|
1012
1095
|
}
|
|
1013
1096
|
exports.AssetsController = AssetsController;
|
|
1014
|
-
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_captureException = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_accountRefreshMutex = 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_customAssetGraduationMiddleware = new WeakMap(), _AssetsController_rpcFallbackMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_queryApiClient = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(),
|
|
1015
|
-
controller: 'AssetsController',
|
|
1016
|
-
}) {
|
|
1017
|
-
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
__classPrivateFieldGet(this, _AssetsController_trace, "f").call(this, { name, data, tags }, () => undefined)?.catch(() => {
|
|
1021
|
-
// Telemetry failure must not break.
|
|
1022
|
-
});
|
|
1023
|
-
}, _AssetsController_emitStateSizeTrace = function _AssetsController_emitStateSizeTrace() {
|
|
1097
|
+
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_captureException = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_accountRefreshMutex = 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_customAssetGraduationMiddleware = new WeakMap(), _AssetsController_rpcFallbackMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_queryApiClient = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_emitStateSizeTrace = function _AssetsController_emitStateSizeTrace() {
|
|
1024
1098
|
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f") || __classPrivateFieldGet(this, _AssetsController_stateSizeReported, "f")) {
|
|
1025
1099
|
return;
|
|
1026
1100
|
}
|
|
@@ -1048,14 +1122,20 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
|
|
|
1048
1122
|
customAssetEntries += ids.length;
|
|
1049
1123
|
}
|
|
1050
1124
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1125
|
+
(0, trace_js_1.emitTrace)({
|
|
1126
|
+
name: TRACE_STATE_SIZE,
|
|
1127
|
+
trace: __classPrivateFieldGet(this, _AssetsController_trace, "f"),
|
|
1128
|
+
data: {
|
|
1129
|
+
balance_entries: balanceEntries,
|
|
1130
|
+
balance_accounts: Object.keys(balances).length,
|
|
1131
|
+
// `asset_count` matches the Assets Health dashboard widget field name.
|
|
1132
|
+
asset_count: uniqueAssets.size,
|
|
1133
|
+
unique_asset_count: uniqueAssets.size,
|
|
1134
|
+
network_count: uniqueNetworks.size,
|
|
1135
|
+
metadata_entries: Object.keys(assetsInfo).length,
|
|
1136
|
+
price_entries: Object.keys(assetsPrice).length,
|
|
1137
|
+
custom_asset_entries: customAssetEntries,
|
|
1138
|
+
},
|
|
1059
1139
|
});
|
|
1060
1140
|
}, _AssetsController_getSelectedAccounts = function _AssetsController_getSelectedAccounts() {
|
|
1061
1141
|
const accounts = this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
|
|
@@ -1380,12 +1460,16 @@ async function _AssetsController_runStartupRefresh(accounts) {
|
|
|
1380
1460
|
* Execute middlewares with request/response context.
|
|
1381
1461
|
* Returns response and exclusive duration per source (sum ≈ wall time).
|
|
1382
1462
|
*
|
|
1383
|
-
* @param
|
|
1384
|
-
* @param
|
|
1385
|
-
* @param
|
|
1463
|
+
* @param params - Middleware execution options.
|
|
1464
|
+
* @param params.sources - Data sources or middlewares with getName() and assetsMiddleware.
|
|
1465
|
+
* @param params.request - The data request.
|
|
1466
|
+
* @param params.initialResponse - Optional initial response (for enriching existing data).
|
|
1467
|
+
* @param params.parentContext - Optional parent Sentry span; per-source timings nest under it.
|
|
1468
|
+
* @param params.trace - Optional trace callback; omit after unlock/first-init to skip spans.
|
|
1386
1469
|
* @returns Response and durationByDataSource (exclusive ms per source name).
|
|
1387
1470
|
*/
|
|
1388
|
-
async function _AssetsController_executeMiddlewares(
|
|
1471
|
+
async function _AssetsController_executeMiddlewares(params) {
|
|
1472
|
+
const { sources, request, initialResponse = {}, parentContext, trace, } = params;
|
|
1389
1473
|
const names = sources.map((source) => source.getName());
|
|
1390
1474
|
const middlewares = sources.map((source) => source.assetsMiddleware);
|
|
1391
1475
|
const inclusive = [];
|
|
@@ -1429,13 +1513,24 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1429
1513
|
durationByDataSource[key] = ms;
|
|
1430
1514
|
}
|
|
1431
1515
|
}
|
|
1432
|
-
// Emit per-source timing
|
|
1516
|
+
// Emit per-source timing as subspans under the parent fetch/update span
|
|
1517
|
+
// (no-op when `trace` is omitted — unlock/first-init only).
|
|
1433
1518
|
for (const [sourceName, durationMs] of Object.entries(durationByDataSource)) {
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1519
|
+
(0, trace_js_1.emitTrace)({
|
|
1520
|
+
name: TRACE_DATA_SOURCE_TIMING,
|
|
1521
|
+
trace,
|
|
1522
|
+
data: {
|
|
1523
|
+
source: sourceName,
|
|
1524
|
+
duration_ms: durationMs,
|
|
1525
|
+
chain_count: request.chainIds.length,
|
|
1526
|
+
account_count: request.accountsWithSupportedChains.length,
|
|
1527
|
+
},
|
|
1528
|
+
tags: {
|
|
1529
|
+
controller: 'AssetsController',
|
|
1530
|
+
// String tag so Spans widgets can group by `source`.
|
|
1531
|
+
source: sourceName,
|
|
1532
|
+
},
|
|
1533
|
+
parentContext,
|
|
1439
1534
|
});
|
|
1440
1535
|
}
|
|
1441
1536
|
// Failed middlewares: Issues (optional) + perf/Dashboard spans
|
|
@@ -1452,14 +1547,20 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1452
1547
|
catch {
|
|
1453
1548
|
// Never let telemetry throw.
|
|
1454
1549
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1550
|
+
(0, trace_js_1.emitTrace)({
|
|
1551
|
+
name: TRACE_DATA_SOURCE_ERROR,
|
|
1552
|
+
trace,
|
|
1553
|
+
data: {
|
|
1554
|
+
failed_sources: failedSources,
|
|
1555
|
+
error_count: middlewareErrors.length,
|
|
1556
|
+
chain_count: request.chainIds.length,
|
|
1557
|
+
},
|
|
1558
|
+
tags: {
|
|
1559
|
+
controller: 'AssetsController',
|
|
1560
|
+
severity: 'error',
|
|
1561
|
+
error_type: assetsError.name,
|
|
1562
|
+
},
|
|
1563
|
+
parentContext,
|
|
1463
1564
|
});
|
|
1464
1565
|
}
|
|
1465
1566
|
return { response: result.response, durationByDataSource };
|
|
@@ -2081,9 +2182,13 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
2081
2182
|
};
|
|
2082
2183
|
source.subscribe(subscribeReq).catch((error) => {
|
|
2083
2184
|
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2185
|
+
(0, trace_js_1.emitTrace)({
|
|
2186
|
+
name: TRACE_SUBSCRIPTION_ERROR,
|
|
2187
|
+
trace: __classPrivateFieldGet(this, _AssetsController_trace, "f"),
|
|
2188
|
+
data: {
|
|
2189
|
+
source: sourceId,
|
|
2190
|
+
error_message: String(error),
|
|
2191
|
+
},
|
|
2087
2192
|
});
|
|
2088
2193
|
});
|
|
2089
2194
|
// Track subscription
|