@metamask-previews/profile-metrics-controller 4.0.2-preview-40d5fb1e2 → 4.0.2-preview-a3e31582e

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/ProfileMetricsController-method-action-types.cjs.map +1 -1
  3. package/dist/ProfileMetricsController-method-action-types.d.cts.map +1 -1
  4. package/dist/ProfileMetricsController-method-action-types.d.mts.map +1 -1
  5. package/dist/ProfileMetricsController-method-action-types.mjs.map +1 -1
  6. package/dist/ProfileMetricsController.cjs +3 -3
  7. package/dist/ProfileMetricsController.cjs.map +1 -1
  8. package/dist/ProfileMetricsController.d.cts +5 -6
  9. package/dist/ProfileMetricsController.d.cts.map +1 -1
  10. package/dist/ProfileMetricsController.d.mts +5 -6
  11. package/dist/ProfileMetricsController.d.mts.map +1 -1
  12. package/dist/ProfileMetricsController.mjs.map +1 -1
  13. package/dist/ProfileMetricsService-method-action-types.cjs.map +1 -1
  14. package/dist/ProfileMetricsService-method-action-types.d.cts.map +1 -1
  15. package/dist/ProfileMetricsService-method-action-types.d.mts.map +1 -1
  16. package/dist/ProfileMetricsService-method-action-types.mjs.map +1 -1
  17. package/dist/ProfileMetricsService.cjs.map +1 -1
  18. package/dist/ProfileMetricsService.d.cts.map +1 -1
  19. package/dist/ProfileMetricsService.d.mts.map +1 -1
  20. package/dist/ProfileMetricsService.mjs.map +1 -1
  21. package/dist/ProofOfOwnershipService-method-action-types.cjs.map +1 -1
  22. package/dist/ProofOfOwnershipService-method-action-types.d.cts.map +1 -1
  23. package/dist/ProofOfOwnershipService-method-action-types.d.mts.map +1 -1
  24. package/dist/ProofOfOwnershipService-method-action-types.mjs.map +1 -1
  25. package/dist/ProofOfOwnershipService.cjs +4 -4
  26. package/dist/ProofOfOwnershipService.cjs.map +1 -1
  27. package/dist/ProofOfOwnershipService.d.cts.map +1 -1
  28. package/dist/ProofOfOwnershipService.d.mts.map +1 -1
  29. package/dist/ProofOfOwnershipService.mjs.map +1 -1
  30. package/dist/index.cjs +10 -10
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts.map +1 -1
  33. package/dist/index.d.mts.map +1 -1
  34. package/dist/index.mjs.map +1 -1
  35. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Changed
11
+
12
+ - Bump `@metamask/transaction-controller` from `^69.0.0` to `^69.2.1` ([#9568](https://github.com/MetaMask/core/pull/9568), [#9589](https://github.com/MetaMask/core/pull/9589), [#9593](https://github.com/MetaMask/core/pull/9593))
13
+
10
14
  ## [4.0.2]
11
15
 
12
16
  ### Changed
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController-method-action-types.cjs","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsController } from './ProfileMetricsController';\n\n/**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\nexport type ProfileMetricsControllerSkipInitialDelayAction = {\n type: `ProfileMetricsController:skipInitialDelay`;\n handler: ProfileMetricsController['skipInitialDelay'];\n};\n\n/**\n * Union of all ProfileMetricsController action types.\n */\nexport type ProfileMetricsControllerMethodActions =\n ProfileMetricsControllerSkipInitialDelayAction;\n"]}
1
+ {"version":3,"file":"ProfileMetricsController-method-action-types.cjs","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsController } from './ProfileMetricsController.js';\n\n/**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\nexport type ProfileMetricsControllerSkipInitialDelayAction = {\n type: `ProfileMetricsController:skipInitialDelay`;\n handler: ProfileMetricsController['skipInitialDelay'];\n};\n\n/**\n * Union of all ProfileMetricsController action types.\n */\nexport type ProfileMetricsControllerMethodActions =\n ProfileMetricsControllerSkipInitialDelayAction;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,uCAAmC;AAE3E;;;GAGG;AACH,MAAM,MAAM,8CAA8C,GAAG;IAC3D,IAAI,EAAE,2CAA2C,CAAC;IAClD,OAAO,EAAE,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;CACvD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAC/C,8CAA8C,CAAC"}
1
+ {"version":3,"file":"ProfileMetricsController-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,uCAAsC;AAE9E;;;GAGG;AACH,MAAM,MAAM,8CAA8C,GAAG;IAC3D,IAAI,EAAE,2CAA2C,CAAC;IAClD,OAAO,EAAE,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;CACvD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAC/C,8CAA8C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,uCAAmC;AAE3E;;;GAGG;AACH,MAAM,MAAM,8CAA8C,GAAG;IAC3D,IAAI,EAAE,2CAA2C,CAAC;IAClD,OAAO,EAAE,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;CACvD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAC/C,8CAA8C,CAAC"}
1
+ {"version":3,"file":"ProfileMetricsController-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,uCAAsC;AAE9E;;;GAGG;AACH,MAAM,MAAM,8CAA8C,GAAG;IAC3D,IAAI,EAAE,2CAA2C,CAAC;IAClD,OAAO,EAAE,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;CACvD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qCAAqC,GAC/C,8CAA8C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController-method-action-types.mjs","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsController } from './ProfileMetricsController';\n\n/**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\nexport type ProfileMetricsControllerSkipInitialDelayAction = {\n type: `ProfileMetricsController:skipInitialDelay`;\n handler: ProfileMetricsController['skipInitialDelay'];\n};\n\n/**\n * Union of all ProfileMetricsController action types.\n */\nexport type ProfileMetricsControllerMethodActions =\n ProfileMetricsControllerSkipInitialDelayAction;\n"]}
1
+ {"version":3,"file":"ProfileMetricsController-method-action-types.mjs","sourceRoot":"","sources":["../src/ProfileMetricsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsController } from './ProfileMetricsController.js';\n\n/**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\nexport type ProfileMetricsControllerSkipInitialDelayAction = {\n type: `ProfileMetricsController:skipInitialDelay`;\n handler: ProfileMetricsController['skipInitialDelay'];\n};\n\n/**\n * Union of all ProfileMetricsController action types.\n */\nexport type ProfileMetricsControllerMethodActions =\n ProfileMetricsControllerSkipInitialDelayAction;\n"]}
@@ -16,7 +16,7 @@ exports.ProfileMetricsController = exports.getDefaultProfileMetricsControllerSta
16
16
  const polling_controller_1 = require("@metamask/polling-controller");
17
17
  const utils_1 = require("@metamask/utils");
18
18
  const async_mutex_1 = require("async-mutex");
19
- const canonicalize_1 = require("./utils/canonicalize.cjs");
19
+ const canonicalize_js_1 = require("./utils/canonicalize.cjs");
20
20
  /**
21
21
  * The name of the {@link ProfileMetricsController}, used to namespace the
22
22
  * controller's actions and events and to namespace the controller's state data
@@ -220,7 +220,7 @@ async function _ProfileMetricsController_attachProofs(accounts, fullAccountsByAd
220
220
  throw new Error(`Scope not found for account ${fullAccount.id}`);
221
221
  }
222
222
  const { namespace } = (0, utils_1.parseCaipChainId)(scope);
223
- const canonicalAddress = (0, canonicalize_1.canonicalizeAddress)(fullAccount.address, namespace);
223
+ const canonicalAddress = (0, canonicalize_js_1.canonicalizeAddress)(fullAccount.address, namespace);
224
224
  candidates.set(queued.address, {
225
225
  account: fullAccount,
226
226
  canonicalAddress,
@@ -230,7 +230,7 @@ async function _ProfileMetricsController_attachProofs(accounts, fullAccountsByAd
230
230
  catch (error) {
231
231
  // Unsupported namespaces are an expected pass-through; anything
232
232
  // else is logged so a new namespace doesn't go unnoticed.
233
- if (!(error instanceof canonicalize_1.ProofUnsupportedNamespaceError)) {
233
+ if (!(error instanceof canonicalize_js_1.ProofUnsupportedNamespaceError)) {
234
234
  console.error(`Skipping proof for account ${fullAccount.id}:`, error);
235
235
  }
236
236
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController.cjs","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerGetStateAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { TransactionControllerTransactionSubmittedEvent } from '@metamask/transaction-controller';\nimport { Duration, inMilliseconds, parseCaipChainId } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport type { ProfileMetricsControllerMethodActions } from './ProfileMetricsController-method-action-types';\nimport type {\n AccountOwnershipProof,\n AccountWithScopes,\n} from './ProfileMetricsService';\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize';\n\n/**\n * The name of the {@link ProfileMetricsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'ProfileMetricsController';\n\n/**\n * The default delay duration before data is sent for the first time.\n */\nexport const DEFAULT_INITIAL_DELAY_DURATION = inMilliseconds(\n 1,\n Duration.Minute,\n);\n\n/**\n * Describes the shape of the state object for {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerState = {\n /**\n * Whether existing accounts have been added\n * to the queue.\n */\n initialEnqueueCompleted: boolean;\n /**\n * The queue of accounts to be synced.\n * Each key is an entropy source ID, and each value is an array of account\n * addresses associated with that entropy source. Accounts with no entropy\n * source ID are grouped under the key \"null\".\n */\n syncQueue: Record<string, AccountWithScopes[]>;\n /**\n * The timestamp when the first data sending can be attempted.\n */\n initialDelayEndTimestamp?: number;\n /**\n * Whether previously-synced accounts have been re-enqueued so their\n * proofs of ownership are submitted alongside everything else. Set on\n * the first unlock after upgrading to a version that signs proofs of\n * ownership; fresh installs flip this on their initial sync since the\n * first poll already attaches proofs.\n */\n proofBackfillEnqueued: boolean;\n};\n\n/**\n * The metadata for each property in {@link ProfileMetricsControllerState}.\n */\nconst profileMetricsControllerMetadata = {\n initialEnqueueCompleted: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n syncQueue: {\n persist: true,\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n usedInUi: false,\n },\n initialDelayEndTimestamp: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n proofBackfillEnqueued: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<ProfileMetricsControllerState>;\n\n/**\n * Constructs the default {@link ProfileMetricsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link ProfileMetricsController} state.\n */\nexport function getDefaultProfileMetricsControllerState(): ProfileMetricsControllerState {\n return {\n initialEnqueueCompleted: false,\n syncQueue: {},\n proofBackfillEnqueued: false,\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = ['skipInitialDelay'] as const;\n\n/**\n * Retrieves the state of the {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ProfileMetricsControllerState\n>;\n\n/**\n * Actions that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerActions =\n | ProfileMetricsControllerGetStateAction\n | ProfileMetricsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsControllerMessenger} calls.\n */\ntype AllowedActions =\n | ProfileMetricsServiceMethodActions\n | ProofOfOwnershipServiceMethodActions\n | AccountsControllerGetStateAction;\n\n/**\n * Published when the state of {@link ProfileMetricsController} changes.\n */\nexport type ProfileMetricsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n ProfileMetricsControllerState\n >;\n\n/**\n * Events that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerEvents =\n ProfileMetricsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ProfileMetricsControllerMessenger} subscribes\n * to.\n */\ntype AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | TransactionControllerTransactionSubmittedEvent;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerMessenger = Messenger<\n typeof controllerName,\n ProfileMetricsControllerActions | AllowedActions,\n ProfileMetricsControllerEvents | AllowedEvents\n>;\n\n/**\n * Manages user profile metrics.\n *\n * For users who opt-in to metrics, this controller ensures we have metrics about their user\n * profile (metrics ID and accounts).\n */\nexport class ProfileMetricsController extends StaticIntervalPollingController()<\n typeof controllerName,\n ProfileMetricsControllerState,\n ProfileMetricsControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n readonly #assertUserOptedIn: () => boolean;\n\n readonly #getMetaMetricsId: () => string;\n\n readonly #initialDelayDuration: number;\n\n /**\n * Constructs a new {@link ProfileMetricsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.assertUserOptedIn - A function that asserts whether the user has\n * opted in to user profile features. If the user has not opted in, sync\n * operations will be no-ops.\n * @param args.getMetaMetricsId - A function that returns the MetaMetrics ID\n * of the user.\n * @param args.interval - The interval, in milliseconds, at which the controller will\n * attempt to send user profile data. Defaults to 10 seconds.\n * @param args.initialDelayDuration - The delay duration before data is sent\n * for the first time, in milliseconds. Defaults to 10 minutes.\n */\n constructor({\n messenger,\n state,\n assertUserOptedIn,\n getMetaMetricsId,\n interval = 10 * 1000,\n initialDelayDuration = DEFAULT_INITIAL_DELAY_DURATION,\n }: {\n messenger: ProfileMetricsControllerMessenger;\n state?: Partial<ProfileMetricsControllerState>;\n interval?: number;\n assertUserOptedIn: () => boolean;\n getMetaMetricsId: () => string;\n initialDelayDuration?: number;\n }) {\n super({\n messenger,\n metadata: profileMetricsControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultProfileMetricsControllerState(),\n ...state,\n },\n });\n\n this.#assertUserOptedIn = assertUserOptedIn;\n this.#getMetaMetricsId = getMetaMetricsId;\n this.#initialDelayDuration = initialDelayDuration;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n if (this.#assertUserOptedIn()) {\n // If the user has already opted in at the start of the session,\n // it must have opted in during onboarding, or during a previous session.\n this.skipInitialDelay();\n }\n this.#enqueueAccountsIfNeeded().catch(\n this.messenger.captureException ?? console.error,\n );\n this.startPolling(null);\n });\n\n this.messenger.subscribe('KeyringController:lock', () =>\n this.stopAllPolling(),\n );\n\n this.messenger.subscribe('TransactionController:transactionSubmitted', () =>\n this.skipInitialDelay(),\n );\n\n this.messenger.subscribe('AccountsController:accountAdded', (account) => {\n this.#addAccountToQueue(account).catch(console.error);\n });\n\n this.messenger.subscribe('AccountsController:accountRemoved', (account) => {\n this.#removeAccountFromQueue(account).catch(console.error);\n });\n\n this.setIntervalLength(interval);\n }\n\n /**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\n skipInitialDelay(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp = Date.now();\n });\n }\n\n /**\n * Execute a single poll to sync user profile data.\n *\n * The queued accounts are sent to the ProfileMetricsService, each with\n * a proof of ownership when one can be produced (see {@link #attachProofs}),\n * and the sync queue is cleared. This operation is mutexed to prevent\n * concurrent executions.\n *\n * @returns A promise that resolves when the poll is complete.\n */\n async _executePoll(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n this.#setInitialDelayEndTimestampIfNull();\n if (!this.#isInitialDelayComplete()) {\n return;\n }\n const fullAccountsByAddress = this.#getFullAccountsByAddress();\n for (const [entropySourceId, accounts] of Object.entries(\n this.state.syncQueue,\n )) {\n const normalizedEntropySourceId =\n entropySourceId === 'null' ? null : entropySourceId;\n // Skip proof-of-ownership for accounts without an entropy source\n const accountsWithProofs =\n normalizedEntropySourceId === null\n ? accounts\n : await this.#attachProofs(\n accounts,\n fullAccountsByAddress,\n normalizedEntropySourceId,\n );\n try {\n await this.messenger.call('ProfileMetricsService:submitMetrics', {\n metametricsId: this.#getMetaMetricsId(),\n entropySourceId: normalizedEntropySourceId,\n accounts: accountsWithProofs,\n });\n this.update((state) => {\n delete state.syncQueue[entropySourceId];\n });\n } catch (error) {\n // We want to log the error but continue processing other batches.\n console.error(\n `Failed to submit profile metrics for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n }\n });\n }\n\n /**\n * Attach a proof of ownership to each account in a single entropy-source\n * batch when possible, canonicalizing the address along the way.\n *\n * Per-account failures (unknown namespace, snap missing the\n * `signProofOfOwnership` method, snap rejection) and whole-batch nonce\n * failures are caught and downgraded to \"submit without a proof\" so the\n * batch still goes through and the proof is retried on the next poll.\n *\n * @param accounts - The queued accounts for a single batch.\n * @param fullAccountsByAddress - Live `InternalAccount` lookup keyed by address.\n * @param entropySourceId - The entropy source ID for this batch. Callers\n * are expected to short-circuit before invoking this method when the\n * batch has no entropy source; see `_executePoll` for why.\n * @returns The accounts with `proof` populated where signing succeeded.\n */\n async #attachProofs(\n accounts: AccountWithScopes[],\n fullAccountsByAddress: Map<string, InternalAccount>,\n entropySourceId: string,\n ): Promise<AccountWithScopes[]> {\n const candidates = new Map<\n string,\n { account: InternalAccount; canonicalAddress: string }\n >();\n const identifiers = new Set<string>();\n for (const queued of accounts) {\n const fullAccount = fullAccountsByAddress.get(queued.address);\n if (!fullAccount) {\n continue;\n }\n try {\n const [scope] = fullAccount.scopes;\n if (!scope) {\n throw new Error(`Scope not found for account ${fullAccount.id}`);\n }\n const { namespace } = parseCaipChainId(scope);\n const canonicalAddress = canonicalizeAddress(\n fullAccount.address,\n namespace,\n );\n candidates.set(queued.address, {\n account: fullAccount,\n canonicalAddress,\n });\n identifiers.add(canonicalAddress);\n } catch (error) {\n // Unsupported namespaces are an expected pass-through; anything\n // else is logged so a new namespace doesn't go unnoticed.\n if (!(error instanceof ProofUnsupportedNamespaceError)) {\n console.error(`Skipping proof for account ${fullAccount.id}:`, error);\n }\n }\n }\n\n if (candidates.size === 0) {\n return accounts;\n }\n\n let nonces: Record<string, string> = {};\n try {\n nonces = await this.messenger.call('ProfileMetricsService:fetchNonces', {\n identifiers: [...identifiers],\n entropySourceId,\n });\n } catch (error) {\n console.error(\n `Failed to fetch proof-of-ownership nonces for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n\n return await Promise.all(\n accounts.map(async (queued): Promise<AccountWithScopes> => {\n const candidate = candidates.get(queued.address);\n if (!candidate) {\n return queued;\n }\n const nonce = nonces[candidate.canonicalAddress];\n if (!nonce) {\n return { ...queued, address: candidate.canonicalAddress };\n }\n let proof: AccountOwnershipProof;\n try {\n proof = await this.messenger.call('ProofOfOwnershipService:sign', {\n account: candidate.account,\n nonce,\n });\n } catch (error) {\n console.error(\n `Failed to sign proof of ownership for account ${candidate.account.id}:`,\n error,\n );\n return { ...queued, address: candidate.canonicalAddress };\n }\n return {\n address: candidate.canonicalAddress,\n scopes: queued.scopes,\n proof,\n };\n }),\n );\n }\n\n /**\n * Snapshot the live `InternalAccount` map keyed by address for the\n * current poll.\n *\n * @returns A map of address → `InternalAccount`.\n */\n #getFullAccountsByAddress(): Map<string, InternalAccount> {\n const byAddress = new Map<string, InternalAccount>();\n const accountsState = this.messenger.call('AccountsController:getState');\n for (const account of Object.values(\n accountsState.internalAccounts.accounts,\n )) {\n byAddress.set(account.address, account);\n }\n return byAddress;\n }\n\n /**\n * Enqueue all currently-known accounts onto the sync queue if needed.\n * Single entry point covering both the fresh-install first sync and\n * the one-time proof-of-ownership backfill for users upgrading.\n *\n * Bails for opted-out users (the poll wouldn't drain the queue\n * anyway), and bails once both bootstrap steps have already run.\n * Otherwise enqueues all known accounts and flips both flags so this\n * becomes a permanent no-op for the lifetime of the install.\n */\n async #enqueueAccountsIfNeeded(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n if (\n this.state.initialEnqueueCompleted &&\n this.state.proofBackfillEnqueued\n ) {\n return;\n }\n const groupedAccounts = groupAccountsByEntropySourceId(\n Object.values(\n this.messenger.call('AccountsController:getState').internalAccounts\n .accounts,\n ),\n );\n this.update((state) => {\n // Replace the queue rather than append. `AccountsController` is\n // the source of truth and the queue is otherwise kept in sync\n // with it via the `accountAdded` / `accountRemoved` subscriptions,\n // so assigning here avoids duplicating entries that survived from\n // a prior session or were pushed earlier in this same unlock\n // cycle. Duplicates would matter because nonces are single-use:\n // letting one through causes `#attachProofs` to sign and submit\n // twice with the same nonce.\n state.syncQueue = groupedAccounts;\n state.initialEnqueueCompleted = true;\n state.proofBackfillEnqueued = true;\n });\n });\n }\n\n /**\n * Set the initial delay end timestamp if it is not already set.\n */\n #setInitialDelayEndTimestampIfNull(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp ??=\n Date.now() + this.#initialDelayDuration;\n });\n }\n\n /**\n * Check if the initial delay end timestamp is in the past.\n *\n * @returns True if the initial delay period has completed, false otherwise.\n */\n #isInitialDelayComplete(): boolean {\n return (\n this.state.initialDelayEndTimestamp !== undefined &&\n Date.now() >= this.state.initialDelayEndTimestamp\n );\n }\n\n /**\n * Queue the given account to be synced at the next poll.\n *\n * @param account - The account to sync.\n */\n async #addAccountToQueue(account: InternalAccount): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n const entropySourceId = getAccountEntropySourceId(account) ?? 'null';\n if (!state.syncQueue[entropySourceId]) {\n state.syncQueue[entropySourceId] = [];\n }\n state.syncQueue[entropySourceId].push({\n address: account.address,\n scopes: account.scopes,\n });\n });\n });\n }\n\n /**\n * Remove the given account from the sync queue.\n *\n * @param account - The account address to remove.\n */\n async #removeAccountFromQueue(account: string): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n for (const [entropySourceId, groupedAddresses] of Object.entries(\n state.syncQueue,\n )) {\n const index = groupedAddresses.findIndex(\n ({ address }) => address === account,\n );\n if (index === -1) {\n continue;\n }\n groupedAddresses.splice(index, 1);\n if (groupedAddresses.length === 0) {\n delete state.syncQueue[entropySourceId];\n }\n break;\n }\n });\n });\n }\n}\n\n/**\n * Retrieves the entropy source ID from the given account, if it exists.\n *\n * @param account - The account from which to retrieve the entropy source ID.\n * @returns The entropy source ID, or null if it does not exist.\n */\nfunction getAccountEntropySourceId(account: InternalAccount): string | null {\n if (account.options.entropy?.type === 'mnemonic') {\n return account.options.entropy.id;\n }\n return null;\n}\n\n/**\n * Groups accounts by their entropy source ID.\n *\n * @param accounts - The accounts to group.\n * @returns An object where each key is an entropy source ID and each value is\n * an array of account addresses associated with that entropy source ID.\n */\nfunction groupAccountsByEntropySourceId(\n accounts: InternalAccount[],\n): Record<string, AccountWithScopes[]> {\n return accounts.reduce(\n (result: Record<string, AccountWithScopes[]>, account) => {\n const entropySourceId = getAccountEntropySourceId(account);\n const key = entropySourceId ?? 'null';\n if (!result[key]) {\n result[key] = [];\n }\n result[key].push({ address: account.address, scopes: account.scopes });\n return result;\n },\n {},\n );\n}\n"]}
1
+ {"version":3,"file":"ProfileMetricsController.cjs","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerGetStateAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { TransactionControllerTransactionSubmittedEvent } from '@metamask/transaction-controller';\nimport { Duration, inMilliseconds, parseCaipChainId } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport type { ProfileMetricsControllerMethodActions } from './ProfileMetricsController-method-action-types.js';\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types.js';\nimport type {\n AccountOwnershipProof,\n AccountWithScopes,\n} from './ProfileMetricsService.js';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types.js';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize.js';\n\n/**\n * The name of the {@link ProfileMetricsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'ProfileMetricsController';\n\n/**\n * The default delay duration before data is sent for the first time.\n */\nexport const DEFAULT_INITIAL_DELAY_DURATION = inMilliseconds(\n 1,\n Duration.Minute,\n);\n\n/**\n * Describes the shape of the state object for {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerState = {\n /**\n * Whether existing accounts have been added\n * to the queue.\n */\n initialEnqueueCompleted: boolean;\n /**\n * The queue of accounts to be synced.\n * Each key is an entropy source ID, and each value is an array of account\n * addresses associated with that entropy source. Accounts with no entropy\n * source ID are grouped under the key \"null\".\n */\n syncQueue: Record<string, AccountWithScopes[]>;\n /**\n * The timestamp when the first data sending can be attempted.\n */\n initialDelayEndTimestamp?: number;\n /**\n * Whether previously-synced accounts have been re-enqueued so their\n * proofs of ownership are submitted alongside everything else. Set on\n * the first unlock after upgrading to a version that signs proofs of\n * ownership; fresh installs flip this on their initial sync since the\n * first poll already attaches proofs.\n */\n proofBackfillEnqueued: boolean;\n};\n\n/**\n * The metadata for each property in {@link ProfileMetricsControllerState}.\n */\nconst profileMetricsControllerMetadata = {\n initialEnqueueCompleted: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n syncQueue: {\n persist: true,\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n usedInUi: false,\n },\n initialDelayEndTimestamp: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n proofBackfillEnqueued: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<ProfileMetricsControllerState>;\n\n/**\n * Constructs the default {@link ProfileMetricsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link ProfileMetricsController} state.\n */\nexport function getDefaultProfileMetricsControllerState(): ProfileMetricsControllerState {\n return {\n initialEnqueueCompleted: false,\n syncQueue: {},\n proofBackfillEnqueued: false,\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = ['skipInitialDelay'] as const;\n\n/**\n * Retrieves the state of the {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ProfileMetricsControllerState\n>;\n\n/**\n * Actions that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerActions =\n | ProfileMetricsControllerGetStateAction\n | ProfileMetricsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsControllerMessenger} calls.\n */\ntype AllowedActions =\n | ProfileMetricsServiceMethodActions\n | ProofOfOwnershipServiceMethodActions\n | AccountsControllerGetStateAction;\n\n/**\n * Published when the state of {@link ProfileMetricsController} changes.\n */\nexport type ProfileMetricsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n ProfileMetricsControllerState\n >;\n\n/**\n * Events that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerEvents =\n ProfileMetricsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ProfileMetricsControllerMessenger} subscribes\n * to.\n */\ntype AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | TransactionControllerTransactionSubmittedEvent;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerMessenger = Messenger<\n typeof controllerName,\n ProfileMetricsControllerActions | AllowedActions,\n ProfileMetricsControllerEvents | AllowedEvents\n>;\n\n/**\n * Manages user profile metrics.\n *\n * For users who opt-in to metrics, this controller ensures we have metrics about their user\n * profile (metrics ID and accounts).\n */\nexport class ProfileMetricsController extends StaticIntervalPollingController()<\n typeof controllerName,\n ProfileMetricsControllerState,\n ProfileMetricsControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n readonly #assertUserOptedIn: () => boolean;\n\n readonly #getMetaMetricsId: () => string;\n\n readonly #initialDelayDuration: number;\n\n /**\n * Constructs a new {@link ProfileMetricsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.assertUserOptedIn - A function that asserts whether the user has\n * opted in to user profile features. If the user has not opted in, sync\n * operations will be no-ops.\n * @param args.getMetaMetricsId - A function that returns the MetaMetrics ID\n * of the user.\n * @param args.interval - The interval, in milliseconds, at which the controller will\n * attempt to send user profile data. Defaults to 10 seconds.\n * @param args.initialDelayDuration - The delay duration before data is sent\n * for the first time, in milliseconds. Defaults to 10 minutes.\n */\n constructor({\n messenger,\n state,\n assertUserOptedIn,\n getMetaMetricsId,\n interval = 10 * 1000,\n initialDelayDuration = DEFAULT_INITIAL_DELAY_DURATION,\n }: {\n messenger: ProfileMetricsControllerMessenger;\n state?: Partial<ProfileMetricsControllerState>;\n interval?: number;\n assertUserOptedIn: () => boolean;\n getMetaMetricsId: () => string;\n initialDelayDuration?: number;\n }) {\n super({\n messenger,\n metadata: profileMetricsControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultProfileMetricsControllerState(),\n ...state,\n },\n });\n\n this.#assertUserOptedIn = assertUserOptedIn;\n this.#getMetaMetricsId = getMetaMetricsId;\n this.#initialDelayDuration = initialDelayDuration;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n if (this.#assertUserOptedIn()) {\n // If the user has already opted in at the start of the session,\n // it must have opted in during onboarding, or during a previous session.\n this.skipInitialDelay();\n }\n this.#enqueueAccountsIfNeeded().catch(\n this.messenger.captureException ?? console.error,\n );\n this.startPolling(null);\n });\n\n this.messenger.subscribe('KeyringController:lock', () =>\n this.stopAllPolling(),\n );\n\n this.messenger.subscribe('TransactionController:transactionSubmitted', () =>\n this.skipInitialDelay(),\n );\n\n this.messenger.subscribe('AccountsController:accountAdded', (account) => {\n this.#addAccountToQueue(account).catch(console.error);\n });\n\n this.messenger.subscribe('AccountsController:accountRemoved', (account) => {\n this.#removeAccountFromQueue(account).catch(console.error);\n });\n\n this.setIntervalLength(interval);\n }\n\n /**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\n skipInitialDelay(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp = Date.now();\n });\n }\n\n /**\n * Execute a single poll to sync user profile data.\n *\n * The queued accounts are sent to the ProfileMetricsService, each with\n * a proof of ownership when one can be produced (see {@link #attachProofs}),\n * and the sync queue is cleared. This operation is mutexed to prevent\n * concurrent executions.\n *\n * @returns A promise that resolves when the poll is complete.\n */\n async _executePoll(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n this.#setInitialDelayEndTimestampIfNull();\n if (!this.#isInitialDelayComplete()) {\n return;\n }\n const fullAccountsByAddress = this.#getFullAccountsByAddress();\n for (const [entropySourceId, accounts] of Object.entries(\n this.state.syncQueue,\n )) {\n const normalizedEntropySourceId =\n entropySourceId === 'null' ? null : entropySourceId;\n // Skip proof-of-ownership for accounts without an entropy source\n const accountsWithProofs =\n normalizedEntropySourceId === null\n ? accounts\n : await this.#attachProofs(\n accounts,\n fullAccountsByAddress,\n normalizedEntropySourceId,\n );\n try {\n await this.messenger.call('ProfileMetricsService:submitMetrics', {\n metametricsId: this.#getMetaMetricsId(),\n entropySourceId: normalizedEntropySourceId,\n accounts: accountsWithProofs,\n });\n this.update((state) => {\n delete state.syncQueue[entropySourceId];\n });\n } catch (error) {\n // We want to log the error but continue processing other batches.\n console.error(\n `Failed to submit profile metrics for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n }\n });\n }\n\n /**\n * Attach a proof of ownership to each account in a single entropy-source\n * batch when possible, canonicalizing the address along the way.\n *\n * Per-account failures (unknown namespace, snap missing the\n * `signProofOfOwnership` method, snap rejection) and whole-batch nonce\n * failures are caught and downgraded to \"submit without a proof\" so the\n * batch still goes through and the proof is retried on the next poll.\n *\n * @param accounts - The queued accounts for a single batch.\n * @param fullAccountsByAddress - Live `InternalAccount` lookup keyed by address.\n * @param entropySourceId - The entropy source ID for this batch. Callers\n * are expected to short-circuit before invoking this method when the\n * batch has no entropy source; see `_executePoll` for why.\n * @returns The accounts with `proof` populated where signing succeeded.\n */\n async #attachProofs(\n accounts: AccountWithScopes[],\n fullAccountsByAddress: Map<string, InternalAccount>,\n entropySourceId: string,\n ): Promise<AccountWithScopes[]> {\n const candidates = new Map<\n string,\n { account: InternalAccount; canonicalAddress: string }\n >();\n const identifiers = new Set<string>();\n for (const queued of accounts) {\n const fullAccount = fullAccountsByAddress.get(queued.address);\n if (!fullAccount) {\n continue;\n }\n try {\n const [scope] = fullAccount.scopes;\n if (!scope) {\n throw new Error(`Scope not found for account ${fullAccount.id}`);\n }\n const { namespace } = parseCaipChainId(scope);\n const canonicalAddress = canonicalizeAddress(\n fullAccount.address,\n namespace,\n );\n candidates.set(queued.address, {\n account: fullAccount,\n canonicalAddress,\n });\n identifiers.add(canonicalAddress);\n } catch (error) {\n // Unsupported namespaces are an expected pass-through; anything\n // else is logged so a new namespace doesn't go unnoticed.\n if (!(error instanceof ProofUnsupportedNamespaceError)) {\n console.error(`Skipping proof for account ${fullAccount.id}:`, error);\n }\n }\n }\n\n if (candidates.size === 0) {\n return accounts;\n }\n\n let nonces: Record<string, string> = {};\n try {\n nonces = await this.messenger.call('ProfileMetricsService:fetchNonces', {\n identifiers: [...identifiers],\n entropySourceId,\n });\n } catch (error) {\n console.error(\n `Failed to fetch proof-of-ownership nonces for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n\n return await Promise.all(\n accounts.map(async (queued): Promise<AccountWithScopes> => {\n const candidate = candidates.get(queued.address);\n if (!candidate) {\n return queued;\n }\n const nonce = nonces[candidate.canonicalAddress];\n if (!nonce) {\n return { ...queued, address: candidate.canonicalAddress };\n }\n let proof: AccountOwnershipProof;\n try {\n proof = await this.messenger.call('ProofOfOwnershipService:sign', {\n account: candidate.account,\n nonce,\n });\n } catch (error) {\n console.error(\n `Failed to sign proof of ownership for account ${candidate.account.id}:`,\n error,\n );\n return { ...queued, address: candidate.canonicalAddress };\n }\n return {\n address: candidate.canonicalAddress,\n scopes: queued.scopes,\n proof,\n };\n }),\n );\n }\n\n /**\n * Snapshot the live `InternalAccount` map keyed by address for the\n * current poll.\n *\n * @returns A map of address → `InternalAccount`.\n */\n #getFullAccountsByAddress(): Map<string, InternalAccount> {\n const byAddress = new Map<string, InternalAccount>();\n const accountsState = this.messenger.call('AccountsController:getState');\n for (const account of Object.values(\n accountsState.internalAccounts.accounts,\n )) {\n byAddress.set(account.address, account);\n }\n return byAddress;\n }\n\n /**\n * Enqueue all currently-known accounts onto the sync queue if needed.\n * Single entry point covering both the fresh-install first sync and\n * the one-time proof-of-ownership backfill for users upgrading.\n *\n * Bails for opted-out users (the poll wouldn't drain the queue\n * anyway), and bails once both bootstrap steps have already run.\n * Otherwise enqueues all known accounts and flips both flags so this\n * becomes a permanent no-op for the lifetime of the install.\n */\n async #enqueueAccountsIfNeeded(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n if (\n this.state.initialEnqueueCompleted &&\n this.state.proofBackfillEnqueued\n ) {\n return;\n }\n const groupedAccounts = groupAccountsByEntropySourceId(\n Object.values(\n this.messenger.call('AccountsController:getState').internalAccounts\n .accounts,\n ),\n );\n this.update((state) => {\n // Replace the queue rather than append. `AccountsController` is\n // the source of truth and the queue is otherwise kept in sync\n // with it via the `accountAdded` / `accountRemoved` subscriptions,\n // so assigning here avoids duplicating entries that survived from\n // a prior session or were pushed earlier in this same unlock\n // cycle. Duplicates would matter because nonces are single-use:\n // letting one through causes `#attachProofs` to sign and submit\n // twice with the same nonce.\n state.syncQueue = groupedAccounts;\n state.initialEnqueueCompleted = true;\n state.proofBackfillEnqueued = true;\n });\n });\n }\n\n /**\n * Set the initial delay end timestamp if it is not already set.\n */\n #setInitialDelayEndTimestampIfNull(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp ??=\n Date.now() + this.#initialDelayDuration;\n });\n }\n\n /**\n * Check if the initial delay end timestamp is in the past.\n *\n * @returns True if the initial delay period has completed, false otherwise.\n */\n #isInitialDelayComplete(): boolean {\n return (\n this.state.initialDelayEndTimestamp !== undefined &&\n Date.now() >= this.state.initialDelayEndTimestamp\n );\n }\n\n /**\n * Queue the given account to be synced at the next poll.\n *\n * @param account - The account to sync.\n */\n async #addAccountToQueue(account: InternalAccount): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n const entropySourceId = getAccountEntropySourceId(account) ?? 'null';\n if (!state.syncQueue[entropySourceId]) {\n state.syncQueue[entropySourceId] = [];\n }\n state.syncQueue[entropySourceId].push({\n address: account.address,\n scopes: account.scopes,\n });\n });\n });\n }\n\n /**\n * Remove the given account from the sync queue.\n *\n * @param account - The account address to remove.\n */\n async #removeAccountFromQueue(account: string): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n for (const [entropySourceId, groupedAddresses] of Object.entries(\n state.syncQueue,\n )) {\n const index = groupedAddresses.findIndex(\n ({ address }) => address === account,\n );\n if (index === -1) {\n continue;\n }\n groupedAddresses.splice(index, 1);\n if (groupedAddresses.length === 0) {\n delete state.syncQueue[entropySourceId];\n }\n break;\n }\n });\n });\n }\n}\n\n/**\n * Retrieves the entropy source ID from the given account, if it exists.\n *\n * @param account - The account from which to retrieve the entropy source ID.\n * @returns The entropy source ID, or null if it does not exist.\n */\nfunction getAccountEntropySourceId(account: InternalAccount): string | null {\n if (account.options.entropy?.type === 'mnemonic') {\n return account.options.entropy.id;\n }\n return null;\n}\n\n/**\n * Groups accounts by their entropy source ID.\n *\n * @param accounts - The accounts to group.\n * @returns An object where each key is an entropy source ID and each value is\n * an array of account addresses associated with that entropy source ID.\n */\nfunction groupAccountsByEntropySourceId(\n accounts: InternalAccount[],\n): Record<string, AccountWithScopes[]> {\n return accounts.reduce(\n (result: Record<string, AccountWithScopes[]>, account) => {\n const entropySourceId = getAccountEntropySourceId(account);\n const key = entropySourceId ?? 'null';\n if (!result[key]) {\n result[key] = [];\n }\n result[key].push({ address: account.address, scopes: account.scopes });\n return result;\n },\n {},\n );\n}\n"]}
@@ -4,8 +4,8 @@ import type { KeyringControllerLockEvent, KeyringControllerUnlockEvent } from "@
4
4
  import type { Messenger } from "@metamask/messenger";
5
5
  import { TransactionControllerTransactionSubmittedEvent } from "@metamask/transaction-controller";
6
6
  import type { ProfileMetricsControllerMethodActions } from "./ProfileMetricsController-method-action-types.cjs";
7
- import type { AccountWithScopes } from "./ProfileMetricsService.cjs";
8
7
  import type { ProfileMetricsServiceMethodActions } from "./ProfileMetricsService-method-action-types.cjs";
8
+ import type { AccountWithScopes } from "./ProfileMetricsService.cjs";
9
9
  import type { ProofOfOwnershipServiceMethodActions } from "./ProofOfOwnershipService-method-action-types.cjs";
10
10
  /**
11
11
  * The name of the {@link ProfileMetricsController}, used to namespace the
@@ -87,16 +87,15 @@ type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent |
87
87
  export type ProfileMetricsControllerMessenger = Messenger<typeof controllerName, ProfileMetricsControllerActions | AllowedActions, ProfileMetricsControllerEvents | AllowedEvents>;
88
88
  declare const ProfileMetricsController_base: (abstract new (...args: any[]) => {
89
89
  readonly "__#17@#intervalIds": Record<string, NodeJS.Timeout>;
90
- "__#17@#intervalLength": number | undefined; /**
91
- * The name of the {@link ProfileMetricsController}, used to namespace the
92
- * controller's actions and events and to namespace the controller's state data
93
- * when composed with other controllers.
94
- */
90
+ "__#17@#intervalLength": number | undefined;
95
91
  setIntervalLength(intervalLength: number): void;
96
92
  getIntervalLength(): number | undefined;
97
93
  _startPolling(input: import("@metamask/utils").Json): void;
98
94
  _stopPollingByPollingTokenSetId(key: string): void;
99
95
  readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
96
+ /**
97
+ * The default delay duration before data is sent for the first time.
98
+ */
100
99
  readonly "__#3@#callbacks": Map<string, Set<(input: import("@metamask/utils").Json) => void>>;
101
100
  _executePoll(input: import("@metamask/utils").Json): Promise<void>;
102
101
  startPolling(input: import("@metamask/utils").Json): string;
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,gCAAgC,EACjC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AAEtC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,EAAE,8CAA8C,EAAE,yCAAyC;AAIlG,OAAO,KAAK,EAAE,qCAAqC,EAAE,2DAAuD;AAC5G,OAAO,KAAK,EAEV,iBAAiB,EAClB,oCAAgC;AACjC,OAAO,KAAK,EAAE,kCAAkC,EAAE,wDAAoD;AACtG,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAsD;AAM1G;;;;GAIG;AACH,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;;OAGG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC/C;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAgCF;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,IAAI,6BAA6B,CAMvF;AAID;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAAG,wBAAwB,CAC3E,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GACvC,sCAAsC,GACtC,qCAAqC,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,GACf,kCAAkC,GAClC,oCAAoC,GACpC,gCAAgC,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAClD,0BAA0B,CACxB,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,wCAAwC,CAAC;AAE3C;;;GAGG;AACH,KAAK,aAAa,GACd,4BAA4B,GAC5B,0BAA0B,GAC1B,mCAAmC,GACnC,qCAAqC,GACrC,8CAA8C,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,iCAAiC,GAAG,SAAS,CACvD,OAAO,cAAc,EACrB,+BAA+B,GAAG,cAAc,EAChD,8BAA8B,GAAG,aAAa,CAC/C,CAAC;;;iDAtJF;;;;OAIG;;;;;;;;;;;;;AAoJH;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,8BAC5C,OAAO,cAAc,EACrB,6BAA6B,EAC7B,iCAAiC,CAClC;;IASC;;;;;;;;;;;;;;;;OAgBG;gBACS,EACV,SAAS,EACT,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,QAAoB,EACpB,oBAAqD,GACtD,EAAE;QACD,SAAS,EAAE,iCAAiC,CAAC;QAC7C,KAAK,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QACjC,gBAAgB,EAAE,MAAM,MAAM,CAAC;QAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B;IAmDD;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAMxB;;;;;;;;;OASG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAoRpC"}
1
+ {"version":3,"file":"ProfileMetricsController.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,gCAAgC,EACjC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AAEtC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,EAAE,8CAA8C,EAAE,yCAAyC;AAIlG,OAAO,KAAK,EAAE,qCAAqC,EAAE,2DAA0D;AAC/G,OAAO,KAAK,EAAE,kCAAkC,EAAE,wDAAuD;AACzG,OAAO,KAAK,EAEV,iBAAiB,EAClB,oCAAmC;AACpC,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAyD;AAM7G;;;;GAIG;AACH,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;;OAGG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC/C;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAgCF;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,IAAI,6BAA6B,CAMvF;AAID;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAAG,wBAAwB,CAC3E,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GACvC,sCAAsC,GACtC,qCAAqC,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,GACf,kCAAkC,GAClC,oCAAoC,GACpC,gCAAgC,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAClD,0BAA0B,CACxB,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,wCAAwC,CAAC;AAE3C;;;GAGG;AACH,KAAK,aAAa,GACd,4BAA4B,GAC5B,0BAA0B,GAC1B,mCAAmC,GACnC,qCAAqC,GACrC,8CAA8C,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,iCAAiC,GAAG,SAAS,CACvD,OAAO,cAAc,EACrB,+BAA+B,GAAG,cAAc,EAChD,8BAA8B,GAAG,aAAa,CAC/C,CAAC;;;;;;;;;IA/IF;;OAEG;;;;;;;;AA+IH;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,8BAC5C,OAAO,cAAc,EACrB,6BAA6B,EAC7B,iCAAiC,CAClC;;IASC;;;;;;;;;;;;;;;;OAgBG;gBACS,EACV,SAAS,EACT,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,QAAoB,EACpB,oBAAqD,GACtD,EAAE;QACD,SAAS,EAAE,iCAAiC,CAAC;QAC7C,KAAK,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QACjC,gBAAgB,EAAE,MAAM,MAAM,CAAC;QAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B;IAmDD;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAMxB;;;;;;;;;OASG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAoRpC"}
@@ -4,8 +4,8 @@ import type { KeyringControllerLockEvent, KeyringControllerUnlockEvent } from "@
4
4
  import type { Messenger } from "@metamask/messenger";
5
5
  import { TransactionControllerTransactionSubmittedEvent } from "@metamask/transaction-controller";
6
6
  import type { ProfileMetricsControllerMethodActions } from "./ProfileMetricsController-method-action-types.mjs";
7
- import type { AccountWithScopes } from "./ProfileMetricsService.mjs";
8
7
  import type { ProfileMetricsServiceMethodActions } from "./ProfileMetricsService-method-action-types.mjs";
8
+ import type { AccountWithScopes } from "./ProfileMetricsService.mjs";
9
9
  import type { ProofOfOwnershipServiceMethodActions } from "./ProofOfOwnershipService-method-action-types.mjs";
10
10
  /**
11
11
  * The name of the {@link ProfileMetricsController}, used to namespace the
@@ -87,16 +87,15 @@ type AllowedEvents = KeyringControllerUnlockEvent | KeyringControllerLockEvent |
87
87
  export type ProfileMetricsControllerMessenger = Messenger<typeof controllerName, ProfileMetricsControllerActions | AllowedActions, ProfileMetricsControllerEvents | AllowedEvents>;
88
88
  declare const ProfileMetricsController_base: (abstract new (...args: any[]) => {
89
89
  readonly "__#17@#intervalIds": Record<string, NodeJS.Timeout>;
90
- "__#17@#intervalLength": number | undefined; /**
91
- * The name of the {@link ProfileMetricsController}, used to namespace the
92
- * controller's actions and events and to namespace the controller's state data
93
- * when composed with other controllers.
94
- */
90
+ "__#17@#intervalLength": number | undefined;
95
91
  setIntervalLength(intervalLength: number): void;
96
92
  getIntervalLength(): number | undefined;
97
93
  _startPolling(input: import("@metamask/utils").Json): void;
98
94
  _stopPollingByPollingTokenSetId(key: string): void;
99
95
  readonly "__#3@#pollingTokenSets": Map<string, Set<string>>;
96
+ /**
97
+ * The default delay duration before data is sent for the first time.
98
+ */
100
99
  readonly "__#3@#callbacks": Map<string, Set<(input: import("@metamask/utils").Json) => void>>;
101
100
  _executePoll(input: import("@metamask/utils").Json): Promise<void>;
102
101
  startPolling(input: import("@metamask/utils").Json): string;
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,gCAAgC,EACjC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AAEtC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,EAAE,8CAA8C,EAAE,yCAAyC;AAIlG,OAAO,KAAK,EAAE,qCAAqC,EAAE,2DAAuD;AAC5G,OAAO,KAAK,EAEV,iBAAiB,EAClB,oCAAgC;AACjC,OAAO,KAAK,EAAE,kCAAkC,EAAE,wDAAoD;AACtG,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAsD;AAM1G;;;;GAIG;AACH,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;;OAGG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC/C;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAgCF;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,IAAI,6BAA6B,CAMvF;AAID;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAAG,wBAAwB,CAC3E,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GACvC,sCAAsC,GACtC,qCAAqC,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,GACf,kCAAkC,GAClC,oCAAoC,GACpC,gCAAgC,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAClD,0BAA0B,CACxB,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,wCAAwC,CAAC;AAE3C;;;GAGG;AACH,KAAK,aAAa,GACd,4BAA4B,GAC5B,0BAA0B,GAC1B,mCAAmC,GACnC,qCAAqC,GACrC,8CAA8C,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,iCAAiC,GAAG,SAAS,CACvD,OAAO,cAAc,EACrB,+BAA+B,GAAG,cAAc,EAChD,8BAA8B,GAAG,aAAa,CAC/C,CAAC;;;iDAtJF;;;;OAIG;;;;;;;;;;;;;AAoJH;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,8BAC5C,OAAO,cAAc,EACrB,6BAA6B,EAC7B,iCAAiC,CAClC;;IASC;;;;;;;;;;;;;;;;OAgBG;gBACS,EACV,SAAS,EACT,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,QAAoB,EACpB,oBAAqD,GACtD,EAAE;QACD,SAAS,EAAE,iCAAiC,CAAC;QAC7C,KAAK,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QACjC,gBAAgB,EAAE,MAAM,MAAM,CAAC;QAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B;IAmDD;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAMxB;;;;;;;;;OASG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAoRpC"}
1
+ {"version":3,"file":"ProfileMetricsController.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mCAAmC,EACnC,qCAAqC,EACrC,gCAAgC,EACjC,sCAAsC;AACvC,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,qCAAqC;AAEtC,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,EAAE,8CAA8C,EAAE,yCAAyC;AAIlG,OAAO,KAAK,EAAE,qCAAqC,EAAE,2DAA0D;AAC/G,OAAO,KAAK,EAAE,kCAAkC,EAAE,wDAAuD;AACzG,OAAO,KAAK,EAEV,iBAAiB,EAClB,oCAAmC;AACpC,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAyD;AAM7G;;;;GAIG;AACH,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C;;;OAGG;IACH,uBAAuB,EAAE,OAAO,CAAC;IACjC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC/C;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;;OAMG;IACH,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAgCF;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,IAAI,6BAA6B,CAMvF;AAID;;GAEG;AACH,MAAM,MAAM,sCAAsC,GAAG,wBAAwB,CAC3E,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GACvC,sCAAsC,GACtC,qCAAqC,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,GACf,kCAAkC,GAClC,oCAAoC,GACpC,gCAAgC,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,wCAAwC,GAClD,0BAA0B,CACxB,OAAO,cAAc,EACrB,6BAA6B,CAC9B,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,wCAAwC,CAAC;AAE3C;;;GAGG;AACH,KAAK,aAAa,GACd,4BAA4B,GAC5B,0BAA0B,GAC1B,mCAAmC,GACnC,qCAAqC,GACrC,8CAA8C,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,iCAAiC,GAAG,SAAS,CACvD,OAAO,cAAc,EACrB,+BAA+B,GAAG,cAAc,EAChD,8BAA8B,GAAG,aAAa,CAC/C,CAAC;;;;;;;;;IA/IF;;OAEG;;;;;;;;AA+IH;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,8BAC5C,OAAO,cAAc,EACrB,6BAA6B,EAC7B,iCAAiC,CAClC;;IASC;;;;;;;;;;;;;;;;OAgBG;gBACS,EACV,SAAS,EACT,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,QAAoB,EACpB,oBAAqD,GACtD,EAAE;QACD,SAAS,EAAE,iCAAiC,CAAC;QAC7C,KAAK,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;QAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QACjC,gBAAgB,EAAE,MAAM,MAAM,CAAC;QAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B;IAmDD;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAMxB;;;;;;;;;OASG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAoRpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsController.mjs","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":";;;;;;;;;;;;AAgBA,OAAO,EAAE,+BAA+B,EAAE,qCAAqC;AAE/E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,wBAAwB;AAC7E,OAAO,EAAE,KAAK,EAAE,oBAAoB;AASpC,OAAO,EACL,mBAAmB,EACnB,8BAA8B,EAC/B,iCAA6B;AAE9B;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAEzD;;GAEG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,cAAc,CAC1D,CAAC,EACD,QAAQ,CAAC,MAAM,CAChB,CAAC;AAgCF;;GAEG;AACH,MAAM,gCAAgC,GAAG;IACvC,uBAAuB,EAAE;QACvB,OAAO,EAAE,IAAI;QACb,sBAAsB,EAAE,IAAI;QAC5B,kBAAkB,EAAE,IAAI;QACxB,QAAQ,EAAE,KAAK;KAChB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,sBAAsB,EAAE,KAAK;QAC7B,kBAAkB,EAAE,IAAI;QACxB,QAAQ,EAAE,KAAK;KAChB;IACD,wBAAwB,EAAE;QACxB,OAAO,EAAE,IAAI;QACb,sBAAsB,EAAE,IAAI;QAC5B,kBAAkB,EAAE,IAAI;QACxB,QAAQ,EAAE,KAAK;KAChB;IACD,qBAAqB,EAAE;QACrB,OAAO,EAAE,IAAI;QACb,sBAAsB,EAAE,IAAI;QAC5B,kBAAkB,EAAE,IAAI;QACxB,QAAQ,EAAE,KAAK;KAChB;CACqD,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,UAAU,uCAAuC;IACrD,OAAO;QACL,uBAAuB,EAAE,KAAK;QAC9B,SAAS,EAAE,EAAE;QACb,qBAAqB,EAAE,KAAK;KAC7B,CAAC;AACJ,CAAC;AAED,MAAM,yBAAyB,GAAG,CAAC,kBAAkB,CAAU,CAAC;AA6DhE;;;;;GAKG;AACH,MAAM,OAAO,wBAAyB,SAAQ,+BAA+B,EAI5E;IASC;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,EACV,SAAS,EACT,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GAAG,EAAE,GAAG,IAAI,EACpB,oBAAoB,GAAG,8BAA8B,GAQtD;QACC,KAAK,CAAC;YACJ,SAAS;YACT,QAAQ,EAAE,gCAAgC;YAC1C,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE;gBACL,GAAG,uCAAuC,EAAE;gBAC5C,GAAG,KAAK;aACT;SACF,CAAC,CAAC;;QAhDI,0CAAS,IAAI,KAAK,EAAE,EAAC;QAErB,8DAAkC;QAElC,6DAAgC;QAEhC,iEAA8B;QA4CrC,uBAAA,IAAI,+CAAsB,iBAAiB,MAAA,CAAC;QAC5C,uBAAA,IAAI,8CAAqB,gBAAgB,MAAA,CAAC;QAC1C,uBAAA,IAAI,kDAAyB,oBAAoB,MAAA,CAAC;QAElD,IAAI,CAAC,SAAS,CAAC,4BAA4B,CACzC,IAAI,EACJ,yBAAyB,CAC1B,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,0BAA0B,EAAE,GAAG,EAAE;YACxD,IAAI,uBAAA,IAAI,mDAAmB,MAAvB,IAAI,CAAqB,EAAE,CAAC;gBAC9B,gEAAgE;gBAChE,yEAAyE;gBACzE,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,CAAC;YACD,uBAAA,IAAI,8FAAyB,MAA7B,IAAI,CAA2B,CAAC,KAAK,CACnC,IAAI,CAAC,SAAS,CAAC,gBAAgB,IAAI,OAAO,CAAC,KAAK,CACjD,CAAC;YACF,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,wBAAwB,EAAE,GAAG,EAAE,CACtD,IAAI,CAAC,cAAc,EAAE,CACtB,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,4CAA4C,EAAE,GAAG,EAAE,CAC1E,IAAI,CAAC,gBAAgB,EAAE,CACxB,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,iCAAiC,EAAE,CAAC,OAAO,EAAE,EAAE;YACtE,uBAAA,IAAI,wFAAmB,MAAvB,IAAI,EAAoB,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,mCAAmC,EAAE,CAAC,OAAO,EAAE,EAAE;YACxE,uBAAA,IAAI,6FAAwB,MAA5B,IAAI,EAAyB,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,gBAAgB;QACd,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,CAAC,wBAAwB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,uBAAA,IAAI,uCAAO,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;YACxC,IAAI,CAAC,uBAAA,IAAI,mDAAmB,MAAvB,IAAI,CAAqB,EAAE,CAAC;gBAC/B,OAAO;YACT,CAAC;YACD,uBAAA,IAAI,wGAAmC,MAAvC,IAAI,CAAqC,CAAC;YAC1C,IAAI,CAAC,uBAAA,IAAI,6FAAwB,MAA5B,IAAI,CAA0B,EAAE,CAAC;gBACpC,OAAO;YACT,CAAC;YACD,MAAM,qBAAqB,GAAG,uBAAA,IAAI,+FAA0B,MAA9B,IAAI,CAA4B,CAAC;YAC/D,KAAK,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CACtD,IAAI,CAAC,KAAK,CAAC,SAAS,CACrB,EAAE,CAAC;gBACF,MAAM,yBAAyB,GAC7B,eAAe,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC;gBACtD,iEAAiE;gBACjE,MAAM,kBAAkB,GACtB,yBAAyB,KAAK,IAAI;oBAChC,CAAC,CAAC,QAAQ;oBACV,CAAC,CAAC,MAAM,uBAAA,IAAI,mFAAc,MAAlB,IAAI,EACR,QAAQ,EACR,qBAAqB,EACrB,yBAAyB,CAC1B,CAAC;gBACR,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,qCAAqC,EAAE;wBAC/D,aAAa,EAAE,uBAAA,IAAI,kDAAkB,MAAtB,IAAI,CAAoB;wBACvC,eAAe,EAAE,yBAAyB;wBAC1C,QAAQ,EAAE,kBAAkB;qBAC7B,CAAC,CAAC;oBACH,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;wBACpB,OAAO,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;oBAC1C,CAAC,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,kEAAkE;oBAClE,OAAO,CAAC,KAAK,CACX,0DAA0D,eAAe,GAAG,EAC5E,KAAK,CACN,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CA0OF;;AAxOC;;;;;;;;;;;;;;;GAeG;AACH,KAAK,iDACH,QAA6B,EAC7B,qBAAmD,EACnD,eAAuB;IAEvB,MAAM,UAAU,GAAG,IAAI,GAAG,EAGvB,CAAC;IACJ,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,WAAW,GAAG,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,+BAA+B,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;YACnE,CAAC;YACD,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,gBAAgB,GAAG,mBAAmB,CAC1C,WAAW,CAAC,OAAO,EACnB,SAAS,CACV,CAAC;YACF,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE;gBAC7B,OAAO,EAAE,WAAW;gBACpB,gBAAgB;aACjB,CAAC,CAAC;YACH,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gEAAgE;YAChE,0DAA0D;YAC1D,IAAI,CAAC,CAAC,KAAK,YAAY,8BAA8B,CAAC,EAAE,CAAC;gBACvD,OAAO,CAAC,KAAK,CAAC,8BAA8B,WAAW,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,GAA2B,EAAE,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,mCAAmC,EAAE;YACtE,WAAW,EAAE,CAAC,GAAG,WAAW,CAAC;YAC7B,eAAe;SAChB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,mEAAmE,eAAe,GAAG,EACrF,KAAK,CACN,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,OAAO,CAAC,GAAG,CACtB,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAA8B,EAAE;QACxD,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC5D,CAAC;QACD,IAAI,KAA4B,CAAC;QACjC,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,8BAA8B,EAAE;gBAChE,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,KAAK;aACN,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,iDAAiD,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,EACxE,KAAK,CACN,CAAC;YACF,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,gBAAgB,EAAE,CAAC;QAC5D,CAAC;QACD,OAAO;YACL,OAAO,EAAE,SAAS,CAAC,gBAAgB;YACnC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;IASC,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IACrD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACzE,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CACjC,aAAa,CAAC,gBAAgB,CAAC,QAAQ,CACxC,EAAE,CAAC;QACF,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK;IACH,MAAM,uBAAA,IAAI,uCAAO,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC,uBAAA,IAAI,mDAAmB,MAAvB,IAAI,CAAqB,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,IACE,IAAI,CAAC,KAAK,CAAC,uBAAuB;YAClC,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAChC,CAAC;YACD,OAAO;QACT,CAAC;QACD,MAAM,eAAe,GAAG,8BAA8B,CACpD,MAAM,CAAC,MAAM,CACX,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,gBAAgB;aAChE,QAAQ,CACZ,CACF,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,gEAAgE;YAChE,8DAA8D;YAC9D,mEAAmE;YACnE,kEAAkE;YAClE,6DAA6D;YAC7D,gEAAgE;YAChE,gEAAgE;YAChE,6BAA6B;YAC7B,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC;YAClC,KAAK,CAAC,uBAAuB,GAAG,IAAI,CAAC;YACrC,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;IAMC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,KAAK,CAAC,wBAAwB,KAA9B,KAAK,CAAC,wBAAwB,GAC5B,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAA,IAAI,sDAAsB,EAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC;IAQC,OAAO,CACL,IAAI,CAAC,KAAK,CAAC,wBAAwB,KAAK,SAAS;QACjD,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAClD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,sDAAoB,OAAwB;IAC/C,MAAM,uBAAA,IAAI,uCAAO,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,eAAe,GAAG,yBAAyB,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC;YACrE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;gBACtC,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC;YACxC,CAAC;YACD,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC;gBACpC,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,KAAK,2DAAyB,OAAe;IAC3C,MAAM,uBAAA,IAAI,uCAAO,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;QACxC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,KAAK,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC,IAAI,MAAM,CAAC,OAAO,CAC9D,KAAK,CAAC,SAAS,CAChB,EAAE,CAAC;gBACF,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CACtC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,CACrC,CAAC;gBACF,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;oBACjB,SAAS;gBACX,CAAC;gBACD,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBAClC,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAClC,OAAO,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;gBAC1C,CAAC;gBACD,MAAM;YACR,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAGH;;;;;GAKG;AACH,SAAS,yBAAyB,CAAC,OAAwB;IACzD,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QACjD,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,8BAA8B,CACrC,QAA2B;IAE3B,OAAO,QAAQ,CAAC,MAAM,CACpB,CAAC,MAA2C,EAAE,OAAO,EAAE,EAAE;QACvD,MAAM,eAAe,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,eAAe,IAAI,MAAM,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACnB,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,EAAE,CACH,CAAC;AACJ,CAAC","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerGetStateAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { TransactionControllerTransactionSubmittedEvent } from '@metamask/transaction-controller';\nimport { Duration, inMilliseconds, parseCaipChainId } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport type { ProfileMetricsControllerMethodActions } from './ProfileMetricsController-method-action-types';\nimport type {\n AccountOwnershipProof,\n AccountWithScopes,\n} from './ProfileMetricsService';\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize';\n\n/**\n * The name of the {@link ProfileMetricsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'ProfileMetricsController';\n\n/**\n * The default delay duration before data is sent for the first time.\n */\nexport const DEFAULT_INITIAL_DELAY_DURATION = inMilliseconds(\n 1,\n Duration.Minute,\n);\n\n/**\n * Describes the shape of the state object for {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerState = {\n /**\n * Whether existing accounts have been added\n * to the queue.\n */\n initialEnqueueCompleted: boolean;\n /**\n * The queue of accounts to be synced.\n * Each key is an entropy source ID, and each value is an array of account\n * addresses associated with that entropy source. Accounts with no entropy\n * source ID are grouped under the key \"null\".\n */\n syncQueue: Record<string, AccountWithScopes[]>;\n /**\n * The timestamp when the first data sending can be attempted.\n */\n initialDelayEndTimestamp?: number;\n /**\n * Whether previously-synced accounts have been re-enqueued so their\n * proofs of ownership are submitted alongside everything else. Set on\n * the first unlock after upgrading to a version that signs proofs of\n * ownership; fresh installs flip this on their initial sync since the\n * first poll already attaches proofs.\n */\n proofBackfillEnqueued: boolean;\n};\n\n/**\n * The metadata for each property in {@link ProfileMetricsControllerState}.\n */\nconst profileMetricsControllerMetadata = {\n initialEnqueueCompleted: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n syncQueue: {\n persist: true,\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n usedInUi: false,\n },\n initialDelayEndTimestamp: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n proofBackfillEnqueued: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<ProfileMetricsControllerState>;\n\n/**\n * Constructs the default {@link ProfileMetricsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link ProfileMetricsController} state.\n */\nexport function getDefaultProfileMetricsControllerState(): ProfileMetricsControllerState {\n return {\n initialEnqueueCompleted: false,\n syncQueue: {},\n proofBackfillEnqueued: false,\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = ['skipInitialDelay'] as const;\n\n/**\n * Retrieves the state of the {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ProfileMetricsControllerState\n>;\n\n/**\n * Actions that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerActions =\n | ProfileMetricsControllerGetStateAction\n | ProfileMetricsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsControllerMessenger} calls.\n */\ntype AllowedActions =\n | ProfileMetricsServiceMethodActions\n | ProofOfOwnershipServiceMethodActions\n | AccountsControllerGetStateAction;\n\n/**\n * Published when the state of {@link ProfileMetricsController} changes.\n */\nexport type ProfileMetricsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n ProfileMetricsControllerState\n >;\n\n/**\n * Events that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerEvents =\n ProfileMetricsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ProfileMetricsControllerMessenger} subscribes\n * to.\n */\ntype AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | TransactionControllerTransactionSubmittedEvent;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerMessenger = Messenger<\n typeof controllerName,\n ProfileMetricsControllerActions | AllowedActions,\n ProfileMetricsControllerEvents | AllowedEvents\n>;\n\n/**\n * Manages user profile metrics.\n *\n * For users who opt-in to metrics, this controller ensures we have metrics about their user\n * profile (metrics ID and accounts).\n */\nexport class ProfileMetricsController extends StaticIntervalPollingController()<\n typeof controllerName,\n ProfileMetricsControllerState,\n ProfileMetricsControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n readonly #assertUserOptedIn: () => boolean;\n\n readonly #getMetaMetricsId: () => string;\n\n readonly #initialDelayDuration: number;\n\n /**\n * Constructs a new {@link ProfileMetricsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.assertUserOptedIn - A function that asserts whether the user has\n * opted in to user profile features. If the user has not opted in, sync\n * operations will be no-ops.\n * @param args.getMetaMetricsId - A function that returns the MetaMetrics ID\n * of the user.\n * @param args.interval - The interval, in milliseconds, at which the controller will\n * attempt to send user profile data. Defaults to 10 seconds.\n * @param args.initialDelayDuration - The delay duration before data is sent\n * for the first time, in milliseconds. Defaults to 10 minutes.\n */\n constructor({\n messenger,\n state,\n assertUserOptedIn,\n getMetaMetricsId,\n interval = 10 * 1000,\n initialDelayDuration = DEFAULT_INITIAL_DELAY_DURATION,\n }: {\n messenger: ProfileMetricsControllerMessenger;\n state?: Partial<ProfileMetricsControllerState>;\n interval?: number;\n assertUserOptedIn: () => boolean;\n getMetaMetricsId: () => string;\n initialDelayDuration?: number;\n }) {\n super({\n messenger,\n metadata: profileMetricsControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultProfileMetricsControllerState(),\n ...state,\n },\n });\n\n this.#assertUserOptedIn = assertUserOptedIn;\n this.#getMetaMetricsId = getMetaMetricsId;\n this.#initialDelayDuration = initialDelayDuration;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n if (this.#assertUserOptedIn()) {\n // If the user has already opted in at the start of the session,\n // it must have opted in during onboarding, or during a previous session.\n this.skipInitialDelay();\n }\n this.#enqueueAccountsIfNeeded().catch(\n this.messenger.captureException ?? console.error,\n );\n this.startPolling(null);\n });\n\n this.messenger.subscribe('KeyringController:lock', () =>\n this.stopAllPolling(),\n );\n\n this.messenger.subscribe('TransactionController:transactionSubmitted', () =>\n this.skipInitialDelay(),\n );\n\n this.messenger.subscribe('AccountsController:accountAdded', (account) => {\n this.#addAccountToQueue(account).catch(console.error);\n });\n\n this.messenger.subscribe('AccountsController:accountRemoved', (account) => {\n this.#removeAccountFromQueue(account).catch(console.error);\n });\n\n this.setIntervalLength(interval);\n }\n\n /**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\n skipInitialDelay(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp = Date.now();\n });\n }\n\n /**\n * Execute a single poll to sync user profile data.\n *\n * The queued accounts are sent to the ProfileMetricsService, each with\n * a proof of ownership when one can be produced (see {@link #attachProofs}),\n * and the sync queue is cleared. This operation is mutexed to prevent\n * concurrent executions.\n *\n * @returns A promise that resolves when the poll is complete.\n */\n async _executePoll(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n this.#setInitialDelayEndTimestampIfNull();\n if (!this.#isInitialDelayComplete()) {\n return;\n }\n const fullAccountsByAddress = this.#getFullAccountsByAddress();\n for (const [entropySourceId, accounts] of Object.entries(\n this.state.syncQueue,\n )) {\n const normalizedEntropySourceId =\n entropySourceId === 'null' ? null : entropySourceId;\n // Skip proof-of-ownership for accounts without an entropy source\n const accountsWithProofs =\n normalizedEntropySourceId === null\n ? accounts\n : await this.#attachProofs(\n accounts,\n fullAccountsByAddress,\n normalizedEntropySourceId,\n );\n try {\n await this.messenger.call('ProfileMetricsService:submitMetrics', {\n metametricsId: this.#getMetaMetricsId(),\n entropySourceId: normalizedEntropySourceId,\n accounts: accountsWithProofs,\n });\n this.update((state) => {\n delete state.syncQueue[entropySourceId];\n });\n } catch (error) {\n // We want to log the error but continue processing other batches.\n console.error(\n `Failed to submit profile metrics for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n }\n });\n }\n\n /**\n * Attach a proof of ownership to each account in a single entropy-source\n * batch when possible, canonicalizing the address along the way.\n *\n * Per-account failures (unknown namespace, snap missing the\n * `signProofOfOwnership` method, snap rejection) and whole-batch nonce\n * failures are caught and downgraded to \"submit without a proof\" so the\n * batch still goes through and the proof is retried on the next poll.\n *\n * @param accounts - The queued accounts for a single batch.\n * @param fullAccountsByAddress - Live `InternalAccount` lookup keyed by address.\n * @param entropySourceId - The entropy source ID for this batch. Callers\n * are expected to short-circuit before invoking this method when the\n * batch has no entropy source; see `_executePoll` for why.\n * @returns The accounts with `proof` populated where signing succeeded.\n */\n async #attachProofs(\n accounts: AccountWithScopes[],\n fullAccountsByAddress: Map<string, InternalAccount>,\n entropySourceId: string,\n ): Promise<AccountWithScopes[]> {\n const candidates = new Map<\n string,\n { account: InternalAccount; canonicalAddress: string }\n >();\n const identifiers = new Set<string>();\n for (const queued of accounts) {\n const fullAccount = fullAccountsByAddress.get(queued.address);\n if (!fullAccount) {\n continue;\n }\n try {\n const [scope] = fullAccount.scopes;\n if (!scope) {\n throw new Error(`Scope not found for account ${fullAccount.id}`);\n }\n const { namespace } = parseCaipChainId(scope);\n const canonicalAddress = canonicalizeAddress(\n fullAccount.address,\n namespace,\n );\n candidates.set(queued.address, {\n account: fullAccount,\n canonicalAddress,\n });\n identifiers.add(canonicalAddress);\n } catch (error) {\n // Unsupported namespaces are an expected pass-through; anything\n // else is logged so a new namespace doesn't go unnoticed.\n if (!(error instanceof ProofUnsupportedNamespaceError)) {\n console.error(`Skipping proof for account ${fullAccount.id}:`, error);\n }\n }\n }\n\n if (candidates.size === 0) {\n return accounts;\n }\n\n let nonces: Record<string, string> = {};\n try {\n nonces = await this.messenger.call('ProfileMetricsService:fetchNonces', {\n identifiers: [...identifiers],\n entropySourceId,\n });\n } catch (error) {\n console.error(\n `Failed to fetch proof-of-ownership nonces for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n\n return await Promise.all(\n accounts.map(async (queued): Promise<AccountWithScopes> => {\n const candidate = candidates.get(queued.address);\n if (!candidate) {\n return queued;\n }\n const nonce = nonces[candidate.canonicalAddress];\n if (!nonce) {\n return { ...queued, address: candidate.canonicalAddress };\n }\n let proof: AccountOwnershipProof;\n try {\n proof = await this.messenger.call('ProofOfOwnershipService:sign', {\n account: candidate.account,\n nonce,\n });\n } catch (error) {\n console.error(\n `Failed to sign proof of ownership for account ${candidate.account.id}:`,\n error,\n );\n return { ...queued, address: candidate.canonicalAddress };\n }\n return {\n address: candidate.canonicalAddress,\n scopes: queued.scopes,\n proof,\n };\n }),\n );\n }\n\n /**\n * Snapshot the live `InternalAccount` map keyed by address for the\n * current poll.\n *\n * @returns A map of address → `InternalAccount`.\n */\n #getFullAccountsByAddress(): Map<string, InternalAccount> {\n const byAddress = new Map<string, InternalAccount>();\n const accountsState = this.messenger.call('AccountsController:getState');\n for (const account of Object.values(\n accountsState.internalAccounts.accounts,\n )) {\n byAddress.set(account.address, account);\n }\n return byAddress;\n }\n\n /**\n * Enqueue all currently-known accounts onto the sync queue if needed.\n * Single entry point covering both the fresh-install first sync and\n * the one-time proof-of-ownership backfill for users upgrading.\n *\n * Bails for opted-out users (the poll wouldn't drain the queue\n * anyway), and bails once both bootstrap steps have already run.\n * Otherwise enqueues all known accounts and flips both flags so this\n * becomes a permanent no-op for the lifetime of the install.\n */\n async #enqueueAccountsIfNeeded(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n if (\n this.state.initialEnqueueCompleted &&\n this.state.proofBackfillEnqueued\n ) {\n return;\n }\n const groupedAccounts = groupAccountsByEntropySourceId(\n Object.values(\n this.messenger.call('AccountsController:getState').internalAccounts\n .accounts,\n ),\n );\n this.update((state) => {\n // Replace the queue rather than append. `AccountsController` is\n // the source of truth and the queue is otherwise kept in sync\n // with it via the `accountAdded` / `accountRemoved` subscriptions,\n // so assigning here avoids duplicating entries that survived from\n // a prior session or were pushed earlier in this same unlock\n // cycle. Duplicates would matter because nonces are single-use:\n // letting one through causes `#attachProofs` to sign and submit\n // twice with the same nonce.\n state.syncQueue = groupedAccounts;\n state.initialEnqueueCompleted = true;\n state.proofBackfillEnqueued = true;\n });\n });\n }\n\n /**\n * Set the initial delay end timestamp if it is not already set.\n */\n #setInitialDelayEndTimestampIfNull(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp ??=\n Date.now() + this.#initialDelayDuration;\n });\n }\n\n /**\n * Check if the initial delay end timestamp is in the past.\n *\n * @returns True if the initial delay period has completed, false otherwise.\n */\n #isInitialDelayComplete(): boolean {\n return (\n this.state.initialDelayEndTimestamp !== undefined &&\n Date.now() >= this.state.initialDelayEndTimestamp\n );\n }\n\n /**\n * Queue the given account to be synced at the next poll.\n *\n * @param account - The account to sync.\n */\n async #addAccountToQueue(account: InternalAccount): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n const entropySourceId = getAccountEntropySourceId(account) ?? 'null';\n if (!state.syncQueue[entropySourceId]) {\n state.syncQueue[entropySourceId] = [];\n }\n state.syncQueue[entropySourceId].push({\n address: account.address,\n scopes: account.scopes,\n });\n });\n });\n }\n\n /**\n * Remove the given account from the sync queue.\n *\n * @param account - The account address to remove.\n */\n async #removeAccountFromQueue(account: string): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n for (const [entropySourceId, groupedAddresses] of Object.entries(\n state.syncQueue,\n )) {\n const index = groupedAddresses.findIndex(\n ({ address }) => address === account,\n );\n if (index === -1) {\n continue;\n }\n groupedAddresses.splice(index, 1);\n if (groupedAddresses.length === 0) {\n delete state.syncQueue[entropySourceId];\n }\n break;\n }\n });\n });\n }\n}\n\n/**\n * Retrieves the entropy source ID from the given account, if it exists.\n *\n * @param account - The account from which to retrieve the entropy source ID.\n * @returns The entropy source ID, or null if it does not exist.\n */\nfunction getAccountEntropySourceId(account: InternalAccount): string | null {\n if (account.options.entropy?.type === 'mnemonic') {\n return account.options.entropy.id;\n }\n return null;\n}\n\n/**\n * Groups accounts by their entropy source ID.\n *\n * @param accounts - The accounts to group.\n * @returns An object where each key is an entropy source ID and each value is\n * an array of account addresses associated with that entropy source ID.\n */\nfunction groupAccountsByEntropySourceId(\n accounts: InternalAccount[],\n): Record<string, AccountWithScopes[]> {\n return accounts.reduce(\n (result: Record<string, AccountWithScopes[]>, account) => {\n const entropySourceId = getAccountEntropySourceId(account);\n const key = entropySourceId ?? 'null';\n if (!result[key]) {\n result[key] = [];\n }\n result[key].push({ address: account.address, scopes: account.scopes });\n return result;\n },\n {},\n );\n}\n"]}
1
+ {"version":3,"file":"ProfileMetricsController.mjs","sourceRoot":"","sources":["../src/ProfileMetricsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerGetStateAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport type {\n KeyringControllerLockEvent,\n KeyringControllerUnlockEvent,\n} from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { TransactionControllerTransactionSubmittedEvent } from '@metamask/transaction-controller';\nimport { Duration, inMilliseconds, parseCaipChainId } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport type { ProfileMetricsControllerMethodActions } from './ProfileMetricsController-method-action-types.js';\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types.js';\nimport type {\n AccountOwnershipProof,\n AccountWithScopes,\n} from './ProfileMetricsService.js';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types.js';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize.js';\n\n/**\n * The name of the {@link ProfileMetricsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'ProfileMetricsController';\n\n/**\n * The default delay duration before data is sent for the first time.\n */\nexport const DEFAULT_INITIAL_DELAY_DURATION = inMilliseconds(\n 1,\n Duration.Minute,\n);\n\n/**\n * Describes the shape of the state object for {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerState = {\n /**\n * Whether existing accounts have been added\n * to the queue.\n */\n initialEnqueueCompleted: boolean;\n /**\n * The queue of accounts to be synced.\n * Each key is an entropy source ID, and each value is an array of account\n * addresses associated with that entropy source. Accounts with no entropy\n * source ID are grouped under the key \"null\".\n */\n syncQueue: Record<string, AccountWithScopes[]>;\n /**\n * The timestamp when the first data sending can be attempted.\n */\n initialDelayEndTimestamp?: number;\n /**\n * Whether previously-synced accounts have been re-enqueued so their\n * proofs of ownership are submitted alongside everything else. Set on\n * the first unlock after upgrading to a version that signs proofs of\n * ownership; fresh installs flip this on their initial sync since the\n * first poll already attaches proofs.\n */\n proofBackfillEnqueued: boolean;\n};\n\n/**\n * The metadata for each property in {@link ProfileMetricsControllerState}.\n */\nconst profileMetricsControllerMetadata = {\n initialEnqueueCompleted: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n syncQueue: {\n persist: true,\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n usedInUi: false,\n },\n initialDelayEndTimestamp: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n proofBackfillEnqueued: {\n persist: true,\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<ProfileMetricsControllerState>;\n\n/**\n * Constructs the default {@link ProfileMetricsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link ProfileMetricsController} state.\n */\nexport function getDefaultProfileMetricsControllerState(): ProfileMetricsControllerState {\n return {\n initialEnqueueCompleted: false,\n syncQueue: {},\n proofBackfillEnqueued: false,\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = ['skipInitialDelay'] as const;\n\n/**\n * Retrieves the state of the {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n ProfileMetricsControllerState\n>;\n\n/**\n * Actions that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerActions =\n | ProfileMetricsControllerGetStateAction\n | ProfileMetricsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsControllerMessenger} calls.\n */\ntype AllowedActions =\n | ProfileMetricsServiceMethodActions\n | ProofOfOwnershipServiceMethodActions\n | AccountsControllerGetStateAction;\n\n/**\n * Published when the state of {@link ProfileMetricsController} changes.\n */\nexport type ProfileMetricsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n ProfileMetricsControllerState\n >;\n\n/**\n * Events that {@link ProfileMetricsControllerMessenger} exposes to other consumers.\n */\nexport type ProfileMetricsControllerEvents =\n ProfileMetricsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link ProfileMetricsControllerMessenger} subscribes\n * to.\n */\ntype AllowedEvents =\n | KeyringControllerUnlockEvent\n | KeyringControllerLockEvent\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent\n | TransactionControllerTransactionSubmittedEvent;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link ProfileMetricsController}.\n */\nexport type ProfileMetricsControllerMessenger = Messenger<\n typeof controllerName,\n ProfileMetricsControllerActions | AllowedActions,\n ProfileMetricsControllerEvents | AllowedEvents\n>;\n\n/**\n * Manages user profile metrics.\n *\n * For users who opt-in to metrics, this controller ensures we have metrics about their user\n * profile (metrics ID and accounts).\n */\nexport class ProfileMetricsController extends StaticIntervalPollingController()<\n typeof controllerName,\n ProfileMetricsControllerState,\n ProfileMetricsControllerMessenger\n> {\n readonly #mutex = new Mutex();\n\n readonly #assertUserOptedIn: () => boolean;\n\n readonly #getMetaMetricsId: () => string;\n\n readonly #initialDelayDuration: number;\n\n /**\n * Constructs a new {@link ProfileMetricsController}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this controller.\n * @param args.state - The desired state with which to initialize this\n * controller. Missing properties will be filled in with defaults.\n * @param args.assertUserOptedIn - A function that asserts whether the user has\n * opted in to user profile features. If the user has not opted in, sync\n * operations will be no-ops.\n * @param args.getMetaMetricsId - A function that returns the MetaMetrics ID\n * of the user.\n * @param args.interval - The interval, in milliseconds, at which the controller will\n * attempt to send user profile data. Defaults to 10 seconds.\n * @param args.initialDelayDuration - The delay duration before data is sent\n * for the first time, in milliseconds. Defaults to 10 minutes.\n */\n constructor({\n messenger,\n state,\n assertUserOptedIn,\n getMetaMetricsId,\n interval = 10 * 1000,\n initialDelayDuration = DEFAULT_INITIAL_DELAY_DURATION,\n }: {\n messenger: ProfileMetricsControllerMessenger;\n state?: Partial<ProfileMetricsControllerState>;\n interval?: number;\n assertUserOptedIn: () => boolean;\n getMetaMetricsId: () => string;\n initialDelayDuration?: number;\n }) {\n super({\n messenger,\n metadata: profileMetricsControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultProfileMetricsControllerState(),\n ...state,\n },\n });\n\n this.#assertUserOptedIn = assertUserOptedIn;\n this.#getMetaMetricsId = getMetaMetricsId;\n this.#initialDelayDuration = initialDelayDuration;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.messenger.subscribe('KeyringController:unlock', () => {\n if (this.#assertUserOptedIn()) {\n // If the user has already opted in at the start of the session,\n // it must have opted in during onboarding, or during a previous session.\n this.skipInitialDelay();\n }\n this.#enqueueAccountsIfNeeded().catch(\n this.messenger.captureException ?? console.error,\n );\n this.startPolling(null);\n });\n\n this.messenger.subscribe('KeyringController:lock', () =>\n this.stopAllPolling(),\n );\n\n this.messenger.subscribe('TransactionController:transactionSubmitted', () =>\n this.skipInitialDelay(),\n );\n\n this.messenger.subscribe('AccountsController:accountAdded', (account) => {\n this.#addAccountToQueue(account).catch(console.error);\n });\n\n this.messenger.subscribe('AccountsController:accountRemoved', (account) => {\n this.#removeAccountFromQueue(account).catch(console.error);\n });\n\n this.setIntervalLength(interval);\n }\n\n /**\n * Skip the initial delay period by setting the end timestamp to the current time.\n * Metrics will be sent on the next poll.\n */\n skipInitialDelay(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp = Date.now();\n });\n }\n\n /**\n * Execute a single poll to sync user profile data.\n *\n * The queued accounts are sent to the ProfileMetricsService, each with\n * a proof of ownership when one can be produced (see {@link #attachProofs}),\n * and the sync queue is cleared. This operation is mutexed to prevent\n * concurrent executions.\n *\n * @returns A promise that resolves when the poll is complete.\n */\n async _executePoll(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n this.#setInitialDelayEndTimestampIfNull();\n if (!this.#isInitialDelayComplete()) {\n return;\n }\n const fullAccountsByAddress = this.#getFullAccountsByAddress();\n for (const [entropySourceId, accounts] of Object.entries(\n this.state.syncQueue,\n )) {\n const normalizedEntropySourceId =\n entropySourceId === 'null' ? null : entropySourceId;\n // Skip proof-of-ownership for accounts without an entropy source\n const accountsWithProofs =\n normalizedEntropySourceId === null\n ? accounts\n : await this.#attachProofs(\n accounts,\n fullAccountsByAddress,\n normalizedEntropySourceId,\n );\n try {\n await this.messenger.call('ProfileMetricsService:submitMetrics', {\n metametricsId: this.#getMetaMetricsId(),\n entropySourceId: normalizedEntropySourceId,\n accounts: accountsWithProofs,\n });\n this.update((state) => {\n delete state.syncQueue[entropySourceId];\n });\n } catch (error) {\n // We want to log the error but continue processing other batches.\n console.error(\n `Failed to submit profile metrics for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n }\n });\n }\n\n /**\n * Attach a proof of ownership to each account in a single entropy-source\n * batch when possible, canonicalizing the address along the way.\n *\n * Per-account failures (unknown namespace, snap missing the\n * `signProofOfOwnership` method, snap rejection) and whole-batch nonce\n * failures are caught and downgraded to \"submit without a proof\" so the\n * batch still goes through and the proof is retried on the next poll.\n *\n * @param accounts - The queued accounts for a single batch.\n * @param fullAccountsByAddress - Live `InternalAccount` lookup keyed by address.\n * @param entropySourceId - The entropy source ID for this batch. Callers\n * are expected to short-circuit before invoking this method when the\n * batch has no entropy source; see `_executePoll` for why.\n * @returns The accounts with `proof` populated where signing succeeded.\n */\n async #attachProofs(\n accounts: AccountWithScopes[],\n fullAccountsByAddress: Map<string, InternalAccount>,\n entropySourceId: string,\n ): Promise<AccountWithScopes[]> {\n const candidates = new Map<\n string,\n { account: InternalAccount; canonicalAddress: string }\n >();\n const identifiers = new Set<string>();\n for (const queued of accounts) {\n const fullAccount = fullAccountsByAddress.get(queued.address);\n if (!fullAccount) {\n continue;\n }\n try {\n const [scope] = fullAccount.scopes;\n if (!scope) {\n throw new Error(`Scope not found for account ${fullAccount.id}`);\n }\n const { namespace } = parseCaipChainId(scope);\n const canonicalAddress = canonicalizeAddress(\n fullAccount.address,\n namespace,\n );\n candidates.set(queued.address, {\n account: fullAccount,\n canonicalAddress,\n });\n identifiers.add(canonicalAddress);\n } catch (error) {\n // Unsupported namespaces are an expected pass-through; anything\n // else is logged so a new namespace doesn't go unnoticed.\n if (!(error instanceof ProofUnsupportedNamespaceError)) {\n console.error(`Skipping proof for account ${fullAccount.id}:`, error);\n }\n }\n }\n\n if (candidates.size === 0) {\n return accounts;\n }\n\n let nonces: Record<string, string> = {};\n try {\n nonces = await this.messenger.call('ProfileMetricsService:fetchNonces', {\n identifiers: [...identifiers],\n entropySourceId,\n });\n } catch (error) {\n console.error(\n `Failed to fetch proof-of-ownership nonces for entropy source ID ${entropySourceId}:`,\n error,\n );\n }\n\n return await Promise.all(\n accounts.map(async (queued): Promise<AccountWithScopes> => {\n const candidate = candidates.get(queued.address);\n if (!candidate) {\n return queued;\n }\n const nonce = nonces[candidate.canonicalAddress];\n if (!nonce) {\n return { ...queued, address: candidate.canonicalAddress };\n }\n let proof: AccountOwnershipProof;\n try {\n proof = await this.messenger.call('ProofOfOwnershipService:sign', {\n account: candidate.account,\n nonce,\n });\n } catch (error) {\n console.error(\n `Failed to sign proof of ownership for account ${candidate.account.id}:`,\n error,\n );\n return { ...queued, address: candidate.canonicalAddress };\n }\n return {\n address: candidate.canonicalAddress,\n scopes: queued.scopes,\n proof,\n };\n }),\n );\n }\n\n /**\n * Snapshot the live `InternalAccount` map keyed by address for the\n * current poll.\n *\n * @returns A map of address → `InternalAccount`.\n */\n #getFullAccountsByAddress(): Map<string, InternalAccount> {\n const byAddress = new Map<string, InternalAccount>();\n const accountsState = this.messenger.call('AccountsController:getState');\n for (const account of Object.values(\n accountsState.internalAccounts.accounts,\n )) {\n byAddress.set(account.address, account);\n }\n return byAddress;\n }\n\n /**\n * Enqueue all currently-known accounts onto the sync queue if needed.\n * Single entry point covering both the fresh-install first sync and\n * the one-time proof-of-ownership backfill for users upgrading.\n *\n * Bails for opted-out users (the poll wouldn't drain the queue\n * anyway), and bails once both bootstrap steps have already run.\n * Otherwise enqueues all known accounts and flips both flags so this\n * becomes a permanent no-op for the lifetime of the install.\n */\n async #enqueueAccountsIfNeeded(): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n if (!this.#assertUserOptedIn()) {\n return;\n }\n if (\n this.state.initialEnqueueCompleted &&\n this.state.proofBackfillEnqueued\n ) {\n return;\n }\n const groupedAccounts = groupAccountsByEntropySourceId(\n Object.values(\n this.messenger.call('AccountsController:getState').internalAccounts\n .accounts,\n ),\n );\n this.update((state) => {\n // Replace the queue rather than append. `AccountsController` is\n // the source of truth and the queue is otherwise kept in sync\n // with it via the `accountAdded` / `accountRemoved` subscriptions,\n // so assigning here avoids duplicating entries that survived from\n // a prior session or were pushed earlier in this same unlock\n // cycle. Duplicates would matter because nonces are single-use:\n // letting one through causes `#attachProofs` to sign and submit\n // twice with the same nonce.\n state.syncQueue = groupedAccounts;\n state.initialEnqueueCompleted = true;\n state.proofBackfillEnqueued = true;\n });\n });\n }\n\n /**\n * Set the initial delay end timestamp if it is not already set.\n */\n #setInitialDelayEndTimestampIfNull(): void {\n this.update((state) => {\n state.initialDelayEndTimestamp ??=\n Date.now() + this.#initialDelayDuration;\n });\n }\n\n /**\n * Check if the initial delay end timestamp is in the past.\n *\n * @returns True if the initial delay period has completed, false otherwise.\n */\n #isInitialDelayComplete(): boolean {\n return (\n this.state.initialDelayEndTimestamp !== undefined &&\n Date.now() >= this.state.initialDelayEndTimestamp\n );\n }\n\n /**\n * Queue the given account to be synced at the next poll.\n *\n * @param account - The account to sync.\n */\n async #addAccountToQueue(account: InternalAccount): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n const entropySourceId = getAccountEntropySourceId(account) ?? 'null';\n if (!state.syncQueue[entropySourceId]) {\n state.syncQueue[entropySourceId] = [];\n }\n state.syncQueue[entropySourceId].push({\n address: account.address,\n scopes: account.scopes,\n });\n });\n });\n }\n\n /**\n * Remove the given account from the sync queue.\n *\n * @param account - The account address to remove.\n */\n async #removeAccountFromQueue(account: string): Promise<void> {\n await this.#mutex.runExclusive(async () => {\n this.update((state) => {\n for (const [entropySourceId, groupedAddresses] of Object.entries(\n state.syncQueue,\n )) {\n const index = groupedAddresses.findIndex(\n ({ address }) => address === account,\n );\n if (index === -1) {\n continue;\n }\n groupedAddresses.splice(index, 1);\n if (groupedAddresses.length === 0) {\n delete state.syncQueue[entropySourceId];\n }\n break;\n }\n });\n });\n }\n}\n\n/**\n * Retrieves the entropy source ID from the given account, if it exists.\n *\n * @param account - The account from which to retrieve the entropy source ID.\n * @returns The entropy source ID, or null if it does not exist.\n */\nfunction getAccountEntropySourceId(account: InternalAccount): string | null {\n if (account.options.entropy?.type === 'mnemonic') {\n return account.options.entropy.id;\n }\n return null;\n}\n\n/**\n * Groups accounts by their entropy source ID.\n *\n * @param accounts - The accounts to group.\n * @returns An object where each key is an entropy source ID and each value is\n * an array of account addresses associated with that entropy source ID.\n */\nfunction groupAccountsByEntropySourceId(\n accounts: InternalAccount[],\n): Record<string, AccountWithScopes[]> {\n return accounts.reduce(\n (result: Record<string, AccountWithScopes[]>, account) => {\n const entropySourceId = getAccountEntropySourceId(account);\n const key = entropySourceId ?? 'null';\n if (!result[key]) {\n result[key] = [];\n }\n result[key].push({ address: account.address, scopes: account.scopes });\n return result;\n },\n {},\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService-method-action-types.cjs","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsService } from './ProfileMetricsService';\n\n/**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\nexport type ProfileMetricsServiceFetchNoncesAction = {\n type: `ProfileMetricsService:fetchNonces`;\n handler: ProfileMetricsService['fetchNonces'];\n};\n\n/**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\nexport type ProfileMetricsServiceSubmitMetricsAction = {\n type: `ProfileMetricsService:submitMetrics`;\n handler: ProfileMetricsService['submitMetrics'];\n};\n\n/**\n * Union of all ProfileMetricsService action types.\n */\nexport type ProfileMetricsServiceMethodActions =\n | ProfileMetricsServiceFetchNoncesAction\n | ProfileMetricsServiceSubmitMetricsAction;\n"]}
1
+ {"version":3,"file":"ProfileMetricsService-method-action-types.cjs","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsService } from './ProfileMetricsService.js';\n\n/**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\nexport type ProfileMetricsServiceFetchNoncesAction = {\n type: `ProfileMetricsService:fetchNonces`;\n handler: ProfileMetricsService['fetchNonces'];\n};\n\n/**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\nexport type ProfileMetricsServiceSubmitMetricsAction = {\n type: `ProfileMetricsService:submitMetrics`;\n handler: ProfileMetricsService['submitMetrics'];\n};\n\n/**\n * Union of all ProfileMetricsService action types.\n */\nexport type ProfileMetricsServiceMethodActions =\n | ProfileMetricsServiceFetchNoncesAction\n | ProfileMetricsServiceSubmitMetricsAction;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAgC;AAErE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,sCAAsC,GAAG;IACnD,IAAI,EAAE,mCAAmC,CAAC;IAC1C,OAAO,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAC;CAC/C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAC1C,sCAAsC,GACtC,wCAAwC,CAAC"}
1
+ {"version":3,"file":"ProfileMetricsService-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAmC;AAExE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,sCAAsC,GAAG;IACnD,IAAI,EAAE,mCAAmC,CAAC;IAC1C,OAAO,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAC;CAC/C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAC1C,sCAAsC,GACtC,wCAAwC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAgC;AAErE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,sCAAsC,GAAG;IACnD,IAAI,EAAE,mCAAmC,CAAC;IAC1C,OAAO,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAC;CAC/C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAC1C,sCAAsC,GACtC,wCAAwC,CAAC"}
1
+ {"version":3,"file":"ProfileMetricsService-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAmC;AAExE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,sCAAsC,GAAG;IACnD,IAAI,EAAE,mCAAmC,CAAC;IAC1C,OAAO,EAAE,qBAAqB,CAAC,aAAa,CAAC,CAAC;CAC/C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wCAAwC,GAAG;IACrD,IAAI,EAAE,qCAAqC,CAAC;IAC5C,OAAO,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAC1C,sCAAsC,GACtC,wCAAwC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService-method-action-types.mjs","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsService } from './ProfileMetricsService';\n\n/**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\nexport type ProfileMetricsServiceFetchNoncesAction = {\n type: `ProfileMetricsService:fetchNonces`;\n handler: ProfileMetricsService['fetchNonces'];\n};\n\n/**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\nexport type ProfileMetricsServiceSubmitMetricsAction = {\n type: `ProfileMetricsService:submitMetrics`;\n handler: ProfileMetricsService['submitMetrics'];\n};\n\n/**\n * Union of all ProfileMetricsService action types.\n */\nexport type ProfileMetricsServiceMethodActions =\n | ProfileMetricsServiceFetchNoncesAction\n | ProfileMetricsServiceSubmitMetricsAction;\n"]}
1
+ {"version":3,"file":"ProfileMetricsService-method-action-types.mjs","sourceRoot":"","sources":["../src/ProfileMetricsService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProfileMetricsService } from './ProfileMetricsService.js';\n\n/**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\nexport type ProfileMetricsServiceFetchNoncesAction = {\n type: `ProfileMetricsService:fetchNonces`;\n handler: ProfileMetricsService['fetchNonces'];\n};\n\n/**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\nexport type ProfileMetricsServiceSubmitMetricsAction = {\n type: `ProfileMetricsService:submitMetrics`;\n handler: ProfileMetricsService['submitMetrics'];\n};\n\n/**\n * Union of all ProfileMetricsService action types.\n */\nexport type ProfileMetricsServiceMethodActions =\n | ProfileMetricsServiceFetchNoncesAction\n | ProfileMetricsServiceSubmitMetricsAction;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService.cjs","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { SDK } from '@metamask/profile-sync-controller';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\nimport {\n array,\n number,\n string,\n type as structType,\n} from '@metamask/superstruct';\nimport type { IDisposable } from 'cockatiel';\n\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types';\n\n/**\n * The shape of an entry in the `POST /api/v2/nonce/batch` response body.\n *\n * `identifier` echoes the request identifier verbatim, mirroring the\n * documented behavior of the single-account `GET /api/v2/nonce` endpoint on\n * the same auth service. Defined with `type()` (not `object()`) so the\n * client tolerates additive server-side schema changes.\n */\nconst NonceBatchResponseStruct = array(\n structType({\n expires_in: number(),\n identifier: string(),\n nonce: string(),\n }),\n);\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProfileMetricsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProfileMetricsService';\n\n/**\n * A cryptographic proof that the caller controls the private key of an\n * account, as defined by the `PUT /api/v2/profile/accounts` endpoint of the\n * auth API. When present, the server verifies the signature against\n * `metamask:proof-of-ownership:<nonce>:<canonical address>` and permanently\n * marks the account as `verified: true`.\n */\nexport type AccountOwnershipProof = {\n /**\n * Single-use nonce obtained from {@link ProfileMetricsService.fetchNonces}.\n * Consumed by the server on verification; replay is not possible.\n */\n nonce: string;\n /**\n * Chain-native signature of `metamask:proof-of-ownership:<nonce>:<address>`,\n * always 0x-prefixed. The exact format varies by chain (see the auth API\n * spec — EIP-191 for `eip155`, ed25519 for `solana`, TIP-191 for `tron`,\n * BIP-322 for `bip122`).\n */\n signature: string;\n};\n\n/**\n * An account address along with its associated scopes and an optional\n * ownership proof.\n */\nexport type AccountWithScopes = {\n address: string;\n scopes: `${string}:${string}`[];\n proof?: AccountOwnershipProof;\n};\n\n/**\n * The shape of the request object for submitting metrics.\n */\nexport type ProfileMetricsSubmitMetricsRequest = {\n metametricsId: string;\n entropySourceId?: string | null;\n accounts: AccountWithScopes[];\n};\n\n/**\n * The shape of the request object for fetching a batch of single-use nonces.\n */\nexport type ProfileMetricsFetchNoncesRequest = {\n /**\n * The identifiers (canonical addresses) to mint a nonce for. The auth API\n * accepts between 1 and {@link MAX_NONCE_BATCH_SIZE} identifiers per call.\n */\n identifiers: string[];\n /**\n * The entropy source ID to use when fetching a bearer token. Pass `null` or\n * omit for accounts that do not belong to any entropy source.\n */\n entropySourceId?: string | null;\n};\n\n/**\n * Maximum number of identifiers the auth API will mint nonces for in a single\n * `POST /api/v2/nonce/batch` request. {@link ProfileMetricsService.fetchNonces}\n * uses this as the chunk size when the caller requests more than this many\n * nonces at once.\n */\nexport const MAX_NONCE_BATCH_SIZE = 50;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['submitMetrics', 'fetchNonces'] as const;\n\n/**\n * Actions that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceActions = ProfileMetricsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsService} calls.\n */\ntype AllowedActions =\n AuthenticationController.AuthenticationControllerGetBearerTokenAction;\n\n/**\n * Events that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProfileMetricsService} subscribes\n * to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProfileMetricsService}.\n */\nexport type ProfileMetricsServiceMessenger = Messenger<\n typeof serviceName,\n ProfileMetricsServiceActions | AllowedActions,\n ProfileMetricsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service for submitting user profile metrics (metrics ID and accounts).\n */\nexport class ProfileMetricsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The API base URL environment.\n */\n readonly #baseURL: string;\n\n /**\n * Constructs a new ProfileMetricsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n * @param args.env - The environment to determine the correct API endpoints.\n */\n constructor({\n messenger,\n fetch: fetchFunction,\n policyOptions = {},\n env = SDK.Env.DEV,\n }: {\n messenger: ProfileMetricsServiceMessenger;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n env?: SDK.Env;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#baseURL = getAuthUrl(env);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): IDisposable {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): IDisposable {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): IDisposable {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\n async fetchNonces(\n data: ProfileMetricsFetchNoncesRequest,\n ): Promise<Record<string, string>> {\n if (data.identifiers.length === 0) {\n throw new RangeError(\n 'ProfileMetricsService.fetchNonces requires at least 1 identifier.',\n );\n }\n const chunks: string[][] = [];\n for (let i = 0; i < data.identifiers.length; i += MAX_NONCE_BATCH_SIZE) {\n chunks.push(data.identifiers.slice(i, i + MAX_NONCE_BATCH_SIZE));\n }\n const chunkResults = await Promise.all(\n chunks.map((identifiers) =>\n this.#fetchNoncesChunk(identifiers, data.entropySourceId),\n ),\n );\n return Object.assign({}, ...chunkResults);\n }\n\n /**\n * Mint nonces for a single ≤ {@link MAX_NONCE_BATCH_SIZE}-sized chunk of\n * identifiers. Wrapped in {@link #policy} for retry / degraded / circuit\n * semantics consistent with the rest of the service.\n *\n * @param identifiers - The identifiers in this chunk. Must be 1..MAX_NONCE_BATCH_SIZE.\n * @param entropySourceId - The entropy source ID forwarded to the bearer\n * token resolver.\n * @returns A map of identifier -> nonce for this chunk.\n */\n async #fetchNoncesChunk(\n identifiers: string[],\n entropySourceId: string | null | undefined,\n ): Promise<Record<string, string>> {\n return await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/nonce/batch`);\n const localResponse = await this.#fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ identifiers }),\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n const body: unknown = await localResponse.json();\n if (!NonceBatchResponseStruct.is(body)) {\n throw new Error(`Malformed response received from '${url.toString()}'`);\n }\n const result: Record<string, string> = {};\n for (const entry of body) {\n result[entry.identifier] = entry.nonce;\n }\n const echoesRequest =\n body.length === identifiers.length &&\n identifiers.every((id) =>\n Object.prototype.hasOwnProperty.call(result, id),\n );\n if (!echoesRequest) {\n throw new Error(\n `Fetching '${url.toString()}' returned a response whose identifier set does not match the request`,\n );\n }\n return result;\n });\n }\n\n /**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\n async submitMetrics(data: ProfileMetricsSubmitMetricsRequest): Promise<void> {\n await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n data.entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/profile/accounts`);\n const localResponse = await this.#fetch(url, {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n metametrics_id: data.metametricsId,\n accounts: data.accounts,\n }),\n // The auth API is stateless (no cookies used)\n // prevent marketing cookies scoped to\n // .metamask.io from being forwarded to api which\n // causes 431 Request Header Fields Too Large errors.\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n return localResponse;\n });\n }\n}\n\n/**\n * Returns the base URL for the given environment.\n *\n * @param env - The environment to get the URL for.\n * @returns The base URL for the environment.\n */\nexport function getAuthUrl(env: SDK.Env): string {\n return `${SDK.getEnvUrls(env).authApiUrl}/api/v2`;\n}\n"]}
1
+ {"version":3,"file":"ProfileMetricsService.cjs","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAIA,iEAA4E;AAE5E,+EAAwD;AAExD,uDAK+B;AAK/B;;;;;;;GAOG;AACH,MAAM,wBAAwB,GAAG,IAAA,mBAAK,EACpC,IAAA,kBAAU,EAAC;IACT,UAAU,EAAE,IAAA,oBAAM,GAAE;IACpB,UAAU,EAAE,IAAA,oBAAM,GAAE;IACpB,KAAK,EAAE,IAAA,oBAAM,GAAE;CAChB,CAAC,CACH,CAAC;AAEF,kBAAkB;AAElB;;;GAGG;AACU,QAAA,WAAW,GAAG,uBAAuB,CAAC;AA2DnD;;;;;GAKG;AACU,QAAA,oBAAoB,GAAG,EAAE,CAAC;AAEvC,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,eAAe,EAAE,aAAa,CAAU,CAAC;AAkC5E,6BAA6B;AAE7B;;GAEG;AACH,MAAa,qBAAqB;IAgChC;;;;;;;;;;;;OAYG;IACH,YAAY,EACV,SAAS,EACT,KAAK,EAAE,aAAa,EACpB,aAAa,GAAG,EAAE,EAClB,GAAG,GAAG,6BAAG,CAAC,GAAG,CAAC,GAAG,GAMlB;;QAjDD;;WAEG;QACM,mDAES;QAElB;;WAEG;QACM,+CAEK;QAEd;;;;WAIG;QACM,gDAAuB;QAEhC;;WAEG;QACM,iDAAiB;QA0BxB,IAAI,CAAC,IAAI,GAAG,mBAAW,CAAC;QACxB,uBAAA,IAAI,oCAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,gCAAU,aAAa,MAAA,CAAC;QAC5B,uBAAA,IAAI,iCAAW,IAAA,sCAAmB,EAAC,aAAa,CAAC,MAAA,CAAC;QAClD,uBAAA,IAAI,kCAAY,UAAU,CAAC,GAAG,CAAC,MAAA,CAAC;QAEhC,uBAAA,IAAI,wCAAW,CAAC,4BAA4B,CAC1C,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAiD;QACvD,OAAO,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAiD;QACvD,OAAO,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CACR,QAAoD;QAEpD,OAAO,uBAAA,IAAI,qCAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,KAAK,CAAC,WAAW,CACf,IAAsC;QAEtC,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,UAAU,CAClB,mEAAmE,CACpE,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,4BAAoB,EAAE,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,4BAAoB,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CACpC,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CACzB,uBAAA,IAAI,iFAAkB,MAAtB,IAAI,EAAmB,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAC1D,CACF,CAAC;QACF,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,YAAY,CAAC,CAAC;IAC5C,CAAC;IA2DD;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,IAAwC;QAC1D,MAAM,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;YACpC,MAAM,SAAS,GAAG,MAAM,uBAAA,IAAI,wCAAW,CAAC,IAAI,CAC1C,yCAAyC,EACzC,IAAI,CAAC,eAAe,IAAI,SAAS,CAClC,CAAC;YACF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,uBAAA,IAAI,sCAAS,mBAAmB,CAAC,CAAC;YACzD,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,oCAAO,MAAX,IAAI,EAAQ,GAAG,EAAE;gBAC3C,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,SAAS,EAAE;oBACpC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,cAAc,EAAE,IAAI,CAAC,aAAa;oBAClC,QAAQ,EAAE,IAAI,CAAC,QAAQ;iBACxB,CAAC;gBACF,8CAA8C;gBAC9C,sCAAsC;gBACtC,iDAAiD;gBACjD,qDAAqD;gBACrD,WAAW,EAAE,MAAM;aACpB,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;gBACtB,MAAM,IAAI,4BAAS,CACjB,aAAa,CAAC,MAAM,EACpB,aAAa,GAAG,CAAC,QAAQ,EAAE,yBAAyB,aAAa,CAAC,MAAM,GAAG,CAC5E,CAAC;YACJ,CAAC;YACD,OAAO,aAAa,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA9PD,sDA8PC;;AA/FC;;;;;;;;;GASG;AACH,KAAK,kDACH,WAAqB,EACrB,eAA0C;IAE1C,OAAO,MAAM,uBAAA,IAAI,qCAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;QAC3C,MAAM,SAAS,GAAG,MAAM,uBAAA,IAAI,wCAAW,CAAC,IAAI,CAC1C,yCAAyC,EACzC,eAAe,IAAI,SAAS,CAC7B,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,uBAAA,IAAI,sCAAS,cAAc,CAAC,CAAC;QACpD,MAAM,aAAa,GAAG,MAAM,uBAAA,IAAI,oCAAO,MAAX,IAAI,EAAQ,GAAG,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,SAAS,EAAE;gBACpC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;YACrC,WAAW,EAAE,MAAM;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;YACtB,MAAM,IAAI,4BAAS,CACjB,aAAa,CAAC,MAAM,EACpB,aAAa,GAAG,CAAC,QAAQ,EAAE,yBAAyB,aAAa,CAAC,MAAM,GAAG,CAC5E,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAY,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,wBAAwB,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;YACzB,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QACzC,CAAC;QACD,MAAM,aAAa,GACjB,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM;YAClC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CACvB,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CACjD,CAAC;QACJ,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,aAAa,GAAG,CAAC,QAAQ,EAAE,uEAAuE,CACnG,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC;AA0CH;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,GAAY;IACrC,OAAO,GAAG,6BAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,SAAS,CAAC;AACpD,CAAC;AAFD,gCAEC","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { SDK } from '@metamask/profile-sync-controller';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\nimport {\n array,\n number,\n string,\n type as structType,\n} from '@metamask/superstruct';\nimport type { IDisposable } from 'cockatiel';\n\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types.js';\n\n/**\n * The shape of an entry in the `POST /api/v2/nonce/batch` response body.\n *\n * `identifier` echoes the request identifier verbatim, mirroring the\n * documented behavior of the single-account `GET /api/v2/nonce` endpoint on\n * the same auth service. Defined with `type()` (not `object()`) so the\n * client tolerates additive server-side schema changes.\n */\nconst NonceBatchResponseStruct = array(\n structType({\n expires_in: number(),\n identifier: string(),\n nonce: string(),\n }),\n);\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProfileMetricsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProfileMetricsService';\n\n/**\n * A cryptographic proof that the caller controls the private key of an\n * account, as defined by the `PUT /api/v2/profile/accounts` endpoint of the\n * auth API. When present, the server verifies the signature against\n * `metamask:proof-of-ownership:<nonce>:<canonical address>` and permanently\n * marks the account as `verified: true`.\n */\nexport type AccountOwnershipProof = {\n /**\n * Single-use nonce obtained from {@link ProfileMetricsService.fetchNonces}.\n * Consumed by the server on verification; replay is not possible.\n */\n nonce: string;\n /**\n * Chain-native signature of `metamask:proof-of-ownership:<nonce>:<address>`,\n * always 0x-prefixed. The exact format varies by chain (see the auth API\n * spec — EIP-191 for `eip155`, ed25519 for `solana`, TIP-191 for `tron`,\n * BIP-322 for `bip122`).\n */\n signature: string;\n};\n\n/**\n * An account address along with its associated scopes and an optional\n * ownership proof.\n */\nexport type AccountWithScopes = {\n address: string;\n scopes: `${string}:${string}`[];\n proof?: AccountOwnershipProof;\n};\n\n/**\n * The shape of the request object for submitting metrics.\n */\nexport type ProfileMetricsSubmitMetricsRequest = {\n metametricsId: string;\n entropySourceId?: string | null;\n accounts: AccountWithScopes[];\n};\n\n/**\n * The shape of the request object for fetching a batch of single-use nonces.\n */\nexport type ProfileMetricsFetchNoncesRequest = {\n /**\n * The identifiers (canonical addresses) to mint a nonce for. The auth API\n * accepts between 1 and {@link MAX_NONCE_BATCH_SIZE} identifiers per call.\n */\n identifiers: string[];\n /**\n * The entropy source ID to use when fetching a bearer token. Pass `null` or\n * omit for accounts that do not belong to any entropy source.\n */\n entropySourceId?: string | null;\n};\n\n/**\n * Maximum number of identifiers the auth API will mint nonces for in a single\n * `POST /api/v2/nonce/batch` request. {@link ProfileMetricsService.fetchNonces}\n * uses this as the chunk size when the caller requests more than this many\n * nonces at once.\n */\nexport const MAX_NONCE_BATCH_SIZE = 50;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['submitMetrics', 'fetchNonces'] as const;\n\n/**\n * Actions that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceActions = ProfileMetricsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsService} calls.\n */\ntype AllowedActions =\n AuthenticationController.AuthenticationControllerGetBearerTokenAction;\n\n/**\n * Events that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProfileMetricsService} subscribes\n * to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProfileMetricsService}.\n */\nexport type ProfileMetricsServiceMessenger = Messenger<\n typeof serviceName,\n ProfileMetricsServiceActions | AllowedActions,\n ProfileMetricsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service for submitting user profile metrics (metrics ID and accounts).\n */\nexport class ProfileMetricsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The API base URL environment.\n */\n readonly #baseURL: string;\n\n /**\n * Constructs a new ProfileMetricsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n * @param args.env - The environment to determine the correct API endpoints.\n */\n constructor({\n messenger,\n fetch: fetchFunction,\n policyOptions = {},\n env = SDK.Env.DEV,\n }: {\n messenger: ProfileMetricsServiceMessenger;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n env?: SDK.Env;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#baseURL = getAuthUrl(env);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): IDisposable {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): IDisposable {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): IDisposable {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\n async fetchNonces(\n data: ProfileMetricsFetchNoncesRequest,\n ): Promise<Record<string, string>> {\n if (data.identifiers.length === 0) {\n throw new RangeError(\n 'ProfileMetricsService.fetchNonces requires at least 1 identifier.',\n );\n }\n const chunks: string[][] = [];\n for (let i = 0; i < data.identifiers.length; i += MAX_NONCE_BATCH_SIZE) {\n chunks.push(data.identifiers.slice(i, i + MAX_NONCE_BATCH_SIZE));\n }\n const chunkResults = await Promise.all(\n chunks.map((identifiers) =>\n this.#fetchNoncesChunk(identifiers, data.entropySourceId),\n ),\n );\n return Object.assign({}, ...chunkResults);\n }\n\n /**\n * Mint nonces for a single ≤ {@link MAX_NONCE_BATCH_SIZE}-sized chunk of\n * identifiers. Wrapped in {@link #policy} for retry / degraded / circuit\n * semantics consistent with the rest of the service.\n *\n * @param identifiers - The identifiers in this chunk. Must be 1..MAX_NONCE_BATCH_SIZE.\n * @param entropySourceId - The entropy source ID forwarded to the bearer\n * token resolver.\n * @returns A map of identifier -> nonce for this chunk.\n */\n async #fetchNoncesChunk(\n identifiers: string[],\n entropySourceId: string | null | undefined,\n ): Promise<Record<string, string>> {\n return await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/nonce/batch`);\n const localResponse = await this.#fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ identifiers }),\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n const body: unknown = await localResponse.json();\n if (!NonceBatchResponseStruct.is(body)) {\n throw new Error(`Malformed response received from '${url.toString()}'`);\n }\n const result: Record<string, string> = {};\n for (const entry of body) {\n result[entry.identifier] = entry.nonce;\n }\n const echoesRequest =\n body.length === identifiers.length &&\n identifiers.every((id) =>\n Object.prototype.hasOwnProperty.call(result, id),\n );\n if (!echoesRequest) {\n throw new Error(\n `Fetching '${url.toString()}' returned a response whose identifier set does not match the request`,\n );\n }\n return result;\n });\n }\n\n /**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\n async submitMetrics(data: ProfileMetricsSubmitMetricsRequest): Promise<void> {\n await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n data.entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/profile/accounts`);\n const localResponse = await this.#fetch(url, {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n metametrics_id: data.metametricsId,\n accounts: data.accounts,\n }),\n // The auth API is stateless (no cookies used)\n // prevent marketing cookies scoped to\n // .metamask.io from being forwarded to api which\n // causes 431 Request Header Fields Too Large errors.\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n return localResponse;\n });\n }\n}\n\n/**\n * Returns the base URL for the given environment.\n *\n * @param env - The environment to get the URL for.\n * @returns The base URL for the environment.\n */\nexport function getAuthUrl(env: SDK.Env): string {\n return `${SDK.getEnvUrls(env).authApiUrl}/api/v2`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProfileMetricsService.d.cts","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProfileMetricsService.d.mts","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetricsService.mjs","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { SDK } from '@metamask/profile-sync-controller';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\nimport {\n array,\n number,\n string,\n type as structType,\n} from '@metamask/superstruct';\nimport type { IDisposable } from 'cockatiel';\n\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types';\n\n/**\n * The shape of an entry in the `POST /api/v2/nonce/batch` response body.\n *\n * `identifier` echoes the request identifier verbatim, mirroring the\n * documented behavior of the single-account `GET /api/v2/nonce` endpoint on\n * the same auth service. Defined with `type()` (not `object()`) so the\n * client tolerates additive server-side schema changes.\n */\nconst NonceBatchResponseStruct = array(\n structType({\n expires_in: number(),\n identifier: string(),\n nonce: string(),\n }),\n);\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProfileMetricsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProfileMetricsService';\n\n/**\n * A cryptographic proof that the caller controls the private key of an\n * account, as defined by the `PUT /api/v2/profile/accounts` endpoint of the\n * auth API. When present, the server verifies the signature against\n * `metamask:proof-of-ownership:<nonce>:<canonical address>` and permanently\n * marks the account as `verified: true`.\n */\nexport type AccountOwnershipProof = {\n /**\n * Single-use nonce obtained from {@link ProfileMetricsService.fetchNonces}.\n * Consumed by the server on verification; replay is not possible.\n */\n nonce: string;\n /**\n * Chain-native signature of `metamask:proof-of-ownership:<nonce>:<address>`,\n * always 0x-prefixed. The exact format varies by chain (see the auth API\n * spec — EIP-191 for `eip155`, ed25519 for `solana`, TIP-191 for `tron`,\n * BIP-322 for `bip122`).\n */\n signature: string;\n};\n\n/**\n * An account address along with its associated scopes and an optional\n * ownership proof.\n */\nexport type AccountWithScopes = {\n address: string;\n scopes: `${string}:${string}`[];\n proof?: AccountOwnershipProof;\n};\n\n/**\n * The shape of the request object for submitting metrics.\n */\nexport type ProfileMetricsSubmitMetricsRequest = {\n metametricsId: string;\n entropySourceId?: string | null;\n accounts: AccountWithScopes[];\n};\n\n/**\n * The shape of the request object for fetching a batch of single-use nonces.\n */\nexport type ProfileMetricsFetchNoncesRequest = {\n /**\n * The identifiers (canonical addresses) to mint a nonce for. The auth API\n * accepts between 1 and {@link MAX_NONCE_BATCH_SIZE} identifiers per call.\n */\n identifiers: string[];\n /**\n * The entropy source ID to use when fetching a bearer token. Pass `null` or\n * omit for accounts that do not belong to any entropy source.\n */\n entropySourceId?: string | null;\n};\n\n/**\n * Maximum number of identifiers the auth API will mint nonces for in a single\n * `POST /api/v2/nonce/batch` request. {@link ProfileMetricsService.fetchNonces}\n * uses this as the chunk size when the caller requests more than this many\n * nonces at once.\n */\nexport const MAX_NONCE_BATCH_SIZE = 50;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['submitMetrics', 'fetchNonces'] as const;\n\n/**\n * Actions that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceActions = ProfileMetricsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsService} calls.\n */\ntype AllowedActions =\n AuthenticationController.AuthenticationControllerGetBearerTokenAction;\n\n/**\n * Events that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProfileMetricsService} subscribes\n * to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProfileMetricsService}.\n */\nexport type ProfileMetricsServiceMessenger = Messenger<\n typeof serviceName,\n ProfileMetricsServiceActions | AllowedActions,\n ProfileMetricsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service for submitting user profile metrics (metrics ID and accounts).\n */\nexport class ProfileMetricsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The API base URL environment.\n */\n readonly #baseURL: string;\n\n /**\n * Constructs a new ProfileMetricsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n * @param args.env - The environment to determine the correct API endpoints.\n */\n constructor({\n messenger,\n fetch: fetchFunction,\n policyOptions = {},\n env = SDK.Env.DEV,\n }: {\n messenger: ProfileMetricsServiceMessenger;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n env?: SDK.Env;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#baseURL = getAuthUrl(env);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): IDisposable {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): IDisposable {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): IDisposable {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\n async fetchNonces(\n data: ProfileMetricsFetchNoncesRequest,\n ): Promise<Record<string, string>> {\n if (data.identifiers.length === 0) {\n throw new RangeError(\n 'ProfileMetricsService.fetchNonces requires at least 1 identifier.',\n );\n }\n const chunks: string[][] = [];\n for (let i = 0; i < data.identifiers.length; i += MAX_NONCE_BATCH_SIZE) {\n chunks.push(data.identifiers.slice(i, i + MAX_NONCE_BATCH_SIZE));\n }\n const chunkResults = await Promise.all(\n chunks.map((identifiers) =>\n this.#fetchNoncesChunk(identifiers, data.entropySourceId),\n ),\n );\n return Object.assign({}, ...chunkResults);\n }\n\n /**\n * Mint nonces for a single ≤ {@link MAX_NONCE_BATCH_SIZE}-sized chunk of\n * identifiers. Wrapped in {@link #policy} for retry / degraded / circuit\n * semantics consistent with the rest of the service.\n *\n * @param identifiers - The identifiers in this chunk. Must be 1..MAX_NONCE_BATCH_SIZE.\n * @param entropySourceId - The entropy source ID forwarded to the bearer\n * token resolver.\n * @returns A map of identifier -> nonce for this chunk.\n */\n async #fetchNoncesChunk(\n identifiers: string[],\n entropySourceId: string | null | undefined,\n ): Promise<Record<string, string>> {\n return await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/nonce/batch`);\n const localResponse = await this.#fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ identifiers }),\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n const body: unknown = await localResponse.json();\n if (!NonceBatchResponseStruct.is(body)) {\n throw new Error(`Malformed response received from '${url.toString()}'`);\n }\n const result: Record<string, string> = {};\n for (const entry of body) {\n result[entry.identifier] = entry.nonce;\n }\n const echoesRequest =\n body.length === identifiers.length &&\n identifiers.every((id) =>\n Object.prototype.hasOwnProperty.call(result, id),\n );\n if (!echoesRequest) {\n throw new Error(\n `Fetching '${url.toString()}' returned a response whose identifier set does not match the request`,\n );\n }\n return result;\n });\n }\n\n /**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\n async submitMetrics(data: ProfileMetricsSubmitMetricsRequest): Promise<void> {\n await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n data.entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/profile/accounts`);\n const localResponse = await this.#fetch(url, {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n metametrics_id: data.metametricsId,\n accounts: data.accounts,\n }),\n // The auth API is stateless (no cookies used)\n // prevent marketing cookies scoped to\n // .metamask.io from being forwarded to api which\n // causes 431 Request Header Fields Too Large errors.\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n return localResponse;\n });\n }\n}\n\n/**\n * Returns the base URL for the given environment.\n *\n * @param env - The environment to get the URL for.\n * @returns The base URL for the environment.\n */\nexport function getAuthUrl(env: SDK.Env): string {\n return `${SDK.getEnvUrls(env).authApiUrl}/api/v2`;\n}\n"]}
1
+ {"version":3,"file":"ProfileMetricsService.mjs","sourceRoot":"","sources":["../src/ProfileMetricsService.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CreateServicePolicyOptions,\n ServicePolicy,\n} from '@metamask/controller-utils';\nimport { createServicePolicy, HttpError } from '@metamask/controller-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { SDK } from '@metamask/profile-sync-controller';\nimport type { AuthenticationController } from '@metamask/profile-sync-controller';\nimport {\n array,\n number,\n string,\n type as structType,\n} from '@metamask/superstruct';\nimport type { IDisposable } from 'cockatiel';\n\nimport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types.js';\n\n/**\n * The shape of an entry in the `POST /api/v2/nonce/batch` response body.\n *\n * `identifier` echoes the request identifier verbatim, mirroring the\n * documented behavior of the single-account `GET /api/v2/nonce` endpoint on\n * the same auth service. Defined with `type()` (not `object()`) so the\n * client tolerates additive server-side schema changes.\n */\nconst NonceBatchResponseStruct = array(\n structType({\n expires_in: number(),\n identifier: string(),\n nonce: string(),\n }),\n);\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProfileMetricsService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProfileMetricsService';\n\n/**\n * A cryptographic proof that the caller controls the private key of an\n * account, as defined by the `PUT /api/v2/profile/accounts` endpoint of the\n * auth API. When present, the server verifies the signature against\n * `metamask:proof-of-ownership:<nonce>:<canonical address>` and permanently\n * marks the account as `verified: true`.\n */\nexport type AccountOwnershipProof = {\n /**\n * Single-use nonce obtained from {@link ProfileMetricsService.fetchNonces}.\n * Consumed by the server on verification; replay is not possible.\n */\n nonce: string;\n /**\n * Chain-native signature of `metamask:proof-of-ownership:<nonce>:<address>`,\n * always 0x-prefixed. The exact format varies by chain (see the auth API\n * spec — EIP-191 for `eip155`, ed25519 for `solana`, TIP-191 for `tron`,\n * BIP-322 for `bip122`).\n */\n signature: string;\n};\n\n/**\n * An account address along with its associated scopes and an optional\n * ownership proof.\n */\nexport type AccountWithScopes = {\n address: string;\n scopes: `${string}:${string}`[];\n proof?: AccountOwnershipProof;\n};\n\n/**\n * The shape of the request object for submitting metrics.\n */\nexport type ProfileMetricsSubmitMetricsRequest = {\n metametricsId: string;\n entropySourceId?: string | null;\n accounts: AccountWithScopes[];\n};\n\n/**\n * The shape of the request object for fetching a batch of single-use nonces.\n */\nexport type ProfileMetricsFetchNoncesRequest = {\n /**\n * The identifiers (canonical addresses) to mint a nonce for. The auth API\n * accepts between 1 and {@link MAX_NONCE_BATCH_SIZE} identifiers per call.\n */\n identifiers: string[];\n /**\n * The entropy source ID to use when fetching a bearer token. Pass `null` or\n * omit for accounts that do not belong to any entropy source.\n */\n entropySourceId?: string | null;\n};\n\n/**\n * Maximum number of identifiers the auth API will mint nonces for in a single\n * `POST /api/v2/nonce/batch` request. {@link ProfileMetricsService.fetchNonces}\n * uses this as the chunk size when the caller requests more than this many\n * nonces at once.\n */\nexport const MAX_NONCE_BATCH_SIZE = 50;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['submitMetrics', 'fetchNonces'] as const;\n\n/**\n * Actions that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceActions = ProfileMetricsServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProfileMetricsService} calls.\n */\ntype AllowedActions =\n AuthenticationController.AuthenticationControllerGetBearerTokenAction;\n\n/**\n * Events that {@link ProfileMetricsService} exposes to other consumers.\n */\nexport type ProfileMetricsServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProfileMetricsService} subscribes\n * to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProfileMetricsService}.\n */\nexport type ProfileMetricsServiceMessenger = Messenger<\n typeof serviceName,\n ProfileMetricsServiceActions | AllowedActions,\n ProfileMetricsServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service for submitting user profile metrics (metrics ID and accounts).\n */\nexport class ProfileMetricsService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['messenger'];\n\n /**\n * A function that can be used to make an HTTP request.\n */\n readonly #fetch: ConstructorParameters<\n typeof ProfileMetricsService\n >[0]['fetch'];\n\n /**\n * The policy that wraps the request.\n *\n * @see {@link createServicePolicy}\n */\n readonly #policy: ServicePolicy;\n\n /**\n * The API base URL environment.\n */\n readonly #baseURL: string;\n\n /**\n * Constructs a new ProfileMetricsService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.fetch - A function that can be used to make an HTTP request. If\n * your JavaScript environment supports `fetch` natively, you'll probably want\n * to pass that; otherwise you can pass an equivalent (such as `fetch` via\n * `node-fetch`).\n * @param args.policyOptions - Options to pass to `createServicePolicy`, which\n * is used to wrap each request. See {@link CreateServicePolicyOptions}.\n * @param args.env - The environment to determine the correct API endpoints.\n */\n constructor({\n messenger,\n fetch: fetchFunction,\n policyOptions = {},\n env = SDK.Env.DEV,\n }: {\n messenger: ProfileMetricsServiceMessenger;\n fetch: typeof fetch;\n policyOptions?: CreateServicePolicyOptions;\n env?: SDK.Env;\n }) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#fetch = fetchFunction;\n this.#policy = createServicePolicy(policyOptions);\n this.#baseURL = getAuthUrl(env);\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Registers a handler that will be called after a request returns a non-500\n * response, causing a retry. Primarily useful in tests where timers are being\n * mocked.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onRetry(listener: Parameters<ServicePolicy['onRetry']>[0]): IDisposable {\n return this.#policy.onRetry(listener);\n }\n\n /**\n * Registers a handler that will be called after a set number of retry rounds\n * prove that requests to the API endpoint consistently return a 5xx response.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n * @see {@link createServicePolicy}\n */\n onBreak(listener: Parameters<ServicePolicy['onBreak']>[0]): IDisposable {\n return this.#policy.onBreak(listener);\n }\n\n /**\n * Registers a handler that will be called under one of two circumstances:\n *\n * 1. After a set number of retries prove that requests to the API\n * consistently result in one of the following failures:\n * 1. A connection initiation error\n * 2. A connection reset error\n * 3. A timeout error\n * 4. A non-JSON response\n * 5. A 502, 503, or 504 response\n * 2. After a successful request is made to the API, but the response takes\n * longer than a set duration to return.\n *\n * @param listener - The handler to be called.\n * @returns An object that can be used to unregister the handler. See\n * {@link CockatielEvent}.\n */\n onDegraded(\n listener: Parameters<ServicePolicy['onDegraded']>[0],\n ): IDisposable {\n return this.#policy.onDegraded(listener);\n }\n\n /**\n * Fetch single-use nonces from the auth API, one per identifier.\n *\n * Requests larger than {@link MAX_NONCE_BATCH_SIZE} are split into multiple\n * `POST /api/v2/nonce/batch` calls fired in parallel; the resulting maps are\n * merged into a single record. Each chunk independently goes through the\n * service policy (retry, circuit-breaker, degraded). If any chunk ultimately\n * fails, the whole call rejects so the caller can soft-degrade the entire\n * entropy-source batch consistently.\n *\n * The returned record is keyed by the auth API's echoed `identifier` field\n * (`response[i].identifier -> response[i].nonce`). The call asserts that\n * the response identifier set is exactly the requested set; any mismatch\n * (missing, extra, or duplicated identifier) causes the chunk to throw so\n * the caller never silently proceeds with partial nonces.\n *\n * @param data - The identifiers to mint nonces for, plus the optional\n * entropy source ID used to scope the bearer token.\n * @returns A map of identifier -> nonce.\n * @throws {RangeError} if no identifiers are provided.\n */\n async fetchNonces(\n data: ProfileMetricsFetchNoncesRequest,\n ): Promise<Record<string, string>> {\n if (data.identifiers.length === 0) {\n throw new RangeError(\n 'ProfileMetricsService.fetchNonces requires at least 1 identifier.',\n );\n }\n const chunks: string[][] = [];\n for (let i = 0; i < data.identifiers.length; i += MAX_NONCE_BATCH_SIZE) {\n chunks.push(data.identifiers.slice(i, i + MAX_NONCE_BATCH_SIZE));\n }\n const chunkResults = await Promise.all(\n chunks.map((identifiers) =>\n this.#fetchNoncesChunk(identifiers, data.entropySourceId),\n ),\n );\n return Object.assign({}, ...chunkResults);\n }\n\n /**\n * Mint nonces for a single ≤ {@link MAX_NONCE_BATCH_SIZE}-sized chunk of\n * identifiers. Wrapped in {@link #policy} for retry / degraded / circuit\n * semantics consistent with the rest of the service.\n *\n * @param identifiers - The identifiers in this chunk. Must be 1..MAX_NONCE_BATCH_SIZE.\n * @param entropySourceId - The entropy source ID forwarded to the bearer\n * token resolver.\n * @returns A map of identifier -> nonce for this chunk.\n */\n async #fetchNoncesChunk(\n identifiers: string[],\n entropySourceId: string | null | undefined,\n ): Promise<Record<string, string>> {\n return await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/nonce/batch`);\n const localResponse = await this.#fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ identifiers }),\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n const body: unknown = await localResponse.json();\n if (!NonceBatchResponseStruct.is(body)) {\n throw new Error(`Malformed response received from '${url.toString()}'`);\n }\n const result: Record<string, string> = {};\n for (const entry of body) {\n result[entry.identifier] = entry.nonce;\n }\n const echoesRequest =\n body.length === identifiers.length &&\n identifiers.every((id) =>\n Object.prototype.hasOwnProperty.call(result, id),\n );\n if (!echoesRequest) {\n throw new Error(\n `Fetching '${url.toString()}' returned a response whose identifier set does not match the request`,\n );\n }\n return result;\n });\n }\n\n /**\n * Submit metrics to the API.\n *\n * @param data - The data to send in the metrics update request.\n * @returns The response from the API.\n */\n async submitMetrics(data: ProfileMetricsSubmitMetricsRequest): Promise<void> {\n await this.#policy.execute(async () => {\n const authToken = await this.#messenger.call(\n 'AuthenticationController:getBearerToken',\n data.entropySourceId ?? undefined,\n );\n const url = new URL(`${this.#baseURL}/profile/accounts`);\n const localResponse = await this.#fetch(url, {\n method: 'PUT',\n headers: {\n Authorization: `Bearer ${authToken}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n metametrics_id: data.metametricsId,\n accounts: data.accounts,\n }),\n // The auth API is stateless (no cookies used)\n // prevent marketing cookies scoped to\n // .metamask.io from being forwarded to api which\n // causes 431 Request Header Fields Too Large errors.\n credentials: 'omit',\n });\n if (!localResponse.ok) {\n throw new HttpError(\n localResponse.status,\n `Fetching '${url.toString()}' failed with status '${localResponse.status}'`,\n );\n }\n return localResponse;\n });\n }\n}\n\n/**\n * Returns the base URL for the given environment.\n *\n * @param env - The environment to get the URL for.\n * @returns The base URL for the environment.\n */\nexport function getAuthUrl(env: SDK.Env): string {\n return `${SDK.getEnvUrls(env).authApiUrl}/api/v2`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService-method-action-types.cjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProofOfOwnershipService } from './ProofOfOwnershipService';\n\n/**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\nexport type ProofOfOwnershipServiceSignAction = {\n type: `ProofOfOwnershipService:sign`;\n handler: ProofOfOwnershipService['sign'];\n};\n\n/**\n * Union of all ProofOfOwnershipService action types.\n */\nexport type ProofOfOwnershipServiceMethodActions =\n ProofOfOwnershipServiceSignAction;\n"]}
1
+ {"version":3,"file":"ProofOfOwnershipService-method-action-types.cjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProofOfOwnershipService } from './ProofOfOwnershipService.js';\n\n/**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\nexport type ProofOfOwnershipServiceSignAction = {\n type: `ProofOfOwnershipService:sign`;\n handler: ProofOfOwnershipService['sign'];\n};\n\n/**\n * Union of all ProofOfOwnershipService action types.\n */\nexport type ProofOfOwnershipServiceMethodActions =\n ProofOfOwnershipServiceSignAction;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AAEzE;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oCAAoC,GAC9C,iCAAiC,CAAC"}
1
+ {"version":3,"file":"ProofOfOwnershipService-method-action-types.d.cts","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAqC;AAE5E;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oCAAoC,GAC9C,iCAAiC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAkC;AAEzE;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oCAAoC,GAC9C,iCAAiC,CAAC"}
1
+ {"version":3,"file":"ProofOfOwnershipService-method-action-types.d.mts","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sCAAqC;AAE5E;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,uBAAuB,CAAC,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oCAAoC,GAC9C,iCAAiC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService-method-action-types.mjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProofOfOwnershipService } from './ProofOfOwnershipService';\n\n/**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\nexport type ProofOfOwnershipServiceSignAction = {\n type: `ProofOfOwnershipService:sign`;\n handler: ProofOfOwnershipService['sign'];\n};\n\n/**\n * Union of all ProofOfOwnershipService action types.\n */\nexport type ProofOfOwnershipServiceMethodActions =\n ProofOfOwnershipServiceSignAction;\n"]}
1
+ {"version":3,"file":"ProofOfOwnershipService-method-action-types.mjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { ProofOfOwnershipService } from './ProofOfOwnershipService.js';\n\n/**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\nexport type ProofOfOwnershipServiceSignAction = {\n type: `ProofOfOwnershipService:sign`;\n handler: ProofOfOwnershipService['sign'];\n};\n\n/**\n * Union of all ProofOfOwnershipService action types.\n */\nexport type ProofOfOwnershipServiceMethodActions =\n ProofOfOwnershipServiceSignAction;\n"]}
@@ -17,7 +17,7 @@ const snaps_utils_1 = require("@metamask/snaps-utils");
17
17
  const superstruct_1 = require("@metamask/superstruct");
18
18
  const utils_1 = require("@metamask/utils");
19
19
  const uuid_1 = require("uuid");
20
- const canonicalize_1 = require("./utils/canonicalize.cjs");
20
+ const canonicalize_js_1 = require("./utils/canonicalize.cjs");
21
21
  // === GENERAL ===
22
22
  /**
23
23
  * The name of the {@link ProofOfOwnershipService}, used to namespace the
@@ -69,7 +69,7 @@ function buildProofMessage(nonce, canonicalAddress) {
69
69
  function getAccountNamespace(account) {
70
70
  const [firstScope] = account.scopes;
71
71
  if (!firstScope) {
72
- throw new canonicalize_1.ProofUnsupportedNamespaceError('<no scope>');
72
+ throw new canonicalize_js_1.ProofUnsupportedNamespaceError('<no scope>');
73
73
  }
74
74
  try {
75
75
  // `parseCaipChainId` validates the `<namespace>:<reference>` shape; it
@@ -78,7 +78,7 @@ function getAccountNamespace(account) {
78
78
  return (0, utils_1.parseCaipChainId)(firstScope).namespace;
79
79
  }
80
80
  catch {
81
- throw new canonicalize_1.ProofUnsupportedNamespaceError(firstScope);
81
+ throw new canonicalize_js_1.ProofUnsupportedNamespaceError(firstScope);
82
82
  }
83
83
  }
84
84
  // === MESSENGER ===
@@ -138,7 +138,7 @@ class ProofOfOwnershipService {
138
138
  async sign(data) {
139
139
  const { account, nonce } = data;
140
140
  const namespace = getAccountNamespace(account);
141
- const canonicalAddress = (0, canonicalize_1.canonicalizeAddress)(account.address, namespace);
141
+ const canonicalAddress = (0, canonicalize_js_1.canonicalizeAddress)(account.address, namespace);
142
142
  const message = buildProofMessage(nonce, canonicalAddress);
143
143
  let signature;
144
144
  if (namespace === utils_1.KnownCaipNamespace.Eip155) {
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService.cjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAKA,uDAAoD;AACpD,uDAAmE;AACnE,2CAAuE;AACvE,+BAAkC;AAIlC,2DAG8B;AAE9B,kBAAkB;AAElB;;;GAGG;AACU,QAAA,WAAW,GAAG,yBAAyB,CAAC;AAqBrD;;;;;;GAMG;AACU,QAAA,mCAAmC,GAAG,sBAAsB,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,IAAA,kBAAU,EAAC;IAC7C,SAAS,EAAE,IAAA,oBAAM,GAAE;CACpB,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,SAAS,iBAAiB,CAAC,KAAa,EAAE,gBAAwB;IAChE,OAAO,+BAA+B,KAAK,IAAI,gBAAgB,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAAC,OAAwB;IACnD,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,6CAA8B,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC;QACH,uEAAuE;QACvE,wEAAwE;QACxE,wEAAwE;QACxE,OAAO,IAAA,wBAAgB,EAAC,UAAU,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,6CAA8B,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,MAAM,CAAU,CAAC;AAoCpD,6BAA6B;AAE7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,uBAAuB;IAWlC;;;;;OAKG;IACH,YAAY,EAAE,SAAS,EAAmD;;QAX1E;;WAEG;QACM,qDAA6C;QASpD,IAAI,CAAC,IAAI,GAAG,mBAAW,CAAC;QACxB,uBAAA,IAAI,sCAAc,SAAS,MAAA,CAAC;QAE5B,uBAAA,IAAI,0CAAW,CAAC,4BAA4B,CAC1C,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,IAAI,CACR,IAAiC;QAEjC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,gBAAgB,GAAG,IAAA,kCAAmB,EAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAE3D,IAAI,SAAiB,CAAC;QACtB,IAAI,SAAS,KAAK,0BAAkB,CAAC,MAAM,EAAE,CAAC;YAC5C,SAAS,GAAG,MAAM,uBAAA,IAAI,4EAAS,MAAb,IAAI,EAAU,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,qEAAqE;YACrE,8DAA8D;YAC9D,SAAS,GAAG,MAAM,uBAAA,IAAI,gFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;CAsEF;AAlID,0DAkIC;;AApEC;;;;;;;GAOG;AACH,KAAK,2CAAU,OAAe,EAAE,OAAe;IAC7C,OAAO,MAAM,uBAAA,IAAI,0CAAW,CAAC,IAAI,CAAC,uCAAuC,EAAE;QACzE,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,+CACH,OAAwB,EACxB,OAAe;IAEf,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,qCAAqC,OAAO,CAAC,EAAE,6CAA6C,CAC7F,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAY,MAAM,uBAAA,IAAI,0CAAW,CAAC,IAAI,CAClD,8BAA8B,EAC9B;QACE,MAAM,EAAE,MAAgB;QACxB,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,yBAAW,CAAC,eAAe;QACpC,OAAO,EAAE;YACP,EAAE,EAAE,IAAA,SAAI,GAAE;YACV,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,2CAAmC;YAC3C,MAAM,EAAE;gBACN,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,OAAO;aACR;SACF;KACF,CACF,CAAC;IAEF,IAAI,CAAC,2BAA2B,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,oEAAoE;QACpE,sEAAsE;QACtE,yBAAyB;QACzB,MAAM,IAAI,KAAK,CACb,kCAAkC,MAAM,uCAAuC,2CAAmC,IAAI,CACvH,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,SAAS,CAAC;AAC5B,CAAC","sourcesContent":["import type { KeyringControllerSignPersonalMessageAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type { SnapControllerHandleRequestAction } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { string, type as structType } from '@metamask/superstruct';\nimport { KnownCaipNamespace, parseCaipChainId } from '@metamask/utils';\nimport { v4 as uuid } from 'uuid';\n\nimport type { AccountOwnershipProof } from './ProfileMetricsService';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProofOfOwnershipService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProofOfOwnershipService';\n\n/**\n * The shape of the request object for signing a proof of ownership for a\n * single account.\n */\nexport type ProofOfOwnershipSignRequest = {\n /**\n * The account to sign the proof for. Provides the address, the scopes used\n * to infer the signing namespace, and (for non-EVM) the snap ID + account\n * ID needed by `SnapController:handleRequest`.\n */\n account: InternalAccount;\n /**\n * A single-use nonce minted by the auth API (see\n * `ProfileMetricsService:fetchNonces`). Consumed server-side on\n * verification; replay is not possible.\n */\n nonce: string;\n};\n\n/**\n * The JSON-RPC method name exposed by non-EVM wallet snaps for silent\n * proof-of-ownership signing. Each supported snap (Bitcoin, Solana, Tron)\n * implements this method under the `onClientRequest` handler and is expected\n * to validate that the signed message begins with\n * `metamask:proof-of-ownership:`.\n */\nexport const SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD = 'signProofOfOwnership';\n\n/**\n * The shape of a successful response from a non-EVM wallet snap's\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} handler. Validated at runtime;\n * declared with `type()` (not `object()`) so additive snap-side schema\n * changes do not break the client.\n */\nconst SnapSignProofResponseStruct = structType({\n signature: string(),\n});\n\n/**\n * Builds the canonical message string that all chains sign for a proof of\n * ownership: `metamask:proof-of-ownership:<nonce>:<canonical address>`.\n * Defined per the auth API spec — kept inline so the contract is visible\n * next to the dispatch logic that uses it.\n *\n * @param nonce - The single-use nonce from the auth API.\n * @param canonicalAddress - The account address in its CAIP-namespace\n * canonical form (see {@link canonicalizeAddress}).\n * @returns The message string to sign.\n */\nfunction buildProofMessage(nonce: string, canonicalAddress: string): string {\n return `metamask:proof-of-ownership:${nonce}:${canonicalAddress}`;\n}\n\n/**\n * Extracts the CAIP-2 namespace from the first scope of an account. All\n * scopes on a single account are expected to share a namespace (e.g. an\n * `eip155` account may carry many `eip155:<chainId>` scopes but never a\n * `solana:<…>` one).\n *\n * @param account - The internal account to inspect.\n * @returns The namespace portion of the first scope.\n * @throws {ProofUnsupportedNamespaceError} if the account has no scopes,\n * or if its first scope does not parse as a CAIP-2 chain ID.\n */\nfunction getAccountNamespace(account: InternalAccount): string {\n const [firstScope] = account.scopes;\n if (!firstScope) {\n throw new ProofUnsupportedNamespaceError('<no scope>');\n }\n try {\n // `parseCaipChainId` validates the `<namespace>:<reference>` shape; it\n // throws on malformed input. We funnel that into the same error type as\n // an unknown namespace so callers only have one failure mode to handle.\n return parseCaipChainId(firstScope).namespace;\n } catch {\n throw new ProofUnsupportedNamespaceError(firstScope);\n }\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['sign'] as const;\n\n/**\n * Actions that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceActions =\n ProofOfOwnershipServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProofOfOwnershipService} calls.\n */\ntype AllowedActions =\n | KeyringControllerSignPersonalMessageAction\n | SnapControllerHandleRequestAction;\n\n/**\n * Events that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProofOfOwnershipService}\n * subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProofOfOwnershipService}.\n */\nexport type ProofOfOwnershipServiceMessenger = Messenger<\n typeof serviceName,\n ProofOfOwnershipServiceActions | AllowedActions,\n ProofOfOwnershipServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service that produces chain-native cryptographic proofs that the wallet\n * controls a given account address.\n *\n * Dispatches by the CAIP-2 namespace of the account's first scope:\n *\n * - `eip155` → `KeyringController:signPersonalMessage` (EIP-191).\n * - `solana`, `tron`, `bip122` → `SnapController:handleRequest` with the\n * `onClientRequest` handler against the wallet snap declared in\n * `account.metadata.snap.id`. Routed this way (rather than through the\n * keyring) so the request is silent and client-internal: no user prompt,\n * no dapp-facing exposure. The snap is expected to implement\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} and to validate the message\n * prefix before signing.\n *\n * Any other namespace yields {@link ProofUnsupportedNamespaceError}, which\n * callers in the polling pipeline catch to submit the account without a\n * proof (the auth API treats `proof` as optional).\n */\nexport class ProofOfOwnershipService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ProofOfOwnershipServiceMessenger;\n\n /**\n * Constructs a new ProofOfOwnershipService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n */\n constructor({ messenger }: { messenger: ProofOfOwnershipServiceMessenger }) {\n this.name = serviceName;\n this.#messenger = messenger;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\n async sign(\n data: ProofOfOwnershipSignRequest,\n ): Promise<AccountOwnershipProof> {\n const { account, nonce } = data;\n const namespace = getAccountNamespace(account);\n const canonicalAddress = canonicalizeAddress(account.address, namespace);\n const message = buildProofMessage(nonce, canonicalAddress);\n\n let signature: string;\n if (namespace === KnownCaipNamespace.Eip155) {\n signature = await this.#signEvm(account.address, message);\n } else {\n // canonicalizeAddress() already threw for any unsupported namespace,\n // so anything reaching here is one of solana / tron / bip122.\n signature = await this.#signViaSnap(account, message);\n }\n\n return { nonce, signature };\n }\n\n /**\n * Sign an EIP-191 personal message via the keyring controller.\n *\n * @param address - The EVM address to sign with (must belong to an\n * unlocked keyring).\n * @param message - The proof message to sign.\n * @returns The 0x-prefixed signature.\n */\n async #signEvm(address: string, message: string): Promise<string> {\n return await this.#messenger.call('KeyringController:signPersonalMessage', {\n data: message,\n from: address,\n });\n }\n\n /**\n * Sign a proof message via the wallet snap declared on the account's\n * metadata. Uses the `onClientRequest` handler with `origin: 'metamask'`,\n * which is what makes the request silent (no user prompt, no\n * dapp-facing exposure).\n *\n * @param account - The internal account; must carry a non-empty\n * `metadata.snap.id`.\n * @param message - The proof message to sign.\n * @returns The signature string as returned by the snap.\n * @throws if the snap response does not match\n * {@link SnapSignProofResponseStruct}.\n */\n async #signViaSnap(\n account: InternalAccount,\n message: string,\n ): Promise<string> {\n const snapId = account.metadata.snap?.id;\n if (!snapId) {\n throw new Error(\n `ProofOfOwnershipService: account '${account.id}' has no snap to sign a proof of ownership.`,\n );\n }\n\n const response: unknown = await this.#messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnClientRequest,\n request: {\n id: uuid(),\n jsonrpc: '2.0',\n method: SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD,\n params: {\n accountId: account.id,\n message,\n },\n },\n },\n );\n\n if (!SnapSignProofResponseStruct.is(response)) {\n // Intentionally generic — a malformed snap response may still carry\n // a partial signature, and we don't want fragments of secret material\n // landing in error logs.\n throw new Error(\n `ProofOfOwnershipService: snap '${snapId}' returned a malformed response to '${SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD}'.`,\n );\n }\n\n return response.signature;\n }\n}\n"]}
1
+ {"version":3,"file":"ProofOfOwnershipService.cjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAKA,uDAAoD;AACpD,uDAAmE;AACnE,2CAAuE;AACvE,+BAAkC;AAIlC,8DAGiC;AAEjC,kBAAkB;AAElB;;;GAGG;AACU,QAAA,WAAW,GAAG,yBAAyB,CAAC;AAqBrD;;;;;;GAMG;AACU,QAAA,mCAAmC,GAAG,sBAAsB,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,IAAA,kBAAU,EAAC;IAC7C,SAAS,EAAE,IAAA,oBAAM,GAAE;CACpB,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,SAAS,iBAAiB,CAAC,KAAa,EAAE,gBAAwB;IAChE,OAAO,+BAA+B,KAAK,IAAI,gBAAgB,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAAC,OAAwB;IACnD,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,gDAA8B,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC;QACH,uEAAuE;QACvE,wEAAwE;QACxE,wEAAwE;QACxE,OAAO,IAAA,wBAAgB,EAAC,UAAU,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,gDAA8B,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,MAAM,CAAU,CAAC;AAoCpD,6BAA6B;AAE7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,uBAAuB;IAWlC;;;;;OAKG;IACH,YAAY,EAAE,SAAS,EAAmD;;QAX1E;;WAEG;QACM,qDAA6C;QASpD,IAAI,CAAC,IAAI,GAAG,mBAAW,CAAC;QACxB,uBAAA,IAAI,sCAAc,SAAS,MAAA,CAAC;QAE5B,uBAAA,IAAI,0CAAW,CAAC,4BAA4B,CAC1C,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,IAAI,CACR,IAAiC;QAEjC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,gBAAgB,GAAG,IAAA,qCAAmB,EAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAE3D,IAAI,SAAiB,CAAC;QACtB,IAAI,SAAS,KAAK,0BAAkB,CAAC,MAAM,EAAE,CAAC;YAC5C,SAAS,GAAG,MAAM,uBAAA,IAAI,4EAAS,MAAb,IAAI,EAAU,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,qEAAqE;YACrE,8DAA8D;YAC9D,SAAS,GAAG,MAAM,uBAAA,IAAI,gFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;CAsEF;AAlID,0DAkIC;;AApEC;;;;;;;GAOG;AACH,KAAK,2CAAU,OAAe,EAAE,OAAe;IAC7C,OAAO,MAAM,uBAAA,IAAI,0CAAW,CAAC,IAAI,CAAC,uCAAuC,EAAE;QACzE,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,+CACH,OAAwB,EACxB,OAAe;IAEf,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,qCAAqC,OAAO,CAAC,EAAE,6CAA6C,CAC7F,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAY,MAAM,uBAAA,IAAI,0CAAW,CAAC,IAAI,CAClD,8BAA8B,EAC9B;QACE,MAAM,EAAE,MAAgB;QACxB,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,yBAAW,CAAC,eAAe;QACpC,OAAO,EAAE;YACP,EAAE,EAAE,IAAA,SAAI,GAAE;YACV,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,2CAAmC;YAC3C,MAAM,EAAE;gBACN,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,OAAO;aACR;SACF;KACF,CACF,CAAC;IAEF,IAAI,CAAC,2BAA2B,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,oEAAoE;QACpE,sEAAsE;QACtE,yBAAyB;QACzB,MAAM,IAAI,KAAK,CACb,kCAAkC,MAAM,uCAAuC,2CAAmC,IAAI,CACvH,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,SAAS,CAAC;AAC5B,CAAC","sourcesContent":["import type { KeyringControllerSignPersonalMessageAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type { SnapControllerHandleRequestAction } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { string, type as structType } from '@metamask/superstruct';\nimport { KnownCaipNamespace, parseCaipChainId } from '@metamask/utils';\nimport { v4 as uuid } from 'uuid';\n\nimport type { AccountOwnershipProof } from './ProfileMetricsService.js';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types.js';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize.js';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProofOfOwnershipService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProofOfOwnershipService';\n\n/**\n * The shape of the request object for signing a proof of ownership for a\n * single account.\n */\nexport type ProofOfOwnershipSignRequest = {\n /**\n * The account to sign the proof for. Provides the address, the scopes used\n * to infer the signing namespace, and (for non-EVM) the snap ID + account\n * ID needed by `SnapController:handleRequest`.\n */\n account: InternalAccount;\n /**\n * A single-use nonce minted by the auth API (see\n * `ProfileMetricsService:fetchNonces`). Consumed server-side on\n * verification; replay is not possible.\n */\n nonce: string;\n};\n\n/**\n * The JSON-RPC method name exposed by non-EVM wallet snaps for silent\n * proof-of-ownership signing. Each supported snap (Bitcoin, Solana, Tron)\n * implements this method under the `onClientRequest` handler and is expected\n * to validate that the signed message begins with\n * `metamask:proof-of-ownership:`.\n */\nexport const SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD = 'signProofOfOwnership';\n\n/**\n * The shape of a successful response from a non-EVM wallet snap's\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} handler. Validated at runtime;\n * declared with `type()` (not `object()`) so additive snap-side schema\n * changes do not break the client.\n */\nconst SnapSignProofResponseStruct = structType({\n signature: string(),\n});\n\n/**\n * Builds the canonical message string that all chains sign for a proof of\n * ownership: `metamask:proof-of-ownership:<nonce>:<canonical address>`.\n * Defined per the auth API spec — kept inline so the contract is visible\n * next to the dispatch logic that uses it.\n *\n * @param nonce - The single-use nonce from the auth API.\n * @param canonicalAddress - The account address in its CAIP-namespace\n * canonical form (see {@link canonicalizeAddress}).\n * @returns The message string to sign.\n */\nfunction buildProofMessage(nonce: string, canonicalAddress: string): string {\n return `metamask:proof-of-ownership:${nonce}:${canonicalAddress}`;\n}\n\n/**\n * Extracts the CAIP-2 namespace from the first scope of an account. All\n * scopes on a single account are expected to share a namespace (e.g. an\n * `eip155` account may carry many `eip155:<chainId>` scopes but never a\n * `solana:<…>` one).\n *\n * @param account - The internal account to inspect.\n * @returns The namespace portion of the first scope.\n * @throws {ProofUnsupportedNamespaceError} if the account has no scopes,\n * or if its first scope does not parse as a CAIP-2 chain ID.\n */\nfunction getAccountNamespace(account: InternalAccount): string {\n const [firstScope] = account.scopes;\n if (!firstScope) {\n throw new ProofUnsupportedNamespaceError('<no scope>');\n }\n try {\n // `parseCaipChainId` validates the `<namespace>:<reference>` shape; it\n // throws on malformed input. We funnel that into the same error type as\n // an unknown namespace so callers only have one failure mode to handle.\n return parseCaipChainId(firstScope).namespace;\n } catch {\n throw new ProofUnsupportedNamespaceError(firstScope);\n }\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['sign'] as const;\n\n/**\n * Actions that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceActions =\n ProofOfOwnershipServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProofOfOwnershipService} calls.\n */\ntype AllowedActions =\n | KeyringControllerSignPersonalMessageAction\n | SnapControllerHandleRequestAction;\n\n/**\n * Events that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProofOfOwnershipService}\n * subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProofOfOwnershipService}.\n */\nexport type ProofOfOwnershipServiceMessenger = Messenger<\n typeof serviceName,\n ProofOfOwnershipServiceActions | AllowedActions,\n ProofOfOwnershipServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service that produces chain-native cryptographic proofs that the wallet\n * controls a given account address.\n *\n * Dispatches by the CAIP-2 namespace of the account's first scope:\n *\n * - `eip155` → `KeyringController:signPersonalMessage` (EIP-191).\n * - `solana`, `tron`, `bip122` → `SnapController:handleRequest` with the\n * `onClientRequest` handler against the wallet snap declared in\n * `account.metadata.snap.id`. Routed this way (rather than through the\n * keyring) so the request is silent and client-internal: no user prompt,\n * no dapp-facing exposure. The snap is expected to implement\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} and to validate the message\n * prefix before signing.\n *\n * Any other namespace yields {@link ProofUnsupportedNamespaceError}, which\n * callers in the polling pipeline catch to submit the account without a\n * proof (the auth API treats `proof` as optional).\n */\nexport class ProofOfOwnershipService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ProofOfOwnershipServiceMessenger;\n\n /**\n * Constructs a new ProofOfOwnershipService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n */\n constructor({ messenger }: { messenger: ProofOfOwnershipServiceMessenger }) {\n this.name = serviceName;\n this.#messenger = messenger;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\n async sign(\n data: ProofOfOwnershipSignRequest,\n ): Promise<AccountOwnershipProof> {\n const { account, nonce } = data;\n const namespace = getAccountNamespace(account);\n const canonicalAddress = canonicalizeAddress(account.address, namespace);\n const message = buildProofMessage(nonce, canonicalAddress);\n\n let signature: string;\n if (namespace === KnownCaipNamespace.Eip155) {\n signature = await this.#signEvm(account.address, message);\n } else {\n // canonicalizeAddress() already threw for any unsupported namespace,\n // so anything reaching here is one of solana / tron / bip122.\n signature = await this.#signViaSnap(account, message);\n }\n\n return { nonce, signature };\n }\n\n /**\n * Sign an EIP-191 personal message via the keyring controller.\n *\n * @param address - The EVM address to sign with (must belong to an\n * unlocked keyring).\n * @param message - The proof message to sign.\n * @returns The 0x-prefixed signature.\n */\n async #signEvm(address: string, message: string): Promise<string> {\n return await this.#messenger.call('KeyringController:signPersonalMessage', {\n data: message,\n from: address,\n });\n }\n\n /**\n * Sign a proof message via the wallet snap declared on the account's\n * metadata. Uses the `onClientRequest` handler with `origin: 'metamask'`,\n * which is what makes the request silent (no user prompt, no\n * dapp-facing exposure).\n *\n * @param account - The internal account; must carry a non-empty\n * `metadata.snap.id`.\n * @param message - The proof message to sign.\n * @returns The signature string as returned by the snap.\n * @throws if the snap response does not match\n * {@link SnapSignProofResponseStruct}.\n */\n async #signViaSnap(\n account: InternalAccount,\n message: string,\n ): Promise<string> {\n const snapId = account.metadata.snap?.id;\n if (!snapId) {\n throw new Error(\n `ProofOfOwnershipService: account '${account.id}' has no snap to sign a proof of ownership.`,\n );\n }\n\n const response: unknown = await this.#messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnClientRequest,\n request: {\n id: uuid(),\n jsonrpc: '2.0',\n method: SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD,\n params: {\n accountId: account.id,\n message,\n },\n },\n },\n );\n\n if (!SnapSignProofResponseStruct.is(response)) {\n // Intentionally generic — a malformed snap response may still carry\n // a partial signature, and we don't want fragments of secret material\n // landing in error logs.\n throw new Error(\n `ProofOfOwnershipService: snap '${snapId}' returned a malformed response to '${SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD}'.`,\n );\n }\n\n return response.signature;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService.d.cts","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0CAA0C,EAAE,qCAAqC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oCAAoC;AAOrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAgC;AACrE,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAsD;AAQ1G;;;GAGG;AACH,eAAO,MAAM,WAAW,4BAA4B,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;;;OAIG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,yBAAyB,CAAC;AAyD1E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,oCAAoC,CAAC;AAEvC;;GAEG;AACH,KAAK,cAAc,GACf,0CAA0C,GAC1C,iCAAiC,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAElD;;;GAGG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG,SAAS,CACtD,OAAO,WAAW,EAClB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,CAC9C,CAAC;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,uBAAuB;;IAClC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,WAAW,CAAC;IAOlC;;;;;OAKG;gBACS,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,gCAAgC,CAAA;KAAE;IAU1E;;;;;;;;;;;;;;OAcG;IACG,IAAI,CACR,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,qBAAqB,CAAC;CAsFlC"}
1
+ {"version":3,"file":"ProofOfOwnershipService.d.cts","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0CAA0C,EAAE,qCAAqC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oCAAoC;AAOrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAmC;AACxE,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAyD;AAQ7G;;;GAGG;AACH,eAAO,MAAM,WAAW,4BAA4B,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;;;OAIG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,yBAAyB,CAAC;AAyD1E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,oCAAoC,CAAC;AAEvC;;GAEG;AACH,KAAK,cAAc,GACf,0CAA0C,GAC1C,iCAAiC,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAElD;;;GAGG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG,SAAS,CACtD,OAAO,WAAW,EAClB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,CAC9C,CAAC;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,uBAAuB;;IAClC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,WAAW,CAAC;IAOlC;;;;;OAKG;gBACS,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,gCAAgC,CAAA;KAAE;IAU1E;;;;;;;;;;;;;;OAcG;IACG,IAAI,CACR,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,qBAAqB,CAAC;CAsFlC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService.d.mts","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0CAA0C,EAAE,qCAAqC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oCAAoC;AAOrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAgC;AACrE,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAsD;AAQ1G;;;GAGG;AACH,eAAO,MAAM,WAAW,4BAA4B,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;;;OAIG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,yBAAyB,CAAC;AAyD1E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,oCAAoC,CAAC;AAEvC;;GAEG;AACH,KAAK,cAAc,GACf,0CAA0C,GAC1C,iCAAiC,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAElD;;;GAGG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG,SAAS,CACtD,OAAO,WAAW,EAClB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,CAC9C,CAAC;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,uBAAuB;;IAClC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,WAAW,CAAC;IAOlC;;;;;OAKG;gBACS,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,gCAAgC,CAAA;KAAE;IAU1E;;;;;;;;;;;;;;OAcG;IACG,IAAI,CACR,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,qBAAqB,CAAC;CAsFlC"}
1
+ {"version":3,"file":"ProofOfOwnershipService.d.mts","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0CAA0C,EAAE,qCAAqC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iCAAiC,EAAE,oCAAoC;AAOrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,oCAAmC;AACxE,OAAO,KAAK,EAAE,oCAAoC,EAAE,0DAAyD;AAQ7G;;;GAGG;AACH,eAAO,MAAM,WAAW,4BAA4B,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;;;OAIG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,yBAAyB,CAAC;AAyD1E;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACxC,oCAAoC,CAAC;AAEvC;;GAEG;AACH,KAAK,cAAc,GACf,0CAA0C,GAC1C,iCAAiC,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAElD;;;GAGG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG,SAAS,CACtD,OAAO,WAAW,EAClB,8BAA8B,GAAG,cAAc,EAC/C,6BAA6B,GAAG,aAAa,CAC9C,CAAC;AAIF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,uBAAuB;;IAClC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,WAAW,CAAC;IAOlC;;;;;OAKG;gBACS,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,gCAAgC,CAAA;KAAE;IAU1E;;;;;;;;;;;;;;OAcG;IACG,IAAI,CACR,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,qBAAqB,CAAC;CAsFlC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProofOfOwnershipService.mjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeyringControllerSignPersonalMessageAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type { SnapControllerHandleRequestAction } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { string, type as structType } from '@metamask/superstruct';\nimport { KnownCaipNamespace, parseCaipChainId } from '@metamask/utils';\nimport { v4 as uuid } from 'uuid';\n\nimport type { AccountOwnershipProof } from './ProfileMetricsService';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProofOfOwnershipService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProofOfOwnershipService';\n\n/**\n * The shape of the request object for signing a proof of ownership for a\n * single account.\n */\nexport type ProofOfOwnershipSignRequest = {\n /**\n * The account to sign the proof for. Provides the address, the scopes used\n * to infer the signing namespace, and (for non-EVM) the snap ID + account\n * ID needed by `SnapController:handleRequest`.\n */\n account: InternalAccount;\n /**\n * A single-use nonce minted by the auth API (see\n * `ProfileMetricsService:fetchNonces`). Consumed server-side on\n * verification; replay is not possible.\n */\n nonce: string;\n};\n\n/**\n * The JSON-RPC method name exposed by non-EVM wallet snaps for silent\n * proof-of-ownership signing. Each supported snap (Bitcoin, Solana, Tron)\n * implements this method under the `onClientRequest` handler and is expected\n * to validate that the signed message begins with\n * `metamask:proof-of-ownership:`.\n */\nexport const SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD = 'signProofOfOwnership';\n\n/**\n * The shape of a successful response from a non-EVM wallet snap's\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} handler. Validated at runtime;\n * declared with `type()` (not `object()`) so additive snap-side schema\n * changes do not break the client.\n */\nconst SnapSignProofResponseStruct = structType({\n signature: string(),\n});\n\n/**\n * Builds the canonical message string that all chains sign for a proof of\n * ownership: `metamask:proof-of-ownership:<nonce>:<canonical address>`.\n * Defined per the auth API spec — kept inline so the contract is visible\n * next to the dispatch logic that uses it.\n *\n * @param nonce - The single-use nonce from the auth API.\n * @param canonicalAddress - The account address in its CAIP-namespace\n * canonical form (see {@link canonicalizeAddress}).\n * @returns The message string to sign.\n */\nfunction buildProofMessage(nonce: string, canonicalAddress: string): string {\n return `metamask:proof-of-ownership:${nonce}:${canonicalAddress}`;\n}\n\n/**\n * Extracts the CAIP-2 namespace from the first scope of an account. All\n * scopes on a single account are expected to share a namespace (e.g. an\n * `eip155` account may carry many `eip155:<chainId>` scopes but never a\n * `solana:<…>` one).\n *\n * @param account - The internal account to inspect.\n * @returns The namespace portion of the first scope.\n * @throws {ProofUnsupportedNamespaceError} if the account has no scopes,\n * or if its first scope does not parse as a CAIP-2 chain ID.\n */\nfunction getAccountNamespace(account: InternalAccount): string {\n const [firstScope] = account.scopes;\n if (!firstScope) {\n throw new ProofUnsupportedNamespaceError('<no scope>');\n }\n try {\n // `parseCaipChainId` validates the `<namespace>:<reference>` shape; it\n // throws on malformed input. We funnel that into the same error type as\n // an unknown namespace so callers only have one failure mode to handle.\n return parseCaipChainId(firstScope).namespace;\n } catch {\n throw new ProofUnsupportedNamespaceError(firstScope);\n }\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['sign'] as const;\n\n/**\n * Actions that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceActions =\n ProofOfOwnershipServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProofOfOwnershipService} calls.\n */\ntype AllowedActions =\n | KeyringControllerSignPersonalMessageAction\n | SnapControllerHandleRequestAction;\n\n/**\n * Events that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProofOfOwnershipService}\n * subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProofOfOwnershipService}.\n */\nexport type ProofOfOwnershipServiceMessenger = Messenger<\n typeof serviceName,\n ProofOfOwnershipServiceActions | AllowedActions,\n ProofOfOwnershipServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service that produces chain-native cryptographic proofs that the wallet\n * controls a given account address.\n *\n * Dispatches by the CAIP-2 namespace of the account's first scope:\n *\n * - `eip155` → `KeyringController:signPersonalMessage` (EIP-191).\n * - `solana`, `tron`, `bip122` → `SnapController:handleRequest` with the\n * `onClientRequest` handler against the wallet snap declared in\n * `account.metadata.snap.id`. Routed this way (rather than through the\n * keyring) so the request is silent and client-internal: no user prompt,\n * no dapp-facing exposure. The snap is expected to implement\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} and to validate the message\n * prefix before signing.\n *\n * Any other namespace yields {@link ProofUnsupportedNamespaceError}, which\n * callers in the polling pipeline catch to submit the account without a\n * proof (the auth API treats `proof` as optional).\n */\nexport class ProofOfOwnershipService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ProofOfOwnershipServiceMessenger;\n\n /**\n * Constructs a new ProofOfOwnershipService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n */\n constructor({ messenger }: { messenger: ProofOfOwnershipServiceMessenger }) {\n this.name = serviceName;\n this.#messenger = messenger;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\n async sign(\n data: ProofOfOwnershipSignRequest,\n ): Promise<AccountOwnershipProof> {\n const { account, nonce } = data;\n const namespace = getAccountNamespace(account);\n const canonicalAddress = canonicalizeAddress(account.address, namespace);\n const message = buildProofMessage(nonce, canonicalAddress);\n\n let signature: string;\n if (namespace === KnownCaipNamespace.Eip155) {\n signature = await this.#signEvm(account.address, message);\n } else {\n // canonicalizeAddress() already threw for any unsupported namespace,\n // so anything reaching here is one of solana / tron / bip122.\n signature = await this.#signViaSnap(account, message);\n }\n\n return { nonce, signature };\n }\n\n /**\n * Sign an EIP-191 personal message via the keyring controller.\n *\n * @param address - The EVM address to sign with (must belong to an\n * unlocked keyring).\n * @param message - The proof message to sign.\n * @returns The 0x-prefixed signature.\n */\n async #signEvm(address: string, message: string): Promise<string> {\n return await this.#messenger.call('KeyringController:signPersonalMessage', {\n data: message,\n from: address,\n });\n }\n\n /**\n * Sign a proof message via the wallet snap declared on the account's\n * metadata. Uses the `onClientRequest` handler with `origin: 'metamask'`,\n * which is what makes the request silent (no user prompt, no\n * dapp-facing exposure).\n *\n * @param account - The internal account; must carry a non-empty\n * `metadata.snap.id`.\n * @param message - The proof message to sign.\n * @returns The signature string as returned by the snap.\n * @throws if the snap response does not match\n * {@link SnapSignProofResponseStruct}.\n */\n async #signViaSnap(\n account: InternalAccount,\n message: string,\n ): Promise<string> {\n const snapId = account.metadata.snap?.id;\n if (!snapId) {\n throw new Error(\n `ProofOfOwnershipService: account '${account.id}' has no snap to sign a proof of ownership.`,\n );\n }\n\n const response: unknown = await this.#messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnClientRequest,\n request: {\n id: uuid(),\n jsonrpc: '2.0',\n method: SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD,\n params: {\n accountId: account.id,\n message,\n },\n },\n },\n );\n\n if (!SnapSignProofResponseStruct.is(response)) {\n // Intentionally generic — a malformed snap response may still carry\n // a partial signature, and we don't want fragments of secret material\n // landing in error logs.\n throw new Error(\n `ProofOfOwnershipService: snap '${snapId}' returned a malformed response to '${SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD}'.`,\n );\n }\n\n return response.signature;\n }\n}\n"]}
1
+ {"version":3,"file":"ProofOfOwnershipService.mjs","sourceRoot":"","sources":["../src/ProofOfOwnershipService.ts"],"names":[],"mappings":";;;;;;;;;;;;AAKA,OAAO,EAAE,WAAW,EAAE,8BAA8B;AACpD,OAAO,EAAE,MAAM,EAAE,IAAI,IAAI,UAAU,EAAE,8BAA8B;AACnE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,wBAAwB;AACvE,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,aAAa;AAIlC,OAAO,EACL,mBAAmB,EACnB,8BAA8B,EAC/B,iCAAgC;AAEjC,kBAAkB;AAElB;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAqBrD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,sBAAsB,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,2BAA2B,GAAG,UAAU,CAAC;IAC7C,SAAS,EAAE,MAAM,EAAE;CACpB,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,SAAS,iBAAiB,CAAC,KAAa,EAAE,gBAAwB;IAChE,OAAO,+BAA+B,KAAK,IAAI,gBAAgB,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,mBAAmB,CAAC,OAAwB;IACnD,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,8BAA8B,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC;QACH,uEAAuE;QACvE,wEAAwE;QACxE,wEAAwE;QACxE,OAAO,gBAAgB,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,8BAA8B,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,oBAAoB;AAEpB,MAAM,yBAAyB,GAAG,CAAC,MAAM,CAAU,CAAC;AAoCpD,6BAA6B;AAE7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,uBAAuB;IAWlC;;;;;OAKG;IACH,YAAY,EAAE,SAAS,EAAmD;;QAX1E;;WAEG;QACM,qDAA6C;QASpD,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,uBAAA,IAAI,sCAAc,SAAS,MAAA,CAAC;QAE5B,uBAAA,IAAI,0CAAW,CAAC,4BAA4B,CAC1C,IAAI,EACJ,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,IAAI,CACR,IAAiC;QAEjC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAE3D,IAAI,SAAiB,CAAC;QACtB,IAAI,SAAS,KAAK,kBAAkB,CAAC,MAAM,EAAE,CAAC;YAC5C,SAAS,GAAG,MAAM,uBAAA,IAAI,4EAAS,MAAb,IAAI,EAAU,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,qEAAqE;YACrE,8DAA8D;YAC9D,SAAS,GAAG,MAAM,uBAAA,IAAI,gFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;CAsEF;;AApEC;;;;;;;GAOG;AACH,KAAK,2CAAU,OAAe,EAAE,OAAe;IAC7C,OAAO,MAAM,uBAAA,IAAI,0CAAW,CAAC,IAAI,CAAC,uCAAuC,EAAE;QACzE,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,+CACH,OAAwB,EACxB,OAAe;IAEf,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,qCAAqC,OAAO,CAAC,EAAE,6CAA6C,CAC7F,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAY,MAAM,uBAAA,IAAI,0CAAW,CAAC,IAAI,CAClD,8BAA8B,EAC9B;QACE,MAAM,EAAE,MAAgB;QACxB,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,WAAW,CAAC,eAAe;QACpC,OAAO,EAAE;YACP,EAAE,EAAE,IAAI,EAAE;YACV,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,mCAAmC;YAC3C,MAAM,EAAE;gBACN,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,OAAO;aACR;SACF;KACF,CACF,CAAC;IAEF,IAAI,CAAC,2BAA2B,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9C,oEAAoE;QACpE,sEAAsE;QACtE,yBAAyB;QACzB,MAAM,IAAI,KAAK,CACb,kCAAkC,MAAM,uCAAuC,mCAAmC,IAAI,CACvH,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,SAAS,CAAC;AAC5B,CAAC","sourcesContent":["import type { KeyringControllerSignPersonalMessageAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { Messenger } from '@metamask/messenger';\nimport type { SnapControllerHandleRequestAction } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { string, type as structType } from '@metamask/superstruct';\nimport { KnownCaipNamespace, parseCaipChainId } from '@metamask/utils';\nimport { v4 as uuid } from 'uuid';\n\nimport type { AccountOwnershipProof } from './ProfileMetricsService.js';\nimport type { ProofOfOwnershipServiceMethodActions } from './ProofOfOwnershipService-method-action-types.js';\nimport {\n canonicalizeAddress,\n ProofUnsupportedNamespaceError,\n} from './utils/canonicalize.js';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link ProofOfOwnershipService}, used to namespace the\n * service's actions and events.\n */\nexport const serviceName = 'ProofOfOwnershipService';\n\n/**\n * The shape of the request object for signing a proof of ownership for a\n * single account.\n */\nexport type ProofOfOwnershipSignRequest = {\n /**\n * The account to sign the proof for. Provides the address, the scopes used\n * to infer the signing namespace, and (for non-EVM) the snap ID + account\n * ID needed by `SnapController:handleRequest`.\n */\n account: InternalAccount;\n /**\n * A single-use nonce minted by the auth API (see\n * `ProfileMetricsService:fetchNonces`). Consumed server-side on\n * verification; replay is not possible.\n */\n nonce: string;\n};\n\n/**\n * The JSON-RPC method name exposed by non-EVM wallet snaps for silent\n * proof-of-ownership signing. Each supported snap (Bitcoin, Solana, Tron)\n * implements this method under the `onClientRequest` handler and is expected\n * to validate that the signed message begins with\n * `metamask:proof-of-ownership:`.\n */\nexport const SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD = 'signProofOfOwnership';\n\n/**\n * The shape of a successful response from a non-EVM wallet snap's\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} handler. Validated at runtime;\n * declared with `type()` (not `object()`) so additive snap-side schema\n * changes do not break the client.\n */\nconst SnapSignProofResponseStruct = structType({\n signature: string(),\n});\n\n/**\n * Builds the canonical message string that all chains sign for a proof of\n * ownership: `metamask:proof-of-ownership:<nonce>:<canonical address>`.\n * Defined per the auth API spec — kept inline so the contract is visible\n * next to the dispatch logic that uses it.\n *\n * @param nonce - The single-use nonce from the auth API.\n * @param canonicalAddress - The account address in its CAIP-namespace\n * canonical form (see {@link canonicalizeAddress}).\n * @returns The message string to sign.\n */\nfunction buildProofMessage(nonce: string, canonicalAddress: string): string {\n return `metamask:proof-of-ownership:${nonce}:${canonicalAddress}`;\n}\n\n/**\n * Extracts the CAIP-2 namespace from the first scope of an account. All\n * scopes on a single account are expected to share a namespace (e.g. an\n * `eip155` account may carry many `eip155:<chainId>` scopes but never a\n * `solana:<…>` one).\n *\n * @param account - The internal account to inspect.\n * @returns The namespace portion of the first scope.\n * @throws {ProofUnsupportedNamespaceError} if the account has no scopes,\n * or if its first scope does not parse as a CAIP-2 chain ID.\n */\nfunction getAccountNamespace(account: InternalAccount): string {\n const [firstScope] = account.scopes;\n if (!firstScope) {\n throw new ProofUnsupportedNamespaceError('<no scope>');\n }\n try {\n // `parseCaipChainId` validates the `<namespace>:<reference>` shape; it\n // throws on malformed input. We funnel that into the same error type as\n // an unknown namespace so callers only have one failure mode to handle.\n return parseCaipChainId(firstScope).namespace;\n } catch {\n throw new ProofUnsupportedNamespaceError(firstScope);\n }\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = ['sign'] as const;\n\n/**\n * Actions that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceActions =\n ProofOfOwnershipServiceMethodActions;\n\n/**\n * Actions from other messengers that {@link ProofOfOwnershipService} calls.\n */\ntype AllowedActions =\n | KeyringControllerSignPersonalMessageAction\n | SnapControllerHandleRequestAction;\n\n/**\n * Events that {@link ProofOfOwnershipService} exposes to other consumers.\n */\nexport type ProofOfOwnershipServiceEvents = never;\n\n/**\n * Events from other messengers that {@link ProofOfOwnershipService}\n * subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link ProofOfOwnershipService}.\n */\nexport type ProofOfOwnershipServiceMessenger = Messenger<\n typeof serviceName,\n ProofOfOwnershipServiceActions | AllowedActions,\n ProofOfOwnershipServiceEvents | AllowedEvents\n>;\n\n// === SERVICE DEFINITION ===\n\n/**\n * A service that produces chain-native cryptographic proofs that the wallet\n * controls a given account address.\n *\n * Dispatches by the CAIP-2 namespace of the account's first scope:\n *\n * - `eip155` → `KeyringController:signPersonalMessage` (EIP-191).\n * - `solana`, `tron`, `bip122` → `SnapController:handleRequest` with the\n * `onClientRequest` handler against the wallet snap declared in\n * `account.metadata.snap.id`. Routed this way (rather than through the\n * keyring) so the request is silent and client-internal: no user prompt,\n * no dapp-facing exposure. The snap is expected to implement\n * {@link SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD} and to validate the message\n * prefix before signing.\n *\n * Any other namespace yields {@link ProofUnsupportedNamespaceError}, which\n * callers in the polling pipeline catch to submit the account without a\n * proof (the auth API treats `proof` as optional).\n */\nexport class ProofOfOwnershipService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n /**\n * The messenger suited for this service.\n */\n readonly #messenger: ProofOfOwnershipServiceMessenger;\n\n /**\n * Constructs a new ProofOfOwnershipService object.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n */\n constructor({ messenger }: { messenger: ProofOfOwnershipServiceMessenger }) {\n this.name = serviceName;\n this.#messenger = messenger;\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Sign a proof of ownership for the given account and server-issued nonce.\n *\n * The returned proof is shaped to drop directly into\n * `AccountWithScopes.proof` for `ProfileMetricsService:submitMetrics`.\n *\n * @param data - The account to prove ownership of and the nonce to bind\n * the proof to.\n * @returns The proof of ownership (nonce echo + signature).\n * @throws {ProofUnsupportedNamespaceError} if the account's first scope\n * carries a namespace this service does not know how to sign for, or if\n * the account has no scopes.\n * @throws if the underlying signer (keyring or snap) rejects, or if the\n * snap returns a malformed response.\n */\n async sign(\n data: ProofOfOwnershipSignRequest,\n ): Promise<AccountOwnershipProof> {\n const { account, nonce } = data;\n const namespace = getAccountNamespace(account);\n const canonicalAddress = canonicalizeAddress(account.address, namespace);\n const message = buildProofMessage(nonce, canonicalAddress);\n\n let signature: string;\n if (namespace === KnownCaipNamespace.Eip155) {\n signature = await this.#signEvm(account.address, message);\n } else {\n // canonicalizeAddress() already threw for any unsupported namespace,\n // so anything reaching here is one of solana / tron / bip122.\n signature = await this.#signViaSnap(account, message);\n }\n\n return { nonce, signature };\n }\n\n /**\n * Sign an EIP-191 personal message via the keyring controller.\n *\n * @param address - The EVM address to sign with (must belong to an\n * unlocked keyring).\n * @param message - The proof message to sign.\n * @returns The 0x-prefixed signature.\n */\n async #signEvm(address: string, message: string): Promise<string> {\n return await this.#messenger.call('KeyringController:signPersonalMessage', {\n data: message,\n from: address,\n });\n }\n\n /**\n * Sign a proof message via the wallet snap declared on the account's\n * metadata. Uses the `onClientRequest` handler with `origin: 'metamask'`,\n * which is what makes the request silent (no user prompt, no\n * dapp-facing exposure).\n *\n * @param account - The internal account; must carry a non-empty\n * `metadata.snap.id`.\n * @param message - The proof message to sign.\n * @returns The signature string as returned by the snap.\n * @throws if the snap response does not match\n * {@link SnapSignProofResponseStruct}.\n */\n async #signViaSnap(\n account: InternalAccount,\n message: string,\n ): Promise<string> {\n const snapId = account.metadata.snap?.id;\n if (!snapId) {\n throw new Error(\n `ProofOfOwnershipService: account '${account.id}' has no snap to sign a proof of ownership.`,\n );\n }\n\n const response: unknown = await this.#messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnClientRequest,\n request: {\n id: uuid(),\n jsonrpc: '2.0',\n method: SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD,\n params: {\n accountId: account.id,\n message,\n },\n },\n },\n );\n\n if (!SnapSignProofResponseStruct.is(response)) {\n // Intentionally generic — a malformed snap response may still carry\n // a partial signature, and we don't want fragments of secret material\n // landing in error logs.\n throw new Error(\n `ProofOfOwnershipService: snap '${snapId}' returned a malformed response to '${SNAP_SIGN_PROOF_OF_OWNERSHIP_METHOD}'.`,\n );\n }\n\n return response.signature;\n }\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.proofOfOwnershipServiceName = exports.ProofOfOwnershipService = exports.profileMetricsServiceName = exports.serviceName = exports.ProfileMetricsService = exports.getDefaultProfileMetricsControllerState = exports.ProfileMetricsController = void 0;
4
- var ProfileMetricsController_1 = require("./ProfileMetricsController.cjs");
5
- Object.defineProperty(exports, "ProfileMetricsController", { enumerable: true, get: function () { return ProfileMetricsController_1.ProfileMetricsController; } });
6
- Object.defineProperty(exports, "getDefaultProfileMetricsControllerState", { enumerable: true, get: function () { return ProfileMetricsController_1.getDefaultProfileMetricsControllerState; } });
7
- var ProfileMetricsService_1 = require("./ProfileMetricsService.cjs");
8
- Object.defineProperty(exports, "ProfileMetricsService", { enumerable: true, get: function () { return ProfileMetricsService_1.ProfileMetricsService; } });
9
- Object.defineProperty(exports, "serviceName", { enumerable: true, get: function () { return ProfileMetricsService_1.serviceName; } });
10
- Object.defineProperty(exports, "profileMetricsServiceName", { enumerable: true, get: function () { return ProfileMetricsService_1.serviceName; } });
11
- var ProofOfOwnershipService_1 = require("./ProofOfOwnershipService.cjs");
12
- Object.defineProperty(exports, "ProofOfOwnershipService", { enumerable: true, get: function () { return ProofOfOwnershipService_1.ProofOfOwnershipService; } });
13
- Object.defineProperty(exports, "proofOfOwnershipServiceName", { enumerable: true, get: function () { return ProofOfOwnershipService_1.serviceName; } });
4
+ var ProfileMetricsController_js_1 = require("./ProfileMetricsController.cjs");
5
+ Object.defineProperty(exports, "ProfileMetricsController", { enumerable: true, get: function () { return ProfileMetricsController_js_1.ProfileMetricsController; } });
6
+ Object.defineProperty(exports, "getDefaultProfileMetricsControllerState", { enumerable: true, get: function () { return ProfileMetricsController_js_1.getDefaultProfileMetricsControllerState; } });
7
+ var ProfileMetricsService_js_1 = require("./ProfileMetricsService.cjs");
8
+ Object.defineProperty(exports, "ProfileMetricsService", { enumerable: true, get: function () { return ProfileMetricsService_js_1.ProfileMetricsService; } });
9
+ Object.defineProperty(exports, "serviceName", { enumerable: true, get: function () { return ProfileMetricsService_js_1.serviceName; } });
10
+ Object.defineProperty(exports, "profileMetricsServiceName", { enumerable: true, get: function () { return ProfileMetricsService_js_1.serviceName; } });
11
+ var ProofOfOwnershipService_js_1 = require("./ProofOfOwnershipService.cjs");
12
+ Object.defineProperty(exports, "ProofOfOwnershipService", { enumerable: true, get: function () { return ProofOfOwnershipService_js_1.ProofOfOwnershipService; } });
13
+ Object.defineProperty(exports, "proofOfOwnershipServiceName", { enumerable: true, get: function () { return ProofOfOwnershipService_js_1.serviceName; } });
14
14
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAQA,2EAGoC;AAFlC,oIAAA,wBAAwB,OAAA;AACxB,mJAAA,uCAAuC,OAAA;AAQzC,qEAIiC;AAH/B,8HAAA,qBAAqB,OAAA;AACrB,oHAAA,WAAW,OAAA;AACX,kIAAA,WAAW,OAA6B;AAQ1C,yEAGmC;AAFjC,kIAAA,uBAAuB,OAAA;AACvB,sIAAA,WAAW,OAA+B","sourcesContent":["export type {\n ProfileMetricsControllerActions,\n ProfileMetricsControllerEvents,\n ProfileMetricsControllerGetStateAction,\n ProfileMetricsControllerMessenger,\n ProfileMetricsControllerState,\n ProfileMetricsControllerStateChangeEvent,\n} from './ProfileMetricsController';\nexport {\n ProfileMetricsController,\n getDefaultProfileMetricsControllerState,\n} from './ProfileMetricsController';\nexport type {\n ProfileMetricsServiceActions,\n ProfileMetricsServiceEvents,\n ProfileMetricsServiceMessenger,\n ProfileMetricsSubmitMetricsRequest,\n} from './ProfileMetricsService';\nexport {\n ProfileMetricsService,\n serviceName,\n serviceName as profileMetricsServiceName,\n} from './ProfileMetricsService';\nexport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types';\nexport type {\n ProofOfOwnershipServiceActions,\n ProofOfOwnershipServiceEvents,\n ProofOfOwnershipServiceMessenger,\n} from './ProofOfOwnershipService';\nexport {\n ProofOfOwnershipService,\n serviceName as proofOfOwnershipServiceName,\n} from './ProofOfOwnershipService';\nexport type {\n ProfileMetricsControllerMethodActions,\n ProfileMetricsControllerSkipInitialDelayAction,\n} from './ProfileMetricsController-method-action-types';\n"]}
1
+ {"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAQA,8EAGuC;AAFrC,uIAAA,wBAAwB,OAAA;AACxB,sJAAA,uCAAuC,OAAA;AAQzC,wEAIoC;AAHlC,iIAAA,qBAAqB,OAAA;AACrB,uHAAA,WAAW,OAAA;AACX,qIAAA,WAAW,OAA6B;AAQ1C,4EAGsC;AAFpC,qIAAA,uBAAuB,OAAA;AACvB,yIAAA,WAAW,OAA+B","sourcesContent":["export type {\n ProfileMetricsControllerActions,\n ProfileMetricsControllerEvents,\n ProfileMetricsControllerGetStateAction,\n ProfileMetricsControllerMessenger,\n ProfileMetricsControllerState,\n ProfileMetricsControllerStateChangeEvent,\n} from './ProfileMetricsController.js';\nexport {\n ProfileMetricsController,\n getDefaultProfileMetricsControllerState,\n} from './ProfileMetricsController.js';\nexport type {\n ProfileMetricsServiceActions,\n ProfileMetricsServiceEvents,\n ProfileMetricsServiceMessenger,\n ProfileMetricsSubmitMetricsRequest,\n} from './ProfileMetricsService.js';\nexport {\n ProfileMetricsService,\n serviceName,\n serviceName as profileMetricsServiceName,\n} from './ProfileMetricsService.js';\nexport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types.js';\nexport type {\n ProofOfOwnershipServiceActions,\n ProofOfOwnershipServiceEvents,\n ProofOfOwnershipServiceMessenger,\n} from './ProofOfOwnershipService.js';\nexport {\n ProofOfOwnershipService,\n serviceName as proofOfOwnershipServiceName,\n} from './ProofOfOwnershipService.js';\nexport type {\n ProfileMetricsControllerMethodActions,\n ProfileMetricsControllerSkipInitialDelayAction,\n} from './ProfileMetricsController-method-action-types.js';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,sCAAsC,EACtC,iCAAiC,EACjC,6BAA6B,EAC7B,wCAAwC,GACzC,uCAAmC;AACpC,OAAO,EACL,wBAAwB,EACxB,uCAAuC,GACxC,uCAAmC;AACpC,YAAY,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,8BAA8B,EAC9B,kCAAkC,GACnC,oCAAgC;AACjC,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,IAAI,yBAAyB,GACzC,oCAAgC;AACjC,YAAY,EAAE,kCAAkC,EAAE,wDAAoD;AACtG,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,gCAAgC,GACjC,sCAAkC;AACnC,OAAO,EACL,uBAAuB,EACvB,WAAW,IAAI,2BAA2B,GAC3C,sCAAkC;AACnC,YAAY,EACV,qCAAqC,EACrC,8CAA8C,GAC/C,2DAAuD"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,sCAAsC,EACtC,iCAAiC,EACjC,6BAA6B,EAC7B,wCAAwC,GACzC,uCAAsC;AACvC,OAAO,EACL,wBAAwB,EACxB,uCAAuC,GACxC,uCAAsC;AACvC,YAAY,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,8BAA8B,EAC9B,kCAAkC,GACnC,oCAAmC;AACpC,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,IAAI,yBAAyB,GACzC,oCAAmC;AACpC,YAAY,EAAE,kCAAkC,EAAE,wDAAuD;AACzG,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,gCAAgC,GACjC,sCAAqC;AACtC,OAAO,EACL,uBAAuB,EACvB,WAAW,IAAI,2BAA2B,GAC3C,sCAAqC;AACtC,YAAY,EACV,qCAAqC,EACrC,8CAA8C,GAC/C,2DAA0D"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,sCAAsC,EACtC,iCAAiC,EACjC,6BAA6B,EAC7B,wCAAwC,GACzC,uCAAmC;AACpC,OAAO,EACL,wBAAwB,EACxB,uCAAuC,GACxC,uCAAmC;AACpC,YAAY,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,8BAA8B,EAC9B,kCAAkC,GACnC,oCAAgC;AACjC,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,IAAI,yBAAyB,GACzC,oCAAgC;AACjC,YAAY,EAAE,kCAAkC,EAAE,wDAAoD;AACtG,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,gCAAgC,GACjC,sCAAkC;AACnC,OAAO,EACL,uBAAuB,EACvB,WAAW,IAAI,2BAA2B,GAC3C,sCAAkC;AACnC,YAAY,EACV,qCAAqC,EACrC,8CAA8C,GAC/C,2DAAuD"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,+BAA+B,EAC/B,8BAA8B,EAC9B,sCAAsC,EACtC,iCAAiC,EACjC,6BAA6B,EAC7B,wCAAwC,GACzC,uCAAsC;AACvC,OAAO,EACL,wBAAwB,EACxB,uCAAuC,GACxC,uCAAsC;AACvC,YAAY,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,8BAA8B,EAC9B,kCAAkC,GACnC,oCAAmC;AACpC,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,IAAI,yBAAyB,GACzC,oCAAmC;AACpC,YAAY,EAAE,kCAAkC,EAAE,wDAAuD;AACzG,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,gCAAgC,GACjC,sCAAqC;AACtC,OAAO,EACL,uBAAuB,EACvB,WAAW,IAAI,2BAA2B,GAC3C,sCAAqC;AACtC,YAAY,EACV,qCAAqC,EACrC,8CAA8C,GAC/C,2DAA0D"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,wBAAwB,EACxB,uCAAuC,EACxC,uCAAmC;AAOpC,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,IAAI,yBAAyB,EACzC,oCAAgC;AAOjC,OAAO,EACL,uBAAuB,EACvB,WAAW,IAAI,2BAA2B,EAC3C,sCAAkC","sourcesContent":["export type {\n ProfileMetricsControllerActions,\n ProfileMetricsControllerEvents,\n ProfileMetricsControllerGetStateAction,\n ProfileMetricsControllerMessenger,\n ProfileMetricsControllerState,\n ProfileMetricsControllerStateChangeEvent,\n} from './ProfileMetricsController';\nexport {\n ProfileMetricsController,\n getDefaultProfileMetricsControllerState,\n} from './ProfileMetricsController';\nexport type {\n ProfileMetricsServiceActions,\n ProfileMetricsServiceEvents,\n ProfileMetricsServiceMessenger,\n ProfileMetricsSubmitMetricsRequest,\n} from './ProfileMetricsService';\nexport {\n ProfileMetricsService,\n serviceName,\n serviceName as profileMetricsServiceName,\n} from './ProfileMetricsService';\nexport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types';\nexport type {\n ProofOfOwnershipServiceActions,\n ProofOfOwnershipServiceEvents,\n ProofOfOwnershipServiceMessenger,\n} from './ProofOfOwnershipService';\nexport {\n ProofOfOwnershipService,\n serviceName as proofOfOwnershipServiceName,\n} from './ProofOfOwnershipService';\nexport type {\n ProfileMetricsControllerMethodActions,\n ProfileMetricsControllerSkipInitialDelayAction,\n} from './ProfileMetricsController-method-action-types';\n"]}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,wBAAwB,EACxB,uCAAuC,EACxC,uCAAsC;AAOvC,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,IAAI,yBAAyB,EACzC,oCAAmC;AAOpC,OAAO,EACL,uBAAuB,EACvB,WAAW,IAAI,2BAA2B,EAC3C,sCAAqC","sourcesContent":["export type {\n ProfileMetricsControllerActions,\n ProfileMetricsControllerEvents,\n ProfileMetricsControllerGetStateAction,\n ProfileMetricsControllerMessenger,\n ProfileMetricsControllerState,\n ProfileMetricsControllerStateChangeEvent,\n} from './ProfileMetricsController.js';\nexport {\n ProfileMetricsController,\n getDefaultProfileMetricsControllerState,\n} from './ProfileMetricsController.js';\nexport type {\n ProfileMetricsServiceActions,\n ProfileMetricsServiceEvents,\n ProfileMetricsServiceMessenger,\n ProfileMetricsSubmitMetricsRequest,\n} from './ProfileMetricsService.js';\nexport {\n ProfileMetricsService,\n serviceName,\n serviceName as profileMetricsServiceName,\n} from './ProfileMetricsService.js';\nexport type { ProfileMetricsServiceMethodActions } from './ProfileMetricsService-method-action-types.js';\nexport type {\n ProofOfOwnershipServiceActions,\n ProofOfOwnershipServiceEvents,\n ProofOfOwnershipServiceMessenger,\n} from './ProofOfOwnershipService.js';\nexport {\n ProofOfOwnershipService,\n serviceName as proofOfOwnershipServiceName,\n} from './ProofOfOwnershipService.js';\nexport type {\n ProfileMetricsControllerMethodActions,\n ProfileMetricsControllerSkipInitialDelayAction,\n} from './ProfileMetricsController-method-action-types.js';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/profile-metrics-controller",
3
- "version": "4.0.2-preview-40d5fb1e2",
3
+ "version": "4.0.2-preview-a3e31582e",
4
4
  "description": "Manages user profile metrics",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -46,8 +46,8 @@
46
46
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/profile-metrics-controller",
47
47
  "lint:tsconfigs": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts",
48
48
  "lint:tsconfigs:fix": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts --fix",
49
- "messenger-action-types:check": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --check",
50
- "messenger-action-types:generate": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --generate",
49
+ "messenger-action-types:check": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --esm --check",
50
+ "messenger-action-types:generate": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --esm --generate",
51
51
  "since-latest-release": "../../scripts/since-latest-release.sh",
52
52
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
53
53
  "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
@@ -66,7 +66,7 @@
66
66
  "@metamask/snaps-sdk": "^11.0.0",
67
67
  "@metamask/snaps-utils": "^12.1.2",
68
68
  "@metamask/superstruct": "^3.1.0",
69
- "@metamask/transaction-controller": "^69.0.0",
69
+ "@metamask/transaction-controller": "^69.2.1",
70
70
  "@metamask/utils": "^11.11.0",
71
71
  "async-mutex": "^0.5.0",
72
72
  "uuid": "^8.3.2"
@@ -75,11 +75,11 @@
75
75
  "@metamask/auto-changelog": "^6.1.0",
76
76
  "@metamask/keyring-internal-api": "^11.0.1",
77
77
  "@ts-bridge/cli": "^0.6.4",
78
- "@types/jest": "^29.5.14",
78
+ "@types/jest": "^30.0.0",
79
79
  "deepmerge": "^4.2.2",
80
- "jest": "^29.7.0",
80
+ "jest": "^30.4.2",
81
81
  "nock": "^13.3.1",
82
- "ts-jest": "^29.2.5",
82
+ "ts-jest": "^29.4.11",
83
83
  "tsx": "^4.20.5",
84
84
  "typedoc": "^0.25.13",
85
85
  "typedoc-plugin-missing-exports": "^2.0.0",