UNPKG

@metamask/multichain-account-service

Version:
141 lines 7.04 kB
import type { Bip44Account } from "@metamask/account-api"; import type { TraceCallback, TraceRequest } from "@metamask/controller-utils"; import type { SnapKeyring as SnapKeyringV2 } from "@metamask/eth-snap-keyring/v2"; import type { CreateAccountBip44DeriveIndexOptions, CreateAccountBip44DeriveIndexRangeOptions, CreateAccountBip44DiscoverOptions, CreateAccountOptions, EntropySourceId, KeyringAccount } from "@metamask/keyring-api"; import type { KeyringCapabilities } from "@metamask/keyring-api/v2"; import type { InternalAccount } from "@metamask/keyring-internal-api"; import type { SnapId } from "@metamask/snaps-sdk"; import type { CaipChainId } from "@metamask/utils"; import type { MultichainAccountServiceMessenger } from "../types.cjs"; import { BaseBip44AccountProvider } from "./BaseBip44AccountProvider.cjs"; import type { SnapKeyringClient } from "./SnapKeyringClient.cjs"; /** * A proxy to the Snap's keyring operations that routes every call through the * `KeyringController` mutex (via {@link SnapAccountProvider.#withSnapKeyring}). * Callers receive this object from {@link SnapAccountProvider.withSnap} and * never interact with the raw keyring or the mutex directly. */ export type SnapKeyringProxy = { createAccounts: SnapKeyringV2['createAccounts']; deleteAccount: SnapKeyringV2['deleteAccount']; }; export type SnapAccountProviderConfig = { maxConcurrency?: number; discovery: { enabled?: boolean; maxAttempts: number; timeoutMs: number; backOffMs: number; }; createAccounts: { /** * Timeout for account creation operations. * * NOTE: Batching (and thus whether a single call may create multiple * accounts) is driven by the Snap's declared capabilities, not this config. * The value might have to be adapted when the Snap supports batching. */ timeoutMs: number; }; resyncAccounts?: { /** * Whether to automatically remove extra Snap accounts when the Snap has * more accounts than MetaMask. If `false`, a warning is logged instead. * Defaults to `true`. */ autoRemoveExtraSnapAccounts?: boolean; }; }; export declare abstract class SnapAccountProvider extends BaseBip44AccountProvider { #private; readonly snapId: SnapId; protected readonly config: SnapAccountProviderConfig; /** * The Snap's keyring capabilities, sourced from `SnapAccountService` (which * reads them from the Snap's manifest). Populated the first time the client * is resolved; defaults to an empty capability set until then. */ capabilities: KeyringCapabilities; /** * Scopes passed to the v1 `discoverAccounts` client method. Only used on the * v1 discovery path. * * TODO: Remove once all Snaps are fully v2 — discovery is then driven by the * Snap's own supported scopes via `createAccounts({ bip44:discover })`. */ protected abstract readonly v1DiscoveryScopes: CaipChainId[]; constructor(snapId: SnapId, messenger: MultichainAccountServiceMessenger, config: SnapAccountProviderConfig, trace?: TraceCallback); /** * Ensures that the Snap is ready to be used. * * Once this resolves, a Snap keyring for {@link snapId} is guaranteed to * exist in the `KeyringController`, so subsequent {@link #withSnapKeyring} * calls will not fail with "No keyring matches the selector". * * @returns A promise that resolves when the Snap is ready. * @throws An error if the Snap could not become ready. */ ensureReady(): Promise<void>; /** * Wraps an async operation with concurrency limiting based on maxConcurrency config. * If maxConcurrency is Infinity (the default), the operation runs immediately without throttling. * Otherwise, it's queued through the semaphore to respect the concurrency limit. * * @param operation - The async operation to execute. * @returns The result of the operation. */ protected withMaxConcurrency<Result>(operation: () => Promise<Result>): Promise<Result>; protected trace<ReturnType>(request: TraceRequest, fn: () => Promise<ReturnType>): Promise<ReturnType>; /** * Whether the Snap supports the v2 keyring protocol, inferred from its * declared capabilities (a v2-capable Snap declares BIP-44 capabilities). * * @returns `true` if the Snap is v2-capable. */ protected isV2(): boolean; resyncAccounts(accounts: Bip44Account<InternalAccount>[]): Promise<void>; protected withSnap<CallbackResult = void>(operation: (snap: { client: SnapKeyringClient; keyring: SnapKeyringProxy; }) => Promise<CallbackResult>): Promise<CallbackResult>; abstract isAccountCompatible(account: Bip44Account<InternalAccount>): boolean; protected toBip44Account(account: KeyringAccount, _options: { entropySource: EntropySourceId; groupIndex: number; }): Bip44Account<KeyringAccount>; protected createBip44Accounts(keyring: SnapKeyringProxy, options: CreateAccountBip44DeriveIndexOptions | CreateAccountBip44DeriveIndexRangeOptions | CreateAccountBip44DiscoverOptions): Promise<Bip44Account<KeyringAccount>[]>; createAccounts(options: CreateAccountOptions): Promise<Bip44Account<KeyringAccount>[]>; /** * Delete a snap account by id. * * Resolves the account's address from the tracked account, then forwards to * the legacy `SnapKeyring.removeAccount(address)`. The Snap keyring takes * care of notifying the snap to clean up its own state through the normal * account-removal flow (same path used by `resyncAccounts`). * * @param id - The id of the account to delete. */ deleteAccount(id: Bip44Account<KeyringAccount>['id']): Promise<void>; /** * Discovers accounts for the given entropy source and group index. * * v2 Snaps drive discovery through `createAccounts({ bip44:discover })`: the * Snap checks for on-chain activity (using its own supported scopes) and * returns the created account(s), or nothing once discovery is exhausted. * * v1 Snaps use the client's `discoverAccounts` to detect activity on * {@link v1DiscoveryScopes}, then create the account for the group index. * * @param options - The discovery options. * @param options.entropySource - The entropy source to discover accounts for. * @param options.groupIndex - The group index to discover accounts for. * @returns The discovered (and created) accounts, or an empty array when * there is nothing to discover at this group index. */ discoverAccounts({ entropySource, groupIndex, }: { entropySource: EntropySourceId; groupIndex: number; }): Promise<Bip44Account<KeyringAccount>[]>; } export declare const isSnapAccountProvider: (provider: unknown) => provider is SnapAccountProvider; //# sourceMappingURL=SnapAccountProvider.d.cts.map