{"version":3,"file":"trezor-keyring.cjs","sourceRoot":"","sources":["../../src/v2/trezor-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} from '@metamask/keyring-api/v2';\nimport { EthKeyringWrapper } from '@metamask/keyring-sdk/v2';\nimport type { AccountId, EthKeyring } from '@metamask/keyring-utils';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport type { TrezorBridge } from '../trezor-bridge';\nimport type {\n  AccountPage,\n  TrezorKeyring as LegacyTrezorKeyring,\n} from '../trezor-keyring';\n\n/**\n * Methods supported by Trezor keyring EOA accounts.\n * Trezor keyrings support a subset of signing methods (no encryption, app keys, or EIP-7702).\n */\nconst TREZOR_KEYRING_METHODS = [\n  EthMethod.SignTransaction,\n  EthMethod.PersonalSign,\n  EthMethod.SignTypedDataV3,\n  EthMethod.SignTypedDataV4,\n];\n\nconst trezorKeyringCapabilities: KeyringCapabilities = {\n  scopes: [EthScope.Eoa],\n  bip44: {\n    deriveIndex: true,\n    derivePath: true,\n  },\n};\n\n/**\n * BIP-44 standard HD path prefix constant for Ethereum.\n * Used as default for derive-index operations.\n */\nexport const BIP44_HD_PATH_PREFIX = `m/44'/60'/0'/0`;\n\n/**\n * SLIP-0044 testnet HD path prefix constant.\n */\nexport const SLIP0044_TESTNET_PATH_PREFIX = `m/44'/1'/0'/0`;\n\n/**\n * Legacy MEW (MyEtherWallet) HD path prefix constant.\n */\nexport const LEGACY_MEW_PATH_PREFIX = `m/44'/60'/0'`;\n\n/**\n * Allowed HD paths for Trezor keyring.\n * These must match the keys in ALLOWED_HD_PATHS from trezor-keyring.ts.\n */\nconst ALLOWED_HD_PATHS = [\n  BIP44_HD_PATH_PREFIX,\n  SLIP0044_TESTNET_PATH_PREFIX,\n  LEGACY_MEW_PATH_PREFIX,\n] as const;\n\n/**\n * Type representing one of the allowed Trezor HD paths.\n * Used by inner.setHdPath which expects one of these specific paths.\n */\ntype AllowedHdPath = (typeof ALLOWED_HD_PATHS)[number];\n\n/**\n * Regex pattern for validating and parsing Trezor derivation paths.\n * Matches BIP-44 style paths: m/44'/{coin}'/{segments}/{index}\n * where coin is 60' (Ethereum) or 1' (testnet).\n * Captures: [1] = base path prefix, [2] = index\n * The prefix is then validated against ALLOWED_HD_PATHS.\n */\nconst DERIVATION_PATH_PATTERN = /^(m\\/44'\\/(?:60'|1')(?:\\/\\d+'?)*)\\/(\\d+)$/u;\n\n/**\n * Concrete {@link Keyring} adapter for {@link TrezorKeyring}.\n *\n * This wrapper exposes the accounts and signing capabilities of the legacy\n * Trezor keyring via the unified V2 interface.\n *\n * All Trezor keyring accounts are BIP-44 derived from the device.\n */\nexport type TrezorKeyringOptions = {\n  legacyKeyring: LegacyTrezorKeyring;\n  entropySource: EntropySourceId;\n  type?: KeyringType.Trezor | KeyringType.OneKey;\n};\n\n// LegacyTrezorKeyring.signTransaction returns `TypedTransaction | OldEthJsTransaction` for\n// backwards compatibility with old ethereumjs-tx, but EthKeyring expects `TypedTxData`.\n// The runtime behavior is correct - we cast the type to satisfy the constraint.\ntype TrezorKeyringAsEthKeyring = LegacyTrezorKeyring & EthKeyring;\n\nexport class TrezorKeyring\n  extends EthKeyringWrapper<\n    TrezorKeyringAsEthKeyring,\n    Bip44Account<KeyringAccount>\n  >\n  implements Keyring\n{\n  readonly entropySource: EntropySourceId;\n\n  constructor(options: TrezorKeyringOptions) {\n    super({\n      type: options.type ?? KeyringType.Trezor,\n      inner: options.legacyKeyring as TrezorKeyringAsEthKeyring,\n      capabilities: trezorKeyringCapabilities,\n    });\n    this.entropySource = options.entropySource;\n  }\n\n  /**\n   * Hydrate the underlying keyring from a previously serialized state.\n   *\n   * Overrides the base class implementation to avoid calling `getAccounts()`\n   * when the Trezor device is locked. The base class calls `getAccounts()` to\n   * rebuild the registry, but for Trezor keyrings this requires the HDKey to\n   * be initialized (via `unlock()`). Since the device may not be connected\n   * during deserialization, we skip the registry rebuild here. The registry\n   * will be populated on the first call to `getAccounts()` after the device\n   * is unlocked.\n   *\n   * @param state - The serialized keyring state.\n   */\n  async deserialize(state: Json): Promise<void> {\n    await this.withLock(async () => {\n      // Clear the registry when deserializing\n      this.registry.clear();\n\n      // Deserialize the legacy keyring state only.\n      // We intentionally skip calling getAccounts() here because the Trezor\n      // device may be locked (HDKey not initialized). The TrezorKeyring's\n      // deserialize restores the accounts array, but not the paths map, so\n      // getIndexForAddress would need to derive addresses which requires an\n      // initialized HDKey. The registry will be populated lazily when\n      // getAccounts() is called after the device is unlocked.\n      await this.inner.deserialize(state);\n    });\n  }\n\n  /**\n   * Parses a derivation path to extract the base HD path and account index.\n   *\n   * Supports the allowed Trezor paths:\n   * - m/44'/60'/0'/0/{index} (BIP44 standard)\n   * - m/44'/60'/0'/{index} (legacy MEW)\n   * - m/44'/1'/0'/0/{index} (SLIP0044 testnet)\n   *\n   * @param derivationPath - The full derivation path (e.g., m/44'/60'/0'/0/5).\n   * @returns The base HD path and account index.\n   * @throws If the path format is invalid or not an allowed Trezor path.\n   */\n  #parseDerivationPath(derivationPath: string): {\n    basePath: AllowedHdPath;\n    index: number;\n  } {\n    const match = derivationPath.match(DERIVATION_PATH_PATTERN);\n    if (!match?.[1] || !match[2]) {\n      throw new Error(\n        `Invalid derivation path: ${derivationPath}. ` +\n          `Expected format: {base}/{index} where base is one of: ` +\n          `${ALLOWED_HD_PATHS.join(', ')}.`,\n      );\n    }\n\n    const basePath = match[1];\n    const index = parseInt(match[2], 10);\n\n    // Validate the base path is one of the allowed paths\n    if (!ALLOWED_HD_PATHS.includes(basePath as AllowedHdPath)) {\n      throw new Error(\n        `Invalid derivation path: ${derivationPath}. ` +\n          `Expected format: {base}/{index} where base is one of: ` +\n          `${ALLOWED_HD_PATHS.join(', ')}.`,\n      );\n    }\n\n    return {\n      basePath: basePath as AllowedHdPath,\n      index,\n    };\n  }\n\n  /**\n   * Creates a Bip44Account object for the given address.\n   *\n   * @param address - The account address.\n   * @param addressIndex - The account index in the derivation path.\n   * @returns The created Bip44Account.\n   */\n  #createKeyringAccount(\n    address: Hex,\n    addressIndex: number,\n  ): Bip44Account<KeyringAccount> {\n    const id = this.registry.register(address);\n    const derivationPath = `${this.inner.hdPath}/${addressIndex}`;\n\n    const account: Bip44Account<KeyringAccount> = {\n      id,\n      type: EthAccountType.Eoa,\n      address,\n      scopes: [...this.capabilities.scopes],\n      methods: [...TREZOR_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  async getAccounts(): Promise<Bip44Account<KeyringAccount>[]> {\n    const addresses = await this.inner.getAccounts();\n\n    if (addresses.length === 0) {\n      return [];\n    }\n\n    // If the device is locked, we cannot derive addresses to find indices.\n    // Return cached accounts if available, otherwise throw a clear error.\n    if (!this.inner.isUnlocked()) {\n      const cachedAccounts = addresses\n        .map((address) => {\n          const existingId = this.registry.getAccountId(address);\n          return existingId ? this.registry.get(existingId) : undefined;\n        })\n        .filter(\n          (account): account is Bip44Account<KeyringAccount> =>\n            account !== undefined,\n        );\n\n      // If we have all accounts cached, return them\n      if (cachedAccounts.length === addresses.length) {\n        return cachedAccounts;\n      }\n\n      // Some accounts are not cached and device is locked\n      throw new Error(\n        'Trezor device is locked. Please unlock the device to access accounts.',\n      );\n    }\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      const addressIndex = this.inner.getIndexForAddress(address);\n      return this.#createKeyringAccount(address, addressIndex);\n    });\n  }\n\n  async createAccounts(\n    options: CreateAccountOptions,\n  ): Promise<Bip44Account<KeyringAccount>[]> {\n    return this.withLock(async () => {\n      if (\n        options.type === 'bip44:derive-path' ||\n        options.type === 'bip44:derive-index'\n      ) {\n        // Validate that the entropy source matches this keyring's entropy source\n        if (options.entropySource !== this.entropySource) {\n          throw new Error(\n            `Entropy source mismatch: expected '${this.entropySource}', got '${options.entropySource}'`,\n          );\n        }\n      } else {\n        throw new Error(\n          `Unsupported account creation type for TrezorKeyring: ${String(\n            options.type,\n          )}`,\n        );\n      }\n\n      // Check if an account at this index already exists with the same derivation path\n      const currentAccounts = await this.getAccounts();\n\n      let targetIndex: number;\n      let basePath: AllowedHdPath;\n      let derivationPath: string;\n\n      if (options.type === 'bip44:derive-path') {\n        // Parse the derivation path to extract base path and index\n        const parsed = this.#parseDerivationPath(options.derivationPath);\n        targetIndex = parsed.index;\n        basePath = parsed.basePath;\n        // Use the normalized path to avoid mismatches with leading zeros\n        // (e.g., \"m/44'/60'/0'/0/007\" becomes \"m/44'/60'/0'/0/7\")\n        derivationPath = `${basePath}/${targetIndex}`;\n      } else {\n        // derive-index uses BIP-44 standard path by default\n        if (options.groupIndex < 0) {\n          throw new Error(\n            `Invalid groupIndex: ${options.groupIndex}. Must be a non-negative integer.`,\n          );\n        }\n        targetIndex = options.groupIndex;\n        basePath = BIP44_HD_PATH_PREFIX;\n        derivationPath = `${basePath}/${targetIndex}`;\n      }\n\n      const existingAccount = currentAccounts.find((account) => {\n        return (\n          account.options.entropy.groupIndex === targetIndex &&\n          account.options.entropy.derivationPath === derivationPath\n        );\n      });\n\n      if (existingAccount) {\n        return [existingAccount];\n      }\n\n      // Derive the account at the specified index.\n      // If the HD path is changing, clear the registry to avoid stale accounts.\n      // The TrezorKeyring operates on a single path at a time - accounts from\n      // different paths cannot coexist in the inner keyring.\n      if (basePath !== this.inner.hdPath) {\n        this.registry.clear();\n      }\n\n      this.inner.setHdPath(basePath);\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.#createKeyringAccount(newAddress, targetIndex);\n\n      return [newAccount];\n    });\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 device model reported by the bridge, or `undefined` if no\n   * device is paired.\n   */\n  getModel(): string | undefined {\n    return this.inner.getModel();\n  }\n\n  /**\n   * @returns The current derivation path used by the inner keyring.\n   */\n  get hdPath(): string {\n    return this.inner.hdPath;\n  }\n\n  /**\n   * @returns The bridge instance used by the inner keyring to communicate\n   * with the device.\n   */\n  get bridge(): TrezorBridge {\n    return this.inner.bridge;\n  }\n\n  /**\n   * Set the derivation path on the inner keyring. Must be one of the allowed\n   * HD paths supported by the legacy Trezor keyring.\n   *\n   * @param hdPath - The derivation path to set.\n   */\n  setHdPath(hdPath: Parameters<LegacyTrezorKeyring['setHdPath']>[0]): void {\n    this.inner.setHdPath(hdPath);\n  }\n\n  /**\n   * Fetch the first page of candidate addresses from the device.\n   *\n   * @returns The first page of accounts.\n   */\n  async getFirstPage(): Promise<AccountPage> {\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 accounts.\n   */\n  async getNextPage(): Promise<AccountPage> {\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 accounts.\n   */\n  async getPreviousPage(): Promise<AccountPage> {\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      this.inner.forgetDevice();\n      this.registry.clear();\n    });\n  }\n\n  /**\n   * @returns Whether the inner keyring has an unlocked HD key.\n   */\n  isUnlocked(): boolean {\n    return this.inner.isUnlocked();\n  }\n}\n"]}