From 40b7f8f90f1a3abbe21446cef9b53f17cddc1fce Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Fri, 19 Sep 2025 22:47:51 -0700 Subject: [PATCH] Wait for polling to end before executing command. --- src/lib/ledger.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/lib/ledger.ts b/src/lib/ledger.ts index 4f7d989..5e9034b 100644 --- a/src/lib/ledger.ts +++ b/src/lib/ledger.ts @@ -42,6 +42,7 @@ interface LedgerSignResponse extends LedgerResponse { */ export class Ledger { static #isBusy: boolean = false + static #isPolling?: Promise static #listenTimeout: 30000 = 30000 static #openTimeout: 3000 = 3000 static #status: LedgerStatus = 'DISCONNECTED' @@ -131,6 +132,7 @@ export class Ledger { } try { this.#isBusy = true + await this.#isPolling if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } @@ -355,6 +357,7 @@ export class Ledger { static async #cacheBlock (index: number = 0, block: Block): Promise { try { this.#isBusy = true + await this.#isPolling if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } @@ -413,6 +416,7 @@ export class Ledger { static async #close (): Promise { try { this.#isBusy = true + await this.#isPolling const transport = await this.#transport.create(this.#openTimeout, this.#listenTimeout) const response = await transport .send(0xb0, 0xa7, this.#ADPU_CODES.paramUnused, this.#ADPU_CODES.paramUnused) @@ -441,6 +445,7 @@ export class Ledger { static async #open (): Promise { try { this.#isBusy = true + await this.#isPolling const name = new TextEncoder().encode('Nano') const transport = await this.#transport.create(this.#openTimeout, this.#listenTimeout) const response = await transport @@ -465,12 +470,15 @@ export class Ledger { * device. */ static async #poll (): Promise { + let resolve: (() => void) | undefined + const poll = new Promise(r => resolve = r) + this.#isPolling = poll try { + const isHidPaired = (await navigator.hid?.getDevices()) + .some(device => device.vendorId === this.ledgerVendorId) + const isUsbPaired = (await navigator.usb?.getDevices()) + .some(device => device.vendorId === this.ledgerVendorId) if (!this.#isBusy) { - const isHidPaired = (await navigator.hid?.getDevices()) - .some(device => device.vendorId === this.ledgerVendorId) - const isUsbPaired = (await navigator.usb?.getDevices()) - .some(device => device.vendorId === this.ledgerVendorId) if (this.#transport === TransportHID && isHidPaired) { await this.connect() } else if (this.#transport === TransportUSB && isUsbPaired) { @@ -484,7 +492,9 @@ export class Ledger { console.warn('Error polling Ledger device') this.#status = 'DISCONNECTED' } finally { - setTimeout(() => this.#poll(), 1000) + resolve?.() + this.#isPolling = undefined + setTimeout(() => this.#poll(), 200) } } @@ -498,6 +508,7 @@ export class Ledger { static async #signBlock (index: number, block: Block): Promise { try { this.#isBusy = true + await this.#isPolling if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } @@ -554,6 +565,7 @@ export class Ledger { static async #signNonce (index: number, nonce: Uint8Array): Promise { try { this.#isBusy = true + await this.#isPolling if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } @@ -598,6 +610,7 @@ export class Ledger { static async #version (): Promise { try { this.#isBusy = true + await this.#isPolling const transport = await this.#transport.create(this.#openTimeout, this.#listenTimeout) const response = await transport .send(0xb0, this.#ADPU_CODES.version, this.#ADPU_CODES.paramUnused, this.#ADPU_CODES.paramUnused) -- 2.47.3