Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/assets-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
32 changes: 16 additions & 16 deletions packages/assets-controller/src/AssetsController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
getDefaultAssetsControllerState,
} from './AssetsController';
import type {
AssetsControllerFirstInitFetchMetaMetricsPayload,
AssetsControllerFirstInitFetchSentryPayload,
AssetsControllerMessenger,
AssetsControllerState,
} from './AssetsController';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -1156,30 +1156,30 @@ 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');
},
);
});

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
Expand All @@ -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);
},
);
});
Expand Down
26 changes: 13 additions & 13 deletions packages/assets-controller/src/AssetsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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']). */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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). */
Expand Down Expand Up @@ -614,7 +614,7 @@ export class AssetsController extends BaseController<
subscribeToBasicFunctionalityChange,
queryApiClient,
rpcDataSourceConfig,
trackMetaMetricsEvent,
reportFirstInitFetchToSentry,
accountsApiDataSourceConfig,
priceDataSourceConfig,
stakedBalanceDataSourceConfig,
Expand All @@ -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 = (
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/assets-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type {
AssetsControllerState,
AssetsControllerMessenger,
AssetsControllerOptions,
AssetsControllerFirstInitFetchMetaMetricsPayload,
AssetsControllerFirstInitFetchSentryPayload,
AssetsControllerGetStateAction,
AssetsControllerActions,
AssetsControllerStateChangeEvent,
Expand Down
Loading