{"version":3,"file":"device.cjs","sourceRoot":"","sources":["../src/device.ts"],"names":[],"mappings":"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","sourcesContent":["import { RLP } from '@ethereumjs/rlp';\nimport { TransactionType, TransactionFactory } from '@ethereumjs/tx';\nimport type { TypedTransaction, TypedTxData } from '@ethereumjs/tx';\nimport { publicToAddress } from '@ethereumjs/util';\nimport {\n  CryptoAccount,\n  CryptoHDKey,\n  DataType,\n  ETHSignature,\n  EthSignRequest,\n  URRegistryDecoder,\n} from '@keystonehq/bc-ur-registry-eth';\nimport type { MessageTypes, TypedMessage } from '@metamask/eth-sig-util';\nimport { add0x, getChecksumAddress, remove0x } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport HdKey from 'hdkey';\nimport { stringify, v4 as uuidv4 } from 'uuid';\n\nimport { QrScanRequestType } from './qr-keyring';\nimport type {\n  QrKeyringBridge,\n  QrSignatureRequest,\n  SerializedUR,\n} from './qr-keyring';\n\nexport const SUPPORTED_UR_TYPE = {\n  CRYPTO_HDKEY: 'crypto-hdkey',\n  CRYPTO_ACCOUNT: 'crypto-account',\n  ETH_SIGNATURE: 'eth-signature',\n};\n\nexport enum DeviceMode {\n  HD = 'hd',\n  ACCOUNT = 'account',\n}\n\nconst DEFAULT_CHILDREN_PATH = '0/*';\n\nconst MAX_INDEX = 1_000;\n\n/**\n * Common details for the device source, which can be either a CryptoAccount or CryptoHDKey.\n */\nexport type CommonDeviceDetails = {\n  /**\n   * Value take out from the device note field, if available.\n   */\n  keyringAccount: string;\n  /**\n   * The name of the device\n   */\n  name: string;\n  /**\n   * The device fingerprint, hex-encoded\n   */\n  xfp: string;\n  /**\n   * Indexes of the accounts derived from the device\n   * in the form of a map from address to index\n   */\n  indexes: Record<Hex, number>;\n};\n\n/**\n * Details for the HD mode of the Device. This mode derives\n * accounts from a root public key (xpub) and a derivation path.\n */\nexport type HDModeDeviceDetails = {\n  /**\n   * The device mode is HD, indicating that it derives accounts from a\n   * root public key (xpub) and a derivation path.\n   */\n  keyringMode: DeviceMode.HD;\n  /**\n   * The xpub of the HD key\n   */\n  xpub: string;\n  /**\n   * The derivation path of the HD key\n   */\n  hdPath: string;\n  /**\n   * The path used to derive child accounts\n   */\n  childrenPath: string;\n};\n\n/**\n * Details for the Account mode of the Device. This mode derives\n * accounts from a set of addresses and their corresponding paths.\n */\nexport type AccountModeDeviceDetails = {\n  /**\n   * The device mode is ACCOUNT, indicating that it derives accounts from\n   * a set of addresses and their corresponding paths.\n   */\n  keyringMode: DeviceMode.ACCOUNT;\n  /**\n   * The derivation paths for each hex-encoded address in the device\n   */\n  paths: Record<Hex, string>;\n};\n\n/**\n * An address with its corresponding index.\n */\nexport type IndexedAddress = {\n  address: Hex;\n  index: number;\n};\n\n/**\n * The details of the source CryptoAccount or CryptoHDKey\n * that the Device uses to derive accounts.\n */\nexport type DeviceDetails = CommonDeviceDetails &\n  (HDModeDeviceDetails | AccountModeDeviceDetails);\n\nexport type DeviceOptions = {\n  /**\n   * The requestScan function to scan the QR code\n   */\n  requestScan: QrKeyringBridge['requestScan'];\n  /**\n   * The source of the device, which can be of type `DeviceDetails`,\n   * `string`, or `SerializedUR`.\n   *\n   * When a `string` or `SerializedUR` is provided, the Device will\n   * initialize itself from the UR.\n   */\n  source: DeviceDetails | string | SerializedUR;\n};\n\n/**\n * Get the fingerprint of the source CryptoAccount or CryptoHDKey\n *\n * @param source - The source CryptoAccount or CryptoHDKey\n * @returns The fingerprint of the source\n */\nfunction getFingerprintFromSource(source: CryptoAccount | CryptoHDKey): string {\n  return source instanceof CryptoAccount\n    ? source.getMasterFingerprint()?.toString('hex')\n    : source.getOrigin()?.getSourceFingerprint()?.toString('hex');\n}\n\n/**\n * Get fingerprint, account paths and names from the a CryptoAccount\n *\n * Note: This function emulates the behavior of the `@keystonehq/base-eth-keyring`\n * library when dealing with CryptoAccount objects (for backwards compatibility\n * reasons). Though, the way it retrieves `name` and `keyringAccount` is questionable,\n * as `name` and `keyringAccount` are updated after each descriptor discovery, effectively\n * returning the last descriptor's `name` and `keyringAccount`.\n *\n * @param source - The source CryptoAccount\n * @returns The paths\n */\nfunction readCryptoAccountOutputDescriptors(source: CryptoAccount): {\n  xfp: string;\n  paths: Record<Hex, string>;\n  name: string;\n  keyringAccount: string;\n} {\n  const descriptors = source.getOutputDescriptors();\n\n  if (!descriptors || descriptors.length === 0) {\n    throw new Error('No output descriptors found in CryptoAccount');\n  }\n\n  let name = '';\n  let keyringAccount = '';\n  const paths = descriptors.reduce(\n    (descriptorsPaths: Record<Hex, string>, current) => {\n      const hdKey = current.getHDKey();\n      if (hdKey) {\n        const path = `M/${hdKey.getOrigin().getPath()}`;\n        const address = getChecksumAddress(\n          add0x(\n            Buffer.from(publicToAddress(hdKey.getKey(), true)).toString('hex'),\n          ),\n        );\n        descriptorsPaths[address] = path;\n        name = hdKey.getName();\n        keyringAccount = hdKey.getNote();\n      }\n      return descriptorsPaths;\n    },\n    {},\n  );\n\n  return {\n    paths,\n    name,\n    keyringAccount,\n    xfp: getFingerprintFromSource(source),\n  };\n}\n\nexport class Device {\n  readonly #requestScan: QrKeyringBridge['requestScan'];\n\n  readonly #pairedDevice: DeviceDetails;\n\n  /**\n   * Create a new Device instance.\n   *\n   * @param options - The options for the Device, including the requestScan function\n   * and the source of the device details.\n   * @param options.requestScan - The function to request a scan of the QR code.\n   * @param options.source - The source of the device details, which can be a\n   * UR string, a `SerializedUR`, or a `DeviceDetails` object.\n   */\n  constructor({ requestScan, source }: DeviceOptions) {\n    this.#requestScan = requestScan;\n    this.#pairedDevice =\n      typeof source === 'string' || 'cbor' in source\n        ? this.#deviceDetailsFromUR(source)\n        : source;\n  }\n\n  /**\n   * Derive an address from the source at a given index\n   *\n   * @param index - The index to derive the address from\n   * @returns The derived address in hex format\n   * @throws Will throw an error if the source is not initialized\n   */\n  addressFromIndex(index: number): Hex {\n    if (this.#pairedDevice.keyringMode === DeviceMode.ACCOUNT) {\n      const address = Object.keys(this.#pairedDevice.paths)[index];\n      if (!address) {\n        throw new Error(`Address not found for index ${index}`);\n      }\n      return add0x(address);\n    }\n    const childPath = `m/${this.#pairedDevice.childrenPath.replace(\n      '*',\n      index.toString(),\n    )}`;\n\n    const hdKey = HdKey.fromExtendedKey(this.#pairedDevice.xpub);\n    const childKey = hdKey.derive(childPath);\n\n    const address = Buffer.from(\n      publicToAddress(childKey.publicKey, true),\n    ).toString('hex');\n\n    const normalizedAddress = getChecksumAddress(add0x(address));\n\n    this.#pairedDevice.indexes[normalizedAddress] = index;\n\n    return normalizedAddress;\n  }\n\n  /**\n   * Retrieve the path of an address derived from the source.\n   *\n   * @param address - The address to retrieve the path for\n   * @returns The path of the address\n   */\n  pathFromAddress(address: Hex): string {\n    const normalizedAddress = getChecksumAddress(add0x(address));\n\n    if (this.#pairedDevice.keyringMode === DeviceMode.ACCOUNT) {\n      const path = this.#pairedDevice.paths[normalizedAddress];\n      if (path === undefined) {\n        throw new Error(`Unknown address ${normalizedAddress}`);\n      }\n      return path;\n    }\n\n    let index = this.#pairedDevice.indexes[normalizedAddress];\n    if (index === undefined) {\n      for (let i = 0; i < MAX_INDEX; i++) {\n        const derivedAddress = this.addressFromIndex(i);\n        if (derivedAddress === normalizedAddress) {\n          index = i;\n          break;\n        }\n      }\n      if (index === undefined) {\n        throw new Error(`Unknown address ${normalizedAddress}`);\n      }\n    }\n\n    return `${this.#pairedDevice.hdPath}/${this.#pairedDevice.childrenPath\n      .replace('*', index.toString())\n      .replace(/\\*/gu, '0')}`;\n  }\n\n  /**\n   * Get a page of addresses derived from the source.\n   *\n   * @param page - The page number to retrieve\n   * @param pageSize - The number of addresses per page\n   * @returns An array of IndexedAddress objects, each containing the address and its index\n   * @throws Will throw an error if the source is not initialized\n   */\n  getAddressesPage(page: number, pageSize = 5): IndexedAddress[] {\n    const startIndex = page * pageSize;\n    const endIndex = startIndex + pageSize;\n    const addresses: IndexedAddress[] = [];\n\n    for (let i = startIndex; i < endIndex; i++) {\n      const address = this.addressFromIndex(i);\n      addresses.push({ address, index: i });\n    }\n\n    return addresses;\n  }\n\n  /**\n   * Retrieve the details of the paired device.\n   *\n   * @returns Thea paired device details\n   */\n  getDeviceDetails(): DeviceDetails {\n    return this.#pairedDevice;\n  }\n\n  /**\n   * Sign a transaction. This is equivalent to the `eth_signTransaction`\n   * Ethereum JSON-RPC method. See the Ethereum JSON-RPC API documentation for\n   * more details.\n   *\n   * @param address - The address of the account to use for signing.\n   * @param transaction - The transaction to sign.\n   * @returns The signed transaction.\n   */\n  async signTransaction(\n    address: Hex,\n    transaction: TypedTransaction,\n  ): Promise<TypedTxData> {\n    const dataType =\n      transaction.type === TransactionType.Legacy\n        ? DataType.transaction\n        : DataType.typedTransaction;\n\n    const messageToSign = transaction.getMessageToSign();\n    const rawTransaction = Buffer.from(\n      Array.isArray(messageToSign) ? RLP.encode(messageToSign) : messageToSign,\n    );\n\n    const requestId = uuidv4();\n    const ethSignRequestUR = EthSignRequest.constructETHRequest(\n      rawTransaction,\n      dataType,\n      this.pathFromAddress(address),\n      this.#pairedDevice.xfp,\n      requestId,\n      Number(transaction.common.chainId()),\n    ).toUR();\n\n    const { r, s, v } = await this.#requestSignature({\n      requestId,\n      payload: {\n        type: ethSignRequestUR.type,\n        cbor: ethSignRequestUR.cbor.toString('hex'),\n      },\n      requestTitle: 'Scan with your hardware wallet',\n      requestDescription:\n        'After your device has signed this message, click on \"Scan\" to receive the signature',\n    });\n\n    return TransactionFactory.fromTxData(\n      {\n        ...transaction.toJSON(),\n        r,\n        s,\n        v,\n      },\n      {\n        common: transaction.common,\n      },\n    );\n  }\n\n  /**\n   * Sign a message. This is equivalent to the `eth_signTypedData` v4 Ethereum\n   * JSON-RPC method.\n   *\n   * @param address - The address of the account to use for signing.\n   * @param data - The data to sign.\n   * @returns The signed message.\n   */\n  async signTypedData<Types extends MessageTypes>(\n    address: Hex,\n    data: TypedMessage<Types>,\n  ): Promise<string> {\n    const requestId = uuidv4();\n    const ethSignRequestUR = EthSignRequest.constructETHRequest(\n      Buffer.from(JSON.stringify(data), 'utf8'),\n      DataType.typedData,\n      this.pathFromAddress(address),\n      this.#pairedDevice.xfp,\n      requestId,\n      undefined,\n      address,\n    ).toUR();\n\n    const { r, s, v } = await this.#requestSignature({\n      requestId,\n      payload: {\n        type: ethSignRequestUR.type,\n        cbor: ethSignRequestUR.cbor.toString('hex'),\n      },\n    });\n\n    return add0x(\n      Buffer.concat([\n        Uint8Array.from(r),\n        Uint8Array.from(s),\n        Uint8Array.from(v),\n      ]).toString('hex'),\n    );\n  }\n\n  /**\n   * Sign a message. This is equivalent to the `eth_sign` Ethereum JSON-RPC\n   * method, which is exposed by MetaMask as the method `personal_sign`. See\n   * the Ethereum JSON-RPC API documentation for more details.\n   *\n   * For more information about this method and why we call it `personal_sign`,\n   * see the {@link https://docs.metamask.io/guide/signing-data.html|MetaMask Docs}.\n   *\n   * @param address - The address of the account to use for signing.\n   * @param message - The message to sign.\n   * @returns The signed message.\n   */\n  async signPersonalMessage(address: Hex, message: Hex): Promise<string> {\n    const requestId = uuidv4();\n    const ethSignRequestUR = EthSignRequest.constructETHRequest(\n      Buffer.from(remove0x(message), 'hex'),\n      DataType.personalMessage,\n      this.pathFromAddress(address),\n      this.#pairedDevice.xfp,\n      requestId,\n      undefined,\n      address,\n    ).toUR();\n\n    const { r, s, v } = await this.#requestSignature({\n      requestId,\n      payload: {\n        type: ethSignRequestUR.type,\n        cbor: ethSignRequestUR.cbor.toString('hex'),\n      },\n    });\n\n    return add0x(\n      Buffer.concat([\n        Uint8Array.from(r),\n        Uint8Array.from(s),\n        Uint8Array.from(v),\n      ]).toString('hex'),\n    );\n  }\n\n  /**\n   * Derive the device details from a UR string\n   *\n   * @param ur - The UR string to set the root account from\n   * @returns The device details derived from the UR\n   */\n  #deviceDetailsFromUR(ur: string | SerializedUR): DeviceDetails {\n    const source = this.#decodeUR(ur);\n    const fingerprint = getFingerprintFromSource(source);\n\n    if (source instanceof CryptoAccount) {\n      const { name, xfp, paths, keyringAccount } =\n        readCryptoAccountOutputDescriptors(source);\n      return {\n        keyringMode: DeviceMode.ACCOUNT,\n        keyringAccount,\n        name,\n        xfp,\n        paths,\n        indexes: {},\n      };\n    }\n\n    const { getBip32Key, getOrigin, getChildren, getName, getNote } = source;\n    return {\n      keyringMode: DeviceMode.HD,\n      keyringAccount: getNote(),\n      name: getName(),\n      xfp: fingerprint,\n      hdPath: `m/${getOrigin().getPath()}`,\n      childrenPath: getChildren()?.getPath() || DEFAULT_CHILDREN_PATH,\n      xpub: getBip32Key(),\n      indexes: {},\n    };\n  }\n\n  /**\n   * Request a signature for a transaction or message.\n   *\n   * @param request - The signature request containing the data to sign.\n   * @returns The signature as an object containing r, s, and v values.\n   */\n  async #requestSignature(\n    request: QrSignatureRequest,\n  ): Promise<{ r: Buffer; s: Buffer; v: Buffer }> {\n    const response = await this.#requestScan({\n      type: QrScanRequestType.SIGN,\n      request,\n    });\n    const signatureEnvelope = ETHSignature.fromCBOR(\n      Buffer.from(response.cbor, 'hex'),\n    );\n    const signature = signatureEnvelope.getSignature();\n    const requestId = signatureEnvelope.getRequestId();\n\n    if (!requestId) {\n      throw new Error('Signature request ID is missing.');\n    }\n\n    if (request.requestId !== stringify(requestId)) {\n      throw new Error(\n        `Signature request ID mismatch. Expected: ${\n          request.requestId\n        }, received: ${requestId.toString('hex')}`,\n      );\n    }\n\n    return {\n      r: signature.subarray(0, 32),\n      s: signature.subarray(32, 64),\n      v: signature.subarray(64),\n    };\n  }\n\n  /**\n   * Decodes a UR\n   *\n   * @param ur - The UR to decode\n   * @returns The decoded CryptoAccount or CryptoHDKey\n   * @throws Will throw an error if the UR type is not supported\n   */\n  #decodeUR(ur: string | SerializedUR): CryptoAccount | CryptoHDKey {\n    const decodedUR =\n      typeof ur === 'string'\n        ? URRegistryDecoder.decode(ur)\n        : {\n            type: ur.type,\n            cbor: Buffer.from(ur.cbor, 'hex'),\n          };\n\n    const { type, cbor } = decodedUR;\n\n    switch (type) {\n      case SUPPORTED_UR_TYPE.CRYPTO_HDKEY:\n        return CryptoHDKey.fromCBOR(cbor);\n      case SUPPORTED_UR_TYPE.CRYPTO_ACCOUNT:\n        return CryptoAccount.fromCBOR(cbor);\n      default:\n        throw new Error('Unsupported UR type');\n    }\n  }\n}\n"]}