From 95273ebec2bdb00b0f925ad2060f8105e7bb41f1 Mon Sep 17 00:00:00 2001 From: Kriys94 Date: Mon, 9 Mar 2026 15:14:34 +0100 Subject: [PATCH] fix(assets-controller): switch from metametrics to sentry for inital fetch --- packages/assets-controller/CHANGELOG.md | 4 +++ .../src/AssetsController.test.ts | 32 +++++++++---------- .../assets-controller/src/AssetsController.ts | 26 +++++++-------- packages/assets-controller/src/index.ts | 2 +- 4 files changed, 34 insertions(+), 30 deletions(-) diff --git a/packages/assets-controller/CHANGELOG.md b/packages/assets-controller/CHANGELOG.md index c7722bfa3f6..4c6d74ec160 100644 --- a/packages/assets-controller/CHANGELOG.md +++ b/packages/assets-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** Rename first-init-fetch measurement from MetaMetrics to Sentry: option `trackMetaMetricsEvent` is now `reportFirstInitFetchToSentry`, and type `AssetsControllerFirstInitFetchMetaMetricsPayload` is now `AssetsControllerFirstInitFetchSentryPayload`. Consumers should report the payload to Sentry (e.g. via addBreadcrumb or setMeasurement) instead of MetaMetrics. + ### Added - Add `getStateForTransactionPay()` method and `AssetsController:getStateForTransactionPay` messenger action. Returns state in the legacy format expected by transaction-pay-controller (TokenBalancesController, AccountTrackerController, TokensController, TokenRatesController, CurrencyRateController shapes) so that when `useAssetsController` is true the transaction-pay-controller can use a single action instead of five separate getState calls. Also export `formatStateForTransactionPay` and types `TransactionPayLegacyFormat`, `AccountForLegacyFormat`, `LegacyToken` from utils ([#8094](https://github.com/MetaMask/core/pull/8094)) diff --git a/packages/assets-controller/src/AssetsController.test.ts b/packages/assets-controller/src/AssetsController.test.ts index 3ee9a856f85..df16e6978b9 100644 --- a/packages/assets-controller/src/AssetsController.test.ts +++ b/packages/assets-controller/src/AssetsController.test.ts @@ -13,7 +13,7 @@ import { getDefaultAssetsControllerState, } from './AssetsController'; import type { - AssetsControllerFirstInitFetchMetaMetricsPayload, + AssetsControllerFirstInitFetchSentryPayload, AssetsControllerMessenger, AssetsControllerState, } from './AssetsController'; @@ -61,13 +61,13 @@ type WithControllerOptions = { isBasicFunctionality?: () => boolean; /** * When set, registers ClientController:getState so the controller sees this UI state. - * Required for tests that rely on asset tracking running (e.g. trackMetaMetricsEvent on unlock). + * Required for tests that rely on asset tracking running (e.g. reportFirstInitFetchToSentry on unlock). */ clientControllerState?: { isUiOpen: boolean }; - /** Extra options passed to AssetsController constructor (e.g. trackMetaMetricsEvent). */ + /** Extra options passed to AssetsController constructor (e.g. reportFirstInitFetchToSentry). */ controllerOptions?: Partial<{ - trackMetaMetricsEvent: ( - payload: AssetsControllerFirstInitFetchMetaMetricsPayload, + reportFirstInitFetchToSentry: ( + payload: AssetsControllerFirstInitFetchSentryPayload, ) => void; priceDataSourceConfig: PriceDataSourceConfig; isEnabled: () => boolean; @@ -1136,13 +1136,13 @@ describe('AssetsController', () => { }); }); - it('invokes trackMetaMetricsEvent with first init fetch duration on unlock', async () => { - const trackMetaMetricsEvent = jest.fn(); + it('invokes reportFirstInitFetchToSentry with first init fetch duration on unlock', async () => { + const reportFirstInitFetchToSentry = jest.fn(); await withController( { clientControllerState: { isUiOpen: true }, - controllerOptions: { trackMetaMetricsEvent }, + controllerOptions: { reportFirstInitFetchToSentry }, }, async ({ messenger }) => { // UI must be open and keyring unlocked for asset tracking to run @@ -1156,16 +1156,16 @@ describe('AssetsController', () => { // Allow #start() -> getAssets() to resolve so the callback runs await new Promise((resolve) => setTimeout(resolve, 100)); - expect(trackMetaMetricsEvent).toHaveBeenCalledTimes(1); - expect(trackMetaMetricsEvent).toHaveBeenCalledWith( + expect(reportFirstInitFetchToSentry).toHaveBeenCalledTimes(1); + expect(reportFirstInitFetchToSentry).toHaveBeenCalledWith( expect.objectContaining({ durationMs: expect.any(Number), chainIds: expect.any(Array), durationByDataSource: expect.any(Object), }), ); - const payload = trackMetaMetricsEvent.mock - .calls[0][0] as AssetsControllerFirstInitFetchMetaMetricsPayload; + const payload = reportFirstInitFetchToSentry.mock + .calls[0][0] as AssetsControllerFirstInitFetchSentryPayload; expect(payload.durationMs).toBeGreaterThanOrEqual(0); expect(Array.isArray(payload.chainIds)).toBe(true); expect(typeof payload.durationByDataSource).toBe('object'); @@ -1173,13 +1173,13 @@ describe('AssetsController', () => { ); }); - it('invokes trackMetaMetricsEvent only once per session until lock', async () => { - const trackMetaMetricsEvent = jest.fn(); + it('invokes reportFirstInitFetchToSentry only once per session until lock', async () => { + const reportFirstInitFetchToSentry = jest.fn(); await withController( { clientControllerState: { isUiOpen: true }, - controllerOptions: { trackMetaMetricsEvent }, + controllerOptions: { reportFirstInitFetchToSentry }, }, async ({ messenger }) => { // UI must be open and keyring unlocked for asset tracking to run @@ -1194,7 +1194,7 @@ describe('AssetsController', () => { messenger.publish('KeyringController:unlock'); await new Promise((resolve) => setTimeout(resolve, 100)); - expect(trackMetaMetricsEvent).toHaveBeenCalledTimes(1); + expect(reportFirstInitFetchToSentry).toHaveBeenCalledTimes(1); }, ); }); diff --git a/packages/assets-controller/src/AssetsController.ts b/packages/assets-controller/src/AssetsController.ts index dbce4103354..7cadb5b27dc 100644 --- a/packages/assets-controller/src/AssetsController.ts +++ b/packages/assets-controller/src/AssetsController.ts @@ -294,11 +294,11 @@ export type AssetsControllerMessenger = Messenger< // ============================================================================ /** - * Payload for the first init/fetch MetaMetrics event. - * Passed to the optional trackMetaMetricsEvent callback when the initial + * Payload for the first init/fetch measurement reported to Sentry. + * Passed to the optional reportFirstInitFetchToSentry callback when the initial * asset fetch completes after unlock or app open. */ -export type AssetsControllerFirstInitFetchMetaMetricsPayload = { +export type AssetsControllerFirstInitFetchSentryPayload = { /** Duration of the first init fetch in milliseconds (wall-clock). */ durationMs: number; /** Chain IDs requested in the fetch (e.g. ['eip155:1', 'eip155:137']). */ @@ -345,10 +345,10 @@ export type AssetsControllerOptions = { rpcDataSourceConfig?: RpcDataSourceConfig; /** * Optional callback invoked when the first init/fetch completes (e.g. after unlock). - * Use this to track first init fetch duration in MetaMetrics. + * Use this to report first init fetch duration to Sentry (e.g. via addBreadcrumb or setMeasurement). */ - trackMetaMetricsEvent?: ( - payload: AssetsControllerFirstInitFetchMetaMetricsPayload, + reportFirstInitFetchToSentry?: ( + payload: AssetsControllerFirstInitFetchSentryPayload, ) => void; /** Optional configuration for AccountsApiDataSource. */ accountsApiDataSourceConfig?: AccountsApiDataSourceConfig; @@ -519,9 +519,9 @@ export class AssetsController extends BaseController< /** Default update interval hint passed to data sources */ readonly #defaultUpdateInterval: number; - /** Optional callback for first init/fetch MetaMetrics (duration). */ - readonly #trackMetaMetricsEvent?: ( - payload: AssetsControllerFirstInitFetchMetaMetricsPayload, + /** Optional callback for first init/fetch Sentry measurement (duration). */ + readonly #reportFirstInitFetchToSentry?: ( + payload: AssetsControllerFirstInitFetchSentryPayload, ) => void; /** Whether we have already reported first init fetch for this session (reset on #stop). */ @@ -614,7 +614,7 @@ export class AssetsController extends BaseController< subscribeToBasicFunctionalityChange, queryApiClient, rpcDataSourceConfig, - trackMetaMetricsEvent, + reportFirstInitFetchToSentry, accountsApiDataSourceConfig, priceDataSourceConfig, stakedBalanceDataSourceConfig, @@ -632,7 +632,7 @@ export class AssetsController extends BaseController< this.#isEnabled = isEnabled(); this.#isBasicFunctionality = isBasicFunctionality ?? ((): boolean => true); this.#defaultUpdateInterval = defaultUpdateInterval; - this.#trackMetaMetricsEvent = trackMetaMetricsEvent; + this.#reportFirstInitFetchToSentry = reportFirstInitFetchToSentry; const rpcConfig = rpcDataSourceConfig ?? {}; this.#onActiveChainsUpdated = ( @@ -1054,10 +1054,10 @@ export class AssetsController extends BaseController< const updateMode = options?.updateMode ?? (isPartialChainFetch ? 'merge' : 'full'); await this.#updateState({ ...response, updateMode }); - if (this.#trackMetaMetricsEvent && !this.#firstInitFetchReported) { + if (this.#reportFirstInitFetchToSentry && !this.#firstInitFetchReported) { this.#firstInitFetchReported = true; const durationMs = Date.now() - startTime; - this.#trackMetaMetricsEvent({ + this.#reportFirstInitFetchToSentry({ durationMs, chainIds, durationByDataSource, diff --git a/packages/assets-controller/src/index.ts b/packages/assets-controller/src/index.ts index f6a6fbb4d06..c06f49093d4 100644 --- a/packages/assets-controller/src/index.ts +++ b/packages/assets-controller/src/index.ts @@ -10,7 +10,7 @@ export type { AssetsControllerState, AssetsControllerMessenger, AssetsControllerOptions, - AssetsControllerFirstInitFetchMetaMetricsPayload, + AssetsControllerFirstInitFetchSentryPayload, AssetsControllerGetStateAction, AssetsControllerActions, AssetsControllerStateChangeEvent,