@metamask-previews/assets-controller 3.1.1-preview-55f19615e → 3.2.0-preview-4f74a56

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 CHANGED
@@ -7,21 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.2.0]
11
+
10
12
  ### Added
11
13
 
12
14
  - 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
15
+ - `AssetsDataSourceTiming` — per-source latency for each middleware in the fetch pipeline
16
+ - `AssetsDataSourceError` — tracks middleware failures with source names and error counts
17
+ - `AssetsFullFetch` — end-to-end fetch timing with asset/price/chain/account counts
18
+ - `AssetsUpdatePipeline` — enrichment pipeline timing for pushed data source updates
19
+ - `AssetsSubscriptionError` — subscription failure tracking per data source
20
+ - `AssetsStateSize` — entry counts for balances, metadata, prices, custom assets, unique assets, and network count (once on app start)
21
+ - `AggregatedBalanceSelector` — balance selector computation time with asset/network/account counts
20
22
  - Add optional `trace` parameter to `getAggregatedBalanceForAccount` selector
21
23
 
22
24
  ### Changed
23
25
 
24
- - Bump `@metamask/transaction-controller` from `^63.1.0` to `^63.2.0` ([#8301](https://github.com/MetaMask/core/pull/8301))
26
+ - Bump `@metamask/account-tree-controller` from `^5.0.1` to `^6.0.0` ([#8317](https://github.com/MetaMask/core/pull/8317))
27
+ - Bump `@metamask/assets-controllers` from `^101.0.1` to `^102.0.0` ([#8317](https://github.com/MetaMask/core/pull/8317))
28
+ - Bump `@metamask/base-controller` from `^9.0.0` to `^9.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
29
+ - Bump `@metamask/client-controller` from `^1.0.0` to `^1.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
30
+ - Bump `@metamask/core-backend` from `^6.2.0` to `^6.2.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
31
+ - Bump `@metamask/keyring-controller` from `^25.1.0` to `^25.1.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
32
+ - Bump `@metamask/messenger` from `^0.3.0` to `^1.0.0` ([#8317](https://github.com/MetaMask/core/pull/8317))
33
+ - Bump `@metamask/network-controller` from `^30.0.0` to `^30.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
34
+ - Bump `@metamask/network-enablement-controller` from `^5.0.0` to `^5.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
35
+ - Bump `@metamask/permission-controller` from `^12.2.1` to `^12.3.0` ([#8317](https://github.com/MetaMask/core/pull/8317))
36
+ - Bump `@metamask/polling-controller` from `^16.0.3` to `^16.0.4` ([#8317](https://github.com/MetaMask/core/pull/8317))
37
+ - Bump `@metamask/preferences-controller` from `^23.0.0` to `^23.1.0` ([#8317](https://github.com/MetaMask/core/pull/8317))
38
+ - Bump `@metamask/transaction-controller` from `^63.1.0` to `^63.3.1` ([#8301](https://github.com/MetaMask/core/pull/8301), [#8313](https://github.com/MetaMask/core/pull/8313), [#8317](https://github.com/MetaMask/core/pull/8317))
25
39
 
26
40
  ## [3.1.1]
27
41
 
@@ -224,7 +238,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
224
238
  - Refactor `RpcDataSource` to delegate polling to `BalanceFetcher` and `TokenDetector` services ([#7709](https://github.com/MetaMask/core/pull/7709))
225
239
  - Refactor `BalanceFetcher` and `TokenDetector` to extend `StaticIntervalPollingControllerOnly` for independent polling management ([#7709](https://github.com/MetaMask/core/pull/7709))
226
240
 
227
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@3.1.1...HEAD
241
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@3.2.0...HEAD
242
+ [3.2.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@3.1.1...@metamask/assets-controller@3.2.0
228
243
  [3.1.1]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@3.1.0...@metamask/assets-controller@3.1.1
229
244
  [3.1.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@3.0.0...@metamask/assets-controller@3.1.0
230
245
  [3.0.0]: https://github.com/MetaMask/core/compare/@metamask/assets-controller@2.4.0...@metamask/assets-controller@3.0.0
@@ -56,13 +56,13 @@ const DEFAULT_POLLING_INTERVAL_MS = 30000;
56
56
  // ============================================================================
57
57
  // TRACE NAMES — used in Sentry spans (search these strings in Discover)
58
58
  // ============================================================================
59
- const TRACE_FIRST_INIT_FETCH = 'AssetsController First Init Fetch';
60
- const TRACE_FULL_FETCH = 'Assets Full Fetch';
61
- const TRACE_DATA_SOURCE_TIMING = 'Assets Data Source Timing';
62
- const TRACE_DATA_SOURCE_ERROR = 'Assets Data Source Error';
63
- const TRACE_UPDATE_PIPELINE = 'Assets Update Pipeline';
64
- const TRACE_SUBSCRIPTION_ERROR = 'Assets Subscription Error';
65
- const TRACE_STATE_SIZE = 'Assets State Size';
59
+ const TRACE_FIRST_INIT_FETCH = 'AssetsControllerFirstInitFetch';
60
+ const TRACE_FULL_FETCH = 'AssetsFullFetch';
61
+ const TRACE_DATA_SOURCE_TIMING = 'AssetsDataSourceTiming';
62
+ const TRACE_DATA_SOURCE_ERROR = 'AssetsDataSourceError';
63
+ const TRACE_UPDATE_PIPELINE = 'AssetsUpdatePipeline';
64
+ const TRACE_SUBSCRIPTION_ERROR = 'AssetsSubscriptionError';
65
+ const TRACE_STATE_SIZE = 'AssetsStateSize';
66
66
  const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, CONTROLLER_NAME);
67
67
  /**
68
68
  * Returns the default state for AssetsController.
@@ -347,7 +347,7 @@ class AssetsController extends base_controller_1.BaseController {
347
347
  customAssets.push(...accountCustomAssets);
348
348
  }
349
349
  if (options?.forceUpdate) {
350
- const startTime = Date.now();
350
+ const startTime = performance.now();
351
351
  const request = __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_buildDataRequest).call(this, accounts, chainIds, {
352
352
  assetTypes,
353
353
  dataTypes,
@@ -381,7 +381,7 @@ class AssetsController extends base_controller_1.BaseController {
381
381
  options.chainIds.length < __classPrivateFieldGet(this, _AssetsController_enabledChains, "f").size;
382
382
  const updateMode = options?.updateMode ?? (isPartialChainFetch ? 'merge' : 'full');
383
383
  await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, { ...response, updateMode });
384
- const durationMs = Date.now() - startTime;
384
+ const durationMs = performance.now() - startTime;
385
385
  // Emit trace for every full fetch (Assets Health dashboard)
386
386
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_FULL_FETCH, {
387
387
  duration_ms: durationMs,
@@ -728,7 +728,7 @@ class AssetsController extends base_controller_1.BaseController {
728
728
  * @param request - Optional original request for context when enriching
729
729
  */
730
730
  async handleAssetsUpdate(response, sourceId, request) {
731
- const updateStart = Date.now();
731
+ const updateStart = performance.now();
732
732
  log('Assets updated from data source', {
733
733
  sourceId,
734
734
  hasBalance: Boolean(response.assetsBalance),
@@ -750,7 +750,7 @@ class AssetsController extends base_controller_1.BaseController {
750
750
  await __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_updateState).call(this, enrichedResponse);
751
751
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_UPDATE_PIPELINE, {
752
752
  source: sourceId,
753
- duration_ms: Date.now() - updateStart,
753
+ duration_ms: performance.now() - updateStart,
754
754
  has_balance: Boolean(response.assetsBalance),
755
755
  has_price: Boolean(response.assetsPrice),
756
756
  has_metadata: Boolean(enrichedResponse.assetsInfo),
@@ -800,23 +800,30 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
800
800
  if (!__classPrivateFieldGet(this, _AssetsController_trace, "f")) {
801
801
  return;
802
802
  }
803
- try {
804
- __classPrivateFieldGet(this, _AssetsController_trace, "f").call(this, { name, data, tags }, () => undefined).catch(() => {
805
- // Telemetry failure must not break.
806
- });
807
- }
808
- catch {
803
+ __classPrivateFieldGet(this, _AssetsController_trace, "f").call(this, { name, data, tags }, () => undefined).catch(() => {
809
804
  // Telemetry failure must not break.
810
- }
805
+ });
811
806
  }, _AssetsController_emitStateSizeTrace = function _AssetsController_emitStateSizeTrace() {
812
807
  if (!__classPrivateFieldGet(this, _AssetsController_trace, "f") || __classPrivateFieldGet(this, _AssetsController_stateSizeReported, "f")) {
813
808
  return;
814
809
  }
815
810
  __classPrivateFieldSet(this, _AssetsController_stateSizeReported, true, "f");
816
811
  const { assetsBalance: balances, customAssets, assetsInfo, assetsPrice, } = this.state;
812
+ // Count balance entries and collect unique asset IDs / chain IDs in one pass.
817
813
  let balanceEntries = 0;
814
+ const uniqueAssets = new Set();
815
+ const uniqueNetworks = new Set();
818
816
  for (const acct of Object.values(balances)) {
819
- balanceEntries += Object.keys(acct).length;
817
+ const assetIds = Object.keys(acct);
818
+ balanceEntries += assetIds.length;
819
+ for (const assetId of assetIds) {
820
+ uniqueAssets.add(assetId);
821
+ // CAIP-19 format: "eip155:1/slip44:60" — chainId is everything before "/"
822
+ const slash = assetId.indexOf('/');
823
+ if (slash > 0) {
824
+ uniqueNetworks.add(assetId.slice(0, slash));
825
+ }
826
+ }
820
827
  }
821
828
  let customAssetEntries = 0;
822
829
  for (const ids of Object.values(customAssets)) {
@@ -827,6 +834,8 @@ _AssetsController_isEnabled = new WeakMap(), _AssetsController_isBasicFunctional
827
834
  __classPrivateFieldGet(this, _AssetsController_instances, "m", _AssetsController_emitTrace).call(this, TRACE_STATE_SIZE, {
828
835
  balance_entries: balanceEntries,
829
836
  balance_accounts: Object.keys(balances).length,
837
+ unique_asset_count: uniqueAssets.size,
838
+ network_count: uniqueNetworks.size,
830
839
  metadata_entries: Object.keys(assetsInfo).length,
831
840
  price_entries: Object.keys(assetsPrice).length,
832
841
  custom_asset_entries: customAssetEntries,
@@ -953,12 +962,12 @@ async function _AssetsController_executeMiddlewares(sources, request, initialRes
953
962
  const middlewares = sources.map((source) => source.assetsMiddleware);
954
963
  const inclusive = [];
955
964
  const wrapped = middlewares.map((middleware, i) => (async (ctx, next) => {
956
- const start = Date.now();
965
+ const start = performance.now();
957
966
  try {
958
967
  return await middleware(ctx, next);
959
968
  }
960
969
  finally {
961
- inclusive[i] = Date.now() - start;
970
+ inclusive[i] = performance.now() - start;
962
971
  }
963
972
  }));
964
973
  const middlewareErrors = [];