@metamask-previews/core-backend 9.0.0-preview-abca9bcea → 9.0.0-preview-8bfa290fb

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.
@@ -1 +1 @@
1
- {"version":3,"file":"shared-types.d.cts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared-types.d.cts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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"}
@@ -64,13 +64,6 @@ export type ApiPlatformClientOptions = {
64
64
  clientVersion?: string;
65
65
  /** Function to get bearer token for authenticated requests */
66
66
  getBearerToken?: () => Promise<string | undefined>;
67
- /**
68
- * Max time (ms) to wait for `getBearerToken` before sending the request
69
- * unauthenticated. The token keeps resolving in the background and is used by
70
- * later requests. Set to `0` to always wait for the token.
71
- * Defaults to {@link DEFAULT_AUTH_TOKEN_TIMEOUT}.
72
- */
73
- authTokenTimeout?: number;
74
67
  /** Optional custom QueryClient instance */
75
68
  queryClient?: QueryClient;
76
69
  };
@@ -117,6 +110,7 @@ export declare const API_URLS: {
117
110
  };
118
111
  /** Stale times for different data types (ms) */
119
112
  export declare const STALE_TIMES: {
113
+ readonly AUTH_TOKEN: number;
120
114
  readonly PRICES: number;
121
115
  readonly BALANCES: number;
122
116
  readonly NETWORKS: number;
@@ -128,11 +122,6 @@ export declare const STALE_TIMES: {
128
122
  readonly TRANSACTIONS: number;
129
123
  readonly DEFAULT: number;
130
124
  };
131
- /**
132
- * Default max time (ms) to wait for the bearer token before falling back to an
133
- * unauthenticated request.
134
- */
135
- export declare const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;
136
125
  /** Garbage collection times (ms) */
137
126
  export declare const GC_TIMES: {
138
127
  readonly DEFAULT: number;
@@ -1 +1 @@
1
- {"version":3,"file":"shared-types.d.mts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared-types.d.mts","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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"}
@@ -29,6 +29,7 @@ export const API_URLS = {
29
29
  };
30
30
  /** Stale times for different data types (ms) */
31
31
  export const STALE_TIMES = {
32
+ AUTH_TOKEN: 5 * 60 * 1000, // 5 minutes - cache the auth token
32
33
  PRICES: 30 * 1000, // 30 seconds
33
34
  BALANCES: 60 * 1000, // 1 minute
34
35
  NETWORKS: 10 * 60 * 1000, // 10 minutes
@@ -40,11 +41,6 @@ export const STALE_TIMES = {
40
41
  TRANSACTIONS: 30 * 1000, // 30 seconds
41
42
  DEFAULT: 30 * 1000, // 30 seconds
42
43
  };
43
- /**
44
- * Default max time (ms) to wait for the bearer token before falling back to an
45
- * unauthenticated request.
46
- */
47
- export const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;
48
44
  /** Garbage collection times (ms) */
49
45
  export const GC_TIMES = {
50
46
  DEFAULT: 5 * 60 * 1000, // 5 minutes
@@ -1 +1 @@
1
- {"version":3,"file":"shared-types.mjs","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiLH;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAsB;IAEtB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EACJ,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,GAAG,EACZ,iBAAiB,EAAE,GAAG,EACtB,GAAG,IAAI,EACR,GAAG,OAGH,CAAC;IACF,OAAO,IAA+B,CAAC;AACzC,CAAC;AAED,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,oBAAoB;AACpB,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,QAAQ,EAAE,qCAAqC;IAC/C,MAAM,EAAE,kCAAkC;IAC1C,KAAK,EAAE,kCAAkC;IACzC,MAAM,EAAE,mCAAmC;CACnC,CAAC;AAEX,gDAAgD;AAChD,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,aAAa;IAChC,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,WAAW;IAChC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,kBAAkB,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACjD,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IAC3C,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACzC,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IAC3C,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACrC,YAAY,EAAE,EAAE,GAAG,IAAI,EAAE,aAAa;IACtC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,aAAa;CACzB,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAE9C,oCAAoC;AACpC,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACpC,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACvC,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;CAC1B,CAAC;AAEX,0BAA0B;AAC1B,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,IAAK;CACR,CAAC;AAEX,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,YAAY,CAAC,UAAU,GAAG,CAAC,IAAI,YAAY,EAC3C,YAAY,CAAC,SAAS,CACvB,CAAC;IACF,OAAO,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB,EAAE,KAAc;IAC9D,+EAA+E;IAC/E,IAAI,YAAY,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,YAAY,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;QAChD,MAAM,EAAE,MAAM,EAAE,GAAG,KAA2B,CAAC;QAC/C,4DAA4D;QAC5D,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACtE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,MAAM,OAAO,SAAU,SAAQ,KAAK;IASlC,YACE,OAAe,EACf,MAAc,EACd,UAAkB,EAClB,GAAW,EACX,IAAc;QAEd,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { FetchQueryOptions, QueryClient } from '@tanstack/query-core';\n\n// ============================================================================\n// SHARED TYPES\n// ============================================================================\n\n/**\n * Pagination info for paginated responses\n */\nexport type PageInfo = {\n count: number;\n hasNextPage: boolean;\n cursor?: string;\n};\n\n/**\n * Supported currencies for Price API\n */\nexport type SupportedCurrency =\n // Crypto\n | 'btc'\n | 'eth'\n | 'ltc'\n | 'bch'\n | 'bnb'\n | 'eos'\n | 'xrp'\n | 'xlm'\n | 'link'\n | 'dot'\n | 'yfi'\n // Fiat\n | 'usd'\n | 'aed'\n | 'ars'\n | 'aud'\n | 'bdt'\n | 'bhd'\n | 'bmd'\n | 'brl'\n | 'cad'\n | 'chf'\n | 'clp'\n | 'cny'\n | 'czk'\n | 'dkk'\n | 'eur'\n | 'gbp'\n | 'gel'\n | 'hkd'\n | 'huf'\n | 'idr'\n | 'ils'\n | 'inr'\n | 'jpy'\n | 'krw'\n | 'kwd'\n | 'lkr'\n | 'mmk'\n | 'mxn'\n | 'myr'\n | 'ngn'\n | 'nok'\n | 'nzd'\n | 'php'\n | 'pkr'\n | 'pln'\n | 'rub'\n | 'sar'\n | 'sek'\n | 'sgd'\n | 'thb'\n | 'try'\n | 'twd'\n | 'uah'\n | 'vef'\n | 'vnd'\n | 'zar';\n\n/**\n * Market data details from Price API spot-prices endpoint\n */\nexport type MarketDataDetails = {\n /** Current price in the requested currency */\n price: number;\n /** Currency code (e.g., 'ETH', 'USD') */\n currency: string;\n /** 24h price change amount */\n priceChange1d: number;\n /** 24h price change percentage */\n pricePercentChange1d: number;\n /** 1h price change percentage */\n pricePercentChange1h: number;\n /** 7d price change percentage */\n pricePercentChange7d: number;\n /** 14d price change percentage */\n pricePercentChange14d: number;\n /** 30d price change percentage */\n pricePercentChange30d: number;\n /** 200d price change percentage */\n pricePercentChange200d: number;\n /** 1y price change percentage */\n pricePercentChange1y: number;\n /** Market capitalization */\n marketCap: number;\n /** Market cap 24h change percentage */\n marketCapPercentChange1d: number;\n /** All-time high price */\n allTimeHigh: number;\n /** All-time low price */\n allTimeLow: number;\n /** 24h high price */\n high1d: number;\n /** 24h low price */\n low1d: number;\n /** Total trading volume */\n totalVolume: number;\n /** Circulating supply */\n circulatingSupply: number;\n /** Diluted market cap */\n dilutedMarketCap: number;\n};\n\n// ============================================================================\n// CLIENT OPTIONS\n// ============================================================================\n\nexport type ApiPlatformClientOptions = {\n /** Client product identifier (e.g., 'metamask-extension') */\n clientProduct: string;\n /** Optional client version */\n clientVersion?: string;\n /** Function to get bearer token for authenticated requests */\n getBearerToken?: () => Promise<string | undefined>;\n /**\n * Max time (ms) to wait for `getBearerToken` before sending the request\n * unauthenticated. The token keeps resolving in the background and is used by\n * later requests. Set to `0` to always wait for the token.\n * Defaults to {@link DEFAULT_AUTH_TOKEN_TIMEOUT}.\n */\n authTokenTimeout?: number;\n /** Optional custom QueryClient instance */\n queryClient?: QueryClient;\n};\n\n/**\n * Options for API fetch and query methods.\n * Extends TanStack Query options (e.g. select, initialPageParam, retry) so callers\n * can pass them through to useQuery / useInfiniteQuery. queryKey and queryFn are\n * always set by the client and cannot be overridden.\n * staleTime and gcTime are explicitly number (not function) so that client defaults apply without type conflicts.\n */\nexport type FetchOptions = {\n /** Custom stale time (ms). */\n staleTime?: number;\n /** Custom GC time (ms). */\n gcTime?: number;\n /**\n * When true, bypass caching for this request: the client-side query cache is\n * skipped (stale time defaults to 0) and, on endpoints that support it, a\n * random `bypassServerCache` query param is appended so server-side HTTP caches\n * (keyed on the full URL) miss. Use sparingly — only when a hard refresh is\n * required, e.g. right after a transaction confirms.\n */\n bypassServerCache?: boolean;\n} & Partial<\n Omit<\n FetchQueryOptions<unknown, Error, unknown>,\n 'queryKey' | 'queryFn' | 'staleTime' | 'gcTime'\n >\n> & {\n /** Allowed for infinite query options (e.g. useInfiniteQuery). */\n initialPageParam?: unknown;\n };\n\n/**\n * Returns options with queryKey and queryFn omitted, for merging into\n * get*QueryOptions return values without overwriting the client's queryKey/queryFn.\n * Return type is intentionally loose so that spreading into FetchQueryOptions<T>\n * does not conflict with T-specific option types (e.g. select, staleTime).\n *\n * @param options - Optional FetchOptions from the caller.\n * @returns Options safe to spread into query options, or undefined.\n */\nexport function getQueryOptionsOverrides(\n options?: FetchOptions,\n): Record<string, unknown> | undefined {\n if (options === null || options === undefined) {\n return undefined;\n }\n const {\n queryKey: _qk,\n queryFn: _qf,\n bypassServerCache: _bc,\n ...rest\n } = options as FetchOptions & {\n queryKey?: unknown;\n queryFn?: unknown;\n };\n return rest as Record<string, unknown>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** API Base URLs */\nexport const API_URLS = {\n ACCOUNTS: 'https://accounts.api.cx.metamask.io',\n PRICES: 'https://price.api.cx.metamask.io',\n TOKEN: 'https://token.api.cx.metamask.io',\n TOKENS: 'https://tokens.api.cx.metamask.io',\n} as const;\n\n/** Stale times for different data types (ms) */\nexport const STALE_TIMES = {\n PRICES: 30 * 1000, // 30 seconds\n BALANCES: 60 * 1000, // 1 minute\n NETWORKS: 10 * 60 * 1000, // 10 minutes\n SUPPORTED_NETWORKS: 30 * 60 * 1000, // 30 minutes\n TOKEN_METADATA: 5 * 60 * 1000, // 5 minutes\n TOKEN_LIST: 10 * 60 * 1000, // 10 minutes\n EXCHANGE_RATES: 5 * 60 * 1000, // 5 minutes\n TRENDING: 2 * 60 * 1000, // 2 minutes\n TRANSACTIONS: 30 * 1000, // 30 seconds\n DEFAULT: 30 * 1000, // 30 seconds\n} as const;\n\n/**\n * Default max time (ms) to wait for the bearer token before falling back to an\n * unauthenticated request.\n */\nexport const DEFAULT_AUTH_TOKEN_TIMEOUT = 500;\n\n/** Garbage collection times (ms) */\nexport const GC_TIMES = {\n DEFAULT: 5 * 60 * 1000, // 5 minutes\n EXTENDED: 30 * 60 * 1000, // 30 minutes\n SHORT: 2 * 60 * 1000, // 2 minutes\n} as const;\n\n/** Retry configuration */\nexport const RETRY_CONFIG = {\n MAX_RETRIES: 3,\n BASE_DELAY: 1000,\n MAX_DELAY: 5_000,\n} as const;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Calculate retry delay with exponential backoff and jitter.\n *\n * @param attemptIndex - The current retry attempt (0-indexed).\n * @returns The delay in milliseconds before the next retry.\n */\nexport function calculateRetryDelay(attemptIndex: number): number {\n const delay = Math.min(\n RETRY_CONFIG.BASE_DELAY * 2 ** attemptIndex,\n RETRY_CONFIG.MAX_DELAY,\n );\n return delay / 2 + Math.random() * (delay / 2);\n}\n\n/**\n * Determine if a failed request should be retried.\n *\n * @param failureCount - The number of failures so far (1 = first failure).\n * @param error - The error from the failed request.\n * @returns True if the request should be retried, false otherwise.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n // Allow up to MAX_RETRIES retries (e.g., MAX_RETRIES=3 means 4 total attempts)\n if (failureCount > RETRY_CONFIG.MAX_RETRIES) {\n return false;\n }\n\n if (error instanceof Error && 'status' in error) {\n const { status } = error as { status: number };\n // Don't retry 4xx except 429 (rate limit) and 408 (timeout)\n if (status >= 400 && status < 500 && status !== 429 && status !== 408) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// HTTP ERROR\n// ============================================================================\n\nexport class HttpError extends Error {\n readonly status: number;\n\n readonly statusText: string;\n\n readonly url: string;\n\n readonly body: unknown;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n url: string,\n body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n"]}
1
+ {"version":3,"file":"shared-types.mjs","sourceRoot":"","sources":["../../src/api/shared-types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared types, constants, and utilities for the API Platform Client.\n */\n\nimport type { FetchQueryOptions, QueryClient } from '@tanstack/query-core';\n\n// ============================================================================\n// SHARED TYPES\n// ============================================================================\n\n/**\n * Pagination info for paginated responses\n */\nexport type PageInfo = {\n count: number;\n hasNextPage: boolean;\n cursor?: string;\n};\n\n/**\n * Supported currencies for Price API\n */\nexport type SupportedCurrency =\n // Crypto\n | 'btc'\n | 'eth'\n | 'ltc'\n | 'bch'\n | 'bnb'\n | 'eos'\n | 'xrp'\n | 'xlm'\n | 'link'\n | 'dot'\n | 'yfi'\n // Fiat\n | 'usd'\n | 'aed'\n | 'ars'\n | 'aud'\n | 'bdt'\n | 'bhd'\n | 'bmd'\n | 'brl'\n | 'cad'\n | 'chf'\n | 'clp'\n | 'cny'\n | 'czk'\n | 'dkk'\n | 'eur'\n | 'gbp'\n | 'gel'\n | 'hkd'\n | 'huf'\n | 'idr'\n | 'ils'\n | 'inr'\n | 'jpy'\n | 'krw'\n | 'kwd'\n | 'lkr'\n | 'mmk'\n | 'mxn'\n | 'myr'\n | 'ngn'\n | 'nok'\n | 'nzd'\n | 'php'\n | 'pkr'\n | 'pln'\n | 'rub'\n | 'sar'\n | 'sek'\n | 'sgd'\n | 'thb'\n | 'try'\n | 'twd'\n | 'uah'\n | 'vef'\n | 'vnd'\n | 'zar';\n\n/**\n * Market data details from Price API spot-prices endpoint\n */\nexport type MarketDataDetails = {\n /** Current price in the requested currency */\n price: number;\n /** Currency code (e.g., 'ETH', 'USD') */\n currency: string;\n /** 24h price change amount */\n priceChange1d: number;\n /** 24h price change percentage */\n pricePercentChange1d: number;\n /** 1h price change percentage */\n pricePercentChange1h: number;\n /** 7d price change percentage */\n pricePercentChange7d: number;\n /** 14d price change percentage */\n pricePercentChange14d: number;\n /** 30d price change percentage */\n pricePercentChange30d: number;\n /** 200d price change percentage */\n pricePercentChange200d: number;\n /** 1y price change percentage */\n pricePercentChange1y: number;\n /** Market capitalization */\n marketCap: number;\n /** Market cap 24h change percentage */\n marketCapPercentChange1d: number;\n /** All-time high price */\n allTimeHigh: number;\n /** All-time low price */\n allTimeLow: number;\n /** 24h high price */\n high1d: number;\n /** 24h low price */\n low1d: number;\n /** Total trading volume */\n totalVolume: number;\n /** Circulating supply */\n circulatingSupply: number;\n /** Diluted market cap */\n dilutedMarketCap: number;\n};\n\n// ============================================================================\n// CLIENT OPTIONS\n// ============================================================================\n\nexport type ApiPlatformClientOptions = {\n /** Client product identifier (e.g., 'metamask-extension') */\n clientProduct: string;\n /** Optional client version */\n clientVersion?: string;\n /** Function to get bearer token for authenticated requests */\n getBearerToken?: () => Promise<string | undefined>;\n /** Optional custom QueryClient instance */\n queryClient?: QueryClient;\n};\n\n/**\n * Options for API fetch and query methods.\n * Extends TanStack Query options (e.g. select, initialPageParam, retry) so callers\n * can pass them through to useQuery / useInfiniteQuery. queryKey and queryFn are\n * always set by the client and cannot be overridden.\n * staleTime and gcTime are explicitly number (not function) so that client defaults apply without type conflicts.\n */\nexport type FetchOptions = {\n /** Custom stale time (ms). */\n staleTime?: number;\n /** Custom GC time (ms). */\n gcTime?: number;\n /**\n * When true, bypass caching for this request: the client-side query cache is\n * skipped (stale time defaults to 0) and, on endpoints that support it, a\n * random `bypassServerCache` query param is appended so server-side HTTP caches\n * (keyed on the full URL) miss. Use sparingly — only when a hard refresh is\n * required, e.g. right after a transaction confirms.\n */\n bypassServerCache?: boolean;\n} & Partial<\n Omit<\n FetchQueryOptions<unknown, Error, unknown>,\n 'queryKey' | 'queryFn' | 'staleTime' | 'gcTime'\n >\n> & {\n /** Allowed for infinite query options (e.g. useInfiniteQuery). */\n initialPageParam?: unknown;\n };\n\n/**\n * Returns options with queryKey and queryFn omitted, for merging into\n * get*QueryOptions return values without overwriting the client's queryKey/queryFn.\n * Return type is intentionally loose so that spreading into FetchQueryOptions<T>\n * does not conflict with T-specific option types (e.g. select, staleTime).\n *\n * @param options - Optional FetchOptions from the caller.\n * @returns Options safe to spread into query options, or undefined.\n */\nexport function getQueryOptionsOverrides(\n options?: FetchOptions,\n): Record<string, unknown> | undefined {\n if (options === null || options === undefined) {\n return undefined;\n }\n const {\n queryKey: _qk,\n queryFn: _qf,\n bypassServerCache: _bc,\n ...rest\n } = options as FetchOptions & {\n queryKey?: unknown;\n queryFn?: unknown;\n };\n return rest as Record<string, unknown>;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\n/** API Base URLs */\nexport const API_URLS = {\n ACCOUNTS: 'https://accounts.api.cx.metamask.io',\n PRICES: 'https://price.api.cx.metamask.io',\n TOKEN: 'https://token.api.cx.metamask.io',\n TOKENS: 'https://tokens.api.cx.metamask.io',\n} as const;\n\n/** Stale times for different data types (ms) */\nexport const STALE_TIMES = {\n AUTH_TOKEN: 5 * 60 * 1000, // 5 minutes - cache the auth token\n PRICES: 30 * 1000, // 30 seconds\n BALANCES: 60 * 1000, // 1 minute\n NETWORKS: 10 * 60 * 1000, // 10 minutes\n SUPPORTED_NETWORKS: 30 * 60 * 1000, // 30 minutes\n TOKEN_METADATA: 5 * 60 * 1000, // 5 minutes\n TOKEN_LIST: 10 * 60 * 1000, // 10 minutes\n EXCHANGE_RATES: 5 * 60 * 1000, // 5 minutes\n TRENDING: 2 * 60 * 1000, // 2 minutes\n TRANSACTIONS: 30 * 1000, // 30 seconds\n DEFAULT: 30 * 1000, // 30 seconds\n} as const;\n\n/** Garbage collection times (ms) */\nexport const GC_TIMES = {\n DEFAULT: 5 * 60 * 1000, // 5 minutes\n EXTENDED: 30 * 60 * 1000, // 30 minutes\n SHORT: 2 * 60 * 1000, // 2 minutes\n} as const;\n\n/** Retry configuration */\nexport const RETRY_CONFIG = {\n MAX_RETRIES: 3,\n BASE_DELAY: 1000,\n MAX_DELAY: 5_000,\n} as const;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Calculate retry delay with exponential backoff and jitter.\n *\n * @param attemptIndex - The current retry attempt (0-indexed).\n * @returns The delay in milliseconds before the next retry.\n */\nexport function calculateRetryDelay(attemptIndex: number): number {\n const delay = Math.min(\n RETRY_CONFIG.BASE_DELAY * 2 ** attemptIndex,\n RETRY_CONFIG.MAX_DELAY,\n );\n return delay / 2 + Math.random() * (delay / 2);\n}\n\n/**\n * Determine if a failed request should be retried.\n *\n * @param failureCount - The number of failures so far (1 = first failure).\n * @param error - The error from the failed request.\n * @returns True if the request should be retried, false otherwise.\n */\nexport function shouldRetry(failureCount: number, error: unknown): boolean {\n // Allow up to MAX_RETRIES retries (e.g., MAX_RETRIES=3 means 4 total attempts)\n if (failureCount > RETRY_CONFIG.MAX_RETRIES) {\n return false;\n }\n\n if (error instanceof Error && 'status' in error) {\n const { status } = error as { status: number };\n // Don't retry 4xx except 429 (rate limit) and 408 (timeout)\n if (status >= 400 && status < 500 && status !== 429 && status !== 408) {\n return false;\n }\n }\n return true;\n}\n\n// ============================================================================\n// HTTP ERROR\n// ============================================================================\n\nexport class HttpError extends Error {\n readonly status: number;\n\n readonly statusText: string;\n\n readonly url: string;\n\n readonly body: unknown;\n\n constructor(\n message: string,\n status: number,\n statusText: string,\n url: string,\n body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n this.status = status;\n this.statusText = statusText;\n this.url = url;\n this.body = body;\n }\n}\n"]}
@@ -147,7 +147,9 @@ class AccountActivityService {
147
147
  // Promise result intentionally not awaited
148
148
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
149
149
  (connectionInfo) => __classPrivateFieldGet(this, _AccountActivityService_instances, "m", _AccountActivityService_handleWebSocketStateChange).call(this, connectionInfo));
150
- __classPrivateFieldGet(this, _AccountActivityService_messenger, "f").subscribe('RemoteFeatureFlagController:stateChange',
150
+ __classPrivateFieldGet(this, _AccountActivityService_messenger, "f").subscribe(
151
+ // eslint-disable-next-line no-restricted-syntax
152
+ 'RemoteFeatureFlagController:stateChange',
151
153
  // Promise result intentionally not awaited
152
154
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
153
155
  async () => await __classPrivateFieldGet(this, _AccountActivityService_instances, "m", _AccountActivityService_handleFeatureFlagsStateChange).call(this),
@@ -1 +1 @@
1
- {"version":3,"file":"AccountActivityService.cjs","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Account Activity Service for monitoring account transactions and balance changes\n *\n * This service subscribes to account activity and receives all transactions\n * and balance updates for those accounts via the comprehensive AccountActivityMessage format.\n */\n\nimport type {\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n} from '@metamask/account-tree-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n FeatureFlags,\n RemoteFeatureFlagControllerGetStateAction,\n RemoteFeatureFlagControllerStateChangeEvent,\n} from '@metamask/remote-feature-flag-controller';\nimport { isObject } from '@metamask/utils';\n\nimport { projectLogger, createModuleLogger } from '../logger.js';\nimport type {\n Transaction,\n AccountActivityMessage,\n BalanceUpdate,\n} from '../types.js';\nimport type { BackendWebSocketServiceMethodActions } from './BackendWebSocketService-method-action-types.js';\nimport type {\n WebSocketConnectionInfo,\n BackendWebSocketServiceConnectionStateChangedEvent,\n ServerNotificationMessage,\n} from './BackendWebSocketService.js';\nimport { WebSocketState } from './BackendWebSocketService.js';\n\n// =============================================================================\n// Types and Constants\n// =============================================================================\n\n/**\n * System notification data for chain status updates\n */\nexport type SystemNotificationData = {\n /** Array of chain IDs affected (e.g., ['eip155:137', 'eip155:1']) */\n chainIds: string[];\n /** Status of the chains: 'down' or 'up' */\n status: 'down' | 'up';\n /** Timestamp of the notification */\n timestamp?: number;\n};\n\nconst SERVICE_NAME = 'AccountActivityService';\n\nconst log = createModuleLogger(projectLogger, SERVICE_NAME);\n\nconst MESSENGER_EXPOSED_METHODS = [] as const;\n\nconst SUBSCRIPTION_NAMESPACE = 'account-activity.v1';\n\n// Window (in ms) over which consecutive system notifications are accumulated\n// before a single batched `statusChanged` event is published. Coalescing bursts\n// of chain up/down notifications avoids flooding consumers.\nconst STATUS_CHANGE_DEBOUNCE_MS = 1000;\n\n// Maximum random jitter (in ms) added to the debounce window before publishing.\n// Spreading the publish across a random delay prevents many clients reacting to\n// the same system notification from publishing in lockstep (a thundering herd\n// on downstream consumers).\nconst STATUS_CHANGE_JITTER_MS = 1000;\n\n// EVM subscriptions are always enabled.\nconst ALWAYS_SUPPORTED_CHAIN_PREFIXES = ['eip155'] as const;\n\n// Non-EVM chains are gated behind the\n// per-network snaps-migration remote feature flags: a chain is\n// enabled when its flag payload has `stage >= 1`.\nconst CHAIN_PREFIX_FEATURE_FLAGS = {\n solana: 'networkAssetsSnapsMigrationSolana',\n tron: 'networkAssetsSnapsMigrationTron',\n stellar: 'networkAssetsSnapsMigrationStellar',\n} as const;\n\n/**\n * Account subscription options\n */\nexport type SubscriptionOptions = {\n /**\n * Array of addresses to subscribe to, each in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n */\n addresses: string[];\n};\n\n/**\n * Configuration options for the account activity service\n */\nexport type AccountActivityServiceOptions = {\n /** Custom subscription namespace (default: 'account-activity.v1') */\n subscriptionNamespace?: string;\n /** Optional callback to trace performance of account activity operations (default: no-op) */\n traceFn?: TraceCallback;\n};\n\n// =============================================================================\n// Action and Event Types\n// =============================================================================\n\n// Action types for the messaging system\nexport type AccountActivityServiceActions = never;\n\n// Allowed actions that AccountActivityService can call on other controllers\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS = [\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n 'BackendWebSocketService:connect',\n 'BackendWebSocketService:forceReconnection',\n 'BackendWebSocketService:subscribe',\n 'BackendWebSocketService:getConnectionInfo',\n 'BackendWebSocketService:channelHasSubscription',\n 'BackendWebSocketService:getSubscriptionsByChannel',\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n 'BackendWebSocketService:addChannelCallback',\n 'BackendWebSocketService:removeChannelCallback',\n 'RemoteFeatureFlagController:getState',\n] as const;\n\n// Allowed events that AccountActivityService can listen to\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS = [\n 'AccountTreeController:selectedAccountGroupChange',\n 'BackendWebSocketService:connectionStateChanged',\n 'RemoteFeatureFlagController:stateChange',\n] as const;\n\nexport type AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | BackendWebSocketServiceMethodActions\n | RemoteFeatureFlagControllerGetStateAction;\n\n// Event types for the messaging system\n\nexport type AccountActivityServiceTransactionUpdatedEvent = {\n type: `AccountActivityService:transactionUpdated`;\n payload: [Transaction];\n};\n\nexport type AccountActivityServiceBalanceUpdatedEvent = {\n type: `AccountActivityService:balanceUpdated`;\n payload: [{ address: string; chain: string; updates: BalanceUpdate[] }];\n};\n\nexport type AccountActivityServiceSubscriptionErrorEvent = {\n type: `AccountActivityService:subscriptionError`;\n payload: [{ addresses: string[]; error: string; operation: string }];\n};\n\nexport type AccountActivityServiceStatusChangedEvent = {\n type: `AccountActivityService:statusChanged`;\n payload: [\n {\n chainIds: string[];\n status: 'up' | 'down';\n timestamp?: number;\n },\n ];\n};\n\nexport type AccountActivityServiceEvents =\n | AccountActivityServiceTransactionUpdatedEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceSubscriptionErrorEvent\n | AccountActivityServiceStatusChangedEvent;\n\nexport type AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | BackendWebSocketServiceConnectionStateChangedEvent\n | RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type AccountActivityServiceMessenger = Messenger<\n typeof SERVICE_NAME,\n AccountActivityServiceActions | AllowedActions,\n AccountActivityServiceEvents | AllowedEvents\n>;\n\n// =============================================================================\n// Main Service Class\n// =============================================================================\n\n/**\n * High-performance service for real-time account activity monitoring using optimized\n * WebSocket subscriptions with direct callback routing. Automatically subscribes to\n * the currently selected account and switches subscriptions when the selected account changes.\n * Receives transactions and balance updates using the comprehensive AccountActivityMessage format.\n *\n * Performance Features:\n * - Direct callback routing (no EventEmitter overhead)\n * - Minimal subscription tracking (no duplication with BackendWebSocketService)\n * - Optimized cleanup for mobile environments\n * - Single-account subscription (only selected account)\n * - Comprehensive balance updates with transfer tracking\n *\n * Architecture:\n * - Uses messenger pattern to communicate with BackendWebSocketService\n * - AccountActivityService tracks channel-to-subscriptionId mappings via messenger calls\n * - Automatically subscribes to selected account on initialization\n * - Switches subscriptions when selected account changes\n * - No direct dependency on BackendWebSocketService (uses messenger instead)\n *\n * @example\n * ```typescript\n * const service = new AccountActivityService({\n * messenger: activityMessenger,\n * });\n *\n * // Service automatically subscribes to the currently selected account\n * // When user switches accounts, service automatically resubscribes\n *\n * // All transactions and balance updates are received via optimized\n * // WebSocket callbacks and processed with zero-allocation routing\n * // Balance updates include comprehensive transfer details and post-transaction balances\n * ```\n */\nexport class AccountActivityService {\n /**\n * The name of the service.\n */\n readonly name = SERVICE_NAME;\n\n readonly #messenger: AccountActivityServiceMessenger;\n\n readonly #options: Required<Omit<AccountActivityServiceOptions, 'traceFn'>>;\n\n readonly #trace: TraceCallback;\n\n // Track chains that are currently up (based on system notifications)\n readonly #chainsUp: Set<string> = new Set();\n\n // Debouncing for rapid status changes: buffers the latest status per chain\n // and coalesces bursts of system notifications into fewer downstream\n // `statusChanged` events.\n readonly #statusChangeDebouncer: {\n timer: NodeJS.Timeout | null;\n pendingChanges: Map<string, 'up' | 'down'>;\n } = {\n timer: null,\n pendingChanges: new Map(),\n };\n\n // =============================================================================\n // Constructor and Initialization\n // =============================================================================\n\n /**\n * Creates a new Account Activity service instance\n *\n * @param options - Configuration options including messenger\n */\n constructor(\n options: AccountActivityServiceOptions & {\n messenger: AccountActivityServiceMessenger;\n },\n ) {\n this.#messenger = options.messenger;\n\n // Set configuration with defaults\n this.#options = {\n subscriptionNamespace:\n options.subscriptionNamespace ?? SUBSCRIPTION_NAMESPACE,\n };\n\n // Default to no-op trace function to keep core platform-agnostic\n this.#trace =\n options.traceFn ??\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (((_request: any, fn?: any) => fn?.()) as TraceCallback);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleSelectedAccountChange(),\n );\n this.#messenger.subscribe(\n 'BackendWebSocketService:connectionStateChanged',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n (connectionInfo: WebSocketConnectionInfo) =>\n this.#handleWebSocketStateChange(connectionInfo),\n );\n this.#messenger.subscribe(\n 'RemoteFeatureFlagController:stateChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleFeatureFlagsStateChange(),\n // Only react to changes in the set of enabled chain prefixes. The\n // messenger compares selector results with strict equality, so the\n // selector must return a primitive rather than a fresh object.\n (state) =>\n this.#getSupportedChainPrefixes(state.remoteFeatureFlags).join(','),\n );\n this.#messenger.call('BackendWebSocketService:addChannelCallback', {\n channelName: `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n callback: (notification: ServerNotificationMessage) =>\n this.#handleSystemNotification(notification),\n });\n }\n\n /**\n * Subscribe to account activity (transactions and balance updates)\n * Addresses should be in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n *\n * @param subscription - The subscription configuration\n * @param subscription.addresses - Array of addresses to subscribe to, each in CAIP-10 format\n * or an `addresses` array for batch subscription\n */\n async #subscribe({ addresses }: SubscriptionOptions): Promise<void> {\n try {\n await this.#messenger.call('BackendWebSocketService:connect');\n\n // Derive new subscriptions to be created from the provided addresses,\n // filtering out any channels that already have an active subscription\n const channels = addresses\n .map((address) => `${this.#options.subscriptionNamespace}.${address}`)\n .filter(\n (channel) =>\n !this.#messenger.call(\n 'BackendWebSocketService:channelHasSubscription',\n channel,\n ),\n );\n\n if (channels.length === 0) {\n return;\n }\n\n // Create subscription using the proper subscribe method (this will be stored in WebSocketService's internal tracking)\n await this.#messenger.call('BackendWebSocketService:subscribe', {\n channels,\n channelType: this.#options.subscriptionNamespace, // e.g., 'account-activity.v1'\n callback: (notification: ServerNotificationMessage) => {\n this.#handleAccountActivityUpdate(\n notification.data as AccountActivityMessage,\n );\n },\n });\n } catch (error) {\n log('Subscription failed, forcing reconnection', { error });\n await this.#forceReconnection();\n }\n }\n\n /**\n * Handle account activity updates (transactions + balance changes)\n * Processes the comprehensive AccountActivityMessage format with detailed balance updates and transfers\n *\n * @param payload - The account activity message containing transaction and balance updates\n * @example AccountActivityMessage format handling:\n * Input: {\n * address: \"0xd14b52362b5b777ffa754c666ddec6722aaeee08\",\n * tx: { id: \"0x1cde...\", chain: \"eip155:8453\", status: \"confirmed\", timestamp: 1760099871, ... },\n * updates: [{\n * asset: { fungible: true, type: \"eip155:8453/erc20:0x833...\", unit: \"USDC\", decimals: 6 },\n * postBalance: { amount: \"0xc350\" },\n * transfers: [{ from: \"0x7b07...\", to: \"0xd14b...\", amount: \"0x2710\" }]\n * }]\n * }\n * Output: Transaction and balance updates published separately\n */\n #handleAccountActivityUpdate(payload: AccountActivityMessage): void {\n const { address, tx, updates } = payload;\n\n // Calculate time elapsed between transaction time and message receipt\n const txTimestampMs = tx.timestamp * 1000; // Convert Unix timestamp (seconds) to milliseconds\n const elapsedMs = Date.now() - txTimestampMs;\n\n log('Handling account activity update', {\n address,\n updateCount: updates.length,\n elapsedMs,\n });\n\n // Trace message receipt with latency from transaction time to now\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#trace(\n {\n name: `${SERVICE_NAME} Transaction Message`,\n data: {\n chain: tx.chain,\n status: tx.status,\n elapsed_ms: elapsedMs,\n },\n tags: {\n service: SERVICE_NAME,\n notification_type: this.#options.subscriptionNamespace,\n },\n },\n () => {\n // Process transaction update\n this.#messenger.publish(\n `AccountActivityService:transactionUpdated`,\n tx,\n );\n\n // Publish comprehensive balance updates with transfer details\n this.#messenger.publish(`AccountActivityService:balanceUpdated`, {\n address,\n chain: tx.chain,\n updates,\n });\n },\n );\n }\n\n /**\n * Handle selected account change event\n */\n async #handleSelectedAccountChange(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n try {\n // First, unsubscribe from all current account activity subscriptions to avoid multiple subscriptions\n await this.#unsubscribeFromAllAccountActivity();\n\n // Subscribe to the new selected accounts in CAIP-10 format\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n } catch (error) {\n log('Account change failed', { error });\n }\n }\n\n /**\n * Handle system notification for chain status changes\n * Publishes only the status change (delta) for affected chains\n *\n * @param notification - Server notification message containing chain status updates and timestamp\n */\n #handleSystemNotification(notification: ServerNotificationMessage): void {\n const data = notification.data as SystemNotificationData;\n\n // Validate required fields\n if (!data.chainIds || !Array.isArray(data.chainIds) || !data.status) {\n throw new Error(\n 'Invalid system notification data: missing chainIds or status',\n );\n }\n\n if (data.status === 'up') {\n for (const chainId of data.chainIds) {\n this.#chainsUp.add(chainId);\n }\n } else {\n for (const chainId of data.chainIds) {\n this.#chainsUp.delete(chainId);\n }\n }\n\n for (const chainId of data.chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, data.status);\n }\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n // Debounce window plus a random jitter, so clients reacting to the same\n // system notification don't publish in lockstep.\n const delay =\n STATUS_CHANGE_DEBOUNCE_MS + Math.random() * STATUS_CHANGE_JITTER_MS;\n\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, delay);\n\n log(`WebSocket status change - Buffered chains as ${data.status}`, {\n count: data.chainIds.length,\n chains: data.chainIds,\n status: data.status,\n });\n }\n\n /**\n * Publish the buffered status changes as batched `statusChanged` events, one\n * per status (`up`/`down`), then reset the buffer and timer.\n */\n #processAccumulatedStatusChanges(): void {\n const changes = Array.from(\n this.#statusChangeDebouncer.pendingChanges.entries(),\n );\n this.#statusChangeDebouncer.pendingChanges.clear();\n this.#statusChangeDebouncer.timer = null;\n\n // Group buffered chains by their latest status. A chain can only appear in\n // one group because the buffer keeps a single entry per chain.\n const grouped: Record<'up' | 'down', string[]> = { up: [], down: [] };\n for (const [chainId, status] of changes) {\n grouped[status].push(chainId);\n }\n\n for (const status of ['up', 'down'] as const) {\n const chainIds = grouped[status];\n if (chainIds.length === 0) {\n continue;\n }\n\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status,\n });\n\n log(`WebSocket status change - Published batched chains as ${status}`, {\n count: chainIds.length,\n chains: chainIds,\n status,\n });\n }\n }\n\n /**\n * Handle WebSocket connection state changes for fallback polling and resubscription\n *\n * @param connectionInfo - WebSocket connection state information\n */\n async #handleWebSocketStateChange(\n connectionInfo: WebSocketConnectionInfo,\n ): Promise<void> {\n const { state } = connectionInfo;\n\n if (state === WebSocketState.CONNECTED) {\n // WebSocket connected - resubscribe to selected account\n // The system notification will automatically provide the list of chains that are up\n await this.#subscribeToSelectedAccount();\n } else if (state === WebSocketState.DISCONNECTED) {\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n const chainsToMarkDown = new Set(this.#chainsUp);\n for (const chainId of this.#statusChangeDebouncer.pendingChanges.keys()) {\n chainsToMarkDown.add(chainId);\n }\n this.#statusChangeDebouncer.pendingChanges.clear();\n\n if (chainsToMarkDown.size > 0) {\n const chainIds = Array.from(chainsToMarkDown);\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status: 'down',\n timestamp: Date.now(),\n });\n\n log('WebSocket disconnection - Published tracked chains as down', {\n count: chainIds.length,\n chains: chainIds,\n });\n\n // Clear the tracking set since all chains are now down\n this.#chainsUp.clear();\n }\n }\n }\n\n // =============================================================================\n // Private Methods - Subscription Management\n // =============================================================================\n\n /**\n * Subscribe to the currently selected account only\n */\n async #subscribeToSelectedAccount(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n }\n\n /**\n * Unsubscribe from all account activity subscriptions for this service\n * Finds all channels matching the service's namespace and unsubscribes from them\n */\n async #unsubscribeFromAllAccountActivity(): Promise<void> {\n const accountActivitySubscriptions = this.#messenger.call(\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n this.#options.subscriptionNamespace,\n );\n\n // Unsubscribe from all matching subscriptions\n for (const subscription of accountActivitySubscriptions) {\n await subscription.unsubscribe();\n }\n }\n\n // =============================================================================\n // Private Methods - Utility Functions\n // =============================================================================\n\n /**\n * Convert a list of InternalAccount addresses to CAIP-10 format, using the first\n * supported chain prefix matching the account's scopes\n *\n * @param accounts - The internal accounts to convert\n * @returns The CAIP-10 formatted addresses (e.g. [`eip155:0:address`], meaning\n * all chains of that namespace), or an empty array if none of the account's\n * scopes are supported\n */\n #convertToCaip10Addresses(accounts: InternalAccount[]): string[] {\n const supportedChainPrefixes = this.#getSupportedChainPrefixes();\n return accounts.reduce<string[]>((result, account) => {\n const accountPrefix = supportedChainPrefixes.find((prefix) =>\n account.scopes.some((scope) => scope.startsWith(`${prefix}:`)),\n );\n\n if (!accountPrefix) {\n // Skip unsupported accounts\n return result;\n }\n\n result.push(`${accountPrefix}:0:${account.address}`);\n return result;\n }, []);\n }\n\n /**\n * Get the chain prefixes currently enabled for subscriptions: EVM is always\n * enabled, while other chains are gated behind their per-network remote\n * feature flag (enabled when the flag payload has `stage >= 1`).\n *\n * @param remoteFeatureFlags - The remote feature flags state to check for enabled chains.\n * @returns An array of enabled CAIP-2 namespace prefixes (e.g. `['eip155', 'solana']`)\n */\n #getSupportedChainPrefixes(\n remoteFeatureFlags: FeatureFlags = this.#messenger.call(\n 'RemoteFeatureFlagController:getState',\n ).remoteFeatureFlags,\n ): string[] {\n const prefixes: string[] = [...ALWAYS_SUPPORTED_CHAIN_PREFIXES];\n for (const [prefix, flagName] of Object.entries(\n CHAIN_PREFIX_FEATURE_FLAGS,\n )) {\n const flagValue = remoteFeatureFlags[flagName];\n if (\n isObject(flagValue) &&\n typeof flagValue.stage === 'number' &&\n flagValue.stage >= 1\n ) {\n prefixes.push(prefix);\n }\n }\n return prefixes;\n }\n\n /**\n * Handle remote feature flag changes: if the set of enabled chain prefixes\n * changed while connected, resubscribe the selected account so new chains\n * are picked up and disabled ones are dropped.\n */\n async #handleFeatureFlagsStateChange(): Promise<void> {\n try {\n const { state } = this.#messenger.call(\n 'BackendWebSocketService:getConnectionInfo',\n );\n if (state !== WebSocketState.CONNECTED) {\n // Not connected: the next connection will subscribe with fresh flags\n return;\n }\n\n await this.#unsubscribeFromAllAccountActivity();\n await this.#subscribeToSelectedAccount();\n } catch (error) {\n log('Feature flag change handling failed', { error });\n }\n }\n\n /**\n * Force WebSocket reconnection to clean up subscription state\n */\n async #forceReconnection(): Promise<void> {\n log('Forcing WebSocket reconnection to clean up subscription state');\n\n // Use the dedicated forceReconnection method which performs a controlled\n // disconnect-then-connect sequence to clean up subscription state\n await this.#messenger.call('BackendWebSocketService:forceReconnection');\n }\n\n // =============================================================================\n // Public Methods - Cleanup\n // =============================================================================\n\n /**\n * Destroy the service and clean up all resources\n * Optimized for fast cleanup during service destruction or mobile app termination\n */\n destroy(): void {\n // Cancel any pending batched status-change flush\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n // Clean up system notification callback\n this.#messenger.call(\n 'BackendWebSocketService:removeChannelCallback',\n `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"AccountActivityService.cjs","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Account Activity Service for monitoring account transactions and balance changes\n *\n * This service subscribes to account activity and receives all transactions\n * and balance updates for those accounts via the comprehensive AccountActivityMessage format.\n */\n\nimport type {\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n} from '@metamask/account-tree-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n FeatureFlags,\n RemoteFeatureFlagControllerGetStateAction,\n RemoteFeatureFlagControllerStateChangeEvent,\n} from '@metamask/remote-feature-flag-controller';\nimport { isObject } from '@metamask/utils';\n\nimport { projectLogger, createModuleLogger } from '../logger.js';\nimport type {\n Transaction,\n AccountActivityMessage,\n BalanceUpdate,\n} from '../types.js';\nimport type { BackendWebSocketServiceMethodActions } from './BackendWebSocketService-method-action-types.js';\nimport type {\n WebSocketConnectionInfo,\n BackendWebSocketServiceConnectionStateChangedEvent,\n ServerNotificationMessage,\n} from './BackendWebSocketService.js';\nimport { WebSocketState } from './BackendWebSocketService.js';\n\n// =============================================================================\n// Types and Constants\n// =============================================================================\n\n/**\n * System notification data for chain status updates\n */\nexport type SystemNotificationData = {\n /** Array of chain IDs affected (e.g., ['eip155:137', 'eip155:1']) */\n chainIds: string[];\n /** Status of the chains: 'down' or 'up' */\n status: 'down' | 'up';\n /** Timestamp of the notification */\n timestamp?: number;\n};\n\nconst SERVICE_NAME = 'AccountActivityService';\n\nconst log = createModuleLogger(projectLogger, SERVICE_NAME);\n\nconst MESSENGER_EXPOSED_METHODS = [] as const;\n\nconst SUBSCRIPTION_NAMESPACE = 'account-activity.v1';\n\n// Window (in ms) over which consecutive system notifications are accumulated\n// before a single batched `statusChanged` event is published. Coalescing bursts\n// of chain up/down notifications avoids flooding consumers.\nconst STATUS_CHANGE_DEBOUNCE_MS = 1000;\n\n// Maximum random jitter (in ms) added to the debounce window before publishing.\n// Spreading the publish across a random delay prevents many clients reacting to\n// the same system notification from publishing in lockstep (a thundering herd\n// on downstream consumers).\nconst STATUS_CHANGE_JITTER_MS = 1000;\n\n// EVM subscriptions are always enabled.\nconst ALWAYS_SUPPORTED_CHAIN_PREFIXES = ['eip155'] as const;\n\n// Non-EVM chains are gated behind the\n// per-network snaps-migration remote feature flags: a chain is\n// enabled when its flag payload has `stage >= 1`.\nconst CHAIN_PREFIX_FEATURE_FLAGS = {\n solana: 'networkAssetsSnapsMigrationSolana',\n tron: 'networkAssetsSnapsMigrationTron',\n stellar: 'networkAssetsSnapsMigrationStellar',\n} as const;\n\n/**\n * Account subscription options\n */\nexport type SubscriptionOptions = {\n /**\n * Array of addresses to subscribe to, each in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n */\n addresses: string[];\n};\n\n/**\n * Configuration options for the account activity service\n */\nexport type AccountActivityServiceOptions = {\n /** Custom subscription namespace (default: 'account-activity.v1') */\n subscriptionNamespace?: string;\n /** Optional callback to trace performance of account activity operations (default: no-op) */\n traceFn?: TraceCallback;\n};\n\n// =============================================================================\n// Action and Event Types\n// =============================================================================\n\n// Action types for the messaging system\nexport type AccountActivityServiceActions = never;\n\n// Allowed actions that AccountActivityService can call on other controllers\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS = [\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n 'BackendWebSocketService:connect',\n 'BackendWebSocketService:forceReconnection',\n 'BackendWebSocketService:subscribe',\n 'BackendWebSocketService:getConnectionInfo',\n 'BackendWebSocketService:channelHasSubscription',\n 'BackendWebSocketService:getSubscriptionsByChannel',\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n 'BackendWebSocketService:addChannelCallback',\n 'BackendWebSocketService:removeChannelCallback',\n 'RemoteFeatureFlagController:getState',\n] as const;\n\n// Allowed events that AccountActivityService can listen to\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS = [\n 'AccountTreeController:selectedAccountGroupChange',\n 'BackendWebSocketService:connectionStateChanged',\n 'RemoteFeatureFlagController:stateChange',\n] as const;\n\nexport type AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | BackendWebSocketServiceMethodActions\n | RemoteFeatureFlagControllerGetStateAction;\n\n// Event types for the messaging system\n\nexport type AccountActivityServiceTransactionUpdatedEvent = {\n type: `AccountActivityService:transactionUpdated`;\n payload: [Transaction];\n};\n\nexport type AccountActivityServiceBalanceUpdatedEvent = {\n type: `AccountActivityService:balanceUpdated`;\n payload: [{ address: string; chain: string; updates: BalanceUpdate[] }];\n};\n\nexport type AccountActivityServiceSubscriptionErrorEvent = {\n type: `AccountActivityService:subscriptionError`;\n payload: [{ addresses: string[]; error: string; operation: string }];\n};\n\nexport type AccountActivityServiceStatusChangedEvent = {\n type: `AccountActivityService:statusChanged`;\n payload: [\n {\n chainIds: string[];\n status: 'up' | 'down';\n timestamp?: number;\n },\n ];\n};\n\nexport type AccountActivityServiceEvents =\n | AccountActivityServiceTransactionUpdatedEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceSubscriptionErrorEvent\n | AccountActivityServiceStatusChangedEvent;\n\nexport type AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | BackendWebSocketServiceConnectionStateChangedEvent\n | RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type AccountActivityServiceMessenger = Messenger<\n typeof SERVICE_NAME,\n AccountActivityServiceActions | AllowedActions,\n AccountActivityServiceEvents | AllowedEvents\n>;\n\n// =============================================================================\n// Main Service Class\n// =============================================================================\n\n/**\n * High-performance service for real-time account activity monitoring using optimized\n * WebSocket subscriptions with direct callback routing. Automatically subscribes to\n * the currently selected account and switches subscriptions when the selected account changes.\n * Receives transactions and balance updates using the comprehensive AccountActivityMessage format.\n *\n * Performance Features:\n * - Direct callback routing (no EventEmitter overhead)\n * - Minimal subscription tracking (no duplication with BackendWebSocketService)\n * - Optimized cleanup for mobile environments\n * - Single-account subscription (only selected account)\n * - Comprehensive balance updates with transfer tracking\n *\n * Architecture:\n * - Uses messenger pattern to communicate with BackendWebSocketService\n * - AccountActivityService tracks channel-to-subscriptionId mappings via messenger calls\n * - Automatically subscribes to selected account on initialization\n * - Switches subscriptions when selected account changes\n * - No direct dependency on BackendWebSocketService (uses messenger instead)\n *\n * @example\n * ```typescript\n * const service = new AccountActivityService({\n * messenger: activityMessenger,\n * });\n *\n * // Service automatically subscribes to the currently selected account\n * // When user switches accounts, service automatically resubscribes\n *\n * // All transactions and balance updates are received via optimized\n * // WebSocket callbacks and processed with zero-allocation routing\n * // Balance updates include comprehensive transfer details and post-transaction balances\n * ```\n */\nexport class AccountActivityService {\n /**\n * The name of the service.\n */\n readonly name = SERVICE_NAME;\n\n readonly #messenger: AccountActivityServiceMessenger;\n\n readonly #options: Required<Omit<AccountActivityServiceOptions, 'traceFn'>>;\n\n readonly #trace: TraceCallback;\n\n // Track chains that are currently up (based on system notifications)\n readonly #chainsUp: Set<string> = new Set();\n\n // Debouncing for rapid status changes: buffers the latest status per chain\n // and coalesces bursts of system notifications into fewer downstream\n // `statusChanged` events.\n readonly #statusChangeDebouncer: {\n timer: NodeJS.Timeout | null;\n pendingChanges: Map<string, 'up' | 'down'>;\n } = {\n timer: null,\n pendingChanges: new Map(),\n };\n\n // =============================================================================\n // Constructor and Initialization\n // =============================================================================\n\n /**\n * Creates a new Account Activity service instance\n *\n * @param options - Configuration options including messenger\n */\n constructor(\n options: AccountActivityServiceOptions & {\n messenger: AccountActivityServiceMessenger;\n },\n ) {\n this.#messenger = options.messenger;\n\n // Set configuration with defaults\n this.#options = {\n subscriptionNamespace:\n options.subscriptionNamespace ?? SUBSCRIPTION_NAMESPACE,\n };\n\n // Default to no-op trace function to keep core platform-agnostic\n this.#trace =\n options.traceFn ??\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (((_request: any, fn?: any) => fn?.()) as TraceCallback);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleSelectedAccountChange(),\n );\n this.#messenger.subscribe(\n 'BackendWebSocketService:connectionStateChanged',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n (connectionInfo: WebSocketConnectionInfo) =>\n this.#handleWebSocketStateChange(connectionInfo),\n );\n this.#messenger.subscribe(\n // eslint-disable-next-line no-restricted-syntax\n 'RemoteFeatureFlagController:stateChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleFeatureFlagsStateChange(),\n // Only react to changes in the set of enabled chain prefixes. The\n // messenger compares selector results with strict equality, so the\n // selector must return a primitive rather than a fresh object.\n (state) =>\n this.#getSupportedChainPrefixes(state.remoteFeatureFlags).join(','),\n );\n this.#messenger.call('BackendWebSocketService:addChannelCallback', {\n channelName: `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n callback: (notification: ServerNotificationMessage) =>\n this.#handleSystemNotification(notification),\n });\n }\n\n /**\n * Subscribe to account activity (transactions and balance updates)\n * Addresses should be in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n *\n * @param subscription - The subscription configuration\n * @param subscription.addresses - Array of addresses to subscribe to, each in CAIP-10 format\n * or an `addresses` array for batch subscription\n */\n async #subscribe({ addresses }: SubscriptionOptions): Promise<void> {\n try {\n await this.#messenger.call('BackendWebSocketService:connect');\n\n // Derive new subscriptions to be created from the provided addresses,\n // filtering out any channels that already have an active subscription\n const channels = addresses\n .map((address) => `${this.#options.subscriptionNamespace}.${address}`)\n .filter(\n (channel) =>\n !this.#messenger.call(\n 'BackendWebSocketService:channelHasSubscription',\n channel,\n ),\n );\n\n if (channels.length === 0) {\n return;\n }\n\n // Create subscription using the proper subscribe method (this will be stored in WebSocketService's internal tracking)\n await this.#messenger.call('BackendWebSocketService:subscribe', {\n channels,\n channelType: this.#options.subscriptionNamespace, // e.g., 'account-activity.v1'\n callback: (notification: ServerNotificationMessage) => {\n this.#handleAccountActivityUpdate(\n notification.data as AccountActivityMessage,\n );\n },\n });\n } catch (error) {\n log('Subscription failed, forcing reconnection', { error });\n await this.#forceReconnection();\n }\n }\n\n /**\n * Handle account activity updates (transactions + balance changes)\n * Processes the comprehensive AccountActivityMessage format with detailed balance updates and transfers\n *\n * @param payload - The account activity message containing transaction and balance updates\n * @example AccountActivityMessage format handling:\n * Input: {\n * address: \"0xd14b52362b5b777ffa754c666ddec6722aaeee08\",\n * tx: { id: \"0x1cde...\", chain: \"eip155:8453\", status: \"confirmed\", timestamp: 1760099871, ... },\n * updates: [{\n * asset: { fungible: true, type: \"eip155:8453/erc20:0x833...\", unit: \"USDC\", decimals: 6 },\n * postBalance: { amount: \"0xc350\" },\n * transfers: [{ from: \"0x7b07...\", to: \"0xd14b...\", amount: \"0x2710\" }]\n * }]\n * }\n * Output: Transaction and balance updates published separately\n */\n #handleAccountActivityUpdate(payload: AccountActivityMessage): void {\n const { address, tx, updates } = payload;\n\n // Calculate time elapsed between transaction time and message receipt\n const txTimestampMs = tx.timestamp * 1000; // Convert Unix timestamp (seconds) to milliseconds\n const elapsedMs = Date.now() - txTimestampMs;\n\n log('Handling account activity update', {\n address,\n updateCount: updates.length,\n elapsedMs,\n });\n\n // Trace message receipt with latency from transaction time to now\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#trace(\n {\n name: `${SERVICE_NAME} Transaction Message`,\n data: {\n chain: tx.chain,\n status: tx.status,\n elapsed_ms: elapsedMs,\n },\n tags: {\n service: SERVICE_NAME,\n notification_type: this.#options.subscriptionNamespace,\n },\n },\n () => {\n // Process transaction update\n this.#messenger.publish(\n `AccountActivityService:transactionUpdated`,\n tx,\n );\n\n // Publish comprehensive balance updates with transfer details\n this.#messenger.publish(`AccountActivityService:balanceUpdated`, {\n address,\n chain: tx.chain,\n updates,\n });\n },\n );\n }\n\n /**\n * Handle selected account change event\n */\n async #handleSelectedAccountChange(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n try {\n // First, unsubscribe from all current account activity subscriptions to avoid multiple subscriptions\n await this.#unsubscribeFromAllAccountActivity();\n\n // Subscribe to the new selected accounts in CAIP-10 format\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n } catch (error) {\n log('Account change failed', { error });\n }\n }\n\n /**\n * Handle system notification for chain status changes\n * Publishes only the status change (delta) for affected chains\n *\n * @param notification - Server notification message containing chain status updates and timestamp\n */\n #handleSystemNotification(notification: ServerNotificationMessage): void {\n const data = notification.data as SystemNotificationData;\n\n // Validate required fields\n if (!data.chainIds || !Array.isArray(data.chainIds) || !data.status) {\n throw new Error(\n 'Invalid system notification data: missing chainIds or status',\n );\n }\n\n if (data.status === 'up') {\n for (const chainId of data.chainIds) {\n this.#chainsUp.add(chainId);\n }\n } else {\n for (const chainId of data.chainIds) {\n this.#chainsUp.delete(chainId);\n }\n }\n\n for (const chainId of data.chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, data.status);\n }\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n // Debounce window plus a random jitter, so clients reacting to the same\n // system notification don't publish in lockstep.\n const delay =\n STATUS_CHANGE_DEBOUNCE_MS + Math.random() * STATUS_CHANGE_JITTER_MS;\n\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, delay);\n\n log(`WebSocket status change - Buffered chains as ${data.status}`, {\n count: data.chainIds.length,\n chains: data.chainIds,\n status: data.status,\n });\n }\n\n /**\n * Publish the buffered status changes as batched `statusChanged` events, one\n * per status (`up`/`down`), then reset the buffer and timer.\n */\n #processAccumulatedStatusChanges(): void {\n const changes = Array.from(\n this.#statusChangeDebouncer.pendingChanges.entries(),\n );\n this.#statusChangeDebouncer.pendingChanges.clear();\n this.#statusChangeDebouncer.timer = null;\n\n // Group buffered chains by their latest status. A chain can only appear in\n // one group because the buffer keeps a single entry per chain.\n const grouped: Record<'up' | 'down', string[]> = { up: [], down: [] };\n for (const [chainId, status] of changes) {\n grouped[status].push(chainId);\n }\n\n for (const status of ['up', 'down'] as const) {\n const chainIds = grouped[status];\n if (chainIds.length === 0) {\n continue;\n }\n\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status,\n });\n\n log(`WebSocket status change - Published batched chains as ${status}`, {\n count: chainIds.length,\n chains: chainIds,\n status,\n });\n }\n }\n\n /**\n * Handle WebSocket connection state changes for fallback polling and resubscription\n *\n * @param connectionInfo - WebSocket connection state information\n */\n async #handleWebSocketStateChange(\n connectionInfo: WebSocketConnectionInfo,\n ): Promise<void> {\n const { state } = connectionInfo;\n\n if (state === WebSocketState.CONNECTED) {\n // WebSocket connected - resubscribe to selected account\n // The system notification will automatically provide the list of chains that are up\n await this.#subscribeToSelectedAccount();\n } else if (state === WebSocketState.DISCONNECTED) {\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n const chainsToMarkDown = new Set(this.#chainsUp);\n for (const chainId of this.#statusChangeDebouncer.pendingChanges.keys()) {\n chainsToMarkDown.add(chainId);\n }\n this.#statusChangeDebouncer.pendingChanges.clear();\n\n if (chainsToMarkDown.size > 0) {\n const chainIds = Array.from(chainsToMarkDown);\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status: 'down',\n timestamp: Date.now(),\n });\n\n log('WebSocket disconnection - Published tracked chains as down', {\n count: chainIds.length,\n chains: chainIds,\n });\n\n // Clear the tracking set since all chains are now down\n this.#chainsUp.clear();\n }\n }\n }\n\n // =============================================================================\n // Private Methods - Subscription Management\n // =============================================================================\n\n /**\n * Subscribe to the currently selected account only\n */\n async #subscribeToSelectedAccount(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n }\n\n /**\n * Unsubscribe from all account activity subscriptions for this service\n * Finds all channels matching the service's namespace and unsubscribes from them\n */\n async #unsubscribeFromAllAccountActivity(): Promise<void> {\n const accountActivitySubscriptions = this.#messenger.call(\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n this.#options.subscriptionNamespace,\n );\n\n // Unsubscribe from all matching subscriptions\n for (const subscription of accountActivitySubscriptions) {\n await subscription.unsubscribe();\n }\n }\n\n // =============================================================================\n // Private Methods - Utility Functions\n // =============================================================================\n\n /**\n * Convert a list of InternalAccount addresses to CAIP-10 format, using the first\n * supported chain prefix matching the account's scopes\n *\n * @param accounts - The internal accounts to convert\n * @returns The CAIP-10 formatted addresses (e.g. [`eip155:0:address`], meaning\n * all chains of that namespace), or an empty array if none of the account's\n * scopes are supported\n */\n #convertToCaip10Addresses(accounts: InternalAccount[]): string[] {\n const supportedChainPrefixes = this.#getSupportedChainPrefixes();\n return accounts.reduce<string[]>((result, account) => {\n const accountPrefix = supportedChainPrefixes.find((prefix) =>\n account.scopes.some((scope) => scope.startsWith(`${prefix}:`)),\n );\n\n if (!accountPrefix) {\n // Skip unsupported accounts\n return result;\n }\n\n result.push(`${accountPrefix}:0:${account.address}`);\n return result;\n }, []);\n }\n\n /**\n * Get the chain prefixes currently enabled for subscriptions: EVM is always\n * enabled, while other chains are gated behind their per-network remote\n * feature flag (enabled when the flag payload has `stage >= 1`).\n *\n * @param remoteFeatureFlags - The remote feature flags state to check for enabled chains.\n * @returns An array of enabled CAIP-2 namespace prefixes (e.g. `['eip155', 'solana']`)\n */\n #getSupportedChainPrefixes(\n remoteFeatureFlags: FeatureFlags = this.#messenger.call(\n 'RemoteFeatureFlagController:getState',\n ).remoteFeatureFlags,\n ): string[] {\n const prefixes: string[] = [...ALWAYS_SUPPORTED_CHAIN_PREFIXES];\n for (const [prefix, flagName] of Object.entries(\n CHAIN_PREFIX_FEATURE_FLAGS,\n )) {\n const flagValue = remoteFeatureFlags[flagName];\n if (\n isObject(flagValue) &&\n typeof flagValue.stage === 'number' &&\n flagValue.stage >= 1\n ) {\n prefixes.push(prefix);\n }\n }\n return prefixes;\n }\n\n /**\n * Handle remote feature flag changes: if the set of enabled chain prefixes\n * changed while connected, resubscribe the selected account so new chains\n * are picked up and disabled ones are dropped.\n */\n async #handleFeatureFlagsStateChange(): Promise<void> {\n try {\n const { state } = this.#messenger.call(\n 'BackendWebSocketService:getConnectionInfo',\n );\n if (state !== WebSocketState.CONNECTED) {\n // Not connected: the next connection will subscribe with fresh flags\n return;\n }\n\n await this.#unsubscribeFromAllAccountActivity();\n await this.#subscribeToSelectedAccount();\n } catch (error) {\n log('Feature flag change handling failed', { error });\n }\n }\n\n /**\n * Force WebSocket reconnection to clean up subscription state\n */\n async #forceReconnection(): Promise<void> {\n log('Forcing WebSocket reconnection to clean up subscription state');\n\n // Use the dedicated forceReconnection method which performs a controlled\n // disconnect-then-connect sequence to clean up subscription state\n await this.#messenger.call('BackendWebSocketService:forceReconnection');\n }\n\n // =============================================================================\n // Public Methods - Cleanup\n // =============================================================================\n\n /**\n * Destroy the service and clean up all resources\n * Optimized for fast cleanup during service destruction or mobile app termination\n */\n destroy(): void {\n // Cancel any pending batched status-change flush\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n // Clean up system notification callback\n this.#messenger.call(\n 'BackendWebSocketService:removeChannelCallback',\n `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n );\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AccountActivityService.d.cts","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountActivityService.d.cts","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AccountActivityService.d.mts","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AccountActivityService.d.mts","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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"}
@@ -144,7 +144,9 @@ export class AccountActivityService {
144
144
  // Promise result intentionally not awaited
145
145
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
146
146
  (connectionInfo) => __classPrivateFieldGet(this, _AccountActivityService_instances, "m", _AccountActivityService_handleWebSocketStateChange).call(this, connectionInfo));
147
- __classPrivateFieldGet(this, _AccountActivityService_messenger, "f").subscribe('RemoteFeatureFlagController:stateChange',
147
+ __classPrivateFieldGet(this, _AccountActivityService_messenger, "f").subscribe(
148
+ // eslint-disable-next-line no-restricted-syntax
149
+ 'RemoteFeatureFlagController:stateChange',
148
150
  // Promise result intentionally not awaited
149
151
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
150
152
  async () => await __classPrivateFieldGet(this, _AccountActivityService_instances, "m", _AccountActivityService_handleFeatureFlagsStateChange).call(this),
@@ -1 +1 @@
1
- {"version":3,"file":"AccountActivityService.mjs","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Account Activity Service for monitoring account transactions and balance changes\n *\n * This service subscribes to account activity and receives all transactions\n * and balance updates for those accounts via the comprehensive AccountActivityMessage format.\n */\n\nimport type {\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n} from '@metamask/account-tree-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n FeatureFlags,\n RemoteFeatureFlagControllerGetStateAction,\n RemoteFeatureFlagControllerStateChangeEvent,\n} from '@metamask/remote-feature-flag-controller';\nimport { isObject } from '@metamask/utils';\n\nimport { projectLogger, createModuleLogger } from '../logger.js';\nimport type {\n Transaction,\n AccountActivityMessage,\n BalanceUpdate,\n} from '../types.js';\nimport type { BackendWebSocketServiceMethodActions } from './BackendWebSocketService-method-action-types.js';\nimport type {\n WebSocketConnectionInfo,\n BackendWebSocketServiceConnectionStateChangedEvent,\n ServerNotificationMessage,\n} from './BackendWebSocketService.js';\nimport { WebSocketState } from './BackendWebSocketService.js';\n\n// =============================================================================\n// Types and Constants\n// =============================================================================\n\n/**\n * System notification data for chain status updates\n */\nexport type SystemNotificationData = {\n /** Array of chain IDs affected (e.g., ['eip155:137', 'eip155:1']) */\n chainIds: string[];\n /** Status of the chains: 'down' or 'up' */\n status: 'down' | 'up';\n /** Timestamp of the notification */\n timestamp?: number;\n};\n\nconst SERVICE_NAME = 'AccountActivityService';\n\nconst log = createModuleLogger(projectLogger, SERVICE_NAME);\n\nconst MESSENGER_EXPOSED_METHODS = [] as const;\n\nconst SUBSCRIPTION_NAMESPACE = 'account-activity.v1';\n\n// Window (in ms) over which consecutive system notifications are accumulated\n// before a single batched `statusChanged` event is published. Coalescing bursts\n// of chain up/down notifications avoids flooding consumers.\nconst STATUS_CHANGE_DEBOUNCE_MS = 1000;\n\n// Maximum random jitter (in ms) added to the debounce window before publishing.\n// Spreading the publish across a random delay prevents many clients reacting to\n// the same system notification from publishing in lockstep (a thundering herd\n// on downstream consumers).\nconst STATUS_CHANGE_JITTER_MS = 1000;\n\n// EVM subscriptions are always enabled.\nconst ALWAYS_SUPPORTED_CHAIN_PREFIXES = ['eip155'] as const;\n\n// Non-EVM chains are gated behind the\n// per-network snaps-migration remote feature flags: a chain is\n// enabled when its flag payload has `stage >= 1`.\nconst CHAIN_PREFIX_FEATURE_FLAGS = {\n solana: 'networkAssetsSnapsMigrationSolana',\n tron: 'networkAssetsSnapsMigrationTron',\n stellar: 'networkAssetsSnapsMigrationStellar',\n} as const;\n\n/**\n * Account subscription options\n */\nexport type SubscriptionOptions = {\n /**\n * Array of addresses to subscribe to, each in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n */\n addresses: string[];\n};\n\n/**\n * Configuration options for the account activity service\n */\nexport type AccountActivityServiceOptions = {\n /** Custom subscription namespace (default: 'account-activity.v1') */\n subscriptionNamespace?: string;\n /** Optional callback to trace performance of account activity operations (default: no-op) */\n traceFn?: TraceCallback;\n};\n\n// =============================================================================\n// Action and Event Types\n// =============================================================================\n\n// Action types for the messaging system\nexport type AccountActivityServiceActions = never;\n\n// Allowed actions that AccountActivityService can call on other controllers\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS = [\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n 'BackendWebSocketService:connect',\n 'BackendWebSocketService:forceReconnection',\n 'BackendWebSocketService:subscribe',\n 'BackendWebSocketService:getConnectionInfo',\n 'BackendWebSocketService:channelHasSubscription',\n 'BackendWebSocketService:getSubscriptionsByChannel',\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n 'BackendWebSocketService:addChannelCallback',\n 'BackendWebSocketService:removeChannelCallback',\n 'RemoteFeatureFlagController:getState',\n] as const;\n\n// Allowed events that AccountActivityService can listen to\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS = [\n 'AccountTreeController:selectedAccountGroupChange',\n 'BackendWebSocketService:connectionStateChanged',\n 'RemoteFeatureFlagController:stateChange',\n] as const;\n\nexport type AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | BackendWebSocketServiceMethodActions\n | RemoteFeatureFlagControllerGetStateAction;\n\n// Event types for the messaging system\n\nexport type AccountActivityServiceTransactionUpdatedEvent = {\n type: `AccountActivityService:transactionUpdated`;\n payload: [Transaction];\n};\n\nexport type AccountActivityServiceBalanceUpdatedEvent = {\n type: `AccountActivityService:balanceUpdated`;\n payload: [{ address: string; chain: string; updates: BalanceUpdate[] }];\n};\n\nexport type AccountActivityServiceSubscriptionErrorEvent = {\n type: `AccountActivityService:subscriptionError`;\n payload: [{ addresses: string[]; error: string; operation: string }];\n};\n\nexport type AccountActivityServiceStatusChangedEvent = {\n type: `AccountActivityService:statusChanged`;\n payload: [\n {\n chainIds: string[];\n status: 'up' | 'down';\n timestamp?: number;\n },\n ];\n};\n\nexport type AccountActivityServiceEvents =\n | AccountActivityServiceTransactionUpdatedEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceSubscriptionErrorEvent\n | AccountActivityServiceStatusChangedEvent;\n\nexport type AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | BackendWebSocketServiceConnectionStateChangedEvent\n | RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type AccountActivityServiceMessenger = Messenger<\n typeof SERVICE_NAME,\n AccountActivityServiceActions | AllowedActions,\n AccountActivityServiceEvents | AllowedEvents\n>;\n\n// =============================================================================\n// Main Service Class\n// =============================================================================\n\n/**\n * High-performance service for real-time account activity monitoring using optimized\n * WebSocket subscriptions with direct callback routing. Automatically subscribes to\n * the currently selected account and switches subscriptions when the selected account changes.\n * Receives transactions and balance updates using the comprehensive AccountActivityMessage format.\n *\n * Performance Features:\n * - Direct callback routing (no EventEmitter overhead)\n * - Minimal subscription tracking (no duplication with BackendWebSocketService)\n * - Optimized cleanup for mobile environments\n * - Single-account subscription (only selected account)\n * - Comprehensive balance updates with transfer tracking\n *\n * Architecture:\n * - Uses messenger pattern to communicate with BackendWebSocketService\n * - AccountActivityService tracks channel-to-subscriptionId mappings via messenger calls\n * - Automatically subscribes to selected account on initialization\n * - Switches subscriptions when selected account changes\n * - No direct dependency on BackendWebSocketService (uses messenger instead)\n *\n * @example\n * ```typescript\n * const service = new AccountActivityService({\n * messenger: activityMessenger,\n * });\n *\n * // Service automatically subscribes to the currently selected account\n * // When user switches accounts, service automatically resubscribes\n *\n * // All transactions and balance updates are received via optimized\n * // WebSocket callbacks and processed with zero-allocation routing\n * // Balance updates include comprehensive transfer details and post-transaction balances\n * ```\n */\nexport class AccountActivityService {\n /**\n * The name of the service.\n */\n readonly name = SERVICE_NAME;\n\n readonly #messenger: AccountActivityServiceMessenger;\n\n readonly #options: Required<Omit<AccountActivityServiceOptions, 'traceFn'>>;\n\n readonly #trace: TraceCallback;\n\n // Track chains that are currently up (based on system notifications)\n readonly #chainsUp: Set<string> = new Set();\n\n // Debouncing for rapid status changes: buffers the latest status per chain\n // and coalesces bursts of system notifications into fewer downstream\n // `statusChanged` events.\n readonly #statusChangeDebouncer: {\n timer: NodeJS.Timeout | null;\n pendingChanges: Map<string, 'up' | 'down'>;\n } = {\n timer: null,\n pendingChanges: new Map(),\n };\n\n // =============================================================================\n // Constructor and Initialization\n // =============================================================================\n\n /**\n * Creates a new Account Activity service instance\n *\n * @param options - Configuration options including messenger\n */\n constructor(\n options: AccountActivityServiceOptions & {\n messenger: AccountActivityServiceMessenger;\n },\n ) {\n this.#messenger = options.messenger;\n\n // Set configuration with defaults\n this.#options = {\n subscriptionNamespace:\n options.subscriptionNamespace ?? SUBSCRIPTION_NAMESPACE,\n };\n\n // Default to no-op trace function to keep core platform-agnostic\n this.#trace =\n options.traceFn ??\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (((_request: any, fn?: any) => fn?.()) as TraceCallback);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleSelectedAccountChange(),\n );\n this.#messenger.subscribe(\n 'BackendWebSocketService:connectionStateChanged',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n (connectionInfo: WebSocketConnectionInfo) =>\n this.#handleWebSocketStateChange(connectionInfo),\n );\n this.#messenger.subscribe(\n 'RemoteFeatureFlagController:stateChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleFeatureFlagsStateChange(),\n // Only react to changes in the set of enabled chain prefixes. The\n // messenger compares selector results with strict equality, so the\n // selector must return a primitive rather than a fresh object.\n (state) =>\n this.#getSupportedChainPrefixes(state.remoteFeatureFlags).join(','),\n );\n this.#messenger.call('BackendWebSocketService:addChannelCallback', {\n channelName: `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n callback: (notification: ServerNotificationMessage) =>\n this.#handleSystemNotification(notification),\n });\n }\n\n /**\n * Subscribe to account activity (transactions and balance updates)\n * Addresses should be in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n *\n * @param subscription - The subscription configuration\n * @param subscription.addresses - Array of addresses to subscribe to, each in CAIP-10 format\n * or an `addresses` array for batch subscription\n */\n async #subscribe({ addresses }: SubscriptionOptions): Promise<void> {\n try {\n await this.#messenger.call('BackendWebSocketService:connect');\n\n // Derive new subscriptions to be created from the provided addresses,\n // filtering out any channels that already have an active subscription\n const channels = addresses\n .map((address) => `${this.#options.subscriptionNamespace}.${address}`)\n .filter(\n (channel) =>\n !this.#messenger.call(\n 'BackendWebSocketService:channelHasSubscription',\n channel,\n ),\n );\n\n if (channels.length === 0) {\n return;\n }\n\n // Create subscription using the proper subscribe method (this will be stored in WebSocketService's internal tracking)\n await this.#messenger.call('BackendWebSocketService:subscribe', {\n channels,\n channelType: this.#options.subscriptionNamespace, // e.g., 'account-activity.v1'\n callback: (notification: ServerNotificationMessage) => {\n this.#handleAccountActivityUpdate(\n notification.data as AccountActivityMessage,\n );\n },\n });\n } catch (error) {\n log('Subscription failed, forcing reconnection', { error });\n await this.#forceReconnection();\n }\n }\n\n /**\n * Handle account activity updates (transactions + balance changes)\n * Processes the comprehensive AccountActivityMessage format with detailed balance updates and transfers\n *\n * @param payload - The account activity message containing transaction and balance updates\n * @example AccountActivityMessage format handling:\n * Input: {\n * address: \"0xd14b52362b5b777ffa754c666ddec6722aaeee08\",\n * tx: { id: \"0x1cde...\", chain: \"eip155:8453\", status: \"confirmed\", timestamp: 1760099871, ... },\n * updates: [{\n * asset: { fungible: true, type: \"eip155:8453/erc20:0x833...\", unit: \"USDC\", decimals: 6 },\n * postBalance: { amount: \"0xc350\" },\n * transfers: [{ from: \"0x7b07...\", to: \"0xd14b...\", amount: \"0x2710\" }]\n * }]\n * }\n * Output: Transaction and balance updates published separately\n */\n #handleAccountActivityUpdate(payload: AccountActivityMessage): void {\n const { address, tx, updates } = payload;\n\n // Calculate time elapsed between transaction time and message receipt\n const txTimestampMs = tx.timestamp * 1000; // Convert Unix timestamp (seconds) to milliseconds\n const elapsedMs = Date.now() - txTimestampMs;\n\n log('Handling account activity update', {\n address,\n updateCount: updates.length,\n elapsedMs,\n });\n\n // Trace message receipt with latency from transaction time to now\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#trace(\n {\n name: `${SERVICE_NAME} Transaction Message`,\n data: {\n chain: tx.chain,\n status: tx.status,\n elapsed_ms: elapsedMs,\n },\n tags: {\n service: SERVICE_NAME,\n notification_type: this.#options.subscriptionNamespace,\n },\n },\n () => {\n // Process transaction update\n this.#messenger.publish(\n `AccountActivityService:transactionUpdated`,\n tx,\n );\n\n // Publish comprehensive balance updates with transfer details\n this.#messenger.publish(`AccountActivityService:balanceUpdated`, {\n address,\n chain: tx.chain,\n updates,\n });\n },\n );\n }\n\n /**\n * Handle selected account change event\n */\n async #handleSelectedAccountChange(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n try {\n // First, unsubscribe from all current account activity subscriptions to avoid multiple subscriptions\n await this.#unsubscribeFromAllAccountActivity();\n\n // Subscribe to the new selected accounts in CAIP-10 format\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n } catch (error) {\n log('Account change failed', { error });\n }\n }\n\n /**\n * Handle system notification for chain status changes\n * Publishes only the status change (delta) for affected chains\n *\n * @param notification - Server notification message containing chain status updates and timestamp\n */\n #handleSystemNotification(notification: ServerNotificationMessage): void {\n const data = notification.data as SystemNotificationData;\n\n // Validate required fields\n if (!data.chainIds || !Array.isArray(data.chainIds) || !data.status) {\n throw new Error(\n 'Invalid system notification data: missing chainIds or status',\n );\n }\n\n if (data.status === 'up') {\n for (const chainId of data.chainIds) {\n this.#chainsUp.add(chainId);\n }\n } else {\n for (const chainId of data.chainIds) {\n this.#chainsUp.delete(chainId);\n }\n }\n\n for (const chainId of data.chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, data.status);\n }\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n // Debounce window plus a random jitter, so clients reacting to the same\n // system notification don't publish in lockstep.\n const delay =\n STATUS_CHANGE_DEBOUNCE_MS + Math.random() * STATUS_CHANGE_JITTER_MS;\n\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, delay);\n\n log(`WebSocket status change - Buffered chains as ${data.status}`, {\n count: data.chainIds.length,\n chains: data.chainIds,\n status: data.status,\n });\n }\n\n /**\n * Publish the buffered status changes as batched `statusChanged` events, one\n * per status (`up`/`down`), then reset the buffer and timer.\n */\n #processAccumulatedStatusChanges(): void {\n const changes = Array.from(\n this.#statusChangeDebouncer.pendingChanges.entries(),\n );\n this.#statusChangeDebouncer.pendingChanges.clear();\n this.#statusChangeDebouncer.timer = null;\n\n // Group buffered chains by their latest status. A chain can only appear in\n // one group because the buffer keeps a single entry per chain.\n const grouped: Record<'up' | 'down', string[]> = { up: [], down: [] };\n for (const [chainId, status] of changes) {\n grouped[status].push(chainId);\n }\n\n for (const status of ['up', 'down'] as const) {\n const chainIds = grouped[status];\n if (chainIds.length === 0) {\n continue;\n }\n\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status,\n });\n\n log(`WebSocket status change - Published batched chains as ${status}`, {\n count: chainIds.length,\n chains: chainIds,\n status,\n });\n }\n }\n\n /**\n * Handle WebSocket connection state changes for fallback polling and resubscription\n *\n * @param connectionInfo - WebSocket connection state information\n */\n async #handleWebSocketStateChange(\n connectionInfo: WebSocketConnectionInfo,\n ): Promise<void> {\n const { state } = connectionInfo;\n\n if (state === WebSocketState.CONNECTED) {\n // WebSocket connected - resubscribe to selected account\n // The system notification will automatically provide the list of chains that are up\n await this.#subscribeToSelectedAccount();\n } else if (state === WebSocketState.DISCONNECTED) {\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n const chainsToMarkDown = new Set(this.#chainsUp);\n for (const chainId of this.#statusChangeDebouncer.pendingChanges.keys()) {\n chainsToMarkDown.add(chainId);\n }\n this.#statusChangeDebouncer.pendingChanges.clear();\n\n if (chainsToMarkDown.size > 0) {\n const chainIds = Array.from(chainsToMarkDown);\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status: 'down',\n timestamp: Date.now(),\n });\n\n log('WebSocket disconnection - Published tracked chains as down', {\n count: chainIds.length,\n chains: chainIds,\n });\n\n // Clear the tracking set since all chains are now down\n this.#chainsUp.clear();\n }\n }\n }\n\n // =============================================================================\n // Private Methods - Subscription Management\n // =============================================================================\n\n /**\n * Subscribe to the currently selected account only\n */\n async #subscribeToSelectedAccount(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n }\n\n /**\n * Unsubscribe from all account activity subscriptions for this service\n * Finds all channels matching the service's namespace and unsubscribes from them\n */\n async #unsubscribeFromAllAccountActivity(): Promise<void> {\n const accountActivitySubscriptions = this.#messenger.call(\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n this.#options.subscriptionNamespace,\n );\n\n // Unsubscribe from all matching subscriptions\n for (const subscription of accountActivitySubscriptions) {\n await subscription.unsubscribe();\n }\n }\n\n // =============================================================================\n // Private Methods - Utility Functions\n // =============================================================================\n\n /**\n * Convert a list of InternalAccount addresses to CAIP-10 format, using the first\n * supported chain prefix matching the account's scopes\n *\n * @param accounts - The internal accounts to convert\n * @returns The CAIP-10 formatted addresses (e.g. [`eip155:0:address`], meaning\n * all chains of that namespace), or an empty array if none of the account's\n * scopes are supported\n */\n #convertToCaip10Addresses(accounts: InternalAccount[]): string[] {\n const supportedChainPrefixes = this.#getSupportedChainPrefixes();\n return accounts.reduce<string[]>((result, account) => {\n const accountPrefix = supportedChainPrefixes.find((prefix) =>\n account.scopes.some((scope) => scope.startsWith(`${prefix}:`)),\n );\n\n if (!accountPrefix) {\n // Skip unsupported accounts\n return result;\n }\n\n result.push(`${accountPrefix}:0:${account.address}`);\n return result;\n }, []);\n }\n\n /**\n * Get the chain prefixes currently enabled for subscriptions: EVM is always\n * enabled, while other chains are gated behind their per-network remote\n * feature flag (enabled when the flag payload has `stage >= 1`).\n *\n * @param remoteFeatureFlags - The remote feature flags state to check for enabled chains.\n * @returns An array of enabled CAIP-2 namespace prefixes (e.g. `['eip155', 'solana']`)\n */\n #getSupportedChainPrefixes(\n remoteFeatureFlags: FeatureFlags = this.#messenger.call(\n 'RemoteFeatureFlagController:getState',\n ).remoteFeatureFlags,\n ): string[] {\n const prefixes: string[] = [...ALWAYS_SUPPORTED_CHAIN_PREFIXES];\n for (const [prefix, flagName] of Object.entries(\n CHAIN_PREFIX_FEATURE_FLAGS,\n )) {\n const flagValue = remoteFeatureFlags[flagName];\n if (\n isObject(flagValue) &&\n typeof flagValue.stage === 'number' &&\n flagValue.stage >= 1\n ) {\n prefixes.push(prefix);\n }\n }\n return prefixes;\n }\n\n /**\n * Handle remote feature flag changes: if the set of enabled chain prefixes\n * changed while connected, resubscribe the selected account so new chains\n * are picked up and disabled ones are dropped.\n */\n async #handleFeatureFlagsStateChange(): Promise<void> {\n try {\n const { state } = this.#messenger.call(\n 'BackendWebSocketService:getConnectionInfo',\n );\n if (state !== WebSocketState.CONNECTED) {\n // Not connected: the next connection will subscribe with fresh flags\n return;\n }\n\n await this.#unsubscribeFromAllAccountActivity();\n await this.#subscribeToSelectedAccount();\n } catch (error) {\n log('Feature flag change handling failed', { error });\n }\n }\n\n /**\n * Force WebSocket reconnection to clean up subscription state\n */\n async #forceReconnection(): Promise<void> {\n log('Forcing WebSocket reconnection to clean up subscription state');\n\n // Use the dedicated forceReconnection method which performs a controlled\n // disconnect-then-connect sequence to clean up subscription state\n await this.#messenger.call('BackendWebSocketService:forceReconnection');\n }\n\n // =============================================================================\n // Public Methods - Cleanup\n // =============================================================================\n\n /**\n * Destroy the service and clean up all resources\n * Optimized for fast cleanup during service destruction or mobile app termination\n */\n destroy(): void {\n // Cancel any pending batched status-change flush\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n // Clean up system notification callback\n this.#messenger.call(\n 'BackendWebSocketService:removeChannelCallback',\n `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"AccountActivityService.mjs","sourceRoot":"","sources":["../../src/ws/AccountActivityService.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Account Activity Service for monitoring account transactions and balance changes\n *\n * This service subscribes to account activity and receives all transactions\n * and balance updates for those accounts via the comprehensive AccountActivityMessage format.\n */\n\nimport type {\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n} from '@metamask/account-tree-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n FeatureFlags,\n RemoteFeatureFlagControllerGetStateAction,\n RemoteFeatureFlagControllerStateChangeEvent,\n} from '@metamask/remote-feature-flag-controller';\nimport { isObject } from '@metamask/utils';\n\nimport { projectLogger, createModuleLogger } from '../logger.js';\nimport type {\n Transaction,\n AccountActivityMessage,\n BalanceUpdate,\n} from '../types.js';\nimport type { BackendWebSocketServiceMethodActions } from './BackendWebSocketService-method-action-types.js';\nimport type {\n WebSocketConnectionInfo,\n BackendWebSocketServiceConnectionStateChangedEvent,\n ServerNotificationMessage,\n} from './BackendWebSocketService.js';\nimport { WebSocketState } from './BackendWebSocketService.js';\n\n// =============================================================================\n// Types and Constants\n// =============================================================================\n\n/**\n * System notification data for chain status updates\n */\nexport type SystemNotificationData = {\n /** Array of chain IDs affected (e.g., ['eip155:137', 'eip155:1']) */\n chainIds: string[];\n /** Status of the chains: 'down' or 'up' */\n status: 'down' | 'up';\n /** Timestamp of the notification */\n timestamp?: number;\n};\n\nconst SERVICE_NAME = 'AccountActivityService';\n\nconst log = createModuleLogger(projectLogger, SERVICE_NAME);\n\nconst MESSENGER_EXPOSED_METHODS = [] as const;\n\nconst SUBSCRIPTION_NAMESPACE = 'account-activity.v1';\n\n// Window (in ms) over which consecutive system notifications are accumulated\n// before a single batched `statusChanged` event is published. Coalescing bursts\n// of chain up/down notifications avoids flooding consumers.\nconst STATUS_CHANGE_DEBOUNCE_MS = 1000;\n\n// Maximum random jitter (in ms) added to the debounce window before publishing.\n// Spreading the publish across a random delay prevents many clients reacting to\n// the same system notification from publishing in lockstep (a thundering herd\n// on downstream consumers).\nconst STATUS_CHANGE_JITTER_MS = 1000;\n\n// EVM subscriptions are always enabled.\nconst ALWAYS_SUPPORTED_CHAIN_PREFIXES = ['eip155'] as const;\n\n// Non-EVM chains are gated behind the\n// per-network snaps-migration remote feature flags: a chain is\n// enabled when its flag payload has `stage >= 1`.\nconst CHAIN_PREFIX_FEATURE_FLAGS = {\n solana: 'networkAssetsSnapsMigrationSolana',\n tron: 'networkAssetsSnapsMigrationTron',\n stellar: 'networkAssetsSnapsMigrationStellar',\n} as const;\n\n/**\n * Account subscription options\n */\nexport type SubscriptionOptions = {\n /**\n * Array of addresses to subscribe to, each in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n */\n addresses: string[];\n};\n\n/**\n * Configuration options for the account activity service\n */\nexport type AccountActivityServiceOptions = {\n /** Custom subscription namespace (default: 'account-activity.v1') */\n subscriptionNamespace?: string;\n /** Optional callback to trace performance of account activity operations (default: no-op) */\n traceFn?: TraceCallback;\n};\n\n// =============================================================================\n// Action and Event Types\n// =============================================================================\n\n// Action types for the messaging system\nexport type AccountActivityServiceActions = never;\n\n// Allowed actions that AccountActivityService can call on other controllers\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_ACTIONS = [\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n 'BackendWebSocketService:connect',\n 'BackendWebSocketService:forceReconnection',\n 'BackendWebSocketService:subscribe',\n 'BackendWebSocketService:getConnectionInfo',\n 'BackendWebSocketService:channelHasSubscription',\n 'BackendWebSocketService:getSubscriptionsByChannel',\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n 'BackendWebSocketService:addChannelCallback',\n 'BackendWebSocketService:removeChannelCallback',\n 'RemoteFeatureFlagController:getState',\n] as const;\n\n// Allowed events that AccountActivityService can listen to\nexport const ACCOUNT_ACTIVITY_SERVICE_ALLOWED_EVENTS = [\n 'AccountTreeController:selectedAccountGroupChange',\n 'BackendWebSocketService:connectionStateChanged',\n 'RemoteFeatureFlagController:stateChange',\n] as const;\n\nexport type AllowedActions =\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | BackendWebSocketServiceMethodActions\n | RemoteFeatureFlagControllerGetStateAction;\n\n// Event types for the messaging system\n\nexport type AccountActivityServiceTransactionUpdatedEvent = {\n type: `AccountActivityService:transactionUpdated`;\n payload: [Transaction];\n};\n\nexport type AccountActivityServiceBalanceUpdatedEvent = {\n type: `AccountActivityService:balanceUpdated`;\n payload: [{ address: string; chain: string; updates: BalanceUpdate[] }];\n};\n\nexport type AccountActivityServiceSubscriptionErrorEvent = {\n type: `AccountActivityService:subscriptionError`;\n payload: [{ addresses: string[]; error: string; operation: string }];\n};\n\nexport type AccountActivityServiceStatusChangedEvent = {\n type: `AccountActivityService:statusChanged`;\n payload: [\n {\n chainIds: string[];\n status: 'up' | 'down';\n timestamp?: number;\n },\n ];\n};\n\nexport type AccountActivityServiceEvents =\n | AccountActivityServiceTransactionUpdatedEvent\n | AccountActivityServiceBalanceUpdatedEvent\n | AccountActivityServiceSubscriptionErrorEvent\n | AccountActivityServiceStatusChangedEvent;\n\nexport type AllowedEvents =\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | BackendWebSocketServiceConnectionStateChangedEvent\n | RemoteFeatureFlagControllerStateChangeEvent;\n\nexport type AccountActivityServiceMessenger = Messenger<\n typeof SERVICE_NAME,\n AccountActivityServiceActions | AllowedActions,\n AccountActivityServiceEvents | AllowedEvents\n>;\n\n// =============================================================================\n// Main Service Class\n// =============================================================================\n\n/**\n * High-performance service for real-time account activity monitoring using optimized\n * WebSocket subscriptions with direct callback routing. Automatically subscribes to\n * the currently selected account and switches subscriptions when the selected account changes.\n * Receives transactions and balance updates using the comprehensive AccountActivityMessage format.\n *\n * Performance Features:\n * - Direct callback routing (no EventEmitter overhead)\n * - Minimal subscription tracking (no duplication with BackendWebSocketService)\n * - Optimized cleanup for mobile environments\n * - Single-account subscription (only selected account)\n * - Comprehensive balance updates with transfer tracking\n *\n * Architecture:\n * - Uses messenger pattern to communicate with BackendWebSocketService\n * - AccountActivityService tracks channel-to-subscriptionId mappings via messenger calls\n * - Automatically subscribes to selected account on initialization\n * - Switches subscriptions when selected account changes\n * - No direct dependency on BackendWebSocketService (uses messenger instead)\n *\n * @example\n * ```typescript\n * const service = new AccountActivityService({\n * messenger: activityMessenger,\n * });\n *\n * // Service automatically subscribes to the currently selected account\n * // When user switches accounts, service automatically resubscribes\n *\n * // All transactions and balance updates are received via optimized\n * // WebSocket callbacks and processed with zero-allocation routing\n * // Balance updates include comprehensive transfer details and post-transaction balances\n * ```\n */\nexport class AccountActivityService {\n /**\n * The name of the service.\n */\n readonly name = SERVICE_NAME;\n\n readonly #messenger: AccountActivityServiceMessenger;\n\n readonly #options: Required<Omit<AccountActivityServiceOptions, 'traceFn'>>;\n\n readonly #trace: TraceCallback;\n\n // Track chains that are currently up (based on system notifications)\n readonly #chainsUp: Set<string> = new Set();\n\n // Debouncing for rapid status changes: buffers the latest status per chain\n // and coalesces bursts of system notifications into fewer downstream\n // `statusChanged` events.\n readonly #statusChangeDebouncer: {\n timer: NodeJS.Timeout | null;\n pendingChanges: Map<string, 'up' | 'down'>;\n } = {\n timer: null,\n pendingChanges: new Map(),\n };\n\n // =============================================================================\n // Constructor and Initialization\n // =============================================================================\n\n /**\n * Creates a new Account Activity service instance\n *\n * @param options - Configuration options including messenger\n */\n constructor(\n options: AccountActivityServiceOptions & {\n messenger: AccountActivityServiceMessenger;\n },\n ) {\n this.#messenger = options.messenger;\n\n // Set configuration with defaults\n this.#options = {\n subscriptionNamespace:\n options.subscriptionNamespace ?? SUBSCRIPTION_NAMESPACE,\n };\n\n // Default to no-op trace function to keep core platform-agnostic\n this.#trace =\n options.traceFn ??\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (((_request: any, fn?: any) => fn?.()) as TraceCallback);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleSelectedAccountChange(),\n );\n this.#messenger.subscribe(\n 'BackendWebSocketService:connectionStateChanged',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n (connectionInfo: WebSocketConnectionInfo) =>\n this.#handleWebSocketStateChange(connectionInfo),\n );\n this.#messenger.subscribe(\n // eslint-disable-next-line no-restricted-syntax\n 'RemoteFeatureFlagController:stateChange',\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n async () => await this.#handleFeatureFlagsStateChange(),\n // Only react to changes in the set of enabled chain prefixes. The\n // messenger compares selector results with strict equality, so the\n // selector must return a primitive rather than a fresh object.\n (state) =>\n this.#getSupportedChainPrefixes(state.remoteFeatureFlags).join(','),\n );\n this.#messenger.call('BackendWebSocketService:addChannelCallback', {\n channelName: `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n callback: (notification: ServerNotificationMessage) =>\n this.#handleSystemNotification(notification),\n });\n }\n\n /**\n * Subscribe to account activity (transactions and balance updates)\n * Addresses should be in CAIP-10 format (e.g., \"eip155:0:0x1234...\" or \"solana:0:ABC123...\")\n *\n * @param subscription - The subscription configuration\n * @param subscription.addresses - Array of addresses to subscribe to, each in CAIP-10 format\n * or an `addresses` array for batch subscription\n */\n async #subscribe({ addresses }: SubscriptionOptions): Promise<void> {\n try {\n await this.#messenger.call('BackendWebSocketService:connect');\n\n // Derive new subscriptions to be created from the provided addresses,\n // filtering out any channels that already have an active subscription\n const channels = addresses\n .map((address) => `${this.#options.subscriptionNamespace}.${address}`)\n .filter(\n (channel) =>\n !this.#messenger.call(\n 'BackendWebSocketService:channelHasSubscription',\n channel,\n ),\n );\n\n if (channels.length === 0) {\n return;\n }\n\n // Create subscription using the proper subscribe method (this will be stored in WebSocketService's internal tracking)\n await this.#messenger.call('BackendWebSocketService:subscribe', {\n channels,\n channelType: this.#options.subscriptionNamespace, // e.g., 'account-activity.v1'\n callback: (notification: ServerNotificationMessage) => {\n this.#handleAccountActivityUpdate(\n notification.data as AccountActivityMessage,\n );\n },\n });\n } catch (error) {\n log('Subscription failed, forcing reconnection', { error });\n await this.#forceReconnection();\n }\n }\n\n /**\n * Handle account activity updates (transactions + balance changes)\n * Processes the comprehensive AccountActivityMessage format with detailed balance updates and transfers\n *\n * @param payload - The account activity message containing transaction and balance updates\n * @example AccountActivityMessage format handling:\n * Input: {\n * address: \"0xd14b52362b5b777ffa754c666ddec6722aaeee08\",\n * tx: { id: \"0x1cde...\", chain: \"eip155:8453\", status: \"confirmed\", timestamp: 1760099871, ... },\n * updates: [{\n * asset: { fungible: true, type: \"eip155:8453/erc20:0x833...\", unit: \"USDC\", decimals: 6 },\n * postBalance: { amount: \"0xc350\" },\n * transfers: [{ from: \"0x7b07...\", to: \"0xd14b...\", amount: \"0x2710\" }]\n * }]\n * }\n * Output: Transaction and balance updates published separately\n */\n #handleAccountActivityUpdate(payload: AccountActivityMessage): void {\n const { address, tx, updates } = payload;\n\n // Calculate time elapsed between transaction time and message receipt\n const txTimestampMs = tx.timestamp * 1000; // Convert Unix timestamp (seconds) to milliseconds\n const elapsedMs = Date.now() - txTimestampMs;\n\n log('Handling account activity update', {\n address,\n updateCount: updates.length,\n elapsedMs,\n });\n\n // Trace message receipt with latency from transaction time to now\n // Promise result intentionally not awaited\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#trace(\n {\n name: `${SERVICE_NAME} Transaction Message`,\n data: {\n chain: tx.chain,\n status: tx.status,\n elapsed_ms: elapsedMs,\n },\n tags: {\n service: SERVICE_NAME,\n notification_type: this.#options.subscriptionNamespace,\n },\n },\n () => {\n // Process transaction update\n this.#messenger.publish(\n `AccountActivityService:transactionUpdated`,\n tx,\n );\n\n // Publish comprehensive balance updates with transfer details\n this.#messenger.publish(`AccountActivityService:balanceUpdated`, {\n address,\n chain: tx.chain,\n updates,\n });\n },\n );\n }\n\n /**\n * Handle selected account change event\n */\n async #handleSelectedAccountChange(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n try {\n // First, unsubscribe from all current account activity subscriptions to avoid multiple subscriptions\n await this.#unsubscribeFromAllAccountActivity();\n\n // Subscribe to the new selected accounts in CAIP-10 format\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n } catch (error) {\n log('Account change failed', { error });\n }\n }\n\n /**\n * Handle system notification for chain status changes\n * Publishes only the status change (delta) for affected chains\n *\n * @param notification - Server notification message containing chain status updates and timestamp\n */\n #handleSystemNotification(notification: ServerNotificationMessage): void {\n const data = notification.data as SystemNotificationData;\n\n // Validate required fields\n if (!data.chainIds || !Array.isArray(data.chainIds) || !data.status) {\n throw new Error(\n 'Invalid system notification data: missing chainIds or status',\n );\n }\n\n if (data.status === 'up') {\n for (const chainId of data.chainIds) {\n this.#chainsUp.add(chainId);\n }\n } else {\n for (const chainId of data.chainIds) {\n this.#chainsUp.delete(chainId);\n }\n }\n\n for (const chainId of data.chainIds) {\n this.#statusChangeDebouncer.pendingChanges.set(chainId, data.status);\n }\n\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n }\n\n // Debounce window plus a random jitter, so clients reacting to the same\n // system notification don't publish in lockstep.\n const delay =\n STATUS_CHANGE_DEBOUNCE_MS + Math.random() * STATUS_CHANGE_JITTER_MS;\n\n this.#statusChangeDebouncer.timer = setTimeout(() => {\n this.#processAccumulatedStatusChanges();\n }, delay);\n\n log(`WebSocket status change - Buffered chains as ${data.status}`, {\n count: data.chainIds.length,\n chains: data.chainIds,\n status: data.status,\n });\n }\n\n /**\n * Publish the buffered status changes as batched `statusChanged` events, one\n * per status (`up`/`down`), then reset the buffer and timer.\n */\n #processAccumulatedStatusChanges(): void {\n const changes = Array.from(\n this.#statusChangeDebouncer.pendingChanges.entries(),\n );\n this.#statusChangeDebouncer.pendingChanges.clear();\n this.#statusChangeDebouncer.timer = null;\n\n // Group buffered chains by their latest status. A chain can only appear in\n // one group because the buffer keeps a single entry per chain.\n const grouped: Record<'up' | 'down', string[]> = { up: [], down: [] };\n for (const [chainId, status] of changes) {\n grouped[status].push(chainId);\n }\n\n for (const status of ['up', 'down'] as const) {\n const chainIds = grouped[status];\n if (chainIds.length === 0) {\n continue;\n }\n\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status,\n });\n\n log(`WebSocket status change - Published batched chains as ${status}`, {\n count: chainIds.length,\n chains: chainIds,\n status,\n });\n }\n }\n\n /**\n * Handle WebSocket connection state changes for fallback polling and resubscription\n *\n * @param connectionInfo - WebSocket connection state information\n */\n async #handleWebSocketStateChange(\n connectionInfo: WebSocketConnectionInfo,\n ): Promise<void> {\n const { state } = connectionInfo;\n\n if (state === WebSocketState.CONNECTED) {\n // WebSocket connected - resubscribe to selected account\n // The system notification will automatically provide the list of chains that are up\n await this.#subscribeToSelectedAccount();\n } else if (state === WebSocketState.DISCONNECTED) {\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n const chainsToMarkDown = new Set(this.#chainsUp);\n for (const chainId of this.#statusChangeDebouncer.pendingChanges.keys()) {\n chainsToMarkDown.add(chainId);\n }\n this.#statusChangeDebouncer.pendingChanges.clear();\n\n if (chainsToMarkDown.size > 0) {\n const chainIds = Array.from(chainsToMarkDown);\n this.#messenger.publish(`AccountActivityService:statusChanged`, {\n chainIds,\n status: 'down',\n timestamp: Date.now(),\n });\n\n log('WebSocket disconnection - Published tracked chains as down', {\n count: chainIds.length,\n chains: chainIds,\n });\n\n // Clear the tracking set since all chains are now down\n this.#chainsUp.clear();\n }\n }\n }\n\n // =============================================================================\n // Private Methods - Subscription Management\n // =============================================================================\n\n /**\n * Subscribe to the currently selected account only\n */\n async #subscribeToSelectedAccount(): Promise<void> {\n const selectedAccounts = this.#messenger.call(\n 'AccountTreeController:getAccountsFromSelectedAccountGroup',\n );\n\n await this.#subscribe({\n addresses: this.#convertToCaip10Addresses(selectedAccounts),\n });\n }\n\n /**\n * Unsubscribe from all account activity subscriptions for this service\n * Finds all channels matching the service's namespace and unsubscribes from them\n */\n async #unsubscribeFromAllAccountActivity(): Promise<void> {\n const accountActivitySubscriptions = this.#messenger.call(\n 'BackendWebSocketService:findSubscriptionsByChannelPrefix',\n this.#options.subscriptionNamespace,\n );\n\n // Unsubscribe from all matching subscriptions\n for (const subscription of accountActivitySubscriptions) {\n await subscription.unsubscribe();\n }\n }\n\n // =============================================================================\n // Private Methods - Utility Functions\n // =============================================================================\n\n /**\n * Convert a list of InternalAccount addresses to CAIP-10 format, using the first\n * supported chain prefix matching the account's scopes\n *\n * @param accounts - The internal accounts to convert\n * @returns The CAIP-10 formatted addresses (e.g. [`eip155:0:address`], meaning\n * all chains of that namespace), or an empty array if none of the account's\n * scopes are supported\n */\n #convertToCaip10Addresses(accounts: InternalAccount[]): string[] {\n const supportedChainPrefixes = this.#getSupportedChainPrefixes();\n return accounts.reduce<string[]>((result, account) => {\n const accountPrefix = supportedChainPrefixes.find((prefix) =>\n account.scopes.some((scope) => scope.startsWith(`${prefix}:`)),\n );\n\n if (!accountPrefix) {\n // Skip unsupported accounts\n return result;\n }\n\n result.push(`${accountPrefix}:0:${account.address}`);\n return result;\n }, []);\n }\n\n /**\n * Get the chain prefixes currently enabled for subscriptions: EVM is always\n * enabled, while other chains are gated behind their per-network remote\n * feature flag (enabled when the flag payload has `stage >= 1`).\n *\n * @param remoteFeatureFlags - The remote feature flags state to check for enabled chains.\n * @returns An array of enabled CAIP-2 namespace prefixes (e.g. `['eip155', 'solana']`)\n */\n #getSupportedChainPrefixes(\n remoteFeatureFlags: FeatureFlags = this.#messenger.call(\n 'RemoteFeatureFlagController:getState',\n ).remoteFeatureFlags,\n ): string[] {\n const prefixes: string[] = [...ALWAYS_SUPPORTED_CHAIN_PREFIXES];\n for (const [prefix, flagName] of Object.entries(\n CHAIN_PREFIX_FEATURE_FLAGS,\n )) {\n const flagValue = remoteFeatureFlags[flagName];\n if (\n isObject(flagValue) &&\n typeof flagValue.stage === 'number' &&\n flagValue.stage >= 1\n ) {\n prefixes.push(prefix);\n }\n }\n return prefixes;\n }\n\n /**\n * Handle remote feature flag changes: if the set of enabled chain prefixes\n * changed while connected, resubscribe the selected account so new chains\n * are picked up and disabled ones are dropped.\n */\n async #handleFeatureFlagsStateChange(): Promise<void> {\n try {\n const { state } = this.#messenger.call(\n 'BackendWebSocketService:getConnectionInfo',\n );\n if (state !== WebSocketState.CONNECTED) {\n // Not connected: the next connection will subscribe with fresh flags\n return;\n }\n\n await this.#unsubscribeFromAllAccountActivity();\n await this.#subscribeToSelectedAccount();\n } catch (error) {\n log('Feature flag change handling failed', { error });\n }\n }\n\n /**\n * Force WebSocket reconnection to clean up subscription state\n */\n async #forceReconnection(): Promise<void> {\n log('Forcing WebSocket reconnection to clean up subscription state');\n\n // Use the dedicated forceReconnection method which performs a controlled\n // disconnect-then-connect sequence to clean up subscription state\n await this.#messenger.call('BackendWebSocketService:forceReconnection');\n }\n\n // =============================================================================\n // Public Methods - Cleanup\n // =============================================================================\n\n /**\n * Destroy the service and clean up all resources\n * Optimized for fast cleanup during service destruction or mobile app termination\n */\n destroy(): void {\n // Cancel any pending batched status-change flush\n if (this.#statusChangeDebouncer.timer) {\n clearTimeout(this.#statusChangeDebouncer.timer);\n this.#statusChangeDebouncer.timer = null;\n }\n\n // Clean up system notification callback\n this.#messenger.call(\n 'BackendWebSocketService:removeChannelCallback',\n `system-notifications.v1.${this.#options.subscriptionNamespace}`,\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/core-backend",
3
- "version": "9.0.0-preview-abca9bcea",
3
+ "version": "9.0.0-preview-8bfa290fb",
4
4
  "description": "Core backend services for MetaMask",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -55,12 +55,12 @@
55
55
  "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
56
56
  },
57
57
  "dependencies": {
58
- "@metamask/account-tree-controller": "^8.1.0",
58
+ "@metamask/account-tree-controller": "^8.0.0",
59
59
  "@metamask/controller-utils": "^12.3.0",
60
60
  "@metamask/keyring-controller": "^27.1.1",
61
61
  "@metamask/messenger": "^2.0.0",
62
62
  "@metamask/profile-sync-controller": "^29.0.0",
63
- "@metamask/remote-feature-flag-controller": "^6.1.1",
63
+ "@metamask/remote-feature-flag-controller": "^6.1.0",
64
64
  "@metamask/utils": "^11.12.0",
65
65
  "@tanstack/query-core": "^5.62.16",
66
66
  "async-mutex": "^0.5.0",