@metamask/multichain-account-service 10.0.2 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/dist/MultichainAccountGroup.cjs +15 -0
  3. package/dist/MultichainAccountGroup.cjs.map +1 -1
  4. package/dist/MultichainAccountGroup.d.cts +10 -0
  5. package/dist/MultichainAccountGroup.d.cts.map +1 -1
  6. package/dist/MultichainAccountGroup.d.mts +10 -0
  7. package/dist/MultichainAccountGroup.d.mts.map +1 -1
  8. package/dist/MultichainAccountGroup.mjs +15 -0
  9. package/dist/MultichainAccountGroup.mjs.map +1 -1
  10. package/dist/MultichainAccountService-method-action-types.cjs.map +1 -1
  11. package/dist/MultichainAccountService-method-action-types.d.cts +10 -6
  12. package/dist/MultichainAccountService-method-action-types.d.cts.map +1 -1
  13. package/dist/MultichainAccountService-method-action-types.d.mts +10 -6
  14. package/dist/MultichainAccountService-method-action-types.d.mts.map +1 -1
  15. package/dist/MultichainAccountService-method-action-types.mjs.map +1 -1
  16. package/dist/MultichainAccountService.cjs +67 -8
  17. package/dist/MultichainAccountService.cjs.map +1 -1
  18. package/dist/MultichainAccountService.d.cts +31 -7
  19. package/dist/MultichainAccountService.d.cts.map +1 -1
  20. package/dist/MultichainAccountService.d.mts +31 -7
  21. package/dist/MultichainAccountService.d.mts.map +1 -1
  22. package/dist/MultichainAccountService.mjs +67 -8
  23. package/dist/MultichainAccountService.mjs.map +1 -1
  24. package/dist/MultichainAccountWallet.cjs +20 -0
  25. package/dist/MultichainAccountWallet.cjs.map +1 -1
  26. package/dist/MultichainAccountWallet.d.cts +10 -0
  27. package/dist/MultichainAccountWallet.d.cts.map +1 -1
  28. package/dist/MultichainAccountWallet.d.mts +10 -0
  29. package/dist/MultichainAccountWallet.d.mts.map +1 -1
  30. package/dist/MultichainAccountWallet.mjs +20 -0
  31. package/dist/MultichainAccountWallet.mjs.map +1 -1
  32. package/dist/providers/AccountProviderWrapper.cjs +43 -0
  33. package/dist/providers/AccountProviderWrapper.cjs.map +1 -1
  34. package/dist/providers/AccountProviderWrapper.d.cts +37 -0
  35. package/dist/providers/AccountProviderWrapper.d.cts.map +1 -1
  36. package/dist/providers/AccountProviderWrapper.d.mts +37 -0
  37. package/dist/providers/AccountProviderWrapper.d.mts.map +1 -1
  38. package/dist/providers/AccountProviderWrapper.mjs +43 -0
  39. package/dist/providers/AccountProviderWrapper.mjs.map +1 -1
  40. package/dist/providers/BaseBip44AccountProvider.cjs +3 -18
  41. package/dist/providers/BaseBip44AccountProvider.cjs.map +1 -1
  42. package/dist/providers/BaseBip44AccountProvider.d.cts +36 -16
  43. package/dist/providers/BaseBip44AccountProvider.d.cts.map +1 -1
  44. package/dist/providers/BaseBip44AccountProvider.d.mts +36 -16
  45. package/dist/providers/BaseBip44AccountProvider.d.mts.map +1 -1
  46. package/dist/providers/BaseBip44AccountProvider.mjs +3 -18
  47. package/dist/providers/BaseBip44AccountProvider.mjs.map +1 -1
  48. package/dist/providers/EvmAccountProvider.cjs +19 -0
  49. package/dist/providers/EvmAccountProvider.cjs.map +1 -1
  50. package/dist/providers/EvmAccountProvider.d.cts +12 -0
  51. package/dist/providers/EvmAccountProvider.d.cts.map +1 -1
  52. package/dist/providers/EvmAccountProvider.d.mts +12 -0
  53. package/dist/providers/EvmAccountProvider.d.mts.map +1 -1
  54. package/dist/providers/EvmAccountProvider.mjs +19 -0
  55. package/dist/providers/EvmAccountProvider.mjs.map +1 -1
  56. package/dist/providers/SnapAccountProvider.cjs +28 -11
  57. package/dist/providers/SnapAccountProvider.cjs.map +1 -1
  58. package/dist/providers/SnapAccountProvider.d.cts +16 -4
  59. package/dist/providers/SnapAccountProvider.d.cts.map +1 -1
  60. package/dist/providers/SnapAccountProvider.d.mts +16 -4
  61. package/dist/providers/SnapAccountProvider.d.mts.map +1 -1
  62. package/dist/providers/SnapAccountProvider.mjs +28 -11
  63. package/dist/providers/SnapAccountProvider.mjs.map +1 -1
  64. package/dist/tests/providers.cjs +4 -0
  65. package/dist/tests/providers.cjs.map +1 -1
  66. package/dist/tests/providers.d.cts +2 -0
  67. package/dist/tests/providers.d.cts.map +1 -1
  68. package/dist/tests/providers.d.mts +2 -0
  69. package/dist/tests/providers.d.mts.map +1 -1
  70. package/dist/tests/providers.mjs +4 -0
  71. package/dist/tests/providers.mjs.map +1 -1
  72. package/dist/utils.cjs.map +1 -1
  73. package/dist/utils.d.cts +14 -1
  74. package/dist/utils.d.cts.map +1 -1
  75. package/dist/utils.d.mts +14 -1
  76. package/dist/utils.d.mts.map +1 -1
  77. package/dist/utils.mjs.map +1 -1
  78. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountProvider.cjs","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsBip44Account } from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback, TraceRequest } from '@metamask/controller-utils';\nimport type { SnapKeyring } from '@metamask/eth-snap-keyring';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n} from '@metamask/keyring-api';\nimport type {\n CreateAccountBip44DeriveIndexOptions,\n CreateAccountBip44DeriveIndexRangeOptions,\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport type { KeyringMetadata } from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Semaphore } from 'async-mutex';\n\nimport {\n toCreateAccountsV2DataTraces,\n traceFallback,\n TraceName,\n} from '../analytics';\nimport { reportError } from '../errors';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { BaseBip44AccountProvider } from './BaseBip44AccountProvider';\nimport { withTimeout } from './utils';\n\nexport type RestrictedSnapKeyring = {\n createAccount: (options: Record<string, Json>) => Promise<KeyringAccount>;\n createAccounts: (options: CreateAccountOptions) => Promise<KeyringAccount[]>;\n removeAccount: (address: string) => Promise<void>;\n};\n\nexport type SnapAccountProviderConfig = {\n maxConcurrency?: number;\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n createAccounts: {\n /**\n * Whether to enable account batching with `createAccounts` method. If `true`, accounts will\n * be created in batch.\n *\n * NOTE: The Snap has to implement this optional method for batching support.\n * Defaults to `false`.\n */\n batched: boolean;\n /**\n * Timeout for account creation operations.\n *\n * NOTE: The value might have to be adapted in case batching is enabled!\n */\n timeoutMs: number;\n };\n resyncAccounts?: {\n /**\n * Whether to automatically remove extra Snap accounts when the Snap has\n * more accounts than MetaMask. If `false`, a warning is logged instead.\n * Defaults to `true`.\n */\n autoRemoveExtraSnapAccounts?: boolean;\n };\n};\n\nexport abstract class SnapAccountProvider extends BaseBip44AccountProvider {\n readonly snapId: SnapId;\n\n protected readonly config: SnapAccountProviderConfig;\n\n readonly #client: KeyringClient;\n\n readonly #queue?: Semaphore;\n\n readonly #trace: TraceCallback;\n\n constructor(\n snapId: SnapId,\n messenger: MultichainAccountServiceMessenger,\n config: SnapAccountProviderConfig,\n /* istanbul ignore next */\n trace: TraceCallback = traceFallback,\n ) {\n super(messenger);\n\n this.snapId = snapId;\n this.#client = this.#getKeyringClientFromSnapId(snapId);\n\n const maxConcurrency = config.maxConcurrency ?? Infinity;\n this.config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n maxConcurrency,\n };\n\n // Create semaphore only if concurrency is limited\n if (isFinite(maxConcurrency)) {\n this.#queue = new Semaphore(maxConcurrency);\n }\n\n this.#trace = trace;\n }\n\n /**\n * Ensures that the Snap is ready to be used.\n *\n * @returns A promise that resolves when the Snap is ready.\n * @throws An error if the Snap could not become ready.\n */\n async ensureReady(): Promise<void> {\n return this.messenger.call('SnapAccountService:ensureReady', this.snapId);\n }\n\n /**\n * Wraps an async operation with concurrency limiting based on maxConcurrency config.\n * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling.\n * Otherwise, it's queued through the semaphore to respect the concurrency limit.\n *\n * @param operation - The async operation to execute.\n * @returns The result of the operation.\n */\n protected async withMaxConcurrency<Result>(\n operation: () => Promise<Result>,\n ): Promise<Result> {\n if (this.#queue) {\n return this.#queue.runExclusive(operation);\n }\n return operation();\n }\n\n protected async trace<ReturnType>(\n request: TraceRequest,\n fn: () => Promise<ReturnType>,\n ): Promise<ReturnType> {\n return this.#trace(request, fn);\n }\n\n async #getRestrictedSnapKeyring(): Promise<RestrictedSnapKeyring> {\n // NOTE: We're not supposed to make the keyring instance escape `withKeyring` but\n // we have to use the `SnapKeyring` instance to be able to create Solana account\n // without triggering UI confirmation.\n // Also, creating account that way won't invalidate the Snap keyring state. The\n // account will get created and persisted properly with the Snap account creation\n // flow \"asynchronously\" (with `notify:accountCreated`).\n const { createAccount, createAccounts } = await this.#withSnapKeyring<{\n createAccount: SnapKeyring['createAccount'];\n createAccounts: SnapKeyring['createAccounts'];\n }>(async ({ keyring }) => ({\n createAccount: keyring.createAccount.bind(keyring),\n createAccounts: keyring.createAccounts.bind(keyring),\n }));\n\n return {\n createAccount: async (options) =>\n // We use the \"unguarded\" account creation here (see explanation above).\n await createAccount(this.snapId, options, {\n displayAccountNameSuggestion: false,\n displayConfirmation: false,\n setSelectedAccount: false,\n }),\n createAccounts: async (options) =>\n await createAccounts(this.snapId, options),\n removeAccount: async (address: string) =>\n // Though, when removing account, we can use the normal flow.\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.removeAccount(address);\n }),\n };\n }\n\n #getKeyringClientFromSnapId(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest): Promise<Json> => {\n const response = await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n },\n );\n return response as Json;\n },\n });\n }\n\n async resyncAccounts(\n accounts: Bip44Account<InternalAccount>[],\n ): Promise<void> {\n await this.withSnap(async ({ keyring }) => {\n const localSnapAccounts = accounts.filter(\n (account) => account.metadata.snap?.id === this.snapId,\n );\n const snapAccounts = new Set(\n (await this.#client.listAccounts()).map((account) => account.id),\n );\n\n // NOTE: This should never happen, but if it does, we recover by deleting the\n // extra accounts from the Snap to bring it back in sync with MetaMask.\n if (localSnapAccounts.length < snapAccounts.size) {\n const autoRemoveExtraSnapAccounts =\n this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;\n\n if (autoRemoveExtraSnapAccounts) {\n // Build a set of local account IDs for quick lookup\n const localAccountIds = new Set(\n localSnapAccounts.map((account) => account.id),\n );\n\n // Find and delete accounts that exist in Snap but not in MetaMask\n await Promise.all(\n [...snapAccounts].map(async (snapAccountId) => {\n try {\n if (!localAccountIds.has(snapAccountId)) {\n // This account exists in the Snap but not in MetaMask, delete it from\n // the Snap.\n await this.#client.deleteAccount(snapAccountId);\n // Update the local Set so subsequent checks use the correct size\n snapAccounts.delete(snapAccountId);\n }\n } catch (error) {\n reportError(\n this.messenger,\n `Unable to delete de-synced Snap account: ${this.snapId}`,\n error,\n {\n provider: this.getName(),\n snapAccountId,\n },\n );\n }\n }),\n );\n } else {\n const message = `Snap \"${this.snapId}\" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n return;\n }\n }\n\n // We want this part to be fast, so we only check for sizes, but we might need\n // to make a real \"diff\" between the 2 states to not miss any de-sync.\n if (localSnapAccounts.length > snapAccounts.size) {\n // We always use the MetaMask list as the main reference here.\n await Promise.all(\n localSnapAccounts.map(async (account) => {\n const { id: entropySource, groupIndex } = account.options.entropy;\n\n try {\n if (!snapAccounts.has(account.id)) {\n // We still need to remove the accounts from the Snap keyring since we're\n // about to create the same account again, which will use a new ID, but will\n // keep using the same address, and the Snap keyring does not allow this.\n await keyring.removeAccount(account.address);\n // The Snap has no account in its state for this one, we re-create it.\n await this.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n }\n } catch (error) {\n reportError(this.messenger, 'Unable to re-sync accounts', error, {\n provider: this.getName(),\n groupIndex,\n });\n }\n }),\n );\n }\n });\n }\n\n async #withSnapKeyring<CallbackResult = void>(\n operation: ({\n keyring,\n metadata,\n }: {\n keyring: SnapKeyring;\n metadata: KeyringMetadata;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n return this.withKeyring<SnapKeyring, CallbackResult>(\n { type: KeyringTypes.snap },\n (args) => {\n return operation(args);\n },\n );\n }\n\n protected async withSnap<CallbackResult = void>(\n operation: (snap: {\n client: KeyringClient;\n keyring: RestrictedSnapKeyring;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n await this.ensureReady();\n\n return await operation({\n client: this.#client,\n keyring: await this.#getRestrictedSnapKeyring(),\n });\n }\n\n abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;\n\n protected abstract createAccountV1(\n keyring: RestrictedSnapKeyring,\n options: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount>;\n\n protected toBip44Account(\n account: KeyringAccount,\n _options: { entropySource: EntropySourceId; groupIndex: number },\n ): Bip44Account<KeyringAccount> {\n assertIsBip44Account(account);\n return account;\n }\n\n protected async createBip44Accounts(\n keyring: RestrictedSnapKeyring,\n options:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withMaxConcurrency(async () => {\n let groupIndexOffset = 0;\n let snapAccounts: KeyringAccount[] = [];\n\n const batched = this.config.createAccounts.batched ?? false;\n const { entropySource } = options;\n\n const createAccountV1 = async (\n groupIndex: number,\n ): Promise<KeyringAccount> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccountV1,\n data: {\n provider: this.getName(),\n groupIndex,\n },\n },\n () =>\n this.createAccountV1(keyring, { entropySource, groupIndex }),\n ),\n this.config.createAccounts.timeoutMs,\n );\n const createAccountsV2 = async (\n optionsV2:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<KeyringAccount[]> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccounts,\n data: {\n provider: this.getName(),\n ...toCreateAccountsV2DataTraces(optionsV2),\n },\n },\n () => keyring.createAccounts(optionsV2),\n ),\n this.config.createAccounts.timeoutMs,\n );\n\n if (options.type === `${AccountCreationType.Bip44DeriveIndexRange}`) {\n if (batched) {\n // Batch account creations.\n snapAccounts = await createAccountsV2(options);\n } else {\n const { range } = options;\n\n // Create accounts one by one.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts.push(snapAccount);\n }\n }\n\n // Group indices are sequential, so we just need the starting index.\n groupIndexOffset = options.range.from;\n } else {\n if (batched) {\n // Create account using new v2-like flow (no async flow + no Snap keyring events).\n snapAccounts = await createAccountsV2(options);\n } else {\n const { groupIndex } = options;\n\n // Create account using the existing v1 flow.\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts = [snapAccount];\n }\n\n // For single account, there will only be 1 account, so we can use the\n // provided group index directly.\n groupIndexOffset = options.groupIndex;\n }\n\n return snapAccounts.map((snapAccount, index) => {\n const groupIndex = groupIndexOffset + index;\n const account = this.toBip44Account(snapAccount, {\n entropySource,\n groupIndex,\n });\n\n this.accounts.add(snapAccount.id);\n return account;\n });\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n return this.withSnap(async ({ keyring }) =>\n this.createBip44Accounts(keyring, options),\n );\n }\n\n abstract discoverAccounts(options: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]>;\n}\n\nexport const isSnapAccountProvider = (\n provider: unknown,\n): provider is SnapAccountProvider => {\n return provider instanceof SnapAccountProvider;\n};\n"]}
1
+ {"version":3,"file":"SnapAccountProvider.cjs","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsBip44Account } from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback, TraceRequest } from '@metamask/controller-utils';\nimport type { SnapKeyring as SnapKeyringV2 } from '@metamask/eth-snap-keyring/v2';\nimport { isSnapKeyring } from '@metamask/eth-snap-keyring/v2';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n} from '@metamask/keyring-api';\nimport type {\n CreateAccountBip44DeriveIndexOptions,\n CreateAccountBip44DeriveIndexRangeOptions,\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport type { KeyringMetadata } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Semaphore } from 'async-mutex';\n\nimport {\n toCreateAccountsV2DataTraces,\n traceFallback,\n TraceName,\n} from '../analytics';\nimport { reportError } from '../errors';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { BaseBip44AccountProvider } from './BaseBip44AccountProvider';\nimport { withTimeout } from './utils';\n\nexport type RestrictedSnapKeyring = {\n createAccount: SnapKeyringV2['createAccount'];\n createAccounts: SnapKeyringV2['createAccounts'];\n deleteAccount: SnapKeyringV2['deleteAccount'];\n};\n\nexport type SnapAccountProviderConfig = {\n maxConcurrency?: number;\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n createAccounts: {\n /**\n * Whether to enable account batching with `createAccounts` method. If `true`, accounts will\n * be created in batch.\n *\n * NOTE: The Snap has to implement this optional method for batching support.\n * Defaults to `false`.\n */\n batched: boolean;\n /**\n * Timeout for account creation operations.\n *\n * NOTE: The value might have to be adapted in case batching is enabled!\n */\n timeoutMs: number;\n };\n resyncAccounts?: {\n /**\n * Whether to automatically remove extra Snap accounts when the Snap has\n * more accounts than MetaMask. If `false`, a warning is logged instead.\n * Defaults to `true`.\n */\n autoRemoveExtraSnapAccounts?: boolean;\n };\n};\n\nexport abstract class SnapAccountProvider extends BaseBip44AccountProvider {\n readonly snapId: SnapId;\n\n protected readonly config: SnapAccountProviderConfig;\n\n readonly #client: KeyringClient;\n\n readonly #queue?: Semaphore;\n\n readonly #trace: TraceCallback;\n\n constructor(\n snapId: SnapId,\n messenger: MultichainAccountServiceMessenger,\n config: SnapAccountProviderConfig,\n /* istanbul ignore next */\n trace: TraceCallback = traceFallback,\n ) {\n super(messenger);\n\n this.snapId = snapId;\n this.#client = this.#getKeyringClientFromSnapId(snapId);\n\n const maxConcurrency = config.maxConcurrency ?? Infinity;\n this.config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n maxConcurrency,\n };\n\n // Create semaphore only if concurrency is limited\n if (isFinite(maxConcurrency)) {\n this.#queue = new Semaphore(maxConcurrency);\n }\n\n this.#trace = trace;\n }\n\n /**\n * Ensures that the Snap is ready to be used.\n *\n * @returns A promise that resolves when the Snap is ready.\n * @throws An error if the Snap could not become ready.\n */\n async ensureReady(): Promise<void> {\n return this.messenger.call('SnapAccountService:ensureReady', this.snapId);\n }\n\n /**\n * Wraps an async operation with concurrency limiting based on maxConcurrency config.\n * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling.\n * Otherwise, it's queued through the semaphore to respect the concurrency limit.\n *\n * @param operation - The async operation to execute.\n * @returns The result of the operation.\n */\n protected async withMaxConcurrency<Result>(\n operation: () => Promise<Result>,\n ): Promise<Result> {\n if (this.#queue) {\n return this.#queue.runExclusive(operation);\n }\n return operation();\n }\n\n protected async trace<ReturnType>(\n request: TraceRequest,\n fn: () => Promise<ReturnType>,\n ): Promise<ReturnType> {\n return this.#trace(request, fn);\n }\n\n async #getRestrictedSnapKeyring(): Promise<RestrictedSnapKeyring> {\n // NOTE: We're not supposed to make the keyring instance escape `withKeyringV2` but\n // we have to use the `SnapKeyringV2` instance to be able to create Solana account\n // without triggering UI confirmation.\n // Also, creating account that way won't invalidate the Snap keyring state. The\n // account will get created and persisted properly with the Snap account creation\n // flow \"asynchronously\" (with `notify:accountCreated`).\n const { createAccount, createAccounts } = await this.#withSnapKeyring<{\n createAccount: SnapKeyringV2['createAccount'];\n createAccounts: SnapKeyringV2['createAccounts'];\n }>(async ({ keyring }) => ({\n createAccount: keyring.createAccount.bind(keyring),\n createAccounts: keyring.createAccounts.bind(keyring),\n }));\n\n return {\n createAccount: async (options) =>\n // We use the \"unguarded\" account creation here (see explanation above).\n await createAccount(options, {\n displayAccountNameSuggestion: false,\n displayConfirmation: false,\n setSelectedAccount: false,\n }),\n createAccounts: async (options) => await createAccounts(options),\n deleteAccount: async (id: string) =>\n // Though, when removing account, we can use the normal flow.\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(id);\n }),\n };\n }\n\n #getKeyringClientFromSnapId(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest): Promise<Json> => {\n const response = await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n },\n );\n return response as Json;\n },\n });\n }\n\n async resyncAccounts(\n accounts: Bip44Account<InternalAccount>[],\n ): Promise<void> {\n await this.withSnap(async ({ keyring }) => {\n const localSnapAccounts = accounts.filter(\n (account) => account.metadata.snap?.id === this.snapId,\n );\n const snapAccounts = new Set(\n (await this.#client.listAccounts()).map((account) => account.id),\n );\n\n // NOTE: This should never happen, but if it does, we recover by deleting the\n // extra accounts from the Snap to bring it back in sync with MetaMask.\n if (localSnapAccounts.length < snapAccounts.size) {\n const autoRemoveExtraSnapAccounts =\n this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;\n\n if (autoRemoveExtraSnapAccounts) {\n // Build a set of local account IDs for quick lookup\n const localAccountIds = new Set(\n localSnapAccounts.map((account) => account.id),\n );\n\n // Find and delete accounts that exist in Snap but not in MetaMask\n await Promise.all(\n [...snapAccounts].map(async (snapAccountId) => {\n try {\n if (!localAccountIds.has(snapAccountId)) {\n // This account exists in the Snap but not in MetaMask, delete it from\n // the Snap.\n await this.#client.deleteAccount(snapAccountId);\n // Update the local Set so subsequent checks use the correct size\n snapAccounts.delete(snapAccountId);\n }\n } catch (error) {\n reportError(\n this.messenger,\n `Unable to delete de-synced Snap account: ${this.snapId}`,\n error,\n {\n provider: this.getName(),\n snapAccountId,\n },\n );\n }\n }),\n );\n } else {\n const message = `Snap \"${this.snapId}\" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n return;\n }\n }\n\n // We want this part to be fast, so we only check for sizes, but we might need\n // to make a real \"diff\" between the 2 states to not miss any de-sync.\n if (localSnapAccounts.length > snapAccounts.size) {\n // We always use the MetaMask list as the main reference here.\n await Promise.all(\n localSnapAccounts.map(async (account) => {\n const { id: entropySource, groupIndex } = account.options.entropy;\n\n try {\n if (!snapAccounts.has(account.id)) {\n // We still need to remove the accounts from the Snap keyring since we're\n // about to create the same account again, which will use a new ID, but will\n // keep using the same address, and the Snap keyring does not allow this.\n await keyring.deleteAccount(account.id);\n // The Snap has no account in its state for this one, we re-create it.\n await this.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n }\n } catch (error) {\n reportError(this.messenger, 'Unable to re-sync accounts', error, {\n provider: this.getName(),\n groupIndex,\n });\n }\n }),\n );\n }\n });\n }\n\n async #withSnapKeyring<CallbackResult = void>(\n operation: ({\n keyring,\n metadata,\n }: {\n keyring: SnapKeyringV2;\n metadata: KeyringMetadata;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n return this.withKeyringV2<SnapKeyringV2, CallbackResult>(\n {\n filter: (keyring) =>\n isSnapKeyring(keyring) && keyring.snapId === this.snapId,\n },\n (args) => operation(args),\n );\n }\n\n protected async withSnap<CallbackResult = void>(\n operation: (snap: {\n client: KeyringClient;\n keyring: RestrictedSnapKeyring;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n await this.ensureReady();\n\n return await operation({\n client: this.#client,\n keyring: await this.#getRestrictedSnapKeyring(),\n });\n }\n\n abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;\n\n protected abstract createAccountV1(\n keyring: RestrictedSnapKeyring,\n options: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount>;\n\n protected toBip44Account(\n account: KeyringAccount,\n _options: { entropySource: EntropySourceId; groupIndex: number },\n ): Bip44Account<KeyringAccount> {\n assertIsBip44Account(account);\n return account;\n }\n\n protected async createBip44Accounts(\n keyring: RestrictedSnapKeyring,\n options:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withMaxConcurrency(async () => {\n let groupIndexOffset = 0;\n let snapAccounts: KeyringAccount[] = [];\n\n const batched = this.config.createAccounts.batched ?? false;\n const { entropySource } = options;\n\n const createAccountV1 = async (\n groupIndex: number,\n ): Promise<KeyringAccount> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccountV1,\n data: {\n provider: this.getName(),\n groupIndex,\n },\n },\n () =>\n this.createAccountV1(keyring, { entropySource, groupIndex }),\n ),\n this.config.createAccounts.timeoutMs,\n );\n const createAccountsV2 = async (\n optionsV2:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<KeyringAccount[]> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccounts,\n data: {\n provider: this.getName(),\n ...toCreateAccountsV2DataTraces(optionsV2),\n },\n },\n () => keyring.createAccounts(optionsV2),\n ),\n this.config.createAccounts.timeoutMs,\n );\n\n if (options.type === `${AccountCreationType.Bip44DeriveIndexRange}`) {\n if (batched) {\n // Batch account creations.\n snapAccounts = await createAccountsV2(options);\n } else {\n const { range } = options;\n\n // Create accounts one by one.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts.push(snapAccount);\n }\n }\n\n // Group indices are sequential, so we just need the starting index.\n groupIndexOffset = options.range.from;\n } else {\n if (batched) {\n // Create account using new v2-like flow (no async flow + no Snap keyring events).\n snapAccounts = await createAccountsV2(options);\n } else {\n const { groupIndex } = options;\n\n // Create account using the existing v1 flow.\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts = [snapAccount];\n }\n\n // For single account, there will only be 1 account, so we can use the\n // provided group index directly.\n groupIndexOffset = options.groupIndex;\n }\n\n return snapAccounts.map((snapAccount, index) => {\n const groupIndex = groupIndexOffset + index;\n const account = this.toBip44Account(snapAccount, {\n entropySource,\n groupIndex,\n });\n\n this.accounts.add(snapAccount.id);\n return account;\n });\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n return this.withSnap(async ({ keyring }) =>\n this.createBip44Accounts(keyring, options),\n );\n }\n\n /**\n * Delete a snap account by id.\n *\n * Resolves the account's address from the tracked account, then forwards to\n * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes\n * care of notifying the snap to clean up its own state through the normal\n * account-removal flow (same path used by `resyncAccounts`).\n *\n * @param id - The id of the account to delete.\n */\n async deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void> {\n const account = this.getAccount(id);\n\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(account.id);\n });\n\n this.accounts.delete(id);\n }\n\n abstract discoverAccounts(options: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]>;\n}\n\nexport const isSnapAccountProvider = (\n provider: unknown,\n): provider is SnapAccountProvider => {\n return provider instanceof SnapAccountProvider;\n};\n"]}
@@ -1,15 +1,16 @@
1
1
  import type { Bip44Account } from "@metamask/account-api";
2
2
  import type { TraceCallback, TraceRequest } from "@metamask/controller-utils";
3
+ import type { SnapKeyring as SnapKeyringV2 } from "@metamask/eth-snap-keyring/v2";
3
4
  import type { CreateAccountBip44DeriveIndexOptions, CreateAccountBip44DeriveIndexRangeOptions, CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
4
5
  import type { InternalAccount } from "@metamask/keyring-internal-api";
5
6
  import { KeyringClient } from "@metamask/keyring-snap-client";
6
- import type { Json, SnapId } from "@metamask/snaps-sdk";
7
+ import type { SnapId } from "@metamask/snaps-sdk";
7
8
  import type { MultichainAccountServiceMessenger } from "../types.cjs";
8
9
  import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.cjs";
9
10
  export type RestrictedSnapKeyring = {
10
- createAccount: (options: Record<string, Json>) => Promise<KeyringAccount>;
11
- createAccounts: (options: CreateAccountOptions) => Promise<KeyringAccount[]>;
12
- removeAccount: (address: string) => Promise<void>;
11
+ createAccount: SnapKeyringV2['createAccount'];
12
+ createAccounts: SnapKeyringV2['createAccounts'];
13
+ deleteAccount: SnapKeyringV2['deleteAccount'];
13
14
  };
14
15
  export type SnapAccountProviderConfig = {
15
16
  maxConcurrency?: number;
@@ -82,6 +83,17 @@ export declare abstract class SnapAccountProvider extends BaseBip44AccountProvid
82
83
  }): Bip44Account<KeyringAccount>;
83
84
  protected createBip44Accounts(keyring: RestrictedSnapKeyring, options: CreateAccountBip44DeriveIndexOptions | CreateAccountBip44DeriveIndexRangeOptions): Promise<Bip44Account<KeyringAccount>[]>;
84
85
  createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
86
+ /**
87
+ * Delete a snap account by id.
88
+ *
89
+ * Resolves the account's address from the tracked account, then forwards to
90
+ * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes
91
+ * care of notifying the snap to clean up its own state through the normal
92
+ * account-removal flow (same path used by `resyncAccounts`).
93
+ *
94
+ * @param id - The id of the account to delete.
95
+ */
96
+ deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void>;
85
97
  abstract discoverAccounts(options: {
86
98
  entropySource: EntropySourceId;
87
99
  groupIndex: number;
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SnapAccountProvider.d.cts","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,16 @@
1
1
  import type { Bip44Account } from "@metamask/account-api";
2
2
  import type { TraceCallback, TraceRequest } from "@metamask/controller-utils";
3
+ import type { SnapKeyring as SnapKeyringV2 } from "@metamask/eth-snap-keyring/v2";
3
4
  import type { CreateAccountBip44DeriveIndexOptions, CreateAccountBip44DeriveIndexRangeOptions, CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api";
4
5
  import type { InternalAccount } from "@metamask/keyring-internal-api";
5
6
  import { KeyringClient } from "@metamask/keyring-snap-client";
6
- import type { Json, SnapId } from "@metamask/snaps-sdk";
7
+ import type { SnapId } from "@metamask/snaps-sdk";
7
8
  import type { MultichainAccountServiceMessenger } from "../types.mjs";
8
9
  import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.mjs";
9
10
  export type RestrictedSnapKeyring = {
10
- createAccount: (options: Record<string, Json>) => Promise<KeyringAccount>;
11
- createAccounts: (options: CreateAccountOptions) => Promise<KeyringAccount[]>;
12
- removeAccount: (address: string) => Promise<void>;
11
+ createAccount: SnapKeyringV2['createAccount'];
12
+ createAccounts: SnapKeyringV2['createAccounts'];
13
+ deleteAccount: SnapKeyringV2['deleteAccount'];
13
14
  };
14
15
  export type SnapAccountProviderConfig = {
15
16
  maxConcurrency?: number;
@@ -82,6 +83,17 @@ export declare abstract class SnapAccountProvider extends BaseBip44AccountProvid
82
83
  }): Bip44Account<KeyringAccount>;
83
84
  protected createBip44Accounts(keyring: RestrictedSnapKeyring, options: CreateAccountBip44DeriveIndexOptions | CreateAccountBip44DeriveIndexRangeOptions): Promise<Bip44Account<KeyringAccount>[]>;
84
85
  createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>;
86
+ /**
87
+ * Delete a snap account by id.
88
+ *
89
+ * Resolves the account's address from the tracked account, then forwards to
90
+ * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes
91
+ * care of notifying the snap to clean up its own state through the normal
92
+ * account-removal flow (same path used by `resyncAccounts`).
93
+ *
94
+ * @param id - The id of the account to delete.
95
+ */
96
+ deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void>;
85
97
  abstract discoverAccounts(options: {
86
98
  entropySource: EntropySourceId;
87
99
  groupIndex: number;
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SnapAccountProvider.d.mts","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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"}
@@ -11,8 +11,8 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
11
11
  };
12
12
  var _SnapAccountProvider_instances, _SnapAccountProvider_client, _SnapAccountProvider_queue, _SnapAccountProvider_trace, _SnapAccountProvider_getRestrictedSnapKeyring, _SnapAccountProvider_getKeyringClientFromSnapId, _SnapAccountProvider_withSnapKeyring;
13
13
  import { assertIsBip44Account } from "@metamask/account-api";
14
+ import { isSnapKeyring } from "@metamask/eth-snap-keyring/v2";
14
15
  import { AccountCreationType, assertCreateAccountOptionIsSupported } from "@metamask/keyring-api";
15
- import { KeyringTypes } from "@metamask/keyring-controller";
16
16
  import { KeyringClient } from "@metamask/keyring-snap-client";
17
17
  import { HandlerType } from "@metamask/snaps-utils";
18
18
  import { Semaphore } from "async-mutex";
@@ -121,7 +121,7 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
121
121
  // We still need to remove the accounts from the Snap keyring since we're
122
122
  // about to create the same account again, which will use a new ID, but will
123
123
  // keep using the same address, and the Snap keyring does not allow this.
124
- await keyring.removeAccount(account.address);
124
+ await keyring.deleteAccount(account.id);
125
125
  // The Snap has no account in its state for this one, we re-create it.
126
126
  await this.createAccounts({
127
127
  type: AccountCreationType.Bip44DeriveIndex,
@@ -220,10 +220,27 @@ export class SnapAccountProvider extends BaseBip44AccountProvider {
220
220
  ]);
221
221
  return this.withSnap(async ({ keyring }) => this.createBip44Accounts(keyring, options));
222
222
  }
223
+ /**
224
+ * Delete a snap account by id.
225
+ *
226
+ * Resolves the account's address from the tracked account, then forwards to
227
+ * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes
228
+ * care of notifying the snap to clean up its own state through the normal
229
+ * account-removal flow (same path used by `resyncAccounts`).
230
+ *
231
+ * @param id - The id of the account to delete.
232
+ */
233
+ async deleteAccount(id) {
234
+ const account = this.getAccount(id);
235
+ await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => {
236
+ await keyring.deleteAccount(account.id);
237
+ });
238
+ this.accounts.delete(id);
239
+ }
223
240
  }
224
241
  _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new WeakMap(), _SnapAccountProvider_trace = new WeakMap(), _SnapAccountProvider_instances = new WeakSet(), _SnapAccountProvider_getRestrictedSnapKeyring = async function _SnapAccountProvider_getRestrictedSnapKeyring() {
225
- // NOTE: We're not supposed to make the keyring instance escape `withKeyring` but
226
- // we have to use the `SnapKeyring` instance to be able to create Solana account
242
+ // NOTE: We're not supposed to make the keyring instance escape `withKeyringV2` but
243
+ // we have to use the `SnapKeyringV2` instance to be able to create Solana account
227
244
  // without triggering UI confirmation.
228
245
  // Also, creating account that way won't invalidate the Snap keyring state. The
229
246
  // account will get created and persisted properly with the Snap account creation
@@ -235,16 +252,16 @@ _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new We
235
252
  return {
236
253
  createAccount: async (options) =>
237
254
  // We use the "unguarded" account creation here (see explanation above).
238
- await createAccount(this.snapId, options, {
255
+ await createAccount(options, {
239
256
  displayAccountNameSuggestion: false,
240
257
  displayConfirmation: false,
241
258
  setSelectedAccount: false,
242
259
  }),
243
- createAccounts: async (options) => await createAccounts(this.snapId, options),
244
- removeAccount: async (address) =>
260
+ createAccounts: async (options) => await createAccounts(options),
261
+ deleteAccount: async (id) =>
245
262
  // Though, when removing account, we can use the normal flow.
246
263
  await __classPrivateFieldGet(this, _SnapAccountProvider_instances, "m", _SnapAccountProvider_withSnapKeyring).call(this, async ({ keyring }) => {
247
- await keyring.removeAccount(address);
264
+ await keyring.deleteAccount(id);
248
265
  }),
249
266
  };
250
267
  }, _SnapAccountProvider_getKeyringClientFromSnapId = function _SnapAccountProvider_getKeyringClientFromSnapId(snapId) {
@@ -260,9 +277,9 @@ _SnapAccountProvider_client = new WeakMap(), _SnapAccountProvider_queue = new We
260
277
  },
261
278
  });
262
279
  }, _SnapAccountProvider_withSnapKeyring = async function _SnapAccountProvider_withSnapKeyring(operation) {
263
- return this.withKeyring({ type: KeyringTypes.snap }, (args) => {
264
- return operation(args);
265
- });
280
+ return this.withKeyringV2({
281
+ filter: (keyring) => isSnapKeyring(keyring) && keyring.snapId === this.snapId,
282
+ }, (args) => operation(args));
266
283
  };
267
284
  export const isSnapAccountProvider = (provider) => {
268
285
  return provider instanceof SnapAccountProvider;
@@ -1 +1 @@
1
- {"version":3,"file":"SnapAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsBip44Account } from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback, TraceRequest } from '@metamask/controller-utils';\nimport type { SnapKeyring } from '@metamask/eth-snap-keyring';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n} from '@metamask/keyring-api';\nimport type {\n CreateAccountBip44DeriveIndexOptions,\n CreateAccountBip44DeriveIndexRangeOptions,\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport type { KeyringMetadata } from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Semaphore } from 'async-mutex';\n\nimport {\n toCreateAccountsV2DataTraces,\n traceFallback,\n TraceName,\n} from '../analytics';\nimport { reportError } from '../errors';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { BaseBip44AccountProvider } from './BaseBip44AccountProvider';\nimport { withTimeout } from './utils';\n\nexport type RestrictedSnapKeyring = {\n createAccount: (options: Record<string, Json>) => Promise<KeyringAccount>;\n createAccounts: (options: CreateAccountOptions) => Promise<KeyringAccount[]>;\n removeAccount: (address: string) => Promise<void>;\n};\n\nexport type SnapAccountProviderConfig = {\n maxConcurrency?: number;\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n createAccounts: {\n /**\n * Whether to enable account batching with `createAccounts` method. If `true`, accounts will\n * be created in batch.\n *\n * NOTE: The Snap has to implement this optional method for batching support.\n * Defaults to `false`.\n */\n batched: boolean;\n /**\n * Timeout for account creation operations.\n *\n * NOTE: The value might have to be adapted in case batching is enabled!\n */\n timeoutMs: number;\n };\n resyncAccounts?: {\n /**\n * Whether to automatically remove extra Snap accounts when the Snap has\n * more accounts than MetaMask. If `false`, a warning is logged instead.\n * Defaults to `true`.\n */\n autoRemoveExtraSnapAccounts?: boolean;\n };\n};\n\nexport abstract class SnapAccountProvider extends BaseBip44AccountProvider {\n readonly snapId: SnapId;\n\n protected readonly config: SnapAccountProviderConfig;\n\n readonly #client: KeyringClient;\n\n readonly #queue?: Semaphore;\n\n readonly #trace: TraceCallback;\n\n constructor(\n snapId: SnapId,\n messenger: MultichainAccountServiceMessenger,\n config: SnapAccountProviderConfig,\n /* istanbul ignore next */\n trace: TraceCallback = traceFallback,\n ) {\n super(messenger);\n\n this.snapId = snapId;\n this.#client = this.#getKeyringClientFromSnapId(snapId);\n\n const maxConcurrency = config.maxConcurrency ?? Infinity;\n this.config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n maxConcurrency,\n };\n\n // Create semaphore only if concurrency is limited\n if (isFinite(maxConcurrency)) {\n this.#queue = new Semaphore(maxConcurrency);\n }\n\n this.#trace = trace;\n }\n\n /**\n * Ensures that the Snap is ready to be used.\n *\n * @returns A promise that resolves when the Snap is ready.\n * @throws An error if the Snap could not become ready.\n */\n async ensureReady(): Promise<void> {\n return this.messenger.call('SnapAccountService:ensureReady', this.snapId);\n }\n\n /**\n * Wraps an async operation with concurrency limiting based on maxConcurrency config.\n * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling.\n * Otherwise, it's queued through the semaphore to respect the concurrency limit.\n *\n * @param operation - The async operation to execute.\n * @returns The result of the operation.\n */\n protected async withMaxConcurrency<Result>(\n operation: () => Promise<Result>,\n ): Promise<Result> {\n if (this.#queue) {\n return this.#queue.runExclusive(operation);\n }\n return operation();\n }\n\n protected async trace<ReturnType>(\n request: TraceRequest,\n fn: () => Promise<ReturnType>,\n ): Promise<ReturnType> {\n return this.#trace(request, fn);\n }\n\n async #getRestrictedSnapKeyring(): Promise<RestrictedSnapKeyring> {\n // NOTE: We're not supposed to make the keyring instance escape `withKeyring` but\n // we have to use the `SnapKeyring` instance to be able to create Solana account\n // without triggering UI confirmation.\n // Also, creating account that way won't invalidate the Snap keyring state. The\n // account will get created and persisted properly with the Snap account creation\n // flow \"asynchronously\" (with `notify:accountCreated`).\n const { createAccount, createAccounts } = await this.#withSnapKeyring<{\n createAccount: SnapKeyring['createAccount'];\n createAccounts: SnapKeyring['createAccounts'];\n }>(async ({ keyring }) => ({\n createAccount: keyring.createAccount.bind(keyring),\n createAccounts: keyring.createAccounts.bind(keyring),\n }));\n\n return {\n createAccount: async (options) =>\n // We use the \"unguarded\" account creation here (see explanation above).\n await createAccount(this.snapId, options, {\n displayAccountNameSuggestion: false,\n displayConfirmation: false,\n setSelectedAccount: false,\n }),\n createAccounts: async (options) =>\n await createAccounts(this.snapId, options),\n removeAccount: async (address: string) =>\n // Though, when removing account, we can use the normal flow.\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.removeAccount(address);\n }),\n };\n }\n\n #getKeyringClientFromSnapId(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest): Promise<Json> => {\n const response = await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n },\n );\n return response as Json;\n },\n });\n }\n\n async resyncAccounts(\n accounts: Bip44Account<InternalAccount>[],\n ): Promise<void> {\n await this.withSnap(async ({ keyring }) => {\n const localSnapAccounts = accounts.filter(\n (account) => account.metadata.snap?.id === this.snapId,\n );\n const snapAccounts = new Set(\n (await this.#client.listAccounts()).map((account) => account.id),\n );\n\n // NOTE: This should never happen, but if it does, we recover by deleting the\n // extra accounts from the Snap to bring it back in sync with MetaMask.\n if (localSnapAccounts.length < snapAccounts.size) {\n const autoRemoveExtraSnapAccounts =\n this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;\n\n if (autoRemoveExtraSnapAccounts) {\n // Build a set of local account IDs for quick lookup\n const localAccountIds = new Set(\n localSnapAccounts.map((account) => account.id),\n );\n\n // Find and delete accounts that exist in Snap but not in MetaMask\n await Promise.all(\n [...snapAccounts].map(async (snapAccountId) => {\n try {\n if (!localAccountIds.has(snapAccountId)) {\n // This account exists in the Snap but not in MetaMask, delete it from\n // the Snap.\n await this.#client.deleteAccount(snapAccountId);\n // Update the local Set so subsequent checks use the correct size\n snapAccounts.delete(snapAccountId);\n }\n } catch (error) {\n reportError(\n this.messenger,\n `Unable to delete de-synced Snap account: ${this.snapId}`,\n error,\n {\n provider: this.getName(),\n snapAccountId,\n },\n );\n }\n }),\n );\n } else {\n const message = `Snap \"${this.snapId}\" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n return;\n }\n }\n\n // We want this part to be fast, so we only check for sizes, but we might need\n // to make a real \"diff\" between the 2 states to not miss any de-sync.\n if (localSnapAccounts.length > snapAccounts.size) {\n // We always use the MetaMask list as the main reference here.\n await Promise.all(\n localSnapAccounts.map(async (account) => {\n const { id: entropySource, groupIndex } = account.options.entropy;\n\n try {\n if (!snapAccounts.has(account.id)) {\n // We still need to remove the accounts from the Snap keyring since we're\n // about to create the same account again, which will use a new ID, but will\n // keep using the same address, and the Snap keyring does not allow this.\n await keyring.removeAccount(account.address);\n // The Snap has no account in its state for this one, we re-create it.\n await this.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n }\n } catch (error) {\n reportError(this.messenger, 'Unable to re-sync accounts', error, {\n provider: this.getName(),\n groupIndex,\n });\n }\n }),\n );\n }\n });\n }\n\n async #withSnapKeyring<CallbackResult = void>(\n operation: ({\n keyring,\n metadata,\n }: {\n keyring: SnapKeyring;\n metadata: KeyringMetadata;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n return this.withKeyring<SnapKeyring, CallbackResult>(\n { type: KeyringTypes.snap },\n (args) => {\n return operation(args);\n },\n );\n }\n\n protected async withSnap<CallbackResult = void>(\n operation: (snap: {\n client: KeyringClient;\n keyring: RestrictedSnapKeyring;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n await this.ensureReady();\n\n return await operation({\n client: this.#client,\n keyring: await this.#getRestrictedSnapKeyring(),\n });\n }\n\n abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;\n\n protected abstract createAccountV1(\n keyring: RestrictedSnapKeyring,\n options: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount>;\n\n protected toBip44Account(\n account: KeyringAccount,\n _options: { entropySource: EntropySourceId; groupIndex: number },\n ): Bip44Account<KeyringAccount> {\n assertIsBip44Account(account);\n return account;\n }\n\n protected async createBip44Accounts(\n keyring: RestrictedSnapKeyring,\n options:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withMaxConcurrency(async () => {\n let groupIndexOffset = 0;\n let snapAccounts: KeyringAccount[] = [];\n\n const batched = this.config.createAccounts.batched ?? false;\n const { entropySource } = options;\n\n const createAccountV1 = async (\n groupIndex: number,\n ): Promise<KeyringAccount> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccountV1,\n data: {\n provider: this.getName(),\n groupIndex,\n },\n },\n () =>\n this.createAccountV1(keyring, { entropySource, groupIndex }),\n ),\n this.config.createAccounts.timeoutMs,\n );\n const createAccountsV2 = async (\n optionsV2:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<KeyringAccount[]> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccounts,\n data: {\n provider: this.getName(),\n ...toCreateAccountsV2DataTraces(optionsV2),\n },\n },\n () => keyring.createAccounts(optionsV2),\n ),\n this.config.createAccounts.timeoutMs,\n );\n\n if (options.type === `${AccountCreationType.Bip44DeriveIndexRange}`) {\n if (batched) {\n // Batch account creations.\n snapAccounts = await createAccountsV2(options);\n } else {\n const { range } = options;\n\n // Create accounts one by one.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts.push(snapAccount);\n }\n }\n\n // Group indices are sequential, so we just need the starting index.\n groupIndexOffset = options.range.from;\n } else {\n if (batched) {\n // Create account using new v2-like flow (no async flow + no Snap keyring events).\n snapAccounts = await createAccountsV2(options);\n } else {\n const { groupIndex } = options;\n\n // Create account using the existing v1 flow.\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts = [snapAccount];\n }\n\n // For single account, there will only be 1 account, so we can use the\n // provided group index directly.\n groupIndexOffset = options.groupIndex;\n }\n\n return snapAccounts.map((snapAccount, index) => {\n const groupIndex = groupIndexOffset + index;\n const account = this.toBip44Account(snapAccount, {\n entropySource,\n groupIndex,\n });\n\n this.accounts.add(snapAccount.id);\n return account;\n });\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n return this.withSnap(async ({ keyring }) =>\n this.createBip44Accounts(keyring, options),\n );\n }\n\n abstract discoverAccounts(options: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]>;\n}\n\nexport const isSnapAccountProvider = (\n provider: unknown,\n): provider is SnapAccountProvider => {\n return provider instanceof SnapAccountProvider;\n};\n"]}
1
+ {"version":3,"file":"SnapAccountProvider.mjs","sourceRoot":"","sources":["../../src/providers/SnapAccountProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsBip44Account } from '@metamask/account-api';\nimport type { Bip44Account } from '@metamask/account-api';\nimport type { TraceCallback, TraceRequest } from '@metamask/controller-utils';\nimport type { SnapKeyring as SnapKeyringV2 } from '@metamask/eth-snap-keyring/v2';\nimport { isSnapKeyring } from '@metamask/eth-snap-keyring/v2';\nimport {\n AccountCreationType,\n assertCreateAccountOptionIsSupported,\n} from '@metamask/keyring-api';\nimport type {\n CreateAccountBip44DeriveIndexOptions,\n CreateAccountBip44DeriveIndexRangeOptions,\n CreateAccountOptions,\n EntropySourceId,\n KeyringAccount,\n} from '@metamask/keyring-api';\nimport type { KeyringMetadata } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { KeyringClient } from '@metamask/keyring-snap-client';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport { Semaphore } from 'async-mutex';\n\nimport {\n toCreateAccountsV2DataTraces,\n traceFallback,\n TraceName,\n} from '../analytics';\nimport { reportError } from '../errors';\nimport { projectLogger as log, WARNING_PREFIX } from '../logger';\nimport type { MultichainAccountServiceMessenger } from '../types';\nimport { BaseBip44AccountProvider } from './BaseBip44AccountProvider';\nimport { withTimeout } from './utils';\n\nexport type RestrictedSnapKeyring = {\n createAccount: SnapKeyringV2['createAccount'];\n createAccounts: SnapKeyringV2['createAccounts'];\n deleteAccount: SnapKeyringV2['deleteAccount'];\n};\n\nexport type SnapAccountProviderConfig = {\n maxConcurrency?: number;\n discovery: {\n enabled?: boolean;\n maxAttempts: number;\n timeoutMs: number;\n backOffMs: number;\n };\n createAccounts: {\n /**\n * Whether to enable account batching with `createAccounts` method. If `true`, accounts will\n * be created in batch.\n *\n * NOTE: The Snap has to implement this optional method for batching support.\n * Defaults to `false`.\n */\n batched: boolean;\n /**\n * Timeout for account creation operations.\n *\n * NOTE: The value might have to be adapted in case batching is enabled!\n */\n timeoutMs: number;\n };\n resyncAccounts?: {\n /**\n * Whether to automatically remove extra Snap accounts when the Snap has\n * more accounts than MetaMask. If `false`, a warning is logged instead.\n * Defaults to `true`.\n */\n autoRemoveExtraSnapAccounts?: boolean;\n };\n};\n\nexport abstract class SnapAccountProvider extends BaseBip44AccountProvider {\n readonly snapId: SnapId;\n\n protected readonly config: SnapAccountProviderConfig;\n\n readonly #client: KeyringClient;\n\n readonly #queue?: Semaphore;\n\n readonly #trace: TraceCallback;\n\n constructor(\n snapId: SnapId,\n messenger: MultichainAccountServiceMessenger,\n config: SnapAccountProviderConfig,\n /* istanbul ignore next */\n trace: TraceCallback = traceFallback,\n ) {\n super(messenger);\n\n this.snapId = snapId;\n this.#client = this.#getKeyringClientFromSnapId(snapId);\n\n const maxConcurrency = config.maxConcurrency ?? Infinity;\n this.config = {\n ...config,\n discovery: {\n ...config.discovery,\n enabled: config.discovery.enabled ?? true,\n },\n maxConcurrency,\n };\n\n // Create semaphore only if concurrency is limited\n if (isFinite(maxConcurrency)) {\n this.#queue = new Semaphore(maxConcurrency);\n }\n\n this.#trace = trace;\n }\n\n /**\n * Ensures that the Snap is ready to be used.\n *\n * @returns A promise that resolves when the Snap is ready.\n * @throws An error if the Snap could not become ready.\n */\n async ensureReady(): Promise<void> {\n return this.messenger.call('SnapAccountService:ensureReady', this.snapId);\n }\n\n /**\n * Wraps an async operation with concurrency limiting based on maxConcurrency config.\n * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling.\n * Otherwise, it's queued through the semaphore to respect the concurrency limit.\n *\n * @param operation - The async operation to execute.\n * @returns The result of the operation.\n */\n protected async withMaxConcurrency<Result>(\n operation: () => Promise<Result>,\n ): Promise<Result> {\n if (this.#queue) {\n return this.#queue.runExclusive(operation);\n }\n return operation();\n }\n\n protected async trace<ReturnType>(\n request: TraceRequest,\n fn: () => Promise<ReturnType>,\n ): Promise<ReturnType> {\n return this.#trace(request, fn);\n }\n\n async #getRestrictedSnapKeyring(): Promise<RestrictedSnapKeyring> {\n // NOTE: We're not supposed to make the keyring instance escape `withKeyringV2` but\n // we have to use the `SnapKeyringV2` instance to be able to create Solana account\n // without triggering UI confirmation.\n // Also, creating account that way won't invalidate the Snap keyring state. The\n // account will get created and persisted properly with the Snap account creation\n // flow \"asynchronously\" (with `notify:accountCreated`).\n const { createAccount, createAccounts } = await this.#withSnapKeyring<{\n createAccount: SnapKeyringV2['createAccount'];\n createAccounts: SnapKeyringV2['createAccounts'];\n }>(async ({ keyring }) => ({\n createAccount: keyring.createAccount.bind(keyring),\n createAccounts: keyring.createAccounts.bind(keyring),\n }));\n\n return {\n createAccount: async (options) =>\n // We use the \"unguarded\" account creation here (see explanation above).\n await createAccount(options, {\n displayAccountNameSuggestion: false,\n displayConfirmation: false,\n setSelectedAccount: false,\n }),\n createAccounts: async (options) => await createAccounts(options),\n deleteAccount: async (id: string) =>\n // Though, when removing account, we can use the normal flow.\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(id);\n }),\n };\n }\n\n #getKeyringClientFromSnapId(snapId: string): KeyringClient {\n return new KeyringClient({\n send: async (request: JsonRpcRequest): Promise<Json> => {\n const response = await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId: snapId as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnKeyringRequest,\n request,\n },\n );\n return response as Json;\n },\n });\n }\n\n async resyncAccounts(\n accounts: Bip44Account<InternalAccount>[],\n ): Promise<void> {\n await this.withSnap(async ({ keyring }) => {\n const localSnapAccounts = accounts.filter(\n (account) => account.metadata.snap?.id === this.snapId,\n );\n const snapAccounts = new Set(\n (await this.#client.listAccounts()).map((account) => account.id),\n );\n\n // NOTE: This should never happen, but if it does, we recover by deleting the\n // extra accounts from the Snap to bring it back in sync with MetaMask.\n if (localSnapAccounts.length < snapAccounts.size) {\n const autoRemoveExtraSnapAccounts =\n this.config.resyncAccounts?.autoRemoveExtraSnapAccounts ?? true;\n\n if (autoRemoveExtraSnapAccounts) {\n // Build a set of local account IDs for quick lookup\n const localAccountIds = new Set(\n localSnapAccounts.map((account) => account.id),\n );\n\n // Find and delete accounts that exist in Snap but not in MetaMask\n await Promise.all(\n [...snapAccounts].map(async (snapAccountId) => {\n try {\n if (!localAccountIds.has(snapAccountId)) {\n // This account exists in the Snap but not in MetaMask, delete it from\n // the Snap.\n await this.#client.deleteAccount(snapAccountId);\n // Update the local Set so subsequent checks use the correct size\n snapAccounts.delete(snapAccountId);\n }\n } catch (error) {\n reportError(\n this.messenger,\n `Unable to delete de-synced Snap account: ${this.snapId}`,\n error,\n {\n provider: this.getName(),\n snapAccountId,\n },\n );\n }\n }),\n );\n } else {\n const message = `Snap \"${this.snapId}\" has de-synced accounts, Snap has more accounts than MetaMask! (${localSnapAccounts.length} < ${snapAccounts.size})`;\n log(`${WARNING_PREFIX} ${message}`);\n console.warn(message);\n return;\n }\n }\n\n // We want this part to be fast, so we only check for sizes, but we might need\n // to make a real \"diff\" between the 2 states to not miss any de-sync.\n if (localSnapAccounts.length > snapAccounts.size) {\n // We always use the MetaMask list as the main reference here.\n await Promise.all(\n localSnapAccounts.map(async (account) => {\n const { id: entropySource, groupIndex } = account.options.entropy;\n\n try {\n if (!snapAccounts.has(account.id)) {\n // We still need to remove the accounts from the Snap keyring since we're\n // about to create the same account again, which will use a new ID, but will\n // keep using the same address, and the Snap keyring does not allow this.\n await keyring.deleteAccount(account.id);\n // The Snap has no account in its state for this one, we re-create it.\n await this.createAccounts({\n type: AccountCreationType.Bip44DeriveIndex,\n entropySource,\n groupIndex,\n });\n }\n } catch (error) {\n reportError(this.messenger, 'Unable to re-sync accounts', error, {\n provider: this.getName(),\n groupIndex,\n });\n }\n }),\n );\n }\n });\n }\n\n async #withSnapKeyring<CallbackResult = void>(\n operation: ({\n keyring,\n metadata,\n }: {\n keyring: SnapKeyringV2;\n metadata: KeyringMetadata;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n return this.withKeyringV2<SnapKeyringV2, CallbackResult>(\n {\n filter: (keyring) =>\n isSnapKeyring(keyring) && keyring.snapId === this.snapId,\n },\n (args) => operation(args),\n );\n }\n\n protected async withSnap<CallbackResult = void>(\n operation: (snap: {\n client: KeyringClient;\n keyring: RestrictedSnapKeyring;\n }) => Promise<CallbackResult>,\n ): Promise<CallbackResult> {\n await this.ensureReady();\n\n return await operation({\n client: this.#client,\n keyring: await this.#getRestrictedSnapKeyring(),\n });\n }\n\n abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean;\n\n protected abstract createAccountV1(\n keyring: RestrictedSnapKeyring,\n options: { entropySource: EntropySourceId; groupIndex: number },\n ): Promise<KeyringAccount>;\n\n protected toBip44Account(\n account: KeyringAccount,\n _options: { entropySource: EntropySourceId; groupIndex: number },\n ): Bip44Account<KeyringAccount> {\n assertIsBip44Account(account);\n return account;\n }\n\n protected async createBip44Accounts(\n keyring: RestrictedSnapKeyring,\n options:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n return this.withMaxConcurrency(async () => {\n let groupIndexOffset = 0;\n let snapAccounts: KeyringAccount[] = [];\n\n const batched = this.config.createAccounts.batched ?? false;\n const { entropySource } = options;\n\n const createAccountV1 = async (\n groupIndex: number,\n ): Promise<KeyringAccount> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccountV1,\n data: {\n provider: this.getName(),\n groupIndex,\n },\n },\n () =>\n this.createAccountV1(keyring, { entropySource, groupIndex }),\n ),\n this.config.createAccounts.timeoutMs,\n );\n const createAccountsV2 = async (\n optionsV2:\n | CreateAccountBip44DeriveIndexOptions\n | CreateAccountBip44DeriveIndexRangeOptions,\n ): Promise<KeyringAccount[]> =>\n await withTimeout(\n () =>\n this.trace(\n {\n name: TraceName.ProviderCreateAccounts,\n data: {\n provider: this.getName(),\n ...toCreateAccountsV2DataTraces(optionsV2),\n },\n },\n () => keyring.createAccounts(optionsV2),\n ),\n this.config.createAccounts.timeoutMs,\n );\n\n if (options.type === `${AccountCreationType.Bip44DeriveIndexRange}`) {\n if (batched) {\n // Batch account creations.\n snapAccounts = await createAccountsV2(options);\n } else {\n const { range } = options;\n\n // Create accounts one by one.\n for (\n let groupIndex = range.from;\n groupIndex <= range.to;\n groupIndex++\n ) {\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts.push(snapAccount);\n }\n }\n\n // Group indices are sequential, so we just need the starting index.\n groupIndexOffset = options.range.from;\n } else {\n if (batched) {\n // Create account using new v2-like flow (no async flow + no Snap keyring events).\n snapAccounts = await createAccountsV2(options);\n } else {\n const { groupIndex } = options;\n\n // Create account using the existing v1 flow.\n const snapAccount = await createAccountV1(groupIndex);\n\n snapAccounts = [snapAccount];\n }\n\n // For single account, there will only be 1 account, so we can use the\n // provided group index directly.\n groupIndexOffset = options.groupIndex;\n }\n\n return snapAccounts.map((snapAccount, index) => {\n const groupIndex = groupIndexOffset + index;\n const account = this.toBip44Account(snapAccount, {\n entropySource,\n groupIndex,\n });\n\n this.accounts.add(snapAccount.id);\n return account;\n });\n });\n }\n\n async createAccounts(\n options: CreateAccountOptions,\n ): Promise<Bip44Account<KeyringAccount>[]> {\n assertCreateAccountOptionIsSupported(options, [\n `${AccountCreationType.Bip44DeriveIndex}`,\n `${AccountCreationType.Bip44DeriveIndexRange}`,\n ]);\n\n return this.withSnap(async ({ keyring }) =>\n this.createBip44Accounts(keyring, options),\n );\n }\n\n /**\n * Delete a snap account by id.\n *\n * Resolves the account's address from the tracked account, then forwards to\n * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes\n * care of notifying the snap to clean up its own state through the normal\n * account-removal flow (same path used by `resyncAccounts`).\n *\n * @param id - The id of the account to delete.\n */\n async deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void> {\n const account = this.getAccount(id);\n\n await this.#withSnapKeyring(async ({ keyring }) => {\n await keyring.deleteAccount(account.id);\n });\n\n this.accounts.delete(id);\n }\n\n abstract discoverAccounts(options: {\n entropySource: EntropySourceId;\n groupIndex: number;\n }): Promise<Bip44Account<KeyringAccount>[]>;\n}\n\nexport const isSnapAccountProvider = (\n provider: unknown,\n): provider is SnapAccountProvider => {\n return provider instanceof SnapAccountProvider;\n};\n"]}
@@ -24,8 +24,10 @@ function makeMockAccountProvider(accounts = []) {
24
24
  getAccount: jest.fn(),
25
25
  getAccounts: jest.fn(),
26
26
  createAccounts: jest.fn(),
27
+ deleteAccount: jest.fn(),
27
28
  discoverAccounts: jest.fn(),
28
29
  isAccountCompatible: jest.fn(),
30
+ isAligned: jest.fn().mockReturnValue(false),
29
31
  getName: jest.fn(),
30
32
  isDisabled: jest.fn(),
31
33
  setEnabled: jest.fn(),
@@ -53,6 +55,8 @@ function setupBip44AccountProvider({ name = 'Mocked Provider', accounts, mocks =
53
55
  mocks.init.mockImplementation((accountIds) => {
54
56
  accountIds.forEach((id) => mocks.accounts.add(id));
55
57
  });
58
+ mocks.isAligned.mockImplementation((_context, accountIds) => accountIds.length >= 1 &&
59
+ accountIds.every((id) => mocks.accounts.has(id)));
56
60
  if (index === 0) {
57
61
  // Make the first provider to always be an `EvmAccountProvider`, since we
58
62
  // check for this pre-condition in some methods.
@@ -1 +1 @@
1
- {"version":3,"file":"providers.cjs","sourceRoot":"","sources":["../../src/tests/providers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport { BtcScope, EthScope, SolScope, TrxScope } from '@metamask/keyring-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\n\nimport { AccountProviderWrapper, EvmAccountProvider } from '../providers';\nimport { GroupIndexRange } from '../utils';\n\nexport type MockAccountProvider = {\n mockAccounts: KeyringAccount[];\n accounts: Set<KeyringAccount['id']>;\n capabilities: KeyringCapabilities;\n constructor: jest.Mock;\n alignAccounts: jest.Mock;\n init: jest.Mock;\n resyncAccounts: jest.Mock;\n getAccount: jest.Mock;\n getAccounts: jest.Mock;\n createAccounts: jest.Mock;\n discoverAccounts: jest.Mock;\n isAccountCompatible: jest.Mock;\n getName: jest.Mock;\n isEnabled: boolean;\n isDisabled: jest.Mock;\n setEnabled: jest.Mock;\n};\n\nexport function makeMockAccountProvider(\n accounts: KeyringAccount[] = [],\n): MockAccountProvider {\n return {\n mockAccounts: accounts,\n accounts: new Set(),\n capabilities: {\n scopes: [\n SolScope.Devnet,\n SolScope.Testnet,\n BtcScope.Testnet,\n TrxScope.Shasta,\n EthScope.Eoa,\n ],\n bip44: { deriveIndex: true },\n },\n constructor: jest.fn(),\n alignAccounts: jest.fn(),\n init: jest.fn(),\n resyncAccounts: jest.fn(),\n getAccount: jest.fn(),\n getAccounts: jest.fn(),\n createAccounts: jest.fn(),\n discoverAccounts: jest.fn(),\n isAccountCompatible: jest.fn(),\n getName: jest.fn(),\n isDisabled: jest.fn(),\n setEnabled: jest.fn(),\n isEnabled: true,\n };\n}\n\nexport function setupBip44AccountProvider({\n name = 'Mocked Provider',\n accounts,\n mocks = makeMockAccountProvider(),\n index,\n}: {\n name?: string;\n mocks?: MockAccountProvider;\n accounts: KeyringAccount[];\n filter?: (account: KeyringAccount) => boolean;\n index?: number;\n}): MockAccountProvider {\n // You can mock this and all other mocks will re-use that list\n // of accounts.\n mocks.mockAccounts = accounts;\n mocks.accounts = new Set(accounts.map((account) => account.id));\n // Toggle enabled state only\n mocks.setEnabled.mockImplementation((enabled: boolean) => {\n mocks.isEnabled = enabled;\n });\n mocks.isDisabled.mockImplementation(() => !mocks.isEnabled);\n\n const getAccounts = (): KeyringAccount[] =>\n mocks.mockAccounts.filter((account) =>\n [...mocks.accounts].includes(account.id),\n );\n\n mocks.getName.mockImplementation(() => name);\n\n mocks.getAccounts.mockImplementation(getAccounts);\n mocks.getAccount.mockImplementation(\n (id: Bip44Account<KeyringAccount>['id']) =>\n // Assuming this never fails.\n getAccounts().find((account) => account.id === id),\n );\n mocks.createAccounts.mockResolvedValue([]);\n mocks.init.mockImplementation(\n (accountIds: Bip44Account<KeyringAccount>['id'][]) => {\n accountIds.forEach((id) => mocks.accounts.add(id));\n },\n );\n\n if (index === 0) {\n // Make the first provider to always be an `EvmAccountProvider`, since we\n // check for this pre-condition in some methods.\n Object.setPrototypeOf(mocks, EvmAccountProvider.prototype);\n }\n\n if (index !== 0) {\n Object.setPrototypeOf(mocks, AccountProviderWrapper.prototype);\n }\n\n return mocks;\n}\n\n/**\n * Helper to mock a single createAccounts call while updating the provider's\n * internal state so subsequent getAccount/getAccounts can resolve the accounts.\n *\n * @param provider - The mock provider whose createAccounts call to mock.\n * @param created - The accounts to be returned and persisted in the mock state.\n */\nexport function mockCreateAccountsOnce(\n provider: MockAccountProvider,\n created: KeyringAccount[],\n): void {\n provider.createAccounts.mockImplementationOnce(async () => {\n // Add newly created accounts to the provider's internal store\n for (const acc of created) {\n if (!provider.mockAccounts.some((a) => a.id === acc.id)) {\n provider.mockAccounts.push(acc);\n }\n }\n // Merge IDs into the visible list used by getAccounts/getAccount\n const ids = created.map((a) => a.id);\n for (const id of ids) {\n provider.accounts.add(id);\n }\n\n return created;\n });\n}\n\n/**\n * Helper to convert a group index range to an array of group indices, inclusive of the\n * start and end indices.\n *\n * @param range - The range.\n * @param range.from - The starting index of the range (inclusive).\n * @param range.to - The ending index of the range (inclusive).\n * @returns An array of group indices from `from` to `to`, inclusive.\n */\nexport function toGroupIndexRangeArray({\n from = 0,\n to,\n}: GroupIndexRange): number[] {\n return Array.from({ length: to - from + 1 }, (_, i) => from + i);\n}\n"]}
1
+ {"version":3,"file":"providers.cjs","sourceRoot":"","sources":["../../src/tests/providers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport { BtcScope, EthScope, SolScope, TrxScope } from '@metamask/keyring-api';\nimport type { KeyringAccount } from '@metamask/keyring-api';\nimport type { KeyringCapabilities } from '@metamask/keyring-api/v2';\n\nimport { AccountProviderWrapper, EvmAccountProvider } from '../providers';\nimport { GroupIndexRange } from '../utils';\n\nexport type MockAccountProvider = {\n mockAccounts: KeyringAccount[];\n accounts: Set<KeyringAccount['id']>;\n capabilities: KeyringCapabilities;\n constructor: jest.Mock;\n alignAccounts: jest.Mock;\n init: jest.Mock;\n resyncAccounts: jest.Mock;\n getAccount: jest.Mock;\n getAccounts: jest.Mock;\n createAccounts: jest.Mock;\n deleteAccount: jest.Mock;\n discoverAccounts: jest.Mock;\n isAccountCompatible: jest.Mock;\n isAligned: jest.Mock;\n getName: jest.Mock;\n isEnabled: boolean;\n isDisabled: jest.Mock;\n setEnabled: jest.Mock;\n};\n\nexport function makeMockAccountProvider(\n accounts: KeyringAccount[] = [],\n): MockAccountProvider {\n return {\n mockAccounts: accounts,\n accounts: new Set(),\n capabilities: {\n scopes: [\n SolScope.Devnet,\n SolScope.Testnet,\n BtcScope.Testnet,\n TrxScope.Shasta,\n EthScope.Eoa,\n ],\n bip44: { deriveIndex: true },\n },\n constructor: jest.fn(),\n alignAccounts: jest.fn(),\n init: jest.fn(),\n resyncAccounts: jest.fn(),\n getAccount: jest.fn(),\n getAccounts: jest.fn(),\n createAccounts: jest.fn(),\n deleteAccount: jest.fn(),\n discoverAccounts: jest.fn(),\n isAccountCompatible: jest.fn(),\n isAligned: jest.fn().mockReturnValue(false),\n getName: jest.fn(),\n isDisabled: jest.fn(),\n setEnabled: jest.fn(),\n isEnabled: true,\n };\n}\n\nexport function setupBip44AccountProvider({\n name = 'Mocked Provider',\n accounts,\n mocks = makeMockAccountProvider(),\n index,\n}: {\n name?: string;\n mocks?: MockAccountProvider;\n accounts: KeyringAccount[];\n filter?: (account: KeyringAccount) => boolean;\n index?: number;\n}): MockAccountProvider {\n // You can mock this and all other mocks will re-use that list\n // of accounts.\n mocks.mockAccounts = accounts;\n mocks.accounts = new Set(accounts.map((account) => account.id));\n // Toggle enabled state only\n mocks.setEnabled.mockImplementation((enabled: boolean) => {\n mocks.isEnabled = enabled;\n });\n mocks.isDisabled.mockImplementation(() => !mocks.isEnabled);\n\n const getAccounts = (): KeyringAccount[] =>\n mocks.mockAccounts.filter((account) =>\n [...mocks.accounts].includes(account.id),\n );\n\n mocks.getName.mockImplementation(() => name);\n\n mocks.getAccounts.mockImplementation(getAccounts);\n mocks.getAccount.mockImplementation(\n (id: Bip44Account<KeyringAccount>['id']) =>\n // Assuming this never fails.\n getAccounts().find((account) => account.id === id),\n );\n mocks.createAccounts.mockResolvedValue([]);\n mocks.init.mockImplementation(\n (accountIds: Bip44Account<KeyringAccount>['id'][]) => {\n accountIds.forEach((id) => mocks.accounts.add(id));\n },\n );\n\n mocks.isAligned.mockImplementation(\n (\n _context: { entropySource: string; groupIndex: number },\n accountIds: string[],\n ) =>\n accountIds.length >= 1 &&\n accountIds.every((id) => mocks.accounts.has(id)),\n );\n\n if (index === 0) {\n // Make the first provider to always be an `EvmAccountProvider`, since we\n // check for this pre-condition in some methods.\n Object.setPrototypeOf(mocks, EvmAccountProvider.prototype);\n }\n\n if (index !== 0) {\n Object.setPrototypeOf(mocks, AccountProviderWrapper.prototype);\n }\n\n return mocks;\n}\n\n/**\n * Helper to mock a single createAccounts call while updating the provider's\n * internal state so subsequent getAccount/getAccounts can resolve the accounts.\n *\n * @param provider - The mock provider whose createAccounts call to mock.\n * @param created - The accounts to be returned and persisted in the mock state.\n */\nexport function mockCreateAccountsOnce(\n provider: MockAccountProvider,\n created: KeyringAccount[],\n): void {\n provider.createAccounts.mockImplementationOnce(async () => {\n // Add newly created accounts to the provider's internal store\n for (const acc of created) {\n if (!provider.mockAccounts.some((a) => a.id === acc.id)) {\n provider.mockAccounts.push(acc);\n }\n }\n // Merge IDs into the visible list used by getAccounts/getAccount\n const ids = created.map((a) => a.id);\n for (const id of ids) {\n provider.accounts.add(id);\n }\n\n return created;\n });\n}\n\n/**\n * Helper to convert a group index range to an array of group indices, inclusive of the\n * start and end indices.\n *\n * @param range - The range.\n * @param range.from - The starting index of the range (inclusive).\n * @param range.to - The ending index of the range (inclusive).\n * @returns An array of group indices from `from` to `to`, inclusive.\n */\nexport function toGroupIndexRangeArray({\n from = 0,\n to,\n}: GroupIndexRange): number[] {\n return Array.from({ length: to - from + 1 }, (_, i) => from + i);\n}\n"]}
@@ -13,8 +13,10 @@ export type MockAccountProvider = {
13
13
  getAccount: jest.Mock;
14
14
  getAccounts: jest.Mock;
15
15
  createAccounts: jest.Mock;
16
+ deleteAccount: jest.Mock;
16
17
  discoverAccounts: jest.Mock;
17
18
  isAccountCompatible: jest.Mock;
19
+ isAligned: jest.Mock;
18
20
  getName: jest.Mock;
19
21
  isEnabled: boolean;
20
22
  isDisabled: jest.Mock;
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.cts","sourceRoot":"","sources":["../../src/tests/providers.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAAiC;AAGpE,OAAO,EAAE,eAAe,EAAE,qBAAiB;AAE3C,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,YAAY,EAAE,mBAAmB,CAAC;IAClC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACzB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC5B,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC/B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,QAAQ,GAAE,cAAc,EAAO,GAC9B,mBAAmB,CA4BrB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,IAAwB,EACxB,QAAQ,EACR,KAAiC,EACjC,KAAK,GACN,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CA0CtB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,cAAc,EAAE,GACxB,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,IAAQ,EACR,EAAE,GACH,EAAE,eAAe,GAAG,MAAM,EAAE,CAE5B"}
1
+ {"version":3,"file":"providers.d.cts","sourceRoot":"","sources":["../../src/tests/providers.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAAiC;AAGpE,OAAO,EAAE,eAAe,EAAE,qBAAiB;AAE3C,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,YAAY,EAAE,mBAAmB,CAAC;IAClC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACzB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACzB,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC5B,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC/B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;IACrB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,QAAQ,GAAE,cAAc,EAAO,GAC9B,mBAAmB,CA8BrB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,IAAwB,EACxB,QAAQ,EACR,KAAiC,EACjC,KAAK,GACN,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CAmDtB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,cAAc,EAAE,GACxB,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,IAAQ,EACR,EAAE,GACH,EAAE,eAAe,GAAG,MAAM,EAAE,CAE5B"}
@@ -13,8 +13,10 @@ export type MockAccountProvider = {
13
13
  getAccount: jest.Mock;
14
14
  getAccounts: jest.Mock;
15
15
  createAccounts: jest.Mock;
16
+ deleteAccount: jest.Mock;
16
17
  discoverAccounts: jest.Mock;
17
18
  isAccountCompatible: jest.Mock;
19
+ isAligned: jest.Mock;
18
20
  getName: jest.Mock;
19
21
  isEnabled: boolean;
20
22
  isDisabled: jest.Mock;
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.mts","sourceRoot":"","sources":["../../src/tests/providers.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAAiC;AAGpE,OAAO,EAAE,eAAe,EAAE,qBAAiB;AAE3C,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,YAAY,EAAE,mBAAmB,CAAC;IAClC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACzB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC5B,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC/B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,QAAQ,GAAE,cAAc,EAAO,GAC9B,mBAAmB,CA4BrB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,IAAwB,EACxB,QAAQ,EACR,KAAiC,EACjC,KAAK,GACN,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CA0CtB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,cAAc,EAAE,GACxB,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,IAAQ,EACR,EAAE,GACH,EAAE,eAAe,GAAG,MAAM,EAAE,CAE5B"}
1
+ {"version":3,"file":"providers.d.mts","sourceRoot":"","sources":["../../src/tests/providers.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,8BAA8B;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,iCAAiC;AAGpE,OAAO,EAAE,eAAe,EAAE,qBAAiB;AAE3C,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,YAAY,EAAE,mBAAmB,CAAC;IAClC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACzB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;IACvB,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC;IAC1B,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC;IACzB,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC5B,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC;IAC/B,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;IACrB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC;CACvB,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,QAAQ,GAAE,cAAc,EAAO,GAC9B,mBAAmB,CA8BrB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,IAAwB,EACxB,QAAQ,EACR,KAAiC,EACjC,KAAK,GACN,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CAmDtB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,cAAc,EAAE,GACxB,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,IAAQ,EACR,EAAE,GACH,EAAE,eAAe,GAAG,MAAM,EAAE,CAE5B"}
@@ -21,8 +21,10 @@ export function makeMockAccountProvider(accounts = []) {
21
21
  getAccount: jest.fn(),
22
22
  getAccounts: jest.fn(),
23
23
  createAccounts: jest.fn(),
24
+ deleteAccount: jest.fn(),
24
25
  discoverAccounts: jest.fn(),
25
26
  isAccountCompatible: jest.fn(),
27
+ isAligned: jest.fn().mockReturnValue(false),
26
28
  getName: jest.fn(),
27
29
  isDisabled: jest.fn(),
28
30
  setEnabled: jest.fn(),
@@ -49,6 +51,8 @@ export function setupBip44AccountProvider({ name = 'Mocked Provider', accounts,
49
51
  mocks.init.mockImplementation((accountIds) => {
50
52
  accountIds.forEach((id) => mocks.accounts.add(id));
51
53
  });
54
+ mocks.isAligned.mockImplementation((_context, accountIds) => accountIds.length >= 1 &&
55
+ accountIds.every((id) => mocks.accounts.has(id)));
52
56
  if (index === 0) {
53
57
  // Make the first provider to always be an `EvmAccountProvider`, since we
54
58
  // check for this pre-condition in some methods.