{"version":3,"file":"qr-keyring-deferred-promise-bridge.cjs","sourceRoot":"","sources":["../src/qr-keyring-deferred-promise-bridge.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwD;AAExD,6CAAoC;AA0BpC;;;GAGG;AACH,MAAa,8BAA8B;IAWzC,YAAY,EACV,eAAe,EACf,cAAc,EACd,cAAc,MAC2B,EAAE;QAdpC,+CAAQ,IAAI,mBAAK,EAAE,EAAC;QAEpB,kEAAkE;QAElE,iEAA+D;QAE/D,iEAAuD;QAEhE,8DAAoD;QAOlD,uBAAA,IAAI,mDAAoB,eAAe,MAAA,CAAC;QACxC,uBAAA,IAAI,kDAAmB,cAAc,MAAA,CAAC;QACtC,uBAAA,IAAI,kDAAmB,cAAc,MAAA,CAAC;IACxC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,OAAsB;QACtC,OAAO,uBAAA,IAAI,4CAAM,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE;YACxC,MAAM,eAAe,GAAG,IAAA,6BAAqB,GAAgB,CAAC;YAC9D,uBAAA,IAAI,+CAAgB,eAAe,MAAA,CAAC;YACpC,uBAAA,IAAI,uDAAiB,EAAE,KAAvB,IAAI,EAAoB,OAAO,CAAC,CAAC;YACjC,OAAO,eAAe,CAAC,OAAO,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,kBAAkB,CAAC,MAAoB;QACrC,IAAI,CAAC,uBAAA,IAAI,mDAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QACD,uBAAA,IAAI,mDAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,uBAAA,IAAI,+CAAgB,IAAI,MAAA,CAAC;QACzB,uBAAA,IAAI,sDAAgB,EAAE,KAAtB,IAAI,EAAmB,MAAM,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,KAAY;QAC5B,IAAI,CAAC,uBAAA,IAAI,mDAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QACD,uBAAA,IAAI,mDAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,uBAAA,IAAI,+CAAgB,IAAI,MAAA,CAAC;QACzB,uBAAA,IAAI,sDAAgB,EAAE,KAAtB,IAAI,EAAmB,KAAK,CAAC,CAAC;IAChC,CAAC;CACF;AA/DD,wEA+DC","sourcesContent":["import { createDeferredPromise } from '@metamask/utils';\nimport type { DeferredPromise } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n\nimport type {\n  QrKeyringBridge,\n  QrScanRequest,\n  SerializedUR,\n} from './qr-keyring';\n\nexport type QrKeyringDeferredPromiseBridgeOptions = {\n  /**\n   * Callback invoked when a scan request is made.\n   * This can be used to trigger the actual scanning process.\n   */\n  onScanRequested?: (request: QrScanRequest) => void;\n  /**\n   * Callback invoked when a scan is successfully resolved.\n   * This can be used to handle the result of the scan.\n   */\n  onScanResolved?: (result: SerializedUR) => void;\n  /**\n   * Callback invoked when a scan is rejected with an error.\n   * This can be used to handle errors that occur during the scan.\n   */\n  onScanRejected?: (error: Error) => void;\n};\n\n/**\n * A bridge that turns the scan request into a deferred promise, allowing\n * the consumer to control the resolution and rejection of the scan.\n */\nexport class QrKeyringDeferredPromiseBridge implements QrKeyringBridge {\n  readonly #lock = new Mutex();\n\n  readonly #onScanRequested?: ((request: QrScanRequest) => void) | undefined;\n\n  readonly #onScanResolved?: ((result: SerializedUR) => void) | undefined;\n\n  readonly #onScanRejected?: ((error: Error) => void) | undefined;\n\n  #pendingScan?: DeferredPromise<SerializedUR> | null;\n\n  constructor({\n    onScanRequested,\n    onScanResolved,\n    onScanRejected,\n  }: QrKeyringDeferredPromiseBridgeOptions = {}) {\n    this.#onScanRequested = onScanRequested;\n    this.#onScanResolved = onScanResolved;\n    this.#onScanRejected = onScanRejected;\n  }\n\n  /**\n   * Request a QR code scan, obtaining a CBOR and a type as response.\n   *\n   * @param request - The type of QR scan request.\n   * @returns A promise that resolves with the scanned data as a serialized UR.\n   */\n  async requestScan(request: QrScanRequest): Promise<SerializedUR> {\n    return this.#lock.runExclusive(async () => {\n      const deferredPromise = createDeferredPromise<SerializedUR>();\n      this.#pendingScan = deferredPromise;\n      this.#onScanRequested?.(request);\n      return deferredPromise.promise;\n    });\n  }\n\n  /**\n   * Resolve the pending scan with the given result.\n   *\n   * @param result - The scanned data as a serialized UR.\n   */\n  resolvePendingScan(result: SerializedUR): void {\n    if (!this.#pendingScan) {\n      throw new Error('No pending scan to resolve.');\n    }\n    this.#pendingScan.resolve(result);\n    this.#pendingScan = null;\n    this.#onScanResolved?.(result);\n  }\n\n  /**\n   * Reject the pending scan with the given error.\n   *\n   * @param error - The error to reject the scan with.\n   */\n  rejectPendingScan(error: Error): void {\n    if (!this.#pendingScan) {\n      throw new Error('No pending scan to reject.');\n    }\n    this.#pendingScan.reject(error);\n    this.#pendingScan = null;\n    this.#onScanRejected?.(error);\n  }\n}\n"]}