@metamask-previews/snap-account-service 2.1.0-preview-a42e8d0d2 → 2.1.1-preview-d2f661012

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.1.1]
11
+
12
+ ### Fixed
13
+
14
+ - Fix global catch for migration error ([#9720](https://github.com/MetaMask/core/pull/9720))
15
+ - The global catch was only used during automatic migration on vault unlock.
16
+ - It is now properly setup for any migration entry point.
17
+
10
18
  ## [2.1.0]
11
19
 
12
20
  ### Added
@@ -146,7 +154,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
146
154
  - Bump `@metamask/messenger` from `^1.1.1` to `^1.2.0` ([#8632](https://github.com/MetaMask/core/pull/8632))
147
155
  - Bump `@metamask/account-tree-controller` from `^7.3.0` to `^7.4.0` ([#8783](https://github.com/MetaMask/core/pull/8783))
148
156
 
149
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/snap-account-service@2.1.0...HEAD
157
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/snap-account-service@2.1.1...HEAD
158
+ [2.1.1]: https://github.com/MetaMask/core/compare/@metamask/snap-account-service@2.1.0...@metamask/snap-account-service@2.1.1
150
159
  [2.1.0]: https://github.com/MetaMask/core/compare/@metamask/snap-account-service@2.0.0...@metamask/snap-account-service@2.1.0
151
160
  [2.0.0]: https://github.com/MetaMask/core/compare/@metamask/snap-account-service@1.0.0...@metamask/snap-account-service@2.0.0
152
161
  [1.0.0]: https://github.com/MetaMask/core/compare/@metamask/snap-account-service@0.3.1...@metamask/snap-account-service@1.0.0
@@ -321,7 +321,7 @@ _SnapAccountService_messenger = new WeakMap(), _SnapAccountService_watcher = new
321
321
  void __classPrivateFieldGet(this, _SnapAccountService_instances, "m", _SnapAccountService_forwardSelectedAccounts).call(this, groupId, __classPrivateFieldGet(this, _SnapAccountService_instances, "m", _SnapAccountService_getAccountGroup).call(this, groupId)?.accounts);
322
322
  }, _SnapAccountService_handleUnlock = function _SnapAccountService_handleUnlock() {
323
323
  // eslint-disable-next-line no-void
324
- void (0, errors_js_1.withSafeError)('Snap keyring v2 migration', () => this.ensureMigrated()).then(async () => {
324
+ void this.ensureMigrated().then(async () => {
325
325
  // If the migration is successful, we re-forward the current groups to each new keyrings!
326
326
  const groupId = __classPrivateFieldGet(this, _SnapAccountService_instances, "m", _SnapAccountService_getSelectedAccountGroupId).call(this);
327
327
  // NOTE: This cannot throw, all errors are swallowed under the hood, so we don't need to
@@ -346,7 +346,7 @@ _SnapAccountService_messenger = new WeakMap(), _SnapAccountService_watcher = new
346
346
  * safe to call concurrently.
347
347
  */
348
348
  async function _SnapAccountService_migrate() {
349
- await __classPrivateFieldGet(this, _SnapAccountService_messenger, "f").call('KeyringController:withController', async (controller) => {
349
+ await (0, errors_js_1.withSafeError)('Snap keyring v2 migration', async () => __classPrivateFieldGet(this, _SnapAccountService_messenger, "f").call('KeyringController:withController', async (controller) => {
350
350
  const { keyrings } = controller;
351
351
  const legacySnapKeyringEntry = keyrings.find(({ keyring }) => isLegacySnapKeyring(keyring));
352
352
  if (!legacySnapKeyringEntry) {
@@ -389,7 +389,7 @@ async function _SnapAccountService_migrate() {
389
389
  (0, logger_js_1.projectLogger)('Removing legacy Snap keyring...');
390
390
  await (0, errors_js_1.withSafeError)('Removing legacy Snap keyring', async () => controller.removeKeyring(legacySnapKeyringEntry.metadata.id));
391
391
  (0, logger_js_1.projectLogger)('Migration completed!');
392
- });
392
+ }));
393
393
  }, _SnapAccountService_ensureKeyringIsReady =
394
394
  /**
395
395
  * Ensures a Snap keyring is ready for the given Snap. If it doesn't exist yet, it will be created.
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountService.cjs","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupId } from '@metamask/account-api';\nimport {\n SnapKeyring as LegacySnapKeyring,\n SnapMessage,\n} from '@metamask/eth-snap-keyring';\nimport {\n SnapKeyring,\n SnapKeyringState,\n isSnapKeyring,\n} from '@metamask/eth-snap-keyring/v2';\nimport type {\n AccountAssetListUpdatedEventPayload,\n AccountBalancesUpdatedEventPayload,\n AccountTransactionsUpdatedEventPayload,\n Balance,\n CaipAssetType,\n CaipAssetTypeOrId,\n CaipChainId,\n Pagination,\n ResolvedAccountAddress,\n TransactionsPage,\n} from '@metamask/keyring-api';\nimport {\n AccountAssetListUpdatedEventStruct,\n AccountBalancesUpdatedEventStruct,\n AccountTransactionsUpdatedEventStruct,\n KeyringEvent,\n} from '@metamask/keyring-api';\nimport { KeyringType } from '@metamask/keyring-api/v2';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerStateChangeEvent,\n KeyringControllerUnlockEvent,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringV2Action,\n KeyringControllerWithKeyringV2UnsafeAction,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { KeyringInternalSnapClient } from '@metamask/keyring-internal-snap-client/v2';\nimport { SnapManageAccountsMethod } from '@metamask/keyring-snap-sdk';\nimport type {\n AccountId,\n BaseKeyring,\n JsonRpcRequest,\n} from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n SnapControllerGetRunnableSnapsAction,\n SnapControllerGetSnapAction,\n SnapControllerGetStateAction,\n SnapControllerHandleRequestAction,\n SnapControllerSnapBlockedEvent,\n SnapControllerSnapDisabledEvent,\n SnapControllerSnapEnabledEvent,\n SnapControllerSnapInstalledEvent,\n SnapControllerSnapUnblockedEvent,\n SnapControllerSnapUninstalledEvent,\n SnapControllerStateChangeEvent,\n} from '@metamask/snaps-controllers';\nimport { SnapId } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assertStruct } from '@metamask/utils';\n\nimport { reportError, withSafeError } from './errors.js';\nimport { projectLogger as log } from './logger.js';\nimport type {\n SnapAccountServiceEnsureReadyAction,\n SnapAccountServiceEnsureMigratedAction,\n SnapAccountServiceGetCapabilitiesAction,\n SnapAccountServiceGetAccountAssetsAction,\n SnapAccountServiceGetAccountBalancesAction,\n SnapAccountServiceGetAccountTransactionsAction,\n SnapAccountServiceGetSnapsAction,\n SnapAccountServiceHandleKeyringSnapMessageAction,\n SnapAccountServiceResolveAccountAddressAction,\n SnapAccountServiceSetSelectedAccountsAction,\n} from './SnapAccountService-method-action-types.js';\nimport { SnapPlatformWatcher } from './SnapPlatformWatcher.js';\nimport type { SnapPlatformWatcherConfig } from './SnapPlatformWatcher.js';\nimport { SnapTracker } from './SnapTracker.js';\nimport type {\n AccountTreeControllerGetAccountGroupObjectAction,\n AccountTreeControllerGetSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerAccountGroupCreatedEvent,\n AccountTreeControllerAccountGroupUpdatedEvent,\n AccountTreeControllerAccountGroupRemovedEvent,\n AccountGroupObject,\n} from './types.js';\n\n/**\n * The name of the {@link SnapAccountService}, used to namespace the service's\n * actions and events.\n */\nexport const serviceName = 'SnapAccountService';\n\n/**\n * All of the methods within {@link SnapAccountService} that are exposed via\n * the messenger.\n */\nconst MESSENGER_EXPOSED_METHODS = [\n 'ensureMigrated',\n 'ensureReady',\n 'getCapabilities',\n 'getAccountAssets',\n 'getAccountBalances',\n 'getAccountTransactions',\n 'getSnaps',\n 'handleKeyringSnapMessage',\n 'resolveAccountAddress',\n 'setSelectedAccounts',\n] as const;\n\n/**\n * Actions that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceActions =\n | SnapAccountServiceEnsureMigratedAction\n | SnapAccountServiceEnsureReadyAction\n | SnapAccountServiceGetCapabilitiesAction\n | SnapAccountServiceGetAccountAssetsAction\n | SnapAccountServiceGetAccountBalancesAction\n | SnapAccountServiceGetAccountTransactionsAction\n | SnapAccountServiceGetSnapsAction\n | SnapAccountServiceHandleKeyringSnapMessageAction\n | SnapAccountServiceResolveAccountAddressAction\n | SnapAccountServiceSetSelectedAccountsAction;\n\n/**\n * Actions from other messengers that {@link SnapAccountService} calls.\n */\ntype AllowedActions =\n | SnapControllerGetStateAction\n | SnapControllerGetSnapAction\n | SnapControllerGetRunnableSnapsAction\n | SnapControllerHandleRequestAction\n | KeyringControllerGetStateAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringV2Action\n | KeyringControllerWithKeyringV2UnsafeAction\n | AccountTreeControllerGetAccountGroupObjectAction\n | AccountTreeControllerGetSelectedAccountGroupAction;\n\n/**\n * Events that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceAccountBalancesUpdatedEvent = {\n type: `${typeof serviceName}:accountBalancesUpdated`;\n payload: [AccountBalancesUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountAssetListUpdatedEvent = {\n type: `${typeof serviceName}:accountAssetListUpdated`;\n payload: [AccountAssetListUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountTransactionsUpdatedEvent = {\n type: `${typeof serviceName}:accountTransactionsUpdated`;\n payload: [AccountTransactionsUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceEvents =\n | SnapAccountServiceAccountAssetListUpdatedEvent\n | SnapAccountServiceAccountBalancesUpdatedEvent\n | SnapAccountServiceAccountTransactionsUpdatedEvent;\n\n/**\n * Events from other messengers that {@link SnapAccountService} subscribes to.\n */\ntype AllowedEvents =\n | SnapControllerStateChangeEvent\n | SnapControllerSnapInstalledEvent\n | SnapControllerSnapEnabledEvent\n | SnapControllerSnapDisabledEvent\n | SnapControllerSnapBlockedEvent\n | SnapControllerSnapUnblockedEvent\n | SnapControllerSnapUninstalledEvent\n | KeyringControllerStateChangeEvent\n | KeyringControllerUnlockEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | AccountTreeControllerAccountGroupCreatedEvent\n | AccountTreeControllerAccountGroupUpdatedEvent\n | AccountTreeControllerAccountGroupRemovedEvent;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link SnapAccountService}.\n */\nexport type SnapAccountServiceMessenger = Messenger<\n typeof serviceName,\n SnapAccountServiceActions | AllowedActions,\n SnapAccountServiceEvents | AllowedEvents\n>;\n\n/**\n * Configuration for the {@link SnapAccountService}.\n */\nexport type SnapAccountServiceConfig = {\n snapPlatformWatcher?: SnapPlatformWatcherConfig;\n};\n\n/**\n * The options that {@link SnapAccountService} takes.\n */\nexport type SnapAccountServiceOptions = {\n messenger: SnapAccountServiceMessenger;\n config?: SnapAccountServiceConfig;\n};\n\n/**\n * Checks if a given keyring is a Snap keyring (v2).\n *\n * @param keyring - The keyring to check.\n * @param keyring.type - The type of the keyring.\n * @returns `true` if the keyring is a Snap keyring (v2), `false` otherwise.\n */\nfunction isLegacySnapKeyring(keyring: {\n type: BaseKeyring['type'];\n}): keyring is LegacySnapKeyring {\n return keyring.type === KeyringTypes.snap;\n}\n\n/**\n * Account data update events that can be forwarded from Snaps.\n *\n * These events are then re-emitted by the service for other consumers.\n */\ntype AccountDataUpdatedKeyringEvent =\n | KeyringEvent.AccountAssetListUpdated\n | KeyringEvent.AccountBalancesUpdated\n | KeyringEvent.AccountTransactionsUpdated;\n\n/**\n * Checks if a Snap message method is an account data update event.\n *\n * @param event - The Snap message event.\n * @returns `true` if the method can be forwarded without the legacy Snap keyring.\n */\nfunction isAccountDataUpdatedKeyringEvent(\n event: string,\n): event is AccountDataUpdatedKeyringEvent {\n return (\n event === KeyringEvent.AccountAssetListUpdated ||\n event === KeyringEvent.AccountBalancesUpdated ||\n event === KeyringEvent.AccountTransactionsUpdated\n );\n}\n\n/**\n * Service responsible for managing account management snaps.\n */\nexport class SnapAccountService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n readonly #messenger: SnapAccountServiceMessenger;\n\n readonly #watcher: SnapPlatformWatcher;\n\n readonly #tracker: SnapTracker;\n\n readonly #client: KeyringInternalSnapClient;\n\n #migrated = false;\n\n #migratePromise: Promise<void> | null = null;\n\n /**\n * Constructs a new {@link SnapAccountService}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.config - Optional service configuration.\n */\n constructor({ messenger, config }: SnapAccountServiceOptions) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#watcher = new SnapPlatformWatcher(\n messenger,\n config?.snapPlatformWatcher,\n );\n this.#tracker = new SnapTracker(messenger);\n this.#client = new KeyringInternalSnapClient({\n messenger: messenger.buildChild({\n namespace: 'KeyringInternalSnapClient',\n actions: ['SnapController:handleRequest'],\n }),\n });\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n (groupId) => this.#handleSelectedAccountGroupChange(groupId),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupCreated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupUpdated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupRemoved',\n (groupId) => this.#handleAccountGroupRemoved(groupId),\n );\n\n this.#messenger.subscribe('KeyringController:unlock', () =>\n this.#handleUnlock(),\n );\n }\n\n /**\n * Handles changes to the selected account group by forwarding the new\n * group's accounts to the Snap keyring.\n *\n * @param groupId - The ID of the newly selected account group.\n */\n #handleSelectedAccountGroupChange(groupId: AccountGroupId | ''): void {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n }\n\n /**\n * Handles the keyring controller unlock event by triggering the migration\n * and forwarding the currently selected account group's accounts to the Snap\n * keyring.\n */\n #handleUnlock(): void {\n // eslint-disable-next-line no-void\n void withSafeError('Snap keyring v2 migration', () =>\n this.ensureMigrated(),\n ).then(\n async () => {\n // If the migration is successful, we re-forward the current groups to each new keyrings!\n const groupId = this.#getSelectedAccountGroupId();\n // NOTE: This cannot throw, all errors are swallowed under the hood, so we don't need to\n // catch anything here.\n return await this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n },\n (error) => {\n reportError(this.#messenger, 'Migration failed after unlock', error);\n },\n );\n }\n\n /**\n * Handles created or updated account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the created/updated group is currently selected.\n *\n * @param group - The account group being created or updated.\n */\n #handleAccountGroupCreatedOrUpdated(group: AccountGroupObject): void {\n if (group.id === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(group.id, group.accounts);\n }\n }\n\n /**\n * Handles removed account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the removed group is currently selected.\n *\n * @param groupId - The ID of the account group being removed.\n */\n #handleAccountGroupRemoved(groupId: AccountGroupId): void {\n if (groupId === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n [], // Clearing accounts since the group is removed\n );\n }\n }\n\n /**\n * Returns the IDs of all currently tracked account-management Snaps —\n * Snaps that are installed, enabled, not blocked, and have the\n * `endowment:keyring` permission.\n *\n * @returns The IDs of tracked account-management Snaps.\n */\n getSnaps(): SnapId[] {\n return this.#tracker.getSnaps();\n }\n\n /**\n * Ensures everything is ready to use Snap accounts for the given Snap.\n * 1. Validates that `snapId` is a tracked account-management Snap.\n * 2. Asserts that the legacy -> v2 migration has been triggered (expected to\n * happen at `KeyringController:unlock` time).\n * 3. Atomically creates the v2 keyring for this Snap if it doesn't exist\n * yet.\n * 4. Waits for the Snap platform to be fully started.\n *\n * Safe to call concurrently — each step is idempotent or mutex-protected.\n *\n * @param snapId - ID of the Snap to ensure readiness for.\n * @throws If `snapId` is not a tracked account-management Snap.\n * @throws If the migration has not been triggered yet (wallet not unlocked).\n */\n async ensureReady(snapId: SnapId): Promise<void> {\n if (!this.#tracker.canUse(snapId)) {\n throw new Error(`Unknown snap: \"${snapId}\"`);\n }\n\n // The migration is required to ensure the v2 keyring exists.\n await this.ensureMigrated();\n\n // We still try to create the keyring for the Snap here, since we might\n // want to use a new Snap that never had accounts before.\n await this.#ensureKeyringIsReady(snapId);\n\n // Before doing anything with our Snap, we need to make sure the platform\n // is ready to process requests.\n await this.#watcher.ensureCanUseSnapPlatform();\n }\n\n /**\n * Migrate the legacy Snap keyring to the new (per-snap) Snap keyring v2.\n * Expected to be triggered at `KeyringController:unlock` time.\n * Safe to call concurrently — the migration runs only once; all callers\n * await the same promise.\n *\n * @returns A promise that resolves when the migration is complete.\n */\n async ensureMigrated(): Promise<void> {\n if (this.#migrated) {\n return;\n }\n\n if (!this.#migratePromise) {\n this.#migratePromise = this.#migrate()\n .then(() => {\n this.#migrated = true;\n return undefined;\n })\n .catch((error) => {\n // Clear the promise so the next call can retry.\n this.#migratePromise = null;\n throw error;\n });\n }\n\n await this.#migratePromise;\n }\n\n /**\n * Performs the actual migration logic. Should only be called once, and is not\n * safe to call concurrently.\n */\n async #migrate(): Promise<void> {\n await this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const { keyrings } = controller;\n\n const legacySnapKeyringEntry = keyrings.find(({ keyring }) =>\n isLegacySnapKeyring(keyring),\n );\n if (!legacySnapKeyringEntry) {\n log('No legacy Snap keyring found. Migration not required.');\n return;\n }\n\n log('Migration started...');\n\n // The legacy Snap keyring has never been a true `EthKeyring` so we\n // need to cast it to `unknown` first.\n const legacySnapKeyring =\n legacySnapKeyringEntry.keyring as unknown as LegacySnapKeyring;\n\n // Compute the account list for each Snap, grouped by snap ID.\n const states = new Map<SnapId, SnapKeyringState>();\n for (const internalAccount of legacySnapKeyring.listAccounts()) {\n // Convert `InternalAccount` to `KeyringAccount` since the Snap\n // keyring (v2) expects accounts in that format and will verify it\n // with `superstruct` when adding the keyring.\n const { metadata, ...account } = internalAccount;\n\n const snap = metadata?.snap;\n if (snap) {\n const snapId = snap.id as SnapId;\n\n let state = states.get(snapId);\n if (!state) {\n state = { snapId, accounts: {} };\n states.set(snapId, state);\n }\n state.accounts[account.id] = account;\n }\n }\n\n // Create the new Snap keyring (v2) for each Snap and migrate the\n // accounts over.\n for (const state of states.values()) {\n log(`Migrating accounts for Snap \"${state.snapId}\"...`);\n await withSafeError(\n `Adding v2 Snap keyring for \"${state.snapId}\"`,\n async () =>\n controller.addNewKeyring(\n // IMPORTANT: The Snap keyring (v2) can also be used as a v1\n // keyring. So the builder associated with the v2 keyring type\n // is able to build both v1 and v2 keyrings.\n KeyringType.Snap,\n state,\n ),\n );\n }\n\n // Remove the legacy Snap keyring after migration.\n log('Removing legacy Snap keyring...');\n await withSafeError('Removing legacy Snap keyring', async () =>\n controller.removeKeyring(legacySnapKeyringEntry.metadata.id),\n );\n\n log('Migration completed!');\n },\n );\n }\n\n /**\n * Ensures a Snap keyring is ready for the given Snap. If it doesn't exist yet, it will be created.\n * Safe to call concurrently.\n *\n * @param snapId - The Snap ID to ensure the keyring is ready for.\n */\n async #ensureKeyringIsReady(snapId: SnapId): Promise<void> {\n await this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const hasKeyring = controller.keyrings.some(\n ({ keyringV2 }) =>\n keyringV2 &&\n isSnapKeyring(keyringV2) &&\n keyringV2.snapId === snapId,\n );\n\n if (!hasKeyring) {\n log(`Creating v2 keyring for Snap \"${snapId}\"...`);\n await controller.addNewKeyring(KeyringType.Snap, {\n snapId,\n accounts: {},\n });\n }\n },\n );\n }\n\n /**\n * Shared body for {@link SnapAccountService.#withKeyringV2} and\n * {@link SnapAccountService.#withKeyringV2Unsafe}. Hides the per-Snap\n * filter and the cast back to {@link SnapKeyring} (the messenger action's\n * callback receives a generic `Keyring`; the selector's type predicate\n * doesn't flow through the messenger's generics).\n *\n * @param action - The messenger action to invoke.\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Call<Result>(\n action:\n | 'KeyringController:withKeyringV2'\n | 'KeyringController:withKeyringV2Unsafe',\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#messenger.call(\n action,\n {\n filter: (keyring): keyring is SnapKeyring =>\n isSnapKeyring(keyring) && keyring.snapId === snapId,\n },\n async ({ keyring }) => operation(keyring as SnapKeyring),\n ) as Result;\n }\n\n /**\n * Lock-free variant of {@link SnapAccountService.#withKeyringV2}. Only use\n * for operations that do not mutate keyring or controller state — see\n * `KeyringController.withKeyringV2Unsafe` for the contract.\n *\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Unsafe<Result>(\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#withKeyringV2Call(\n 'KeyringController:withKeyringV2Unsafe',\n snapId,\n operation,\n );\n }\n\n /**\n * Returns the keyring capabilities declared by the given Snap. These are\n * populated by the bridge keyring from the Snap's manifest, and describe\n * which keyring features the Snap supports (scopes, BIP-44 options, etc.).\n *\n * Consumers use this to decide whether to drive the Snap through the v1 or\n * v2 keyring path. Reading capabilities does not mutate state, so the\n * lock-free keyring access is used.\n *\n * @param snapId - ID of the Snap.\n * @returns The Snap's keyring capabilities.\n */\n async getCapabilities(snapId: SnapId): Promise<KeyringCapabilities> {\n return this.#withKeyringV2Unsafe(\n snapId,\n async (keyring) => keyring.capabilities,\n );\n }\n\n /**\n * Returns the CAIP-19 asset type/ID list supported by an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @returns A promise resolving to the list of supported CAIP-19 asset type/IDs.\n */\n async getAccountAssets(\n snapId: SnapId,\n id: AccountId,\n ): Promise<CaipAssetTypeOrId[]> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountAssets(id);\n }\n\n /**\n * Returns the balances for an account for the requested asset types.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param assets - List of CAIP-19 fungible asset types to fetch balances for.\n * @returns A promise resolving to a map of asset type to balance.\n */\n async getAccountBalances(\n snapId: SnapId,\n id: AccountId,\n assets: CaipAssetType[],\n ): Promise<Record<CaipAssetType, Balance>> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountBalances(id, assets);\n }\n\n /**\n * Returns a page of transactions for an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param pagination - Pagination options.\n * @returns A promise resolving to a page of transactions.\n */\n async getAccountTransactions(\n snapId: SnapId,\n id: AccountId,\n pagination: Pagination,\n ): Promise<TransactionsPage> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .getAccountTransactions(id, pagination);\n }\n\n /**\n * Resolves the account address to use for routing a signing request.\n *\n * @param snapId - ID of the Snap.\n * @param scope - CAIP-2 chain ID of the signing request.\n * @param request - The signing JSON-RPC request.\n * @returns A promise resolving to the resolved address, or `null` if the\n * Snap cannot determine an address for this request.\n */\n async resolveAccountAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ): Promise<ResolvedAccountAddress | null> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .resolveAccountAddress(scope, request);\n }\n\n /**\n * Notifies a Snap of the currently selected accounts.\n *\n * For v1 Snaps the call goes through the keyring (signing interface); for\n * v2 Snaps it is routed via the RPC client because the keyring only covers\n * keyring-only operations (signing, account lifecycle).\n *\n * @param snapId - ID of the Snap.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async setSelectedAccounts(\n snapId: SnapId,\n accounts: AccountId[],\n ): Promise<void> {\n await this.ensureReady(snapId);\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n await this.#setSelectedAccountsForKeyring(snapId, keyring, accounts);\n });\n }\n\n /**\n * Dispatches a `setSelectedAccounts` call to the correct layer based on\n * whether the keyring has a v1 interface or not.\n *\n * The keyring is a pure interface for keyring-only operations (signing,\n * account lifecycle). Extra Snap-level methods like `setSelectedAccounts`\n * are invoked via the client for v2 Snaps, which communicates with the Snap\n * over RPC.\n *\n * @param snapId - ID of the Snap.\n * @param keyring - The Snap keyring (v2) instance.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async #setSelectedAccountsForKeyring(\n snapId: SnapId,\n keyring: SnapKeyring,\n accounts: AccountId[],\n ): Promise<void> {\n if (keyring.v1) {\n // We used to keep track of selected accounts in the v1 keyring, so we need to forward the call there for v1 Snaps.\n await keyring.v1.setSelectedAccounts(accounts);\n } else {\n await this.#client.withSnapId(snapId).setSelectedAccounts(accounts);\n }\n }\n\n /**\n * Handle a message from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param message - Message sent by the Snap.\n * @returns The execution result.\n */\n async handleKeyringSnapMessage(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<Json> {\n const { method: event } = message;\n if (isAccountDataUpdatedKeyringEvent(event)) {\n return this.#publishAccountDataUpdatedEvent(snapId, event, message);\n }\n\n // Handle specific methods.\n if (message.method === SnapManageAccountsMethod.GetSelectedAccounts) {\n const groupId = this.#getSelectedAccountGroupId();\n const accounts = this.#getAccountGroup(groupId)?.accounts ?? [];\n\n try {\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) =>\n accounts.filter((id) => keyring.hasAccount(id)),\n );\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n // Some Snaps might be using `getSelectedAccounts` early in their lifecycle, before the keyring is created. So we\n // do not throw in that case to avoid disrupting their initialization process.\n return [];\n }\n\n throw error;\n }\n }\n\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" to its keyring...`,\n );\n\n // We can create a new keyring if the message is an AccountCreated event.\n const isAccountCreatedMessage = event === KeyringEvent.AccountCreated;\n\n // Create the Snap keyring if it doesn't exist yet (in an atomic way). We cannot assume\n // the keyring exists (e.g for the MMI Snap).\n // NOTE: We only auto-create it for v1 account creation flows.\n if (isAccountCreatedMessage) {\n await this.ensureReady(snapId);\n }\n\n // This part of the flow relies on v1 flows, but v2 keyrings are compatible with those messages\n // too.\n try {\n // NOTE: We use \"unsafe\" here since none of the messages should trigger mutations to the keyring state.\n // The exception might be `:accountCreated`, but even in that case, the mutation is handled differently\n // in the client by call `:persistAllKeyrings` explicitly.\n // Using `:withKeyringV2` would cause a deadlock when we're initiating operations like `removeAccount` from\n // the keyring itself:\n // 1: withKeyring(..., ({ keyring }) => { keyring.removeAccount(...) })\n // 2. removeAccount(...) -> handleKeyringSnapMessage(..., { method: 'accountRemoved', ... })\n // 3. handleKeyringSnapMessage tries to acquire the same lock again via withKeyringV2 -> deadlock.\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n if (!keyring.v1) {\n log(\n `Received message \"${event}\" for Snap \"${snapId}\", but that's a v2 keyring... Rejecting.`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring for Snap \"${snapId}\" is v2, not v1.`,\n );\n }\n\n return await keyring.v1.handleKeyringSnapMessage(message);\n });\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n log(\n `No Snap keyring found for Snap \"${snapId}\". Cannot handle message with method \"${event}\".`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring does not exist yet for Snap \"${snapId}\".`,\n );\n }\n\n throw error;\n }\n }\n\n /**\n * Publishes an account data update event from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param event - Account data update event.\n * @param message - Message sent by the Snap.\n * @returns `null`.\n */\n #publishAccountDataUpdatedEvent(\n snapId: SnapId,\n event: AccountDataUpdatedKeyringEvent,\n message: SnapMessage,\n ): null {\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" as a SnapAccountService event...`,\n );\n\n if (event === KeyringEvent.AccountAssetListUpdated) {\n assertStruct(message, AccountAssetListUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountAssetListUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountBalancesUpdated) {\n assertStruct(message, AccountBalancesUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountBalancesUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountTransactionsUpdated) {\n assertStruct(message, AccountTransactionsUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountTransactionsUpdated',\n message.params,\n );\n }\n\n // We need to return a valid JSON value, so we cannot use `undefined` here.\n return null;\n }\n\n // eslint-disable-next-line jsdoc/require-returns\n /**\n * Forwards the accounts of the given account group to the Snap keyring.\n *\n * @param groupId - The ID of the account group whose accounts should be\n * forwarded. If empty, this is a no-op.\n * @param accounts - The accounts to forward. If not defined, this is a no-op.\n */\n async #forwardSelectedAccounts(\n groupId: AccountGroupId | '',\n accounts: AccountId[] | undefined,\n ): Promise<void> {\n const skipping = (reason: string): void =>\n log(`${reason}, skipping forwarding selected accounts to Snap keyring`);\n\n if (!this.#migrated) {\n return skipping('Not migrated yet');\n }\n\n if (!groupId) {\n return skipping('No selected account group');\n }\n\n if (!accounts) {\n return skipping(`Account group (\"${groupId}\") has no accounts`);\n }\n\n const forwardSelectedAccounts = async (): Promise<void> => {\n if (accounts.length) {\n log(\n `Forwarding selected accounts (from \"${groupId}\"): ${accounts.join(', ')}`,\n );\n } else {\n log(`Clearing selected accounts (from \"${groupId}\")`);\n }\n\n await Promise.all(\n this.#tracker.getSnaps().map(async (snapId) => {\n try {\n // We can safely invoke this method without taking the controller lock\n // because it should not mutate the keyring state. So we can use\n // `withKeyringV2Unsafe` in this case.\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n // The group's accounts may belong to several Snaps; only\n // forward the subset this Snap actually owns. An empty\n // subset still gets forwarded to explicitly clear the\n // Snap selected accounts.\n const snapAccounts = accounts.filter((id) =>\n keyring.hasAccount(id),\n );\n await this.#setSelectedAccountsForKeyring(\n snapId,\n keyring,\n snapAccounts,\n );\n });\n } catch (error) {\n // Tracked Snaps without a v2 keyring yet are expected —\n // forwarding will resume on the next event once `ensureReady`\n // has run.\n if (!isKeyringNotFoundError(error)) {\n console.error(\n `Error forwarding selected accounts to Snap \"${snapId}\":`,\n error,\n );\n }\n }\n }),\n );\n };\n\n // There is nothing we can do if forwarding fails. This will auto-recover on the next relevant event.\n return await forwardSelectedAccounts().catch((error) => {\n console.error('Error forwarding selected accounts:', error);\n });\n }\n\n /**\n * Gets the account group object for the given group ID.\n *\n * @param groupId - The ID of the account group.\n * @returns The account group object, or undefined if the group ID is empty or the group does not exist.\n */\n #getAccountGroup(\n groupId: AccountGroupId | '',\n ): AccountGroupObject | undefined {\n if (!groupId) {\n return undefined;\n }\n\n return this.#messenger.call(\n 'AccountTreeController:getAccountGroupObject',\n groupId,\n );\n }\n\n /**\n * Gets the currently selected account group ID.\n *\n * @returns The currently selected account group ID, or an empty string if\n * there is no selected account group.\n */\n #getSelectedAccountGroupId(): AccountGroupId | '' {\n return this.#messenger.call(\n 'AccountTreeController:getSelectedAccountGroup',\n );\n }\n}\n"]}
1
+ {"version":3,"file":"SnapAccountService.cjs","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupId } from '@metamask/account-api';\nimport {\n SnapKeyring as LegacySnapKeyring,\n SnapMessage,\n} from '@metamask/eth-snap-keyring';\nimport {\n SnapKeyring,\n SnapKeyringState,\n isSnapKeyring,\n} from '@metamask/eth-snap-keyring/v2';\nimport type {\n AccountAssetListUpdatedEventPayload,\n AccountBalancesUpdatedEventPayload,\n AccountTransactionsUpdatedEventPayload,\n Balance,\n CaipAssetType,\n CaipAssetTypeOrId,\n CaipChainId,\n Pagination,\n ResolvedAccountAddress,\n TransactionsPage,\n} from '@metamask/keyring-api';\nimport {\n AccountAssetListUpdatedEventStruct,\n AccountBalancesUpdatedEventStruct,\n AccountTransactionsUpdatedEventStruct,\n KeyringEvent,\n} from '@metamask/keyring-api';\nimport { KeyringType } from '@metamask/keyring-api/v2';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerStateChangeEvent,\n KeyringControllerUnlockEvent,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringV2Action,\n KeyringControllerWithKeyringV2UnsafeAction,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { KeyringInternalSnapClient } from '@metamask/keyring-internal-snap-client/v2';\nimport { SnapManageAccountsMethod } from '@metamask/keyring-snap-sdk';\nimport type {\n AccountId,\n BaseKeyring,\n JsonRpcRequest,\n} from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n SnapControllerGetRunnableSnapsAction,\n SnapControllerGetSnapAction,\n SnapControllerGetStateAction,\n SnapControllerHandleRequestAction,\n SnapControllerSnapBlockedEvent,\n SnapControllerSnapDisabledEvent,\n SnapControllerSnapEnabledEvent,\n SnapControllerSnapInstalledEvent,\n SnapControllerSnapUnblockedEvent,\n SnapControllerSnapUninstalledEvent,\n SnapControllerStateChangeEvent,\n} from '@metamask/snaps-controllers';\nimport { SnapId } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assertStruct } from '@metamask/utils';\n\nimport { reportError, withSafeError } from './errors.js';\nimport { projectLogger as log } from './logger.js';\nimport type {\n SnapAccountServiceEnsureReadyAction,\n SnapAccountServiceEnsureMigratedAction,\n SnapAccountServiceGetCapabilitiesAction,\n SnapAccountServiceGetAccountAssetsAction,\n SnapAccountServiceGetAccountBalancesAction,\n SnapAccountServiceGetAccountTransactionsAction,\n SnapAccountServiceGetSnapsAction,\n SnapAccountServiceHandleKeyringSnapMessageAction,\n SnapAccountServiceResolveAccountAddressAction,\n SnapAccountServiceSetSelectedAccountsAction,\n} from './SnapAccountService-method-action-types.js';\nimport { SnapPlatformWatcher } from './SnapPlatformWatcher.js';\nimport type { SnapPlatformWatcherConfig } from './SnapPlatformWatcher.js';\nimport { SnapTracker } from './SnapTracker.js';\nimport type {\n AccountTreeControllerGetAccountGroupObjectAction,\n AccountTreeControllerGetSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerAccountGroupCreatedEvent,\n AccountTreeControllerAccountGroupUpdatedEvent,\n AccountTreeControllerAccountGroupRemovedEvent,\n AccountGroupObject,\n} from './types.js';\n\n/**\n * The name of the {@link SnapAccountService}, used to namespace the service's\n * actions and events.\n */\nexport const serviceName = 'SnapAccountService';\n\n/**\n * All of the methods within {@link SnapAccountService} that are exposed via\n * the messenger.\n */\nconst MESSENGER_EXPOSED_METHODS = [\n 'ensureMigrated',\n 'ensureReady',\n 'getCapabilities',\n 'getAccountAssets',\n 'getAccountBalances',\n 'getAccountTransactions',\n 'getSnaps',\n 'handleKeyringSnapMessage',\n 'resolveAccountAddress',\n 'setSelectedAccounts',\n] as const;\n\n/**\n * Actions that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceActions =\n | SnapAccountServiceEnsureMigratedAction\n | SnapAccountServiceEnsureReadyAction\n | SnapAccountServiceGetCapabilitiesAction\n | SnapAccountServiceGetAccountAssetsAction\n | SnapAccountServiceGetAccountBalancesAction\n | SnapAccountServiceGetAccountTransactionsAction\n | SnapAccountServiceGetSnapsAction\n | SnapAccountServiceHandleKeyringSnapMessageAction\n | SnapAccountServiceResolveAccountAddressAction\n | SnapAccountServiceSetSelectedAccountsAction;\n\n/**\n * Actions from other messengers that {@link SnapAccountService} calls.\n */\ntype AllowedActions =\n | SnapControllerGetStateAction\n | SnapControllerGetSnapAction\n | SnapControllerGetRunnableSnapsAction\n | SnapControllerHandleRequestAction\n | KeyringControllerGetStateAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringV2Action\n | KeyringControllerWithKeyringV2UnsafeAction\n | AccountTreeControllerGetAccountGroupObjectAction\n | AccountTreeControllerGetSelectedAccountGroupAction;\n\n/**\n * Events that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceAccountBalancesUpdatedEvent = {\n type: `${typeof serviceName}:accountBalancesUpdated`;\n payload: [AccountBalancesUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountAssetListUpdatedEvent = {\n type: `${typeof serviceName}:accountAssetListUpdated`;\n payload: [AccountAssetListUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountTransactionsUpdatedEvent = {\n type: `${typeof serviceName}:accountTransactionsUpdated`;\n payload: [AccountTransactionsUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceEvents =\n | SnapAccountServiceAccountAssetListUpdatedEvent\n | SnapAccountServiceAccountBalancesUpdatedEvent\n | SnapAccountServiceAccountTransactionsUpdatedEvent;\n\n/**\n * Events from other messengers that {@link SnapAccountService} subscribes to.\n */\ntype AllowedEvents =\n | SnapControllerStateChangeEvent\n | SnapControllerSnapInstalledEvent\n | SnapControllerSnapEnabledEvent\n | SnapControllerSnapDisabledEvent\n | SnapControllerSnapBlockedEvent\n | SnapControllerSnapUnblockedEvent\n | SnapControllerSnapUninstalledEvent\n | KeyringControllerStateChangeEvent\n | KeyringControllerUnlockEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | AccountTreeControllerAccountGroupCreatedEvent\n | AccountTreeControllerAccountGroupUpdatedEvent\n | AccountTreeControllerAccountGroupRemovedEvent;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link SnapAccountService}.\n */\nexport type SnapAccountServiceMessenger = Messenger<\n typeof serviceName,\n SnapAccountServiceActions | AllowedActions,\n SnapAccountServiceEvents | AllowedEvents\n>;\n\n/**\n * Configuration for the {@link SnapAccountService}.\n */\nexport type SnapAccountServiceConfig = {\n snapPlatformWatcher?: SnapPlatformWatcherConfig;\n};\n\n/**\n * The options that {@link SnapAccountService} takes.\n */\nexport type SnapAccountServiceOptions = {\n messenger: SnapAccountServiceMessenger;\n config?: SnapAccountServiceConfig;\n};\n\n/**\n * Checks if a given keyring is a Snap keyring (v2).\n *\n * @param keyring - The keyring to check.\n * @param keyring.type - The type of the keyring.\n * @returns `true` if the keyring is a Snap keyring (v2), `false` otherwise.\n */\nfunction isLegacySnapKeyring(keyring: {\n type: BaseKeyring['type'];\n}): keyring is LegacySnapKeyring {\n return keyring.type === KeyringTypes.snap;\n}\n\n/**\n * Account data update events that can be forwarded from Snaps.\n *\n * These events are then re-emitted by the service for other consumers.\n */\ntype AccountDataUpdatedKeyringEvent =\n | KeyringEvent.AccountAssetListUpdated\n | KeyringEvent.AccountBalancesUpdated\n | KeyringEvent.AccountTransactionsUpdated;\n\n/**\n * Checks if a Snap message method is an account data update event.\n *\n * @param event - The Snap message event.\n * @returns `true` if the method can be forwarded without the legacy Snap keyring.\n */\nfunction isAccountDataUpdatedKeyringEvent(\n event: string,\n): event is AccountDataUpdatedKeyringEvent {\n return (\n event === KeyringEvent.AccountAssetListUpdated ||\n event === KeyringEvent.AccountBalancesUpdated ||\n event === KeyringEvent.AccountTransactionsUpdated\n );\n}\n\n/**\n * Service responsible for managing account management snaps.\n */\nexport class SnapAccountService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n readonly #messenger: SnapAccountServiceMessenger;\n\n readonly #watcher: SnapPlatformWatcher;\n\n readonly #tracker: SnapTracker;\n\n readonly #client: KeyringInternalSnapClient;\n\n #migrated = false;\n\n #migratePromise: Promise<void> | null = null;\n\n /**\n * Constructs a new {@link SnapAccountService}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.config - Optional service configuration.\n */\n constructor({ messenger, config }: SnapAccountServiceOptions) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#watcher = new SnapPlatformWatcher(\n messenger,\n config?.snapPlatformWatcher,\n );\n this.#tracker = new SnapTracker(messenger);\n this.#client = new KeyringInternalSnapClient({\n messenger: messenger.buildChild({\n namespace: 'KeyringInternalSnapClient',\n actions: ['SnapController:handleRequest'],\n }),\n });\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n (groupId) => this.#handleSelectedAccountGroupChange(groupId),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupCreated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupUpdated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupRemoved',\n (groupId) => this.#handleAccountGroupRemoved(groupId),\n );\n\n this.#messenger.subscribe('KeyringController:unlock', () =>\n this.#handleUnlock(),\n );\n }\n\n /**\n * Handles changes to the selected account group by forwarding the new\n * group's accounts to the Snap keyring.\n *\n * @param groupId - The ID of the newly selected account group.\n */\n #handleSelectedAccountGroupChange(groupId: AccountGroupId | ''): void {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n }\n\n /**\n * Handles the keyring controller unlock event by triggering the migration\n * and forwarding the currently selected account group's accounts to the Snap\n * keyring.\n */\n #handleUnlock(): void {\n // eslint-disable-next-line no-void\n void this.ensureMigrated().then(\n async () => {\n // If the migration is successful, we re-forward the current groups to each new keyrings!\n const groupId = this.#getSelectedAccountGroupId();\n // NOTE: This cannot throw, all errors are swallowed under the hood, so we don't need to\n // catch anything here.\n return await this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n },\n (error) => {\n reportError(this.#messenger, 'Migration failed after unlock', error);\n },\n );\n }\n\n /**\n * Handles created or updated account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the created/updated group is currently selected.\n *\n * @param group - The account group being created or updated.\n */\n #handleAccountGroupCreatedOrUpdated(group: AccountGroupObject): void {\n if (group.id === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(group.id, group.accounts);\n }\n }\n\n /**\n * Handles removed account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the removed group is currently selected.\n *\n * @param groupId - The ID of the account group being removed.\n */\n #handleAccountGroupRemoved(groupId: AccountGroupId): void {\n if (groupId === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n [], // Clearing accounts since the group is removed\n );\n }\n }\n\n /**\n * Returns the IDs of all currently tracked account-management Snaps —\n * Snaps that are installed, enabled, not blocked, and have the\n * `endowment:keyring` permission.\n *\n * @returns The IDs of tracked account-management Snaps.\n */\n getSnaps(): SnapId[] {\n return this.#tracker.getSnaps();\n }\n\n /**\n * Ensures everything is ready to use Snap accounts for the given Snap.\n * 1. Validates that `snapId` is a tracked account-management Snap.\n * 2. Asserts that the legacy -> v2 migration has been triggered (expected to\n * happen at `KeyringController:unlock` time).\n * 3. Atomically creates the v2 keyring for this Snap if it doesn't exist\n * yet.\n * 4. Waits for the Snap platform to be fully started.\n *\n * Safe to call concurrently — each step is idempotent or mutex-protected.\n *\n * @param snapId - ID of the Snap to ensure readiness for.\n * @throws If `snapId` is not a tracked account-management Snap.\n * @throws If the migration has not been triggered yet (wallet not unlocked).\n */\n async ensureReady(snapId: SnapId): Promise<void> {\n if (!this.#tracker.canUse(snapId)) {\n throw new Error(`Unknown snap: \"${snapId}\"`);\n }\n\n // The migration is required to ensure the v2 keyring exists.\n await this.ensureMigrated();\n\n // We still try to create the keyring for the Snap here, since we might\n // want to use a new Snap that never had accounts before.\n await this.#ensureKeyringIsReady(snapId);\n\n // Before doing anything with our Snap, we need to make sure the platform\n // is ready to process requests.\n await this.#watcher.ensureCanUseSnapPlatform();\n }\n\n /**\n * Migrate the legacy Snap keyring to the new (per-snap) Snap keyring v2.\n * Expected to be triggered at `KeyringController:unlock` time.\n * Safe to call concurrently — the migration runs only once; all callers\n * await the same promise.\n *\n * @returns A promise that resolves when the migration is complete.\n */\n async ensureMigrated(): Promise<void> {\n if (this.#migrated) {\n return;\n }\n\n if (!this.#migratePromise) {\n this.#migratePromise = this.#migrate()\n .then(() => {\n this.#migrated = true;\n return undefined;\n })\n .catch((error) => {\n // Clear the promise so the next call can retry.\n this.#migratePromise = null;\n throw error;\n });\n }\n\n await this.#migratePromise;\n }\n\n /**\n * Performs the actual migration logic. Should only be called once, and is not\n * safe to call concurrently.\n */\n async #migrate(): Promise<void> {\n await withSafeError('Snap keyring v2 migration', async () =>\n this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const { keyrings } = controller;\n\n const legacySnapKeyringEntry = keyrings.find(({ keyring }) =>\n isLegacySnapKeyring(keyring),\n );\n if (!legacySnapKeyringEntry) {\n log('No legacy Snap keyring found. Migration not required.');\n return;\n }\n\n log('Migration started...');\n\n // The legacy Snap keyring has never been a true `EthKeyring` so we\n // need to cast it to `unknown` first.\n const legacySnapKeyring =\n legacySnapKeyringEntry.keyring as unknown as LegacySnapKeyring;\n\n // Compute the account list for each Snap, grouped by snap ID.\n const states = new Map<SnapId, SnapKeyringState>();\n for (const internalAccount of legacySnapKeyring.listAccounts()) {\n // Convert `InternalAccount` to `KeyringAccount` since the Snap\n // keyring (v2) expects accounts in that format and will verify it\n // with `superstruct` when adding the keyring.\n const { metadata, ...account } = internalAccount;\n\n const snap = metadata?.snap;\n if (snap) {\n const snapId = snap.id as SnapId;\n\n let state = states.get(snapId);\n if (!state) {\n state = { snapId, accounts: {} };\n states.set(snapId, state);\n }\n state.accounts[account.id] = account;\n }\n }\n\n // Create the new Snap keyring (v2) for each Snap and migrate the\n // accounts over.\n for (const state of states.values()) {\n log(`Migrating accounts for Snap \"${state.snapId}\"...`);\n await withSafeError(\n `Adding v2 Snap keyring for \"${state.snapId}\"`,\n async () =>\n controller.addNewKeyring(\n // IMPORTANT: The Snap keyring (v2) can also be used as a v1\n // keyring. So the builder associated with the v2 keyring type\n // is able to build both v1 and v2 keyrings.\n KeyringType.Snap,\n state,\n ),\n );\n }\n\n // Remove the legacy Snap keyring after migration.\n log('Removing legacy Snap keyring...');\n await withSafeError('Removing legacy Snap keyring', async () =>\n controller.removeKeyring(legacySnapKeyringEntry.metadata.id),\n );\n\n log('Migration completed!');\n },\n ),\n );\n }\n\n /**\n * Ensures a Snap keyring is ready for the given Snap. If it doesn't exist yet, it will be created.\n * Safe to call concurrently.\n *\n * @param snapId - The Snap ID to ensure the keyring is ready for.\n */\n async #ensureKeyringIsReady(snapId: SnapId): Promise<void> {\n await this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const hasKeyring = controller.keyrings.some(\n ({ keyringV2 }) =>\n keyringV2 &&\n isSnapKeyring(keyringV2) &&\n keyringV2.snapId === snapId,\n );\n\n if (!hasKeyring) {\n log(`Creating v2 keyring for Snap \"${snapId}\"...`);\n await controller.addNewKeyring(KeyringType.Snap, {\n snapId,\n accounts: {},\n });\n }\n },\n );\n }\n\n /**\n * Shared body for {@link SnapAccountService.#withKeyringV2} and\n * {@link SnapAccountService.#withKeyringV2Unsafe}. Hides the per-Snap\n * filter and the cast back to {@link SnapKeyring} (the messenger action's\n * callback receives a generic `Keyring`; the selector's type predicate\n * doesn't flow through the messenger's generics).\n *\n * @param action - The messenger action to invoke.\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Call<Result>(\n action:\n | 'KeyringController:withKeyringV2'\n | 'KeyringController:withKeyringV2Unsafe',\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#messenger.call(\n action,\n {\n filter: (keyring): keyring is SnapKeyring =>\n isSnapKeyring(keyring) && keyring.snapId === snapId,\n },\n async ({ keyring }) => operation(keyring as SnapKeyring),\n ) as Result;\n }\n\n /**\n * Lock-free variant of {@link SnapAccountService.#withKeyringV2}. Only use\n * for operations that do not mutate keyring or controller state — see\n * `KeyringController.withKeyringV2Unsafe` for the contract.\n *\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Unsafe<Result>(\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#withKeyringV2Call(\n 'KeyringController:withKeyringV2Unsafe',\n snapId,\n operation,\n );\n }\n\n /**\n * Returns the keyring capabilities declared by the given Snap. These are\n * populated by the bridge keyring from the Snap's manifest, and describe\n * which keyring features the Snap supports (scopes, BIP-44 options, etc.).\n *\n * Consumers use this to decide whether to drive the Snap through the v1 or\n * v2 keyring path. Reading capabilities does not mutate state, so the\n * lock-free keyring access is used.\n *\n * @param snapId - ID of the Snap.\n * @returns The Snap's keyring capabilities.\n */\n async getCapabilities(snapId: SnapId): Promise<KeyringCapabilities> {\n return this.#withKeyringV2Unsafe(\n snapId,\n async (keyring) => keyring.capabilities,\n );\n }\n\n /**\n * Returns the CAIP-19 asset type/ID list supported by an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @returns A promise resolving to the list of supported CAIP-19 asset type/IDs.\n */\n async getAccountAssets(\n snapId: SnapId,\n id: AccountId,\n ): Promise<CaipAssetTypeOrId[]> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountAssets(id);\n }\n\n /**\n * Returns the balances for an account for the requested asset types.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param assets - List of CAIP-19 fungible asset types to fetch balances for.\n * @returns A promise resolving to a map of asset type to balance.\n */\n async getAccountBalances(\n snapId: SnapId,\n id: AccountId,\n assets: CaipAssetType[],\n ): Promise<Record<CaipAssetType, Balance>> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountBalances(id, assets);\n }\n\n /**\n * Returns a page of transactions for an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param pagination - Pagination options.\n * @returns A promise resolving to a page of transactions.\n */\n async getAccountTransactions(\n snapId: SnapId,\n id: AccountId,\n pagination: Pagination,\n ): Promise<TransactionsPage> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .getAccountTransactions(id, pagination);\n }\n\n /**\n * Resolves the account address to use for routing a signing request.\n *\n * @param snapId - ID of the Snap.\n * @param scope - CAIP-2 chain ID of the signing request.\n * @param request - The signing JSON-RPC request.\n * @returns A promise resolving to the resolved address, or `null` if the\n * Snap cannot determine an address for this request.\n */\n async resolveAccountAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ): Promise<ResolvedAccountAddress | null> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .resolveAccountAddress(scope, request);\n }\n\n /**\n * Notifies a Snap of the currently selected accounts.\n *\n * For v1 Snaps the call goes through the keyring (signing interface); for\n * v2 Snaps it is routed via the RPC client because the keyring only covers\n * keyring-only operations (signing, account lifecycle).\n *\n * @param snapId - ID of the Snap.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async setSelectedAccounts(\n snapId: SnapId,\n accounts: AccountId[],\n ): Promise<void> {\n await this.ensureReady(snapId);\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n await this.#setSelectedAccountsForKeyring(snapId, keyring, accounts);\n });\n }\n\n /**\n * Dispatches a `setSelectedAccounts` call to the correct layer based on\n * whether the keyring has a v1 interface or not.\n *\n * The keyring is a pure interface for keyring-only operations (signing,\n * account lifecycle). Extra Snap-level methods like `setSelectedAccounts`\n * are invoked via the client for v2 Snaps, which communicates with the Snap\n * over RPC.\n *\n * @param snapId - ID of the Snap.\n * @param keyring - The Snap keyring (v2) instance.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async #setSelectedAccountsForKeyring(\n snapId: SnapId,\n keyring: SnapKeyring,\n accounts: AccountId[],\n ): Promise<void> {\n if (keyring.v1) {\n // We used to keep track of selected accounts in the v1 keyring, so we need to forward the call there for v1 Snaps.\n await keyring.v1.setSelectedAccounts(accounts);\n } else {\n await this.#client.withSnapId(snapId).setSelectedAccounts(accounts);\n }\n }\n\n /**\n * Handle a message from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param message - Message sent by the Snap.\n * @returns The execution result.\n */\n async handleKeyringSnapMessage(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<Json> {\n const { method: event } = message;\n if (isAccountDataUpdatedKeyringEvent(event)) {\n return this.#publishAccountDataUpdatedEvent(snapId, event, message);\n }\n\n // Handle specific methods.\n if (message.method === SnapManageAccountsMethod.GetSelectedAccounts) {\n const groupId = this.#getSelectedAccountGroupId();\n const accounts = this.#getAccountGroup(groupId)?.accounts ?? [];\n\n try {\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) =>\n accounts.filter((id) => keyring.hasAccount(id)),\n );\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n // Some Snaps might be using `getSelectedAccounts` early in their lifecycle, before the keyring is created. So we\n // do not throw in that case to avoid disrupting their initialization process.\n return [];\n }\n\n throw error;\n }\n }\n\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" to its keyring...`,\n );\n\n // We can create a new keyring if the message is an AccountCreated event.\n const isAccountCreatedMessage = event === KeyringEvent.AccountCreated;\n\n // Create the Snap keyring if it doesn't exist yet (in an atomic way). We cannot assume\n // the keyring exists (e.g for the MMI Snap).\n // NOTE: We only auto-create it for v1 account creation flows.\n if (isAccountCreatedMessage) {\n await this.ensureReady(snapId);\n }\n\n // This part of the flow relies on v1 flows, but v2 keyrings are compatible with those messages\n // too.\n try {\n // NOTE: We use \"unsafe\" here since none of the messages should trigger mutations to the keyring state.\n // The exception might be `:accountCreated`, but even in that case, the mutation is handled differently\n // in the client by call `:persistAllKeyrings` explicitly.\n // Using `:withKeyringV2` would cause a deadlock when we're initiating operations like `removeAccount` from\n // the keyring itself:\n // 1: withKeyring(..., ({ keyring }) => { keyring.removeAccount(...) })\n // 2. removeAccount(...) -> handleKeyringSnapMessage(..., { method: 'accountRemoved', ... })\n // 3. handleKeyringSnapMessage tries to acquire the same lock again via withKeyringV2 -> deadlock.\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n if (!keyring.v1) {\n log(\n `Received message \"${event}\" for Snap \"${snapId}\", but that's a v2 keyring... Rejecting.`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring for Snap \"${snapId}\" is v2, not v1.`,\n );\n }\n\n return await keyring.v1.handleKeyringSnapMessage(message);\n });\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n log(\n `No Snap keyring found for Snap \"${snapId}\". Cannot handle message with method \"${event}\".`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring does not exist yet for Snap \"${snapId}\".`,\n );\n }\n\n throw error;\n }\n }\n\n /**\n * Publishes an account data update event from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param event - Account data update event.\n * @param message - Message sent by the Snap.\n * @returns `null`.\n */\n #publishAccountDataUpdatedEvent(\n snapId: SnapId,\n event: AccountDataUpdatedKeyringEvent,\n message: SnapMessage,\n ): null {\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" as a SnapAccountService event...`,\n );\n\n if (event === KeyringEvent.AccountAssetListUpdated) {\n assertStruct(message, AccountAssetListUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountAssetListUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountBalancesUpdated) {\n assertStruct(message, AccountBalancesUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountBalancesUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountTransactionsUpdated) {\n assertStruct(message, AccountTransactionsUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountTransactionsUpdated',\n message.params,\n );\n }\n\n // We need to return a valid JSON value, so we cannot use `undefined` here.\n return null;\n }\n\n // eslint-disable-next-line jsdoc/require-returns\n /**\n * Forwards the accounts of the given account group to the Snap keyring.\n *\n * @param groupId - The ID of the account group whose accounts should be\n * forwarded. If empty, this is a no-op.\n * @param accounts - The accounts to forward. If not defined, this is a no-op.\n */\n async #forwardSelectedAccounts(\n groupId: AccountGroupId | '',\n accounts: AccountId[] | undefined,\n ): Promise<void> {\n const skipping = (reason: string): void =>\n log(`${reason}, skipping forwarding selected accounts to Snap keyring`);\n\n if (!this.#migrated) {\n return skipping('Not migrated yet');\n }\n\n if (!groupId) {\n return skipping('No selected account group');\n }\n\n if (!accounts) {\n return skipping(`Account group (\"${groupId}\") has no accounts`);\n }\n\n const forwardSelectedAccounts = async (): Promise<void> => {\n if (accounts.length) {\n log(\n `Forwarding selected accounts (from \"${groupId}\"): ${accounts.join(', ')}`,\n );\n } else {\n log(`Clearing selected accounts (from \"${groupId}\")`);\n }\n\n await Promise.all(\n this.#tracker.getSnaps().map(async (snapId) => {\n try {\n // We can safely invoke this method without taking the controller lock\n // because it should not mutate the keyring state. So we can use\n // `withKeyringV2Unsafe` in this case.\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n // The group's accounts may belong to several Snaps; only\n // forward the subset this Snap actually owns. An empty\n // subset still gets forwarded to explicitly clear the\n // Snap selected accounts.\n const snapAccounts = accounts.filter((id) =>\n keyring.hasAccount(id),\n );\n await this.#setSelectedAccountsForKeyring(\n snapId,\n keyring,\n snapAccounts,\n );\n });\n } catch (error) {\n // Tracked Snaps without a v2 keyring yet are expected —\n // forwarding will resume on the next event once `ensureReady`\n // has run.\n if (!isKeyringNotFoundError(error)) {\n console.error(\n `Error forwarding selected accounts to Snap \"${snapId}\":`,\n error,\n );\n }\n }\n }),\n );\n };\n\n // There is nothing we can do if forwarding fails. This will auto-recover on the next relevant event.\n return await forwardSelectedAccounts().catch((error) => {\n console.error('Error forwarding selected accounts:', error);\n });\n }\n\n /**\n * Gets the account group object for the given group ID.\n *\n * @param groupId - The ID of the account group.\n * @returns The account group object, or undefined if the group ID is empty or the group does not exist.\n */\n #getAccountGroup(\n groupId: AccountGroupId | '',\n ): AccountGroupObject | undefined {\n if (!groupId) {\n return undefined;\n }\n\n return this.#messenger.call(\n 'AccountTreeController:getAccountGroupObject',\n groupId,\n );\n }\n\n /**\n * Gets the currently selected account group ID.\n *\n * @returns The currently selected account group ID, or an empty string if\n * there is no selected account group.\n */\n #getSelectedAccountGroupId(): AccountGroupId | '' {\n return this.#messenger.call(\n 'AccountTreeController:getSelectedAccountGroup',\n );\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountService.d.cts","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SnapAccountService.d.cts","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountService.d.mts","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SnapAccountService.d.mts","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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"}
@@ -317,7 +317,7 @@ _SnapAccountService_messenger = new WeakMap(), _SnapAccountService_watcher = new
317
317
  void __classPrivateFieldGet(this, _SnapAccountService_instances, "m", _SnapAccountService_forwardSelectedAccounts).call(this, groupId, __classPrivateFieldGet(this, _SnapAccountService_instances, "m", _SnapAccountService_getAccountGroup).call(this, groupId)?.accounts);
318
318
  }, _SnapAccountService_handleUnlock = function _SnapAccountService_handleUnlock() {
319
319
  // eslint-disable-next-line no-void
320
- void withSafeError('Snap keyring v2 migration', () => this.ensureMigrated()).then(async () => {
320
+ void this.ensureMigrated().then(async () => {
321
321
  // If the migration is successful, we re-forward the current groups to each new keyrings!
322
322
  const groupId = __classPrivateFieldGet(this, _SnapAccountService_instances, "m", _SnapAccountService_getSelectedAccountGroupId).call(this);
323
323
  // NOTE: This cannot throw, all errors are swallowed under the hood, so we don't need to
@@ -342,7 +342,7 @@ _SnapAccountService_messenger = new WeakMap(), _SnapAccountService_watcher = new
342
342
  * safe to call concurrently.
343
343
  */
344
344
  async function _SnapAccountService_migrate() {
345
- await __classPrivateFieldGet(this, _SnapAccountService_messenger, "f").call('KeyringController:withController', async (controller) => {
345
+ await withSafeError('Snap keyring v2 migration', async () => __classPrivateFieldGet(this, _SnapAccountService_messenger, "f").call('KeyringController:withController', async (controller) => {
346
346
  const { keyrings } = controller;
347
347
  const legacySnapKeyringEntry = keyrings.find(({ keyring }) => isLegacySnapKeyring(keyring));
348
348
  if (!legacySnapKeyringEntry) {
@@ -385,7 +385,7 @@ async function _SnapAccountService_migrate() {
385
385
  log('Removing legacy Snap keyring...');
386
386
  await withSafeError('Removing legacy Snap keyring', async () => controller.removeKeyring(legacySnapKeyringEntry.metadata.id));
387
387
  log('Migration completed!');
388
- });
388
+ }));
389
389
  }, _SnapAccountService_ensureKeyringIsReady =
390
390
  /**
391
391
  * Ensures a Snap keyring is ready for the given Snap. If it doesn't exist yet, it will be created.
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountService.mjs","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupId } from '@metamask/account-api';\nimport {\n SnapKeyring as LegacySnapKeyring,\n SnapMessage,\n} from '@metamask/eth-snap-keyring';\nimport {\n SnapKeyring,\n SnapKeyringState,\n isSnapKeyring,\n} from '@metamask/eth-snap-keyring/v2';\nimport type {\n AccountAssetListUpdatedEventPayload,\n AccountBalancesUpdatedEventPayload,\n AccountTransactionsUpdatedEventPayload,\n Balance,\n CaipAssetType,\n CaipAssetTypeOrId,\n CaipChainId,\n Pagination,\n ResolvedAccountAddress,\n TransactionsPage,\n} from '@metamask/keyring-api';\nimport {\n AccountAssetListUpdatedEventStruct,\n AccountBalancesUpdatedEventStruct,\n AccountTransactionsUpdatedEventStruct,\n KeyringEvent,\n} from '@metamask/keyring-api';\nimport { KeyringType } from '@metamask/keyring-api/v2';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerStateChangeEvent,\n KeyringControllerUnlockEvent,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringV2Action,\n KeyringControllerWithKeyringV2UnsafeAction,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { KeyringInternalSnapClient } from '@metamask/keyring-internal-snap-client/v2';\nimport { SnapManageAccountsMethod } from '@metamask/keyring-snap-sdk';\nimport type {\n AccountId,\n BaseKeyring,\n JsonRpcRequest,\n} from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n SnapControllerGetRunnableSnapsAction,\n SnapControllerGetSnapAction,\n SnapControllerGetStateAction,\n SnapControllerHandleRequestAction,\n SnapControllerSnapBlockedEvent,\n SnapControllerSnapDisabledEvent,\n SnapControllerSnapEnabledEvent,\n SnapControllerSnapInstalledEvent,\n SnapControllerSnapUnblockedEvent,\n SnapControllerSnapUninstalledEvent,\n SnapControllerStateChangeEvent,\n} from '@metamask/snaps-controllers';\nimport { SnapId } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assertStruct } from '@metamask/utils';\n\nimport { reportError, withSafeError } from './errors.js';\nimport { projectLogger as log } from './logger.js';\nimport type {\n SnapAccountServiceEnsureReadyAction,\n SnapAccountServiceEnsureMigratedAction,\n SnapAccountServiceGetCapabilitiesAction,\n SnapAccountServiceGetAccountAssetsAction,\n SnapAccountServiceGetAccountBalancesAction,\n SnapAccountServiceGetAccountTransactionsAction,\n SnapAccountServiceGetSnapsAction,\n SnapAccountServiceHandleKeyringSnapMessageAction,\n SnapAccountServiceResolveAccountAddressAction,\n SnapAccountServiceSetSelectedAccountsAction,\n} from './SnapAccountService-method-action-types.js';\nimport { SnapPlatformWatcher } from './SnapPlatformWatcher.js';\nimport type { SnapPlatformWatcherConfig } from './SnapPlatformWatcher.js';\nimport { SnapTracker } from './SnapTracker.js';\nimport type {\n AccountTreeControllerGetAccountGroupObjectAction,\n AccountTreeControllerGetSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerAccountGroupCreatedEvent,\n AccountTreeControllerAccountGroupUpdatedEvent,\n AccountTreeControllerAccountGroupRemovedEvent,\n AccountGroupObject,\n} from './types.js';\n\n/**\n * The name of the {@link SnapAccountService}, used to namespace the service's\n * actions and events.\n */\nexport const serviceName = 'SnapAccountService';\n\n/**\n * All of the methods within {@link SnapAccountService} that are exposed via\n * the messenger.\n */\nconst MESSENGER_EXPOSED_METHODS = [\n 'ensureMigrated',\n 'ensureReady',\n 'getCapabilities',\n 'getAccountAssets',\n 'getAccountBalances',\n 'getAccountTransactions',\n 'getSnaps',\n 'handleKeyringSnapMessage',\n 'resolveAccountAddress',\n 'setSelectedAccounts',\n] as const;\n\n/**\n * Actions that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceActions =\n | SnapAccountServiceEnsureMigratedAction\n | SnapAccountServiceEnsureReadyAction\n | SnapAccountServiceGetCapabilitiesAction\n | SnapAccountServiceGetAccountAssetsAction\n | SnapAccountServiceGetAccountBalancesAction\n | SnapAccountServiceGetAccountTransactionsAction\n | SnapAccountServiceGetSnapsAction\n | SnapAccountServiceHandleKeyringSnapMessageAction\n | SnapAccountServiceResolveAccountAddressAction\n | SnapAccountServiceSetSelectedAccountsAction;\n\n/**\n * Actions from other messengers that {@link SnapAccountService} calls.\n */\ntype AllowedActions =\n | SnapControllerGetStateAction\n | SnapControllerGetSnapAction\n | SnapControllerGetRunnableSnapsAction\n | SnapControllerHandleRequestAction\n | KeyringControllerGetStateAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringV2Action\n | KeyringControllerWithKeyringV2UnsafeAction\n | AccountTreeControllerGetAccountGroupObjectAction\n | AccountTreeControllerGetSelectedAccountGroupAction;\n\n/**\n * Events that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceAccountBalancesUpdatedEvent = {\n type: `${typeof serviceName}:accountBalancesUpdated`;\n payload: [AccountBalancesUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountAssetListUpdatedEvent = {\n type: `${typeof serviceName}:accountAssetListUpdated`;\n payload: [AccountAssetListUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountTransactionsUpdatedEvent = {\n type: `${typeof serviceName}:accountTransactionsUpdated`;\n payload: [AccountTransactionsUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceEvents =\n | SnapAccountServiceAccountAssetListUpdatedEvent\n | SnapAccountServiceAccountBalancesUpdatedEvent\n | SnapAccountServiceAccountTransactionsUpdatedEvent;\n\n/**\n * Events from other messengers that {@link SnapAccountService} subscribes to.\n */\ntype AllowedEvents =\n | SnapControllerStateChangeEvent\n | SnapControllerSnapInstalledEvent\n | SnapControllerSnapEnabledEvent\n | SnapControllerSnapDisabledEvent\n | SnapControllerSnapBlockedEvent\n | SnapControllerSnapUnblockedEvent\n | SnapControllerSnapUninstalledEvent\n | KeyringControllerStateChangeEvent\n | KeyringControllerUnlockEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | AccountTreeControllerAccountGroupCreatedEvent\n | AccountTreeControllerAccountGroupUpdatedEvent\n | AccountTreeControllerAccountGroupRemovedEvent;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link SnapAccountService}.\n */\nexport type SnapAccountServiceMessenger = Messenger<\n typeof serviceName,\n SnapAccountServiceActions | AllowedActions,\n SnapAccountServiceEvents | AllowedEvents\n>;\n\n/**\n * Configuration for the {@link SnapAccountService}.\n */\nexport type SnapAccountServiceConfig = {\n snapPlatformWatcher?: SnapPlatformWatcherConfig;\n};\n\n/**\n * The options that {@link SnapAccountService} takes.\n */\nexport type SnapAccountServiceOptions = {\n messenger: SnapAccountServiceMessenger;\n config?: SnapAccountServiceConfig;\n};\n\n/**\n * Checks if a given keyring is a Snap keyring (v2).\n *\n * @param keyring - The keyring to check.\n * @param keyring.type - The type of the keyring.\n * @returns `true` if the keyring is a Snap keyring (v2), `false` otherwise.\n */\nfunction isLegacySnapKeyring(keyring: {\n type: BaseKeyring['type'];\n}): keyring is LegacySnapKeyring {\n return keyring.type === KeyringTypes.snap;\n}\n\n/**\n * Account data update events that can be forwarded from Snaps.\n *\n * These events are then re-emitted by the service for other consumers.\n */\ntype AccountDataUpdatedKeyringEvent =\n | KeyringEvent.AccountAssetListUpdated\n | KeyringEvent.AccountBalancesUpdated\n | KeyringEvent.AccountTransactionsUpdated;\n\n/**\n * Checks if a Snap message method is an account data update event.\n *\n * @param event - The Snap message event.\n * @returns `true` if the method can be forwarded without the legacy Snap keyring.\n */\nfunction isAccountDataUpdatedKeyringEvent(\n event: string,\n): event is AccountDataUpdatedKeyringEvent {\n return (\n event === KeyringEvent.AccountAssetListUpdated ||\n event === KeyringEvent.AccountBalancesUpdated ||\n event === KeyringEvent.AccountTransactionsUpdated\n );\n}\n\n/**\n * Service responsible for managing account management snaps.\n */\nexport class SnapAccountService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n readonly #messenger: SnapAccountServiceMessenger;\n\n readonly #watcher: SnapPlatformWatcher;\n\n readonly #tracker: SnapTracker;\n\n readonly #client: KeyringInternalSnapClient;\n\n #migrated = false;\n\n #migratePromise: Promise<void> | null = null;\n\n /**\n * Constructs a new {@link SnapAccountService}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.config - Optional service configuration.\n */\n constructor({ messenger, config }: SnapAccountServiceOptions) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#watcher = new SnapPlatformWatcher(\n messenger,\n config?.snapPlatformWatcher,\n );\n this.#tracker = new SnapTracker(messenger);\n this.#client = new KeyringInternalSnapClient({\n messenger: messenger.buildChild({\n namespace: 'KeyringInternalSnapClient',\n actions: ['SnapController:handleRequest'],\n }),\n });\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n (groupId) => this.#handleSelectedAccountGroupChange(groupId),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupCreated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupUpdated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupRemoved',\n (groupId) => this.#handleAccountGroupRemoved(groupId),\n );\n\n this.#messenger.subscribe('KeyringController:unlock', () =>\n this.#handleUnlock(),\n );\n }\n\n /**\n * Handles changes to the selected account group by forwarding the new\n * group's accounts to the Snap keyring.\n *\n * @param groupId - The ID of the newly selected account group.\n */\n #handleSelectedAccountGroupChange(groupId: AccountGroupId | ''): void {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n }\n\n /**\n * Handles the keyring controller unlock event by triggering the migration\n * and forwarding the currently selected account group's accounts to the Snap\n * keyring.\n */\n #handleUnlock(): void {\n // eslint-disable-next-line no-void\n void withSafeError('Snap keyring v2 migration', () =>\n this.ensureMigrated(),\n ).then(\n async () => {\n // If the migration is successful, we re-forward the current groups to each new keyrings!\n const groupId = this.#getSelectedAccountGroupId();\n // NOTE: This cannot throw, all errors are swallowed under the hood, so we don't need to\n // catch anything here.\n return await this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n },\n (error) => {\n reportError(this.#messenger, 'Migration failed after unlock', error);\n },\n );\n }\n\n /**\n * Handles created or updated account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the created/updated group is currently selected.\n *\n * @param group - The account group being created or updated.\n */\n #handleAccountGroupCreatedOrUpdated(group: AccountGroupObject): void {\n if (group.id === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(group.id, group.accounts);\n }\n }\n\n /**\n * Handles removed account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the removed group is currently selected.\n *\n * @param groupId - The ID of the account group being removed.\n */\n #handleAccountGroupRemoved(groupId: AccountGroupId): void {\n if (groupId === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n [], // Clearing accounts since the group is removed\n );\n }\n }\n\n /**\n * Returns the IDs of all currently tracked account-management Snaps —\n * Snaps that are installed, enabled, not blocked, and have the\n * `endowment:keyring` permission.\n *\n * @returns The IDs of tracked account-management Snaps.\n */\n getSnaps(): SnapId[] {\n return this.#tracker.getSnaps();\n }\n\n /**\n * Ensures everything is ready to use Snap accounts for the given Snap.\n * 1. Validates that `snapId` is a tracked account-management Snap.\n * 2. Asserts that the legacy -> v2 migration has been triggered (expected to\n * happen at `KeyringController:unlock` time).\n * 3. Atomically creates the v2 keyring for this Snap if it doesn't exist\n * yet.\n * 4. Waits for the Snap platform to be fully started.\n *\n * Safe to call concurrently — each step is idempotent or mutex-protected.\n *\n * @param snapId - ID of the Snap to ensure readiness for.\n * @throws If `snapId` is not a tracked account-management Snap.\n * @throws If the migration has not been triggered yet (wallet not unlocked).\n */\n async ensureReady(snapId: SnapId): Promise<void> {\n if (!this.#tracker.canUse(snapId)) {\n throw new Error(`Unknown snap: \"${snapId}\"`);\n }\n\n // The migration is required to ensure the v2 keyring exists.\n await this.ensureMigrated();\n\n // We still try to create the keyring for the Snap here, since we might\n // want to use a new Snap that never had accounts before.\n await this.#ensureKeyringIsReady(snapId);\n\n // Before doing anything with our Snap, we need to make sure the platform\n // is ready to process requests.\n await this.#watcher.ensureCanUseSnapPlatform();\n }\n\n /**\n * Migrate the legacy Snap keyring to the new (per-snap) Snap keyring v2.\n * Expected to be triggered at `KeyringController:unlock` time.\n * Safe to call concurrently — the migration runs only once; all callers\n * await the same promise.\n *\n * @returns A promise that resolves when the migration is complete.\n */\n async ensureMigrated(): Promise<void> {\n if (this.#migrated) {\n return;\n }\n\n if (!this.#migratePromise) {\n this.#migratePromise = this.#migrate()\n .then(() => {\n this.#migrated = true;\n return undefined;\n })\n .catch((error) => {\n // Clear the promise so the next call can retry.\n this.#migratePromise = null;\n throw error;\n });\n }\n\n await this.#migratePromise;\n }\n\n /**\n * Performs the actual migration logic. Should only be called once, and is not\n * safe to call concurrently.\n */\n async #migrate(): Promise<void> {\n await this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const { keyrings } = controller;\n\n const legacySnapKeyringEntry = keyrings.find(({ keyring }) =>\n isLegacySnapKeyring(keyring),\n );\n if (!legacySnapKeyringEntry) {\n log('No legacy Snap keyring found. Migration not required.');\n return;\n }\n\n log('Migration started...');\n\n // The legacy Snap keyring has never been a true `EthKeyring` so we\n // need to cast it to `unknown` first.\n const legacySnapKeyring =\n legacySnapKeyringEntry.keyring as unknown as LegacySnapKeyring;\n\n // Compute the account list for each Snap, grouped by snap ID.\n const states = new Map<SnapId, SnapKeyringState>();\n for (const internalAccount of legacySnapKeyring.listAccounts()) {\n // Convert `InternalAccount` to `KeyringAccount` since the Snap\n // keyring (v2) expects accounts in that format and will verify it\n // with `superstruct` when adding the keyring.\n const { metadata, ...account } = internalAccount;\n\n const snap = metadata?.snap;\n if (snap) {\n const snapId = snap.id as SnapId;\n\n let state = states.get(snapId);\n if (!state) {\n state = { snapId, accounts: {} };\n states.set(snapId, state);\n }\n state.accounts[account.id] = account;\n }\n }\n\n // Create the new Snap keyring (v2) for each Snap and migrate the\n // accounts over.\n for (const state of states.values()) {\n log(`Migrating accounts for Snap \"${state.snapId}\"...`);\n await withSafeError(\n `Adding v2 Snap keyring for \"${state.snapId}\"`,\n async () =>\n controller.addNewKeyring(\n // IMPORTANT: The Snap keyring (v2) can also be used as a v1\n // keyring. So the builder associated with the v2 keyring type\n // is able to build both v1 and v2 keyrings.\n KeyringType.Snap,\n state,\n ),\n );\n }\n\n // Remove the legacy Snap keyring after migration.\n log('Removing legacy Snap keyring...');\n await withSafeError('Removing legacy Snap keyring', async () =>\n controller.removeKeyring(legacySnapKeyringEntry.metadata.id),\n );\n\n log('Migration completed!');\n },\n );\n }\n\n /**\n * Ensures a Snap keyring is ready for the given Snap. If it doesn't exist yet, it will be created.\n * Safe to call concurrently.\n *\n * @param snapId - The Snap ID to ensure the keyring is ready for.\n */\n async #ensureKeyringIsReady(snapId: SnapId): Promise<void> {\n await this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const hasKeyring = controller.keyrings.some(\n ({ keyringV2 }) =>\n keyringV2 &&\n isSnapKeyring(keyringV2) &&\n keyringV2.snapId === snapId,\n );\n\n if (!hasKeyring) {\n log(`Creating v2 keyring for Snap \"${snapId}\"...`);\n await controller.addNewKeyring(KeyringType.Snap, {\n snapId,\n accounts: {},\n });\n }\n },\n );\n }\n\n /**\n * Shared body for {@link SnapAccountService.#withKeyringV2} and\n * {@link SnapAccountService.#withKeyringV2Unsafe}. Hides the per-Snap\n * filter and the cast back to {@link SnapKeyring} (the messenger action's\n * callback receives a generic `Keyring`; the selector's type predicate\n * doesn't flow through the messenger's generics).\n *\n * @param action - The messenger action to invoke.\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Call<Result>(\n action:\n | 'KeyringController:withKeyringV2'\n | 'KeyringController:withKeyringV2Unsafe',\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#messenger.call(\n action,\n {\n filter: (keyring): keyring is SnapKeyring =>\n isSnapKeyring(keyring) && keyring.snapId === snapId,\n },\n async ({ keyring }) => operation(keyring as SnapKeyring),\n ) as Result;\n }\n\n /**\n * Lock-free variant of {@link SnapAccountService.#withKeyringV2}. Only use\n * for operations that do not mutate keyring or controller state — see\n * `KeyringController.withKeyringV2Unsafe` for the contract.\n *\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Unsafe<Result>(\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#withKeyringV2Call(\n 'KeyringController:withKeyringV2Unsafe',\n snapId,\n operation,\n );\n }\n\n /**\n * Returns the keyring capabilities declared by the given Snap. These are\n * populated by the bridge keyring from the Snap's manifest, and describe\n * which keyring features the Snap supports (scopes, BIP-44 options, etc.).\n *\n * Consumers use this to decide whether to drive the Snap through the v1 or\n * v2 keyring path. Reading capabilities does not mutate state, so the\n * lock-free keyring access is used.\n *\n * @param snapId - ID of the Snap.\n * @returns The Snap's keyring capabilities.\n */\n async getCapabilities(snapId: SnapId): Promise<KeyringCapabilities> {\n return this.#withKeyringV2Unsafe(\n snapId,\n async (keyring) => keyring.capabilities,\n );\n }\n\n /**\n * Returns the CAIP-19 asset type/ID list supported by an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @returns A promise resolving to the list of supported CAIP-19 asset type/IDs.\n */\n async getAccountAssets(\n snapId: SnapId,\n id: AccountId,\n ): Promise<CaipAssetTypeOrId[]> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountAssets(id);\n }\n\n /**\n * Returns the balances for an account for the requested asset types.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param assets - List of CAIP-19 fungible asset types to fetch balances for.\n * @returns A promise resolving to a map of asset type to balance.\n */\n async getAccountBalances(\n snapId: SnapId,\n id: AccountId,\n assets: CaipAssetType[],\n ): Promise<Record<CaipAssetType, Balance>> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountBalances(id, assets);\n }\n\n /**\n * Returns a page of transactions for an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param pagination - Pagination options.\n * @returns A promise resolving to a page of transactions.\n */\n async getAccountTransactions(\n snapId: SnapId,\n id: AccountId,\n pagination: Pagination,\n ): Promise<TransactionsPage> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .getAccountTransactions(id, pagination);\n }\n\n /**\n * Resolves the account address to use for routing a signing request.\n *\n * @param snapId - ID of the Snap.\n * @param scope - CAIP-2 chain ID of the signing request.\n * @param request - The signing JSON-RPC request.\n * @returns A promise resolving to the resolved address, or `null` if the\n * Snap cannot determine an address for this request.\n */\n async resolveAccountAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ): Promise<ResolvedAccountAddress | null> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .resolveAccountAddress(scope, request);\n }\n\n /**\n * Notifies a Snap of the currently selected accounts.\n *\n * For v1 Snaps the call goes through the keyring (signing interface); for\n * v2 Snaps it is routed via the RPC client because the keyring only covers\n * keyring-only operations (signing, account lifecycle).\n *\n * @param snapId - ID of the Snap.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async setSelectedAccounts(\n snapId: SnapId,\n accounts: AccountId[],\n ): Promise<void> {\n await this.ensureReady(snapId);\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n await this.#setSelectedAccountsForKeyring(snapId, keyring, accounts);\n });\n }\n\n /**\n * Dispatches a `setSelectedAccounts` call to the correct layer based on\n * whether the keyring has a v1 interface or not.\n *\n * The keyring is a pure interface for keyring-only operations (signing,\n * account lifecycle). Extra Snap-level methods like `setSelectedAccounts`\n * are invoked via the client for v2 Snaps, which communicates with the Snap\n * over RPC.\n *\n * @param snapId - ID of the Snap.\n * @param keyring - The Snap keyring (v2) instance.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async #setSelectedAccountsForKeyring(\n snapId: SnapId,\n keyring: SnapKeyring,\n accounts: AccountId[],\n ): Promise<void> {\n if (keyring.v1) {\n // We used to keep track of selected accounts in the v1 keyring, so we need to forward the call there for v1 Snaps.\n await keyring.v1.setSelectedAccounts(accounts);\n } else {\n await this.#client.withSnapId(snapId).setSelectedAccounts(accounts);\n }\n }\n\n /**\n * Handle a message from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param message - Message sent by the Snap.\n * @returns The execution result.\n */\n async handleKeyringSnapMessage(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<Json> {\n const { method: event } = message;\n if (isAccountDataUpdatedKeyringEvent(event)) {\n return this.#publishAccountDataUpdatedEvent(snapId, event, message);\n }\n\n // Handle specific methods.\n if (message.method === SnapManageAccountsMethod.GetSelectedAccounts) {\n const groupId = this.#getSelectedAccountGroupId();\n const accounts = this.#getAccountGroup(groupId)?.accounts ?? [];\n\n try {\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) =>\n accounts.filter((id) => keyring.hasAccount(id)),\n );\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n // Some Snaps might be using `getSelectedAccounts` early in their lifecycle, before the keyring is created. So we\n // do not throw in that case to avoid disrupting their initialization process.\n return [];\n }\n\n throw error;\n }\n }\n\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" to its keyring...`,\n );\n\n // We can create a new keyring if the message is an AccountCreated event.\n const isAccountCreatedMessage = event === KeyringEvent.AccountCreated;\n\n // Create the Snap keyring if it doesn't exist yet (in an atomic way). We cannot assume\n // the keyring exists (e.g for the MMI Snap).\n // NOTE: We only auto-create it for v1 account creation flows.\n if (isAccountCreatedMessage) {\n await this.ensureReady(snapId);\n }\n\n // This part of the flow relies on v1 flows, but v2 keyrings are compatible with those messages\n // too.\n try {\n // NOTE: We use \"unsafe\" here since none of the messages should trigger mutations to the keyring state.\n // The exception might be `:accountCreated`, but even in that case, the mutation is handled differently\n // in the client by call `:persistAllKeyrings` explicitly.\n // Using `:withKeyringV2` would cause a deadlock when we're initiating operations like `removeAccount` from\n // the keyring itself:\n // 1: withKeyring(..., ({ keyring }) => { keyring.removeAccount(...) })\n // 2. removeAccount(...) -> handleKeyringSnapMessage(..., { method: 'accountRemoved', ... })\n // 3. handleKeyringSnapMessage tries to acquire the same lock again via withKeyringV2 -> deadlock.\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n if (!keyring.v1) {\n log(\n `Received message \"${event}\" for Snap \"${snapId}\", but that's a v2 keyring... Rejecting.`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring for Snap \"${snapId}\" is v2, not v1.`,\n );\n }\n\n return await keyring.v1.handleKeyringSnapMessage(message);\n });\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n log(\n `No Snap keyring found for Snap \"${snapId}\". Cannot handle message with method \"${event}\".`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring does not exist yet for Snap \"${snapId}\".`,\n );\n }\n\n throw error;\n }\n }\n\n /**\n * Publishes an account data update event from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param event - Account data update event.\n * @param message - Message sent by the Snap.\n * @returns `null`.\n */\n #publishAccountDataUpdatedEvent(\n snapId: SnapId,\n event: AccountDataUpdatedKeyringEvent,\n message: SnapMessage,\n ): null {\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" as a SnapAccountService event...`,\n );\n\n if (event === KeyringEvent.AccountAssetListUpdated) {\n assertStruct(message, AccountAssetListUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountAssetListUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountBalancesUpdated) {\n assertStruct(message, AccountBalancesUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountBalancesUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountTransactionsUpdated) {\n assertStruct(message, AccountTransactionsUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountTransactionsUpdated',\n message.params,\n );\n }\n\n // We need to return a valid JSON value, so we cannot use `undefined` here.\n return null;\n }\n\n // eslint-disable-next-line jsdoc/require-returns\n /**\n * Forwards the accounts of the given account group to the Snap keyring.\n *\n * @param groupId - The ID of the account group whose accounts should be\n * forwarded. If empty, this is a no-op.\n * @param accounts - The accounts to forward. If not defined, this is a no-op.\n */\n async #forwardSelectedAccounts(\n groupId: AccountGroupId | '',\n accounts: AccountId[] | undefined,\n ): Promise<void> {\n const skipping = (reason: string): void =>\n log(`${reason}, skipping forwarding selected accounts to Snap keyring`);\n\n if (!this.#migrated) {\n return skipping('Not migrated yet');\n }\n\n if (!groupId) {\n return skipping('No selected account group');\n }\n\n if (!accounts) {\n return skipping(`Account group (\"${groupId}\") has no accounts`);\n }\n\n const forwardSelectedAccounts = async (): Promise<void> => {\n if (accounts.length) {\n log(\n `Forwarding selected accounts (from \"${groupId}\"): ${accounts.join(', ')}`,\n );\n } else {\n log(`Clearing selected accounts (from \"${groupId}\")`);\n }\n\n await Promise.all(\n this.#tracker.getSnaps().map(async (snapId) => {\n try {\n // We can safely invoke this method without taking the controller lock\n // because it should not mutate the keyring state. So we can use\n // `withKeyringV2Unsafe` in this case.\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n // The group's accounts may belong to several Snaps; only\n // forward the subset this Snap actually owns. An empty\n // subset still gets forwarded to explicitly clear the\n // Snap selected accounts.\n const snapAccounts = accounts.filter((id) =>\n keyring.hasAccount(id),\n );\n await this.#setSelectedAccountsForKeyring(\n snapId,\n keyring,\n snapAccounts,\n );\n });\n } catch (error) {\n // Tracked Snaps without a v2 keyring yet are expected —\n // forwarding will resume on the next event once `ensureReady`\n // has run.\n if (!isKeyringNotFoundError(error)) {\n console.error(\n `Error forwarding selected accounts to Snap \"${snapId}\":`,\n error,\n );\n }\n }\n }),\n );\n };\n\n // There is nothing we can do if forwarding fails. This will auto-recover on the next relevant event.\n return await forwardSelectedAccounts().catch((error) => {\n console.error('Error forwarding selected accounts:', error);\n });\n }\n\n /**\n * Gets the account group object for the given group ID.\n *\n * @param groupId - The ID of the account group.\n * @returns The account group object, or undefined if the group ID is empty or the group does not exist.\n */\n #getAccountGroup(\n groupId: AccountGroupId | '',\n ): AccountGroupObject | undefined {\n if (!groupId) {\n return undefined;\n }\n\n return this.#messenger.call(\n 'AccountTreeController:getAccountGroupObject',\n groupId,\n );\n }\n\n /**\n * Gets the currently selected account group ID.\n *\n * @returns The currently selected account group ID, or an empty string if\n * there is no selected account group.\n */\n #getSelectedAccountGroupId(): AccountGroupId | '' {\n return this.#messenger.call(\n 'AccountTreeController:getSelectedAccountGroup',\n );\n }\n}\n"]}
1
+ {"version":3,"file":"SnapAccountService.mjs","sourceRoot":"","sources":["../src/SnapAccountService.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountGroupId } from '@metamask/account-api';\nimport {\n SnapKeyring as LegacySnapKeyring,\n SnapMessage,\n} from '@metamask/eth-snap-keyring';\nimport {\n SnapKeyring,\n SnapKeyringState,\n isSnapKeyring,\n} from '@metamask/eth-snap-keyring/v2';\nimport type {\n AccountAssetListUpdatedEventPayload,\n AccountBalancesUpdatedEventPayload,\n AccountTransactionsUpdatedEventPayload,\n Balance,\n CaipAssetType,\n CaipAssetTypeOrId,\n CaipChainId,\n Pagination,\n ResolvedAccountAddress,\n TransactionsPage,\n} from '@metamask/keyring-api';\nimport {\n AccountAssetListUpdatedEventStruct,\n AccountBalancesUpdatedEventStruct,\n AccountTransactionsUpdatedEventStruct,\n KeyringEvent,\n} from '@metamask/keyring-api';\nimport { KeyringType } from '@metamask/keyring-api/v2';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerStateChangeEvent,\n KeyringControllerUnlockEvent,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringV2Action,\n KeyringControllerWithKeyringV2UnsafeAction,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { KeyringInternalSnapClient } from '@metamask/keyring-internal-snap-client/v2';\nimport { SnapManageAccountsMethod } from '@metamask/keyring-snap-sdk';\nimport type {\n AccountId,\n BaseKeyring,\n JsonRpcRequest,\n} from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n SnapControllerGetRunnableSnapsAction,\n SnapControllerGetSnapAction,\n SnapControllerGetStateAction,\n SnapControllerHandleRequestAction,\n SnapControllerSnapBlockedEvent,\n SnapControllerSnapDisabledEvent,\n SnapControllerSnapEnabledEvent,\n SnapControllerSnapInstalledEvent,\n SnapControllerSnapUnblockedEvent,\n SnapControllerSnapUninstalledEvent,\n SnapControllerStateChangeEvent,\n} from '@metamask/snaps-controllers';\nimport { SnapId } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assertStruct } from '@metamask/utils';\n\nimport { reportError, withSafeError } from './errors.js';\nimport { projectLogger as log } from './logger.js';\nimport type {\n SnapAccountServiceEnsureReadyAction,\n SnapAccountServiceEnsureMigratedAction,\n SnapAccountServiceGetCapabilitiesAction,\n SnapAccountServiceGetAccountAssetsAction,\n SnapAccountServiceGetAccountBalancesAction,\n SnapAccountServiceGetAccountTransactionsAction,\n SnapAccountServiceGetSnapsAction,\n SnapAccountServiceHandleKeyringSnapMessageAction,\n SnapAccountServiceResolveAccountAddressAction,\n SnapAccountServiceSetSelectedAccountsAction,\n} from './SnapAccountService-method-action-types.js';\nimport { SnapPlatformWatcher } from './SnapPlatformWatcher.js';\nimport type { SnapPlatformWatcherConfig } from './SnapPlatformWatcher.js';\nimport { SnapTracker } from './SnapTracker.js';\nimport type {\n AccountTreeControllerGetAccountGroupObjectAction,\n AccountTreeControllerGetSelectedAccountGroupAction,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerAccountGroupCreatedEvent,\n AccountTreeControllerAccountGroupUpdatedEvent,\n AccountTreeControllerAccountGroupRemovedEvent,\n AccountGroupObject,\n} from './types.js';\n\n/**\n * The name of the {@link SnapAccountService}, used to namespace the service's\n * actions and events.\n */\nexport const serviceName = 'SnapAccountService';\n\n/**\n * All of the methods within {@link SnapAccountService} that are exposed via\n * the messenger.\n */\nconst MESSENGER_EXPOSED_METHODS = [\n 'ensureMigrated',\n 'ensureReady',\n 'getCapabilities',\n 'getAccountAssets',\n 'getAccountBalances',\n 'getAccountTransactions',\n 'getSnaps',\n 'handleKeyringSnapMessage',\n 'resolveAccountAddress',\n 'setSelectedAccounts',\n] as const;\n\n/**\n * Actions that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceActions =\n | SnapAccountServiceEnsureMigratedAction\n | SnapAccountServiceEnsureReadyAction\n | SnapAccountServiceGetCapabilitiesAction\n | SnapAccountServiceGetAccountAssetsAction\n | SnapAccountServiceGetAccountBalancesAction\n | SnapAccountServiceGetAccountTransactionsAction\n | SnapAccountServiceGetSnapsAction\n | SnapAccountServiceHandleKeyringSnapMessageAction\n | SnapAccountServiceResolveAccountAddressAction\n | SnapAccountServiceSetSelectedAccountsAction;\n\n/**\n * Actions from other messengers that {@link SnapAccountService} calls.\n */\ntype AllowedActions =\n | SnapControllerGetStateAction\n | SnapControllerGetSnapAction\n | SnapControllerGetRunnableSnapsAction\n | SnapControllerHandleRequestAction\n | KeyringControllerGetStateAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringV2Action\n | KeyringControllerWithKeyringV2UnsafeAction\n | AccountTreeControllerGetAccountGroupObjectAction\n | AccountTreeControllerGetSelectedAccountGroupAction;\n\n/**\n * Events that {@link SnapAccountService} exposes to other consumers.\n */\nexport type SnapAccountServiceAccountBalancesUpdatedEvent = {\n type: `${typeof serviceName}:accountBalancesUpdated`;\n payload: [AccountBalancesUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountAssetListUpdatedEvent = {\n type: `${typeof serviceName}:accountAssetListUpdated`;\n payload: [AccountAssetListUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceAccountTransactionsUpdatedEvent = {\n type: `${typeof serviceName}:accountTransactionsUpdated`;\n payload: [AccountTransactionsUpdatedEventPayload];\n};\n\nexport type SnapAccountServiceEvents =\n | SnapAccountServiceAccountAssetListUpdatedEvent\n | SnapAccountServiceAccountBalancesUpdatedEvent\n | SnapAccountServiceAccountTransactionsUpdatedEvent;\n\n/**\n * Events from other messengers that {@link SnapAccountService} subscribes to.\n */\ntype AllowedEvents =\n | SnapControllerStateChangeEvent\n | SnapControllerSnapInstalledEvent\n | SnapControllerSnapEnabledEvent\n | SnapControllerSnapDisabledEvent\n | SnapControllerSnapBlockedEvent\n | SnapControllerSnapUnblockedEvent\n | SnapControllerSnapUninstalledEvent\n | KeyringControllerStateChangeEvent\n | KeyringControllerUnlockEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | AccountTreeControllerAccountGroupCreatedEvent\n | AccountTreeControllerAccountGroupUpdatedEvent\n | AccountTreeControllerAccountGroupRemovedEvent;\n\n/**\n * The messenger which is restricted to actions and events accessed by\n * {@link SnapAccountService}.\n */\nexport type SnapAccountServiceMessenger = Messenger<\n typeof serviceName,\n SnapAccountServiceActions | AllowedActions,\n SnapAccountServiceEvents | AllowedEvents\n>;\n\n/**\n * Configuration for the {@link SnapAccountService}.\n */\nexport type SnapAccountServiceConfig = {\n snapPlatformWatcher?: SnapPlatformWatcherConfig;\n};\n\n/**\n * The options that {@link SnapAccountService} takes.\n */\nexport type SnapAccountServiceOptions = {\n messenger: SnapAccountServiceMessenger;\n config?: SnapAccountServiceConfig;\n};\n\n/**\n * Checks if a given keyring is a Snap keyring (v2).\n *\n * @param keyring - The keyring to check.\n * @param keyring.type - The type of the keyring.\n * @returns `true` if the keyring is a Snap keyring (v2), `false` otherwise.\n */\nfunction isLegacySnapKeyring(keyring: {\n type: BaseKeyring['type'];\n}): keyring is LegacySnapKeyring {\n return keyring.type === KeyringTypes.snap;\n}\n\n/**\n * Account data update events that can be forwarded from Snaps.\n *\n * These events are then re-emitted by the service for other consumers.\n */\ntype AccountDataUpdatedKeyringEvent =\n | KeyringEvent.AccountAssetListUpdated\n | KeyringEvent.AccountBalancesUpdated\n | KeyringEvent.AccountTransactionsUpdated;\n\n/**\n * Checks if a Snap message method is an account data update event.\n *\n * @param event - The Snap message event.\n * @returns `true` if the method can be forwarded without the legacy Snap keyring.\n */\nfunction isAccountDataUpdatedKeyringEvent(\n event: string,\n): event is AccountDataUpdatedKeyringEvent {\n return (\n event === KeyringEvent.AccountAssetListUpdated ||\n event === KeyringEvent.AccountBalancesUpdated ||\n event === KeyringEvent.AccountTransactionsUpdated\n );\n}\n\n/**\n * Service responsible for managing account management snaps.\n */\nexport class SnapAccountService {\n /**\n * The name of the service.\n */\n readonly name: typeof serviceName;\n\n readonly #messenger: SnapAccountServiceMessenger;\n\n readonly #watcher: SnapPlatformWatcher;\n\n readonly #tracker: SnapTracker;\n\n readonly #client: KeyringInternalSnapClient;\n\n #migrated = false;\n\n #migratePromise: Promise<void> | null = null;\n\n /**\n * Constructs a new {@link SnapAccountService}.\n *\n * @param args - The constructor arguments.\n * @param args.messenger - The messenger suited for this service.\n * @param args.config - Optional service configuration.\n */\n constructor({ messenger, config }: SnapAccountServiceOptions) {\n this.name = serviceName;\n this.#messenger = messenger;\n this.#watcher = new SnapPlatformWatcher(\n messenger,\n config?.snapPlatformWatcher,\n );\n this.#tracker = new SnapTracker(messenger);\n this.#client = new KeyringInternalSnapClient({\n messenger: messenger.buildChild({\n namespace: 'KeyringInternalSnapClient',\n actions: ['SnapController:handleRequest'],\n }),\n });\n\n this.#messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:selectedAccountGroupChange',\n (groupId) => this.#handleSelectedAccountGroupChange(groupId),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupCreated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupUpdated',\n (group) => this.#handleAccountGroupCreatedOrUpdated(group),\n );\n\n this.#messenger.subscribe(\n 'AccountTreeController:accountGroupRemoved',\n (groupId) => this.#handleAccountGroupRemoved(groupId),\n );\n\n this.#messenger.subscribe('KeyringController:unlock', () =>\n this.#handleUnlock(),\n );\n }\n\n /**\n * Handles changes to the selected account group by forwarding the new\n * group's accounts to the Snap keyring.\n *\n * @param groupId - The ID of the newly selected account group.\n */\n #handleSelectedAccountGroupChange(groupId: AccountGroupId | ''): void {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n }\n\n /**\n * Handles the keyring controller unlock event by triggering the migration\n * and forwarding the currently selected account group's accounts to the Snap\n * keyring.\n */\n #handleUnlock(): void {\n // eslint-disable-next-line no-void\n void this.ensureMigrated().then(\n async () => {\n // If the migration is successful, we re-forward the current groups to each new keyrings!\n const groupId = this.#getSelectedAccountGroupId();\n // NOTE: This cannot throw, all errors are swallowed under the hood, so we don't need to\n // catch anything here.\n return await this.#forwardSelectedAccounts(\n groupId,\n this.#getAccountGroup(groupId)?.accounts,\n );\n },\n (error) => {\n reportError(this.#messenger, 'Migration failed after unlock', error);\n },\n );\n }\n\n /**\n * Handles created or updated account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the created/updated group is currently selected.\n *\n * @param group - The account group being created or updated.\n */\n #handleAccountGroupCreatedOrUpdated(group: AccountGroupObject): void {\n if (group.id === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(group.id, group.accounts);\n }\n }\n\n /**\n * Handles removed account groups by forwarding the accounts of the currently\n * selected account group to the Snap keyring, if the removed group is currently selected.\n *\n * @param groupId - The ID of the account group being removed.\n */\n #handleAccountGroupRemoved(groupId: AccountGroupId): void {\n if (groupId === this.#getSelectedAccountGroupId()) {\n // eslint-disable-next-line no-void\n void this.#forwardSelectedAccounts(\n groupId,\n [], // Clearing accounts since the group is removed\n );\n }\n }\n\n /**\n * Returns the IDs of all currently tracked account-management Snaps —\n * Snaps that are installed, enabled, not blocked, and have the\n * `endowment:keyring` permission.\n *\n * @returns The IDs of tracked account-management Snaps.\n */\n getSnaps(): SnapId[] {\n return this.#tracker.getSnaps();\n }\n\n /**\n * Ensures everything is ready to use Snap accounts for the given Snap.\n * 1. Validates that `snapId` is a tracked account-management Snap.\n * 2. Asserts that the legacy -> v2 migration has been triggered (expected to\n * happen at `KeyringController:unlock` time).\n * 3. Atomically creates the v2 keyring for this Snap if it doesn't exist\n * yet.\n * 4. Waits for the Snap platform to be fully started.\n *\n * Safe to call concurrently — each step is idempotent or mutex-protected.\n *\n * @param snapId - ID of the Snap to ensure readiness for.\n * @throws If `snapId` is not a tracked account-management Snap.\n * @throws If the migration has not been triggered yet (wallet not unlocked).\n */\n async ensureReady(snapId: SnapId): Promise<void> {\n if (!this.#tracker.canUse(snapId)) {\n throw new Error(`Unknown snap: \"${snapId}\"`);\n }\n\n // The migration is required to ensure the v2 keyring exists.\n await this.ensureMigrated();\n\n // We still try to create the keyring for the Snap here, since we might\n // want to use a new Snap that never had accounts before.\n await this.#ensureKeyringIsReady(snapId);\n\n // Before doing anything with our Snap, we need to make sure the platform\n // is ready to process requests.\n await this.#watcher.ensureCanUseSnapPlatform();\n }\n\n /**\n * Migrate the legacy Snap keyring to the new (per-snap) Snap keyring v2.\n * Expected to be triggered at `KeyringController:unlock` time.\n * Safe to call concurrently — the migration runs only once; all callers\n * await the same promise.\n *\n * @returns A promise that resolves when the migration is complete.\n */\n async ensureMigrated(): Promise<void> {\n if (this.#migrated) {\n return;\n }\n\n if (!this.#migratePromise) {\n this.#migratePromise = this.#migrate()\n .then(() => {\n this.#migrated = true;\n return undefined;\n })\n .catch((error) => {\n // Clear the promise so the next call can retry.\n this.#migratePromise = null;\n throw error;\n });\n }\n\n await this.#migratePromise;\n }\n\n /**\n * Performs the actual migration logic. Should only be called once, and is not\n * safe to call concurrently.\n */\n async #migrate(): Promise<void> {\n await withSafeError('Snap keyring v2 migration', async () =>\n this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const { keyrings } = controller;\n\n const legacySnapKeyringEntry = keyrings.find(({ keyring }) =>\n isLegacySnapKeyring(keyring),\n );\n if (!legacySnapKeyringEntry) {\n log('No legacy Snap keyring found. Migration not required.');\n return;\n }\n\n log('Migration started...');\n\n // The legacy Snap keyring has never been a true `EthKeyring` so we\n // need to cast it to `unknown` first.\n const legacySnapKeyring =\n legacySnapKeyringEntry.keyring as unknown as LegacySnapKeyring;\n\n // Compute the account list for each Snap, grouped by snap ID.\n const states = new Map<SnapId, SnapKeyringState>();\n for (const internalAccount of legacySnapKeyring.listAccounts()) {\n // Convert `InternalAccount` to `KeyringAccount` since the Snap\n // keyring (v2) expects accounts in that format and will verify it\n // with `superstruct` when adding the keyring.\n const { metadata, ...account } = internalAccount;\n\n const snap = metadata?.snap;\n if (snap) {\n const snapId = snap.id as SnapId;\n\n let state = states.get(snapId);\n if (!state) {\n state = { snapId, accounts: {} };\n states.set(snapId, state);\n }\n state.accounts[account.id] = account;\n }\n }\n\n // Create the new Snap keyring (v2) for each Snap and migrate the\n // accounts over.\n for (const state of states.values()) {\n log(`Migrating accounts for Snap \"${state.snapId}\"...`);\n await withSafeError(\n `Adding v2 Snap keyring for \"${state.snapId}\"`,\n async () =>\n controller.addNewKeyring(\n // IMPORTANT: The Snap keyring (v2) can also be used as a v1\n // keyring. So the builder associated with the v2 keyring type\n // is able to build both v1 and v2 keyrings.\n KeyringType.Snap,\n state,\n ),\n );\n }\n\n // Remove the legacy Snap keyring after migration.\n log('Removing legacy Snap keyring...');\n await withSafeError('Removing legacy Snap keyring', async () =>\n controller.removeKeyring(legacySnapKeyringEntry.metadata.id),\n );\n\n log('Migration completed!');\n },\n ),\n );\n }\n\n /**\n * Ensures a Snap keyring is ready for the given Snap. If it doesn't exist yet, it will be created.\n * Safe to call concurrently.\n *\n * @param snapId - The Snap ID to ensure the keyring is ready for.\n */\n async #ensureKeyringIsReady(snapId: SnapId): Promise<void> {\n await this.#messenger.call(\n 'KeyringController:withController',\n async (controller) => {\n const hasKeyring = controller.keyrings.some(\n ({ keyringV2 }) =>\n keyringV2 &&\n isSnapKeyring(keyringV2) &&\n keyringV2.snapId === snapId,\n );\n\n if (!hasKeyring) {\n log(`Creating v2 keyring for Snap \"${snapId}\"...`);\n await controller.addNewKeyring(KeyringType.Snap, {\n snapId,\n accounts: {},\n });\n }\n },\n );\n }\n\n /**\n * Shared body for {@link SnapAccountService.#withKeyringV2} and\n * {@link SnapAccountService.#withKeyringV2Unsafe}. Hides the per-Snap\n * filter and the cast back to {@link SnapKeyring} (the messenger action's\n * callback receives a generic `Keyring`; the selector's type predicate\n * doesn't flow through the messenger's generics).\n *\n * @param action - The messenger action to invoke.\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Call<Result>(\n action:\n | 'KeyringController:withKeyringV2'\n | 'KeyringController:withKeyringV2Unsafe',\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#messenger.call(\n action,\n {\n filter: (keyring): keyring is SnapKeyring =>\n isSnapKeyring(keyring) && keyring.snapId === snapId,\n },\n async ({ keyring }) => operation(keyring as SnapKeyring),\n ) as Result;\n }\n\n /**\n * Lock-free variant of {@link SnapAccountService.#withKeyringV2}. Only use\n * for operations that do not mutate keyring or controller state — see\n * `KeyringController.withKeyringV2Unsafe` for the contract.\n *\n * @param snapId - The Snap ID to look up the keyring for.\n * @param operation - The operation to run with the matching keyring.\n * @returns The result of the operation.\n */\n async #withKeyringV2Unsafe<Result>(\n snapId: SnapId,\n operation: (keyring: SnapKeyring) => Promise<Result>,\n ): Promise<Result> {\n return this.#withKeyringV2Call(\n 'KeyringController:withKeyringV2Unsafe',\n snapId,\n operation,\n );\n }\n\n /**\n * Returns the keyring capabilities declared by the given Snap. These are\n * populated by the bridge keyring from the Snap's manifest, and describe\n * which keyring features the Snap supports (scopes, BIP-44 options, etc.).\n *\n * Consumers use this to decide whether to drive the Snap through the v1 or\n * v2 keyring path. Reading capabilities does not mutate state, so the\n * lock-free keyring access is used.\n *\n * @param snapId - ID of the Snap.\n * @returns The Snap's keyring capabilities.\n */\n async getCapabilities(snapId: SnapId): Promise<KeyringCapabilities> {\n return this.#withKeyringV2Unsafe(\n snapId,\n async (keyring) => keyring.capabilities,\n );\n }\n\n /**\n * Returns the CAIP-19 asset type/ID list supported by an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @returns A promise resolving to the list of supported CAIP-19 asset type/IDs.\n */\n async getAccountAssets(\n snapId: SnapId,\n id: AccountId,\n ): Promise<CaipAssetTypeOrId[]> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountAssets(id);\n }\n\n /**\n * Returns the balances for an account for the requested asset types.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param assets - List of CAIP-19 fungible asset types to fetch balances for.\n * @returns A promise resolving to a map of asset type to balance.\n */\n async getAccountBalances(\n snapId: SnapId,\n id: AccountId,\n assets: CaipAssetType[],\n ): Promise<Record<CaipAssetType, Balance>> {\n await this.ensureReady(snapId);\n return this.#client.withSnapId(snapId).getAccountBalances(id, assets);\n }\n\n /**\n * Returns a page of transactions for an account.\n *\n * @param snapId - ID of the Snap.\n * @param id - ID of the account.\n * @param pagination - Pagination options.\n * @returns A promise resolving to a page of transactions.\n */\n async getAccountTransactions(\n snapId: SnapId,\n id: AccountId,\n pagination: Pagination,\n ): Promise<TransactionsPage> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .getAccountTransactions(id, pagination);\n }\n\n /**\n * Resolves the account address to use for routing a signing request.\n *\n * @param snapId - ID of the Snap.\n * @param scope - CAIP-2 chain ID of the signing request.\n * @param request - The signing JSON-RPC request.\n * @returns A promise resolving to the resolved address, or `null` if the\n * Snap cannot determine an address for this request.\n */\n async resolveAccountAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ): Promise<ResolvedAccountAddress | null> {\n await this.ensureReady(snapId);\n return this.#client\n .withSnapId(snapId)\n .resolveAccountAddress(scope, request);\n }\n\n /**\n * Notifies a Snap of the currently selected accounts.\n *\n * For v1 Snaps the call goes through the keyring (signing interface); for\n * v2 Snaps it is routed via the RPC client because the keyring only covers\n * keyring-only operations (signing, account lifecycle).\n *\n * @param snapId - ID of the Snap.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async setSelectedAccounts(\n snapId: SnapId,\n accounts: AccountId[],\n ): Promise<void> {\n await this.ensureReady(snapId);\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n await this.#setSelectedAccountsForKeyring(snapId, keyring, accounts);\n });\n }\n\n /**\n * Dispatches a `setSelectedAccounts` call to the correct layer based on\n * whether the keyring has a v1 interface or not.\n *\n * The keyring is a pure interface for keyring-only operations (signing,\n * account lifecycle). Extra Snap-level methods like `setSelectedAccounts`\n * are invoked via the client for v2 Snaps, which communicates with the Snap\n * over RPC.\n *\n * @param snapId - ID of the Snap.\n * @param keyring - The Snap keyring (v2) instance.\n * @param accounts - IDs of the accounts to mark as selected.\n */\n async #setSelectedAccountsForKeyring(\n snapId: SnapId,\n keyring: SnapKeyring,\n accounts: AccountId[],\n ): Promise<void> {\n if (keyring.v1) {\n // We used to keep track of selected accounts in the v1 keyring, so we need to forward the call there for v1 Snaps.\n await keyring.v1.setSelectedAccounts(accounts);\n } else {\n await this.#client.withSnapId(snapId).setSelectedAccounts(accounts);\n }\n }\n\n /**\n * Handle a message from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param message - Message sent by the Snap.\n * @returns The execution result.\n */\n async handleKeyringSnapMessage(\n snapId: SnapId,\n message: SnapMessage,\n ): Promise<Json> {\n const { method: event } = message;\n if (isAccountDataUpdatedKeyringEvent(event)) {\n return this.#publishAccountDataUpdatedEvent(snapId, event, message);\n }\n\n // Handle specific methods.\n if (message.method === SnapManageAccountsMethod.GetSelectedAccounts) {\n const groupId = this.#getSelectedAccountGroupId();\n const accounts = this.#getAccountGroup(groupId)?.accounts ?? [];\n\n try {\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) =>\n accounts.filter((id) => keyring.hasAccount(id)),\n );\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n // Some Snaps might be using `getSelectedAccounts` early in their lifecycle, before the keyring is created. So we\n // do not throw in that case to avoid disrupting their initialization process.\n return [];\n }\n\n throw error;\n }\n }\n\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" to its keyring...`,\n );\n\n // We can create a new keyring if the message is an AccountCreated event.\n const isAccountCreatedMessage = event === KeyringEvent.AccountCreated;\n\n // Create the Snap keyring if it doesn't exist yet (in an atomic way). We cannot assume\n // the keyring exists (e.g for the MMI Snap).\n // NOTE: We only auto-create it for v1 account creation flows.\n if (isAccountCreatedMessage) {\n await this.ensureReady(snapId);\n }\n\n // This part of the flow relies on v1 flows, but v2 keyrings are compatible with those messages\n // too.\n try {\n // NOTE: We use \"unsafe\" here since none of the messages should trigger mutations to the keyring state.\n // The exception might be `:accountCreated`, but even in that case, the mutation is handled differently\n // in the client by call `:persistAllKeyrings` explicitly.\n // Using `:withKeyringV2` would cause a deadlock when we're initiating operations like `removeAccount` from\n // the keyring itself:\n // 1: withKeyring(..., ({ keyring }) => { keyring.removeAccount(...) })\n // 2. removeAccount(...) -> handleKeyringSnapMessage(..., { method: 'accountRemoved', ... })\n // 3. handleKeyringSnapMessage tries to acquire the same lock again via withKeyringV2 -> deadlock.\n return await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n if (!keyring.v1) {\n log(\n `Received message \"${event}\" for Snap \"${snapId}\", but that's a v2 keyring... Rejecting.`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring for Snap \"${snapId}\" is v2, not v1.`,\n );\n }\n\n return await keyring.v1.handleKeyringSnapMessage(message);\n });\n } catch (error) {\n if (isKeyringNotFoundError(error)) {\n log(\n `No Snap keyring found for Snap \"${snapId}\". Cannot handle message with method \"${event}\".`,\n );\n\n throw new Error(\n `Cannot delegate keyring Snap message, keyring does not exist yet for Snap \"${snapId}\".`,\n );\n }\n\n throw error;\n }\n }\n\n /**\n * Publishes an account data update event from a Snap.\n *\n * @param snapId - ID of the Snap.\n * @param event - Account data update event.\n * @param message - Message sent by the Snap.\n * @returns `null`.\n */\n #publishAccountDataUpdatedEvent(\n snapId: SnapId,\n event: AccountDataUpdatedKeyringEvent,\n message: SnapMessage,\n ): null {\n log(\n `Forwarding message \"${event}\" from Snap \"${snapId}\" as a SnapAccountService event...`,\n );\n\n if (event === KeyringEvent.AccountAssetListUpdated) {\n assertStruct(message, AccountAssetListUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountAssetListUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountBalancesUpdated) {\n assertStruct(message, AccountBalancesUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountBalancesUpdated',\n message.params,\n );\n } else if (event === KeyringEvent.AccountTransactionsUpdated) {\n assertStruct(message, AccountTransactionsUpdatedEventStruct);\n this.#messenger.publish(\n 'SnapAccountService:accountTransactionsUpdated',\n message.params,\n );\n }\n\n // We need to return a valid JSON value, so we cannot use `undefined` here.\n return null;\n }\n\n // eslint-disable-next-line jsdoc/require-returns\n /**\n * Forwards the accounts of the given account group to the Snap keyring.\n *\n * @param groupId - The ID of the account group whose accounts should be\n * forwarded. If empty, this is a no-op.\n * @param accounts - The accounts to forward. If not defined, this is a no-op.\n */\n async #forwardSelectedAccounts(\n groupId: AccountGroupId | '',\n accounts: AccountId[] | undefined,\n ): Promise<void> {\n const skipping = (reason: string): void =>\n log(`${reason}, skipping forwarding selected accounts to Snap keyring`);\n\n if (!this.#migrated) {\n return skipping('Not migrated yet');\n }\n\n if (!groupId) {\n return skipping('No selected account group');\n }\n\n if (!accounts) {\n return skipping(`Account group (\"${groupId}\") has no accounts`);\n }\n\n const forwardSelectedAccounts = async (): Promise<void> => {\n if (accounts.length) {\n log(\n `Forwarding selected accounts (from \"${groupId}\"): ${accounts.join(', ')}`,\n );\n } else {\n log(`Clearing selected accounts (from \"${groupId}\")`);\n }\n\n await Promise.all(\n this.#tracker.getSnaps().map(async (snapId) => {\n try {\n // We can safely invoke this method without taking the controller lock\n // because it should not mutate the keyring state. So we can use\n // `withKeyringV2Unsafe` in this case.\n await this.#withKeyringV2Unsafe(snapId, async (keyring) => {\n // The group's accounts may belong to several Snaps; only\n // forward the subset this Snap actually owns. An empty\n // subset still gets forwarded to explicitly clear the\n // Snap selected accounts.\n const snapAccounts = accounts.filter((id) =>\n keyring.hasAccount(id),\n );\n await this.#setSelectedAccountsForKeyring(\n snapId,\n keyring,\n snapAccounts,\n );\n });\n } catch (error) {\n // Tracked Snaps without a v2 keyring yet are expected —\n // forwarding will resume on the next event once `ensureReady`\n // has run.\n if (!isKeyringNotFoundError(error)) {\n console.error(\n `Error forwarding selected accounts to Snap \"${snapId}\":`,\n error,\n );\n }\n }\n }),\n );\n };\n\n // There is nothing we can do if forwarding fails. This will auto-recover on the next relevant event.\n return await forwardSelectedAccounts().catch((error) => {\n console.error('Error forwarding selected accounts:', error);\n });\n }\n\n /**\n * Gets the account group object for the given group ID.\n *\n * @param groupId - The ID of the account group.\n * @returns The account group object, or undefined if the group ID is empty or the group does not exist.\n */\n #getAccountGroup(\n groupId: AccountGroupId | '',\n ): AccountGroupObject | undefined {\n if (!groupId) {\n return undefined;\n }\n\n return this.#messenger.call(\n 'AccountTreeController:getAccountGroupObject',\n groupId,\n );\n }\n\n /**\n * Gets the currently selected account group ID.\n *\n * @returns The currently selected account group ID, or an empty string if\n * there is no selected account group.\n */\n #getSelectedAccountGroupId(): AccountGroupId | '' {\n return this.#messenger.call(\n 'AccountTreeController:getSelectedAccountGroup',\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/snap-account-service",
3
- "version": "2.1.0-preview-a42e8d0d2",
3
+ "version": "2.1.1-preview-d2f661012",
4
4
  "description": "Service for Account Management Snaps",
5
5
  "keywords": [
6
6
  "Ethereum",