@metamask-previews/assets-controller 3.1.1-preview-17c76be24 → 3.1.1-preview-dbd93752f
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 +12 -0
- package/dist/AssetsController.cjs +101 -19
- 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 +101 -19
- package/dist/AssetsController.mjs.map +1 -1
- package/dist/selectors/balance.cjs +27 -1
- package/dist/selectors/balance.cjs.map +1 -1
- package/dist/selectors/balance.d.cts +2 -1
- package/dist/selectors/balance.d.cts.map +1 -1
- package/dist/selectors/balance.d.mts +2 -1
- package/dist/selectors/balance.d.mts.map +1 -1
- package/dist/selectors/balance.mjs +27 -1
- package/dist/selectors/balance.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Add Sentry traces for Assets Health dashboard ([#8310](https://github.com/MetaMask/core/pull/8310))
|
|
13
|
+
- `Assets Data Source Timing` — per-source latency for each middleware in the fetch pipeline
|
|
14
|
+
- `Assets Data Source Error` — tracks middleware failures with source names and error counts
|
|
15
|
+
- `Assets Full Fetch` — end-to-end fetch timing with asset/price/chain/account counts
|
|
16
|
+
- `Assets Update Pipeline` — enrichment pipeline timing for pushed data source updates
|
|
17
|
+
- `Assets Subscription Error` — subscription failure tracking per data source
|
|
18
|
+
- `Assets State Size` — entry counts for balances, metadata, prices, and custom assets (once on app start)
|
|
19
|
+
- `Aggregated Balance Selector` — balance selector computation time with asset/network/account counts
|
|
20
|
+
- Add optional `trace` parameter to `getAggregatedBalanceForAccount` selector
|
|
21
|
+
|
|
10
22
|
### Changed
|
|
11
23
|
|
|
12
24
|
- Bump `@metamask/transaction-controller` from `^63.1.0` to `^63.2.0` ([#8301](https://github.com/MetaMask/core/pull/8301))
|
|
@@ -13,7 +13,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_firstInitFetchReported, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_updateActive, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
|
|
16
|
+
var _AssetsController_instances, _AssetsController_isEnabled, _AssetsController_isBasicFunctionality, _AssetsController_defaultUpdateInterval, _AssetsController_trace, _AssetsController_firstInitFetchReported, _AssetsController_stateSizeReported, _AssetsController_emitTrace, _AssetsController_emitStateSizeTrace, _AssetsController_uiOpen, _AssetsController_keyringUnlocked, _AssetsController_controllerMutex, _AssetsController_activeSubscriptions, _AssetsController_enabledChains, _AssetsController_selectedAccounts_get, _AssetsController_backendWebsocketDataSource, _AssetsController_accountsApiDataSource, _AssetsController_snapDataSource, _AssetsController_rpcDataSource, _AssetsController_stakedBalanceDataSource, _AssetsController_allBalanceDataSources_get, _AssetsController_priceDataSource, _AssetsController_detectionMiddleware, _AssetsController_tokenDataSource, _AssetsController_unsubscribeBasicFunctionality, _AssetsController_onActiveChainsUpdated, _AssetsController_initializeState, _AssetsController_extractEnabledChains, _AssetsController_normalizeChainReference, _AssetsController_subscribeToEvents, _AssetsController_updateActive, _AssetsController_registerActionHandlers, _AssetsController_handleActiveChainsUpdate, _AssetsController_executeMiddlewares, _AssetsController_resolveNativeAssetIds, _AssetsController_getNativeAssetIdsForEnabledChains, _AssetsController_getNativeAssetIdsForAccount, _AssetsController_ensureNativeBalancesDefaultZero, _AssetsController_updateState, _AssetsController_getAssetsFromState, _AssetsController_tokenStandardToAssetType, _AssetsController_start, _AssetsController_stop, _AssetsController_subscribeAssets, _AssetsController_subscribeAssetsBalance, _AssetsController_subscribeStakedBalance, _AssetsController_buildChainToAccountsMap, _AssetsController_subscribeDataSource, _AssetsController_unsubscribeDataSource, _AssetsController_buildDataRequest, _AssetsController_getEnabledChainsForAccount, _AssetsController_handleAccountGroupChanged, _AssetsController_handleEnabledNetworksChanged;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.AssetsController = exports.getDefaultAssetsControllerState = void 0;
|
|
19
19
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -220,6 +220,8 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
220
220
|
_AssetsController_trace.set(this, void 0);
|
|
221
221
|
/** Whether we have already reported first init fetch for this session (reset on #stop). */
|
|
222
222
|
_AssetsController_firstInitFetchReported.set(this, false);
|
|
223
|
+
/** Whether we have already reported state size for this session (reset on #stop). */
|
|
224
|
+
_AssetsController_stateSizeReported.set(this, false);
|
|
223
225
|
/** Whether the client (UI) is open. Combined with #keyringUnlocked for #updateActive. */
|
|
224
226
|
_AssetsController_uiOpen.set(this, false);
|
|
225
227
|
/** Whether the keyring is unlocked. Combined with #uiOpen for #updateActive. */
|
|
@@ -369,23 +371,28 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
369
371
|
options.chainIds.length < __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size;
|
|
370
372
|
const updateMode = options?.updateMode ?? (isPartialChainFetch ? 'merge' : 'full');
|
|
371
373
|
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, { ...response, updateMode });
|
|
372
|
-
|
|
374
|
+
const durationMs = Date.now() - startTime;
|
|
375
|
+
// Emit trace for every full fetch (Assets Health dashboard)
|
|
376
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'Assets Full Fetch', {
|
|
377
|
+
duration_ms: durationMs,
|
|
378
|
+
chain_count: chainIds.length,
|
|
379
|
+
account_count: accounts.length,
|
|
380
|
+
basic_functionality: __classPrivateFieldGet(this, _AssetsController_isBasicFunctionality, "f").call(this),
|
|
381
|
+
asset_count: response.assetsBalance
|
|
382
|
+
? Object.values(response.assetsBalance).reduce((sum, acct) => sum + Object.keys(acct).length, 0)
|
|
383
|
+
: 0,
|
|
384
|
+
price_count: response.assetsPrice
|
|
385
|
+
? Object.keys(response.assetsPrice).length
|
|
386
|
+
: 0,
|
|
387
|
+
...durationByDataSource,
|
|
388
|
+
});
|
|
389
|
+
if (!__classPrivateFieldGet(this, _AssetsController_firstInitFetchReported, "f")) {
|
|
373
390
|
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, true, "f");
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
duration_ms: durationMs,
|
|
380
|
-
chain_ids: JSON.stringify(chainIds),
|
|
381
|
-
...durationByDataSource,
|
|
382
|
-
},
|
|
383
|
-
tags: { controller: 'AssetsController' },
|
|
384
|
-
}, () => undefined);
|
|
385
|
-
}
|
|
386
|
-
catch {
|
|
387
|
-
// Telemetry failure must not break.
|
|
388
|
-
}
|
|
391
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'AssetsController First Init Fetch', {
|
|
392
|
+
duration_ms: durationMs,
|
|
393
|
+
chain_ids: JSON.stringify(chainIds),
|
|
394
|
+
...durationByDataSource,
|
|
395
|
+
});
|
|
389
396
|
}
|
|
390
397
|
}
|
|
391
398
|
const result = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_getAssetsFromState).call(this, accounts, chainIds, assetTypes);
|
|
@@ -711,6 +718,7 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
711
718
|
* @param request - Optional original request for context when enriching
|
|
712
719
|
*/
|
|
713
720
|
async handleAssetsUpdate(response, sourceId, request) {
|
|
721
|
+
const updateStart = Date.now();
|
|
714
722
|
log('Assets updated from data source', {
|
|
715
723
|
sourceId,
|
|
716
724
|
hasBalance: Boolean(response.assetsBalance),
|
|
@@ -730,6 +738,16 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
730
738
|
dataTypes: ['balance', 'metadata', 'price'],
|
|
731
739
|
}, response);
|
|
732
740
|
await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
|
|
741
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'Assets Update Pipeline', {
|
|
742
|
+
source: sourceId,
|
|
743
|
+
duration_ms: Date.now() - updateStart,
|
|
744
|
+
has_balance: Boolean(response.assetsBalance),
|
|
745
|
+
has_price: Boolean(response.assetsPrice),
|
|
746
|
+
has_metadata: Boolean(enrichedResponse.assetsInfo),
|
|
747
|
+
balance_account_count: response.assetsBalance
|
|
748
|
+
? Object.keys(response.assetsBalance).length
|
|
749
|
+
: 0,
|
|
750
|
+
});
|
|
733
751
|
}
|
|
734
752
|
// ============================================================================
|
|
735
753
|
// CLEANUP
|
|
@@ -766,7 +784,44 @@ class AssetsController extends base_controller_1.BaseController {
|
|
|
766
784
|
}
|
|
767
785
|
}
|
|
768
786
|
exports.AssetsController = AssetsController;
|
|
769
|
-
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(),
|
|
787
|
+
_AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctionality = new WeakMap(), _AssetsController_defaultUpdateInterval = new WeakMap(), _AssetsController_trace = new WeakMap(), _AssetsController_firstInitFetchReported = new WeakMap(), _AssetsController_stateSizeReported = new WeakMap(), _AssetsController_uiOpen = new WeakMap(), _AssetsController_keyringUnlocked = new WeakMap(), _AssetsController_controllerMutex = new WeakMap(), _AssetsController_activeSubscriptions = new WeakMap(), _AssetsController_enabledChains = new WeakMap(), _AssetsController_backendWebsocketDataSource = new WeakMap(), _AssetsController_accountsApiDataSource = new WeakMap(), _AssetsController_snapDataSource = new WeakMap(), _AssetsController_rpcDataSource = new WeakMap(), _AssetsController_stakedBalanceDataSource = new WeakMap(), _AssetsController_priceDataSource = new WeakMap(), _AssetsController_detectionMiddleware = new WeakMap(), _AssetsController_tokenDataSource = new WeakMap(), _AssetsController_unsubscribeBasicFunctionality = new WeakMap(), _AssetsController_onActiveChainsUpdated = new WeakMap(), _AssetsController_instances = new WeakSet(), _AssetsController_emitTrace = function _AssetsController_emitTrace(name, data, tags = {
|
|
788
|
+
controller: 'AssetsController',
|
|
789
|
+
}) {
|
|
790
|
+
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
try {
|
|
794
|
+
__classPrivateFieldGet(this, _AssetsController_trace, "f").call(this, { name, data, tags }, () => undefined).catch(() => {
|
|
795
|
+
// Telemetry failure must not break.
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
catch {
|
|
799
|
+
// Telemetry failure must not break.
|
|
800
|
+
}
|
|
801
|
+
}, _AssetsController_emitStateSizeTrace = function _AssetsController_emitStateSizeTrace() {
|
|
802
|
+
if (!__classPrivateFieldGet(this, _AssetsController_trace, "f") || __classPrivateFieldGet(this, _AssetsController_stateSizeReported, "f")) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
__classPrivateFieldSet(this, _AssetsController_stateSizeReported, true, "f");
|
|
806
|
+
const { assetsBalance: balances, customAssets, assetsInfo, assetsPrice, } = this.state;
|
|
807
|
+
let balanceEntries = 0;
|
|
808
|
+
for (const acct of Object.values(balances)) {
|
|
809
|
+
balanceEntries += Object.keys(acct).length;
|
|
810
|
+
}
|
|
811
|
+
let customAssetEntries = 0;
|
|
812
|
+
for (const ids of Object.values(customAssets)) {
|
|
813
|
+
if (Array.isArray(ids)) {
|
|
814
|
+
customAssetEntries += ids.length;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'Assets State Size', {
|
|
818
|
+
balance_entries: balanceEntries,
|
|
819
|
+
balance_accounts: Object.keys(balances).length,
|
|
820
|
+
metadata_entries: Object.keys(assetsInfo).length,
|
|
821
|
+
price_entries: Object.keys(assetsPrice).length,
|
|
822
|
+
custom_asset_entries: customAssetEntries,
|
|
823
|
+
});
|
|
824
|
+
}, _AssetsController_selectedAccounts_get = function _AssetsController_selectedAccounts_get() {
|
|
770
825
|
return this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup');
|
|
771
826
|
}, _AssetsController_allBalanceDataSources_get = function _AssetsController_allBalanceDataSources_get() {
|
|
772
827
|
return [
|
|
@@ -896,11 +951,14 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
896
951
|
inclusive[i] = Date.now() - start;
|
|
897
952
|
}
|
|
898
953
|
}));
|
|
899
|
-
const
|
|
954
|
+
const middlewareErrors = [];
|
|
955
|
+
const chain = wrapped.reduceRight((next, middleware, index) => async (ctx) => {
|
|
900
956
|
try {
|
|
901
957
|
return await middleware(ctx, next);
|
|
902
958
|
}
|
|
903
959
|
catch (error) {
|
|
960
|
+
const sourceName = names[index] ?? `middleware_${index}`;
|
|
961
|
+
middlewareErrors.push(sourceName);
|
|
904
962
|
console.error('[AssetsController] Middleware failed:', error);
|
|
905
963
|
return next(ctx);
|
|
906
964
|
}
|
|
@@ -924,6 +982,23 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
924
982
|
durationByDataSource[key] = ms;
|
|
925
983
|
}
|
|
926
984
|
}
|
|
985
|
+
// Emit per-source timing traces for the Assets Health dashboard
|
|
986
|
+
for (const [sourceName, durationMs] of Object.entries(durationByDataSource)) {
|
|
987
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'Assets Data Source Timing', {
|
|
988
|
+
source: sourceName,
|
|
989
|
+
duration_ms: durationMs,
|
|
990
|
+
chain_count: request.chainIds.length,
|
|
991
|
+
account_count: request.accountsWithSupportedChains.length,
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
// Emit error traces for failed middlewares
|
|
995
|
+
if (middlewareErrors.length > 0) {
|
|
996
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'Assets Data Source Error', {
|
|
997
|
+
failed_sources: middlewareErrors.join(','),
|
|
998
|
+
error_count: middlewareErrors.length,
|
|
999
|
+
chain_count: request.chainIds.length,
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
927
1002
|
return { response: result.response, durationByDataSource };
|
|
928
1003
|
}, _AssetsController_resolveNativeAssetIds = function _AssetsController_resolveNativeAssetIds(chains) {
|
|
929
1004
|
const { nativeAssetIdentifiers } = this.messenger.call('NetworkEnablementController:getState');
|
|
@@ -1064,6 +1139,8 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1064
1139
|
}
|
|
1065
1140
|
}
|
|
1066
1141
|
});
|
|
1142
|
+
// Emit state size trace (throttled to avoid JSON.stringify on every update)
|
|
1143
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitStateSizeTrace).call(this);
|
|
1067
1144
|
// Calculate changed prices
|
|
1068
1145
|
const changedPriceAssets = normalizedResponse.assetsPrice
|
|
1069
1146
|
? Object.keys(normalizedResponse.assetsPrice).filter((assetId) => !(0, lodash_1.isEqual)(previousPrices[assetId], normalizedResponse.assetsPrice?.[assetId]))
|
|
@@ -1211,6 +1288,7 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1211
1288
|
hasPriceSubscription: __classPrivateFieldGet(this, _AssetsController_activeSubscriptions, "f").has('ds:PriceDataSource'),
|
|
1212
1289
|
});
|
|
1213
1290
|
__classPrivateFieldSet(this, _AssetsController_firstInitFetchReported, false, "f");
|
|
1291
|
+
__classPrivateFieldSet(this, _AssetsController_stateSizeReported, false, "f");
|
|
1214
1292
|
// Stop price subscription first (uses direct messenger call)
|
|
1215
1293
|
this.unsubscribeAssetsPrice();
|
|
1216
1294
|
// Stop balance subscriptions by properly notifying data sources via messenger
|
|
@@ -1327,6 +1405,10 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
|
|
|
1327
1405
|
};
|
|
1328
1406
|
source.subscribe(subscribeReq).catch((error) => {
|
|
1329
1407
|
console.error(`[AssetsController] Failed to subscribe to '${sourceId}':`, error);
|
|
1408
|
+
__classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, 'Assets Subscription Error', {
|
|
1409
|
+
source: sourceId,
|
|
1410
|
+
error_message: String(error),
|
|
1411
|
+
});
|
|
1330
1412
|
});
|
|
1331
1413
|
// Track subscription
|
|
1332
1414
|
const subscription = {
|