*/
export class Ledger {
static #isBusy: boolean = false
+ static #isPolling?: Promise<void>
static #listenTimeout: 30000 = 30000
static #openTimeout: 3000 = 3000
static #status: LedgerStatus = 'DISCONNECTED'
}
try {
this.#isBusy = true
+ await this.#isPolling
if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) {
throw new TypeError('Invalid account index')
}
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')
}
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)
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
* 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) {
console.warn('Error polling Ledger device')
this.#status = 'DISCONNECTED'
} finally {
- setTimeout(() => this.#poll(), 1000)
+ resolve?.()
+ this.#isPolling = undefined
+ setTimeout(() => this.#poll(), 200)
}
}
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')
}
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')
}
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)