{"version":3,"file":"qr-keyring.cjs","sourceRoot":"","sources":["../../src/v2/qr-keyring.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Bip44Account } from '@metamask/account-api';\nimport {\n  EthAccountType,\n  EthMethod,\n  EthScope,\n  KeyringAccountEntropyTypeOption,\n} from '@metamask/keyring-api';\nimport type { KeyringAccount, EntropySourceId } from '@metamask/keyring-api';\nimport { KeyringType } from '@metamask/keyring-api/v2';\nimport type {\n  CreateAccountOptions,\n  KeyringCapabilities,\n  Keyring,\n  CreateAccountBip44DeriveIndexOptions,\n} from '@metamask/keyring-api/v2';\nimport { EthKeyringWrapper } from '@metamask/keyring-sdk/v2';\nimport type { AccountId } from '@metamask/keyring-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { DeviceMode } from '../device';\nimport type { IndexedAddress } from '../device';\nimport type { QrKeyring as LegacyQrKeyring } from '../qr-keyring';\n\n/**\n * Methods supported by QR keyring EOA accounts.\n * QR keyrings support a subset of signing methods (no encryption, app keys, or EIP-7702).\n */\nconst QR_KEYRING_METHODS = [\n  EthMethod.SignTransaction,\n  EthMethod.PersonalSign,\n  EthMethod.SignTypedDataV4,\n];\n\n/**\n * Capabilities for HD mode devices (index-based derivation supported).\n */\nconst HD_MODE_CAPABILITIES: KeyringCapabilities = {\n  scopes: [EthScope.Eoa],\n  bip44: {\n    deriveIndex: true,\n  },\n};\n\n/**\n * Capabilities for Account mode devices (custom account selection).\n */\nconst ACCOUNT_MODE_CAPABILITIES: KeyringCapabilities = {\n  scopes: [EthScope.Eoa],\n  custom: {\n    createAccounts: true,\n  },\n};\n\n/**\n * Custom options for creating accounts on Account mode QR devices.\n * Account mode devices provide pre-defined addresses that must be selected by index.\n */\nexport type QrAccountModeCreateOptions = {\n  type: 'custom';\n  /**\n   * The entropy source ID (device fingerprint) to verify we're targeting the correct device.\n   */\n  entropySource: EntropySourceId;\n  /**\n   * The index of the pre-defined address to add from the device.\n   * This refers to the position in the device's address list, not a BIP-44 derivation index.\n   */\n  addressIndex: number;\n};\n\n/**\n * Account creation options for QR keyring.\n * Excludes unsupported types (custom, private-key:import) and adds our specific QrAccountModeCreateOptions.\n */\nexport type QrKeyringCreateAccountOptions =\n  | CreateAccountBip44DeriveIndexOptions\n  | QrAccountModeCreateOptions;\n\n/**\n * Concrete {@link Keyring} adapter for {@link QrKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * QR keyring via the unified V2 interface.\n *\n * Account handling differs by device mode:\n * - **HD mode**: Accounts are derived by index with `groupIndex` values.\n * Supports `bip44:derive-index` for index-based derivation.\n * - **Account mode**: Accounts are treated as private key imports since the\n * device provides pre-defined addresses with arbitrary paths. Uses `custom`\n * account creation type to select addresses by their position in the device.\n */\nexport type QrKeyringOptions = {\n  legacyKeyring: LegacyQrKeyring;\n  entropySource: EntropySourceId;\n};\n\nexport class QrKeyring\n  extends EthKeyringWrapper<LegacyQrKeyring>\n  implements Keyring\n{\n  readonly entropySource: EntropySourceId;\n\n  constructor(options: QrKeyringOptions) {\n    super({\n      type: KeyringType.Qr,\n      inner: options.legacyKeyring,\n      // Default capabilities - overridden by getter below\n      capabilities: HD_MODE_CAPABILITIES,\n    });\n    this.entropySource = options.entropySource;\n  }\n\n  /**\n   * Get the capabilities of this keyring.\n   *\n   * Overrides the base class getter to return capabilities dynamically\n   * based on the current device mode.\n   *\n   * @returns The keyring's capabilities.\n   */\n  override get capabilities(): KeyringCapabilities {\n    return this.inner.getMode() === DeviceMode.ACCOUNT\n      ? ACCOUNT_MODE_CAPABILITIES\n      : HD_MODE_CAPABILITIES;\n  }\n\n  /**\n   * Get the device state from the inner keyring.\n   *\n   * @returns The device state, or undefined if no device is paired.\n   */\n  async #getDeviceState(): Promise<\n    | {\n        mode: DeviceMode.HD;\n        indexes: Record<Hex, number>;\n      }\n    | {\n        mode: DeviceMode.ACCOUNT;\n        indexes: Record<Hex, number>;\n        paths: Record<Hex, string>;\n      }\n    | undefined\n  > {\n    const state = await this.inner.serialize();\n\n    if (!state?.initialized) {\n      return undefined;\n    }\n\n    if (state.keyringMode === DeviceMode.ACCOUNT) {\n      return {\n        mode: DeviceMode.ACCOUNT,\n        indexes: state.indexes,\n        paths: state.paths,\n      };\n    }\n\n    return {\n      mode: DeviceMode.HD,\n      indexes: state.indexes,\n    };\n  }\n\n  /**\n   * Creates a Bip44Account for HD mode devices.\n   *\n   * @param address - The account address.\n   * @param addressIndex - The account index in the derivation path.\n   * @returns The created Bip44Account.\n   */\n  #createHdModeAccount(\n    address: Hex,\n    addressIndex: number,\n  ): Bip44Account<KeyringAccount> {\n    const id = this.registry.register(address);\n\n    const derivationPath = this.inner.getPathFromAddress(address);\n\n    if (!derivationPath) {\n      throw new Error(\n        `Cannot create account for address ${address}: derivation path not found in keyring.`,\n      );\n    }\n\n    const account: Bip44Account<KeyringAccount> = {\n      id,\n      type: EthAccountType.Eoa,\n      address,\n      scopes: [...this.capabilities.scopes],\n      methods: [...QR_KEYRING_METHODS],\n      options: {\n        entropy: {\n          type: KeyringAccountEntropyTypeOption.Mnemonic,\n          id: this.entropySource,\n          groupIndex: addressIndex,\n          derivationPath,\n        },\n      },\n    };\n\n    this.registry.set(account);\n    return account;\n  }\n\n  /**\n   * Creates a KeyringAccount for Account mode devices.\n   *\n   * Account mode devices provide pre-defined addresses with arbitrary derivation\n   * paths, so we treat them as private key imports rather than BIP-44 accounts.\n   *\n   * @param address - The account address.\n   * @returns The created KeyringAccount.\n   */\n  #createAccountModeAccount(address: Hex): KeyringAccount {\n    const id = this.registry.register(address);\n\n    const account: KeyringAccount = {\n      id,\n      type: EthAccountType.Eoa,\n      address,\n      scopes: [...this.capabilities.scopes],\n      methods: [...QR_KEYRING_METHODS],\n      options: {\n        entropy: {\n          type: KeyringAccountEntropyTypeOption.Custom,\n        },\n      },\n    };\n\n    this.registry.set(account);\n    return account;\n  }\n\n  async getAccounts(): Promise<KeyringAccount[]> {\n    const addresses = await this.inner.getAccounts();\n    const deviceState = await this.#getDeviceState();\n\n    if (!deviceState) {\n      // No device paired yet, return empty\n      return [];\n    }\n\n    const { mode, indexes } = deviceState;\n\n    return addresses.map((address) => {\n      // Check if we already have this account in the registry\n      const existingId = this.registry.getAccountId(address);\n      if (existingId) {\n        const cached = this.registry.get(existingId);\n        if (cached) {\n          return cached;\n        }\n      }\n\n      if (mode === DeviceMode.HD) {\n        // HD mode: index must be in the map\n        const addressIndex = indexes[address];\n        if (addressIndex === undefined) {\n          throw new Error(\n            `Address ${address} not found in device indexes. This indicates an inconsistent keyring state.`,\n          );\n        }\n        return this.#createHdModeAccount(address, addressIndex);\n      }\n\n      // Account mode: validate address exists in paths map\n      const { paths } = deviceState;\n      if (paths[address] === undefined) {\n        throw new Error(\n          `Address ${address} not found in device paths. This indicates an inconsistent keyring state.`,\n        );\n      }\n      return this.#createAccountModeAccount(address);\n    });\n  }\n\n  async createAccounts(\n    options: QrKeyringCreateAccountOptions,\n  ): Promise<KeyringAccount[]> {\n    return this.withLock(async () => {\n      const deviceState = await this.#getDeviceState();\n\n      if (!deviceState) {\n        throw new Error('No device paired. Cannot create accounts.');\n      }\n\n      // Validate entropy source for all account creation types\n      if (options.entropySource !== this.entropySource) {\n        throw new Error(\n          `Entropy source mismatch: expected '${this.entropySource}', got '${options.entropySource}'`,\n        );\n      }\n\n      // Handle Account mode with custom account creation\n      if (deviceState.mode === DeviceMode.ACCOUNT) {\n        if (options.type !== 'custom') {\n          throw new Error(\n            `Account mode devices only support 'custom' account creation type, got '${options.type}'. ` +\n              `Use { type: 'custom', entropySource, addressIndex } to select a pre-defined address.`,\n          );\n        }\n        return this.#createAccountModeAccounts(options, deviceState);\n      }\n\n      // HD mode: support derive-index\n      return this.#createHdModeAccounts(options, deviceState);\n    });\n  }\n\n  /**\n   * Creates accounts for Account mode devices using custom options.\n   *\n   * @param options - The account creation options.\n   * @param deviceState - The current device state.\n   * @param deviceState.mode - The device mode (ACCOUNT).\n   * @param deviceState.paths - Map of addresses to derivation paths.\n   * @param deviceState.indexes - Map of addresses to their indexes.\n   * @returns The created accounts.\n   */\n  async #createAccountModeAccounts(\n    options: QrAccountModeCreateOptions,\n    deviceState: {\n      mode: DeviceMode.ACCOUNT;\n      paths: Record<Hex, string>;\n      indexes: Record<Hex, number>;\n    },\n  ): Promise<KeyringAccount[]> {\n    const { addressIndex } = options;\n\n    if (!Number.isInteger(addressIndex) || addressIndex < 0) {\n      throw new Error(\n        `Invalid addressIndex: ${String(\n          addressIndex,\n        )}. Must be a non-negative integer.`,\n      );\n    }\n\n    // Get available addresses from paths\n    const availableAddresses = Object.keys(deviceState.paths) as Hex[];\n    if (addressIndex >= availableAddresses.length) {\n      throw new Error(\n        `Address index ${addressIndex} is out of bounds. Device has ${availableAddresses.length} pre-defined address(es).`,\n      );\n    }\n\n    const address = availableAddresses[addressIndex];\n\n    // Check if already exists\n    const currentAccounts = await this.getAccounts();\n    const existingAccount = currentAccounts.find(\n      (account) => account.address.toLowerCase() === address?.toLowerCase(),\n    );\n    if (existingAccount) {\n      return [existingAccount];\n    }\n\n    // Add the account via the inner keyring\n    this.inner.setAccountToUnlock(addressIndex);\n    const [newAddress] = await this.inner.addAccounts(1);\n\n    if (!newAddress) {\n      throw new Error('Failed to create new account');\n    }\n\n    const newAccount = this.#createAccountModeAccount(newAddress);\n    return [newAccount];\n  }\n\n  /**\n   * Creates accounts for HD mode devices using index-based derivation.\n   *\n   * @param options - The account creation options.\n   * @param _deviceState - The current device state (reserved for future use).\n   * @param _deviceState.indexes - Map of addresses to their indexes.\n   * @returns The created accounts.\n   */\n  async #createHdModeAccounts(\n    options: CreateAccountOptions,\n    _deviceState: { indexes: Record<Hex, number> },\n  ): Promise<Bip44Account<KeyringAccount>[]> {\n    if (options.type !== 'bip44:derive-index') {\n      throw new Error(\n        `Unsupported account creation type for HD mode QrKeyring: ${String(\n          options.type,\n        )}. Supported type: 'bip44:derive-index'.`,\n      );\n    }\n\n    if (!Number.isInteger(options.groupIndex) || options.groupIndex < 0) {\n      throw new Error(\n        `Invalid groupIndex: ${options.groupIndex}. Must be a non-negative integer.`,\n      );\n    }\n\n    const targetIndex = options.groupIndex;\n\n    // Check if an account at this index already exists\n    const currentAccounts = await this.getAccounts();\n    const existingAccount = currentAccounts.find(\n      (account) =>\n        account.options.entropy?.type ===\n          KeyringAccountEntropyTypeOption.Mnemonic &&\n        account.options.entropy.groupIndex === targetIndex,\n    );\n\n    if (existingAccount) {\n      return [existingAccount as Bip44Account<KeyringAccount>];\n    }\n\n    // Derive the account at the specified index\n    this.inner.setAccountToUnlock(targetIndex);\n    const [newAddress] = await this.inner.addAccounts(1);\n\n    if (!newAddress) {\n      throw new Error('Failed to create new account');\n    }\n\n    const newAccount = this.#createHdModeAccount(newAddress, targetIndex);\n    return [newAccount];\n  }\n\n  /**\n   * Delete an account from the keyring.\n   *\n   * @param accountId - The account ID to delete.\n   */\n  async deleteAccount(accountId: AccountId): Promise<void> {\n    await this.withLock(async () => {\n      const { address } = await this.getAccount(accountId);\n      const hexAddress = this.toHexAddress(address);\n\n      // Remove from the legacy keyring\n      this.inner.removeAccount(hexAddress);\n\n      // Remove from the registry\n      this.registry.delete(accountId);\n    });\n  }\n\n  /**\n   * @returns The name of the paired device, or the keyring type if no device\n   * is paired.\n   */\n  getName(): string {\n    return this.inner.getName();\n  }\n\n  /**\n   * @returns The current device mode (HD or Account), or `undefined` if no\n   * device is paired.\n   */\n  getMode(): DeviceMode | undefined {\n    return this.inner.getMode();\n  }\n\n  /**\n   * Fetch the first page of candidate addresses from the device.\n   *\n   * @returns The first page of addresses.\n   */\n  async getFirstPage(): Promise<IndexedAddress[]> {\n    return this.inner.getFirstPage();\n  }\n\n  /**\n   * Fetch the next page of candidate addresses from the device.\n   *\n   * @returns The next page of addresses.\n   */\n  async getNextPage(): Promise<IndexedAddress[]> {\n    return this.inner.getNextPage();\n  }\n\n  /**\n   * Fetch the previous page of candidate addresses from the device.\n   *\n   * @returns The previous page of addresses.\n   */\n  async getPreviousPage(): Promise<IndexedAddress[]> {\n    return this.inner.getPreviousPage();\n  }\n\n  /**\n   * Clear the inner keyring's device-pairing state and accounts, and reset\n   * the V2 account registry to keep them in sync.\n   */\n  async forgetDevice(): Promise<void> {\n    await this.withLock(async () => {\n      await this.inner.forgetDevice();\n      this.registry.clear();\n    });\n  }\n}\n"]}