]> git.codecow.com Git - libnemo.git/commitdiff
Wait for polling to end before executing command.
authorChris Duncan <chris@zoso.dev>
Sat, 20 Sep 2025 05:47:51 +0000 (22:47 -0700)
committerChris Duncan <chris@zoso.dev>
Sat, 20 Sep 2025 05:47:51 +0000 (22:47 -0700)
src/lib/ledger.ts

index 4f7d989c2f40d369ebc4c29c5f14c151b2a1dfb4..5e9034b640800407583753d1b8dcd986275c2d0d 100644 (file)
@@ -42,6 +42,7 @@ interface LedgerSignResponse extends LedgerResponse {
 */
 export class Ledger {
        static #isBusy: boolean = false
+       static #isPolling?: Promise<void>
        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<LedgerResponse> {
                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<LedgerResponse> {
                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<LedgerResponse> {
                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<void> {
+               let resolve: (() => void) | undefined
+               const poll = new Promise<void>(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<LedgerSignResponse> {
                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<ArrayBuffer>): Promise<LedgerSignResponse> {
                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<LedgerVersionResponse> {
                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)