{"version":3,"file":"ledger-mobile-bridge.cjs","sourceRoot":"","sources":["../src/ledger-mobile-bridge.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,yDAA8D;AAG9D,+CAAwE;AAgBxE,uDAAyD;AAGzD,uCAAiD;AAEjD,8EAA8E;AAC9E,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAQ5C;;GAEG;AACH,MAAa,kBAAkB;IAO7B,YACE,mBAAwC,EACxC,OAAkC,EAAE;;QAR7B,0DAA2C;QAEpD,2CAAiC;QAEjC,sBAAiB,GAAG,KAAK,CAAC;QAMxB,uBAAA,IAAI,4BAAS,IAAI,MAAA,CAAC;QAClB,uBAAA,IAAI,2CAAwB,mBAAmB,MAAA,CAAC;IAClD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,MAAM,uBAAA,IAAI,iFAAwB,MAA5B,IAAI,CAA0B,CAAC,OAAO,EAAE,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;IACjC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,iBAAiB,CAAC,EACtB,MAAM,EACN,OAAO,GACiB;QACxB,OAAO,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,mBAAmB,CAAC,EACxB,MAAM,EACN,OAAO,GACmB;QAC1B,OAAO,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,iCAAiC,CAAC,EACtC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,QAAQ,EACjB,eAAe,EAAE,gBAAgB,EACjC,KAAK,EAAE,MAAM,GAC2B;QACxC,MAAM,IAAI,KAAK,CACb,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,qBAAqB,CAAC,EAC1B,EAAE,EACF,MAAM,GACsB;QAC5B,MAAM,QAAQ,GAAG,IAAA,8BAAsB,EAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,8BAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClE,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,iCAAqB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEvE,MAAM,MAAM,GAAG,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC;QAEjC,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,EAAE,EAAE;gBACnD,eAAe,EAAE,IAAI;gBACrB,KAAK;gBACL,GAAG;aACJ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,uBAAA,EAAkB,qDAAuB,MAAzC,EAAkB,EAAwB,KAAK,CAAC,EAAE,CAAC;gBACrD,MAAM,KAAK,CAAC;YACd,CAAC;YAED,OAAO,CAAC,IAAI,CACV,0DAA0D,EAC1D,KAAK,CACN,CAAC;YACF,OAAO,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAAC,EACjB,MAAM,GACa;QACnB,OAAO,MAAM,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACjE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU;QACd,OAAO,uBAAA,IAAI,gCAAM,CAAC;IACpB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,IAA+B;QAC9C,uBAAA,IAAI,4BAAS,IAAI,MAAA,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,qBAAqB,CAAC,SAAoB;QAC9C,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QACD,uBAAA,IAAI,iFAAwB,MAA5B,IAAI,CAA0B,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,SAAS,EAAE,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,oBAAoB;QACxB,OAAO,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,oBAAoB,EAAE,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,mBAAmB;QACvB,OAAO,uBAAA,IAAI,oEAAW,MAAf,IAAI,CAAa,CAAC,mBAAmB,EAAE,CAAC;IACjD,CAAC;CAoCF;AAzPD,gDAyPC;;IA5BG,IAAI,uBAAA,IAAI,+CAAqB,EAAE,CAAC;QAC9B,OAAO,uBAAA,IAAI,+CAAqB,CAAC;IACnC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;AACxE,CAAC;IAQC,OAAO,uBAAA,IAAI,iFAAwB,MAA5B,IAAI,CAA0B,CAAC,SAAS,EAAE,CAAC;AACpD,CAAC,iGAS6B,KAAc;IAC1C,OAAO,CACL,KAAK,YAAY,mCAAoB;QACrC,KAAK,CAAC,UAAU,KAAK,4BAA4B,CAClD,CAAC;AACJ,CAAC","sourcesContent":["import { TransportStatusError } from '@ledgerhq/hw-transport';\nimport type Transport from '@ledgerhq/hw-transport';\n\nimport { ERC20_WRITE_SELECTORS, NFT_ONLY_SELECTORS } from './constants';\nimport {\n  AppConfigurationResponse,\n  GetAppNameAndVersionResponse,\n  GetPublicKeyParams,\n  GetPublicKeyResponse,\n  LedgerBridge,\n  LedgerSignDelegationAuthorizationParams,\n  LedgerSignDelegationAuthorizationResponse,\n  LedgerSignMessageParams,\n  LedgerSignMessageResponse,\n  LedgerSignTransactionParams,\n  LedgerSignTransactionResponse,\n  LedgerSignTypedDataParams,\n  LedgerSignTypedDataResponse,\n} from './ledger-bridge';\nimport { MetaMaskLedgerHwAppEth } from './ledger-hw-app';\nimport { TransportMiddleware } from './ledger-transport-middleware';\nimport { LedgerMobileBridgeOptions } from './type';\nimport { getTransactionSelector } from './utils';\n\n/** Ledger APDU: CONDITIONS_OF_USE_NOT_SATISFIED (user rejected on device). */\nconst LEDGER_USER_REJECTION_STATUS = 0x6985;\n\n// MobileBridge Type will always use LedgerBridge with LedgerMobileBridgeOptions\nexport type MobileBridge = LedgerBridge<LedgerMobileBridgeOptions> & {\n  openEthApp(): Promise<void>;\n  closeApps(): Promise<void>;\n};\n\n/**\n * LedgerMobileBridge is a bridge between the LedgerKeyring and the LedgerTransportMiddleware.\n */\nexport class LedgerMobileBridge implements MobileBridge {\n  readonly #transportMiddleware?: TransportMiddleware;\n\n  #opts: LedgerMobileBridgeOptions;\n\n  isDeviceConnected = false;\n\n  constructor(\n    transportMiddleware: TransportMiddleware,\n    opts: LedgerMobileBridgeOptions = {},\n  ) {\n    this.#opts = opts;\n    this.#transportMiddleware = transportMiddleware;\n  }\n\n  /**\n   * Method to initializes the keyring.\n   * Mobile ledger doesnt not require init.\n   *\n   * @returns A promise that will resolve once the bridge is initialized.\n   */\n  async init(): Promise<void> {\n    return Promise.resolve();\n  }\n\n  /**\n   * Method to destroy the keyring.\n   * It will dispose the transportmiddleware and set isDeviceConnected to false.\n   */\n  async destroy(): Promise<void> {\n    try {\n      await this.#getTransportMiddleWare().dispose();\n    } catch (error) {\n      console.error(error);\n    }\n    this.isDeviceConnected = false;\n  }\n\n  /**\n   * Method to sign a string Message.\n   * Sending the string message to the device and returning the signed message.\n   *\n   * @param params - An object contains hdPath and message.\n   * @param params.hdPath - The BIP 32 path of the account.\n   * @param params.message - The message to sign.\n   * @returns Retrieve v, r, s from the signed message.\n   */\n  async deviceSignMessage({\n    hdPath,\n    message,\n  }: LedgerSignMessageParams): Promise<LedgerSignMessageResponse> {\n    return this.#getEthApp().signPersonalMessage(hdPath, message);\n  }\n\n  /**\n   * Method to sign a EIP712 Message.\n   * Sending the typed data message to the device and returning the signed message.\n   *\n   * @param params - An object contains hdPath, domainSeparatorHex and hashStructMessageHex.\n   * @param params.hdPath - The BIP 32 path of the account.\n   * @param params.message - The EIP712 message to sign.\n   * @returns Retrieve v, r, s from the signed message.\n   */\n  async deviceSignTypedData({\n    hdPath,\n    message,\n  }: LedgerSignTypedDataParams): Promise<LedgerSignTypedDataResponse> {\n    return this.#getEthApp().signEIP712Message(hdPath, message);\n  }\n\n  async deviceSignDelegationAuthorization({\n    hdPath: _hdPath,\n    chainId: _chainId,\n    contractAddress: _contractAddress,\n    nonce: _nonce,\n  }: LedgerSignDelegationAuthorizationParams): Promise<LedgerSignDelegationAuthorizationResponse> {\n    throw new Error(\n      'Ledger: signDelegationAuthorization is not supported via mobile bridge',\n    );\n  }\n\n  /**\n   * Method to sign a transaction\n   * Sending the hexadecimal transaction message to the device and returning the signed transaction.\n   *\n   * Tries clear-signing first. If resolution fails (e.g. no Ledger plugin for the chain or contract),\n   * falls back to blind signing via `signTransaction(..., null)` unless the user rejected on the device.\n   *\n   * @param params - An object contains tx, hdPath.\n   * @param params.tx - The raw ethereum transaction in hexadecimal to sign.\n   * @param params.hdPath - The BIP 32 path of the account.\n   * @returns Retrieve v, r, s from the signed transaction.\n   */\n  async deviceSignTransaction({\n    tx,\n    hdPath,\n  }: LedgerSignTransactionParams): Promise<LedgerSignTransactionResponse> {\n    const selector = getTransactionSelector(tx);\n    const nft = Boolean(selector && NFT_ONLY_SELECTORS.has(selector));\n    const erc20 = Boolean(selector && ERC20_WRITE_SELECTORS.has(selector));\n\n    const ethApp = this.#getEthApp();\n\n    try {\n      return await ethApp.clearSignTransaction(hdPath, tx, {\n        externalPlugins: true,\n        erc20,\n        nft,\n      });\n    } catch (error: unknown) {\n      if (LedgerMobileBridge.#isLedgerUserRejection(error)) {\n        throw error;\n      }\n\n      console.warn(\n        'Ledger clear-sign failed; falling back to blind signing.',\n        error,\n      );\n      return ethApp.signTransaction(hdPath, tx, null);\n    }\n  }\n\n  /**\n   * Method to retrieve the ethereum address for a given BIP 32 path.\n   *\n   * @param params - An object contains hdPath.\n   * @param params.hdPath - The BIP 32 path of the account.\n   * @returns An object contains publicKey, address and chainCode.\n   */\n  async getPublicKey({\n    hdPath,\n  }: GetPublicKeyParams): Promise<GetPublicKeyResponse> {\n    return await this.#getEthApp().getAddress(hdPath, false, true);\n  }\n\n  /**\n   * Method to retrieve the current configuration.\n   *\n   * @returns Retrieve current configuration.\n   */\n  async getOptions(): Promise<LedgerMobileBridgeOptions> {\n    return this.#opts;\n  }\n\n  /**\n   * Method to set the current configuration.\n   *\n   * @param opts - An configuration object.\n   */\n  async setOptions(opts: LedgerMobileBridgeOptions): Promise<void> {\n    this.#opts = opts;\n  }\n\n  /**\n   * Method to set the transport object to communicate with the device.\n   *\n   * @param transport - The communication interface with the Ledger hardware wallet. There are different kind of transports based on the technology (channels like U2F, HID, Bluetooth, Webusb).\n   * @returns Retrieve boolean.\n   */\n  async updateTransportMethod(transport: Transport): Promise<boolean> {\n    if (!transport.deviceModel) {\n      throw new Error('Property `deviceModel` is not defined in `transport`.');\n    }\n    if (!transport.deviceModel.id) {\n      throw new Error(\n        'Property `deviceModel.id` is not defined in `transport`.',\n      );\n    }\n    this.#getTransportMiddleWare().setTransport(transport);\n    this.isDeviceConnected = true;\n    return Promise.resolve(true);\n  }\n\n  /**\n   * Method to init eth app object on ledger device.\n   * This method is not supported on mobile.\n   */\n  async attemptMakeApp(): Promise<boolean> {\n    throw new Error('Method not supported.');\n  }\n\n  /**\n   * Method to open ethereum application on ledger device.\n   *\n   */\n  async openEthApp(): Promise<void> {\n    await this.#getEthApp().openEthApp();\n  }\n\n  /**\n   * Method to close all running application on ledger device.\n   *\n   */\n  async closeApps(): Promise<void> {\n    await this.#getEthApp().closeApps();\n  }\n\n  /**\n   * Method to retrieve the name and version of the running application in ledger device.\n   *\n   * @returns An object contains appName and version.\n   */\n  async getAppNameAndVersion(): Promise<GetAppNameAndVersionResponse> {\n    return this.#getEthApp().getAppNameAndVersion();\n  }\n\n  /**\n   * Method to retrieve the current configuration of the Ethereum application on the Ledger device.\n   *\n   * @returns An object containing the application configuration including blind signing support, ERC20 provisioning status, Stark support, and version.\n   */\n  async getAppConfiguration(): Promise<AppConfigurationResponse> {\n    return this.#getEthApp().getAppConfiguration();\n  }\n\n  /**\n   * Method to retrieve the transport middleWare object.\n   *\n   * @returns The TransportMiddleware object.\n   */\n  #getTransportMiddleWare(): TransportMiddleware {\n    if (this.#transportMiddleware) {\n      return this.#transportMiddleware;\n    }\n    throw new Error('Instance `transportMiddleware` is not initialized.');\n  }\n\n  /**\n   * Method to retrieve the ledger Eth App object.\n   *\n   * @returns The ledger Eth App object.\n   */\n  #getEthApp(): MetaMaskLedgerHwAppEth {\n    return this.#getTransportMiddleWare().getEthApp();\n  }\n\n  /**\n   * Detects an explicit on-device rejection so we do not fall back to blind signing\n   * and re-prompt the user.\n   *\n   * @param error - Error from Ledger transport or hw-app-eth.\n   * @returns True when the user rejected the action on the device.\n   */\n  static #isLedgerUserRejection(error: unknown): boolean {\n    return (\n      error instanceof TransportStatusError &&\n      error.statusCode === LEDGER_USER_REJECTION_STATUS\n    );\n  }\n}\n"]}