From d8a97fb3eec69c3613d28454fd47b2c5410aaa85 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Mon, 11 Aug 2025 06:00:24 -0700 Subject: [PATCH] Privatize some ledger properties and rearrance them toward the bottom of the file. Update JSdoc for accounts method. --- src/lib/wallet/ledger.ts | 88 ++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/src/lib/wallet/ledger.ts b/src/lib/wallet/ledger.ts index 9f471c6..5bfd3c6 100644 --- a/src/lib/wallet/ledger.ts +++ b/src/lib/wallet/ledger.ts @@ -55,8 +55,8 @@ export class Ledger extends Wallet { static DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID static SYMBOL: Symbol = Symbol('Ledger') - static get listenTimeout (): 30000 { return 30000 } - static get openTimeout (): 3000 { return 3000 } + static get #listenTimeout (): 30000 { return 30000 } + static get #openTimeout (): 3000 { return 3000 } /** * Check which transport protocols are supported by the browser and return the @@ -105,10 +105,6 @@ export class Ledger extends Wallet { return Ledger.create() } - #accounts: AccountList - #status: DeviceStatus = 'DISCONNECTED' - get status (): DeviceStatus { return this.#status } - private constructor () { if (!Ledger.#isInternal) { throw new Error(`Ledger cannot be instantiated directly. Use 'await Ledger.create()' instead.`) @@ -118,6 +114,8 @@ export class Ledger extends Wallet { this.#accounts = new AccountList() } + get status (): DeviceStatus { return this.#status } + /** * Gets the public key for an account from the Ledger device. * @@ -141,14 +139,15 @@ export class Ledger extends Wallet { * that index in the wallet. * * ``` - * console.log(await wallet.accounts(5)) - * // outputs sixth account of the wallet - * // { - * // 5: { - * // privateKey: <...>, - * // index: 5 - * // } - * // } + * const accounts = await wallet.accounts(0, 1)) + * + * // outputs the first and second account of the wallet + * console.log(accounts) + * // { 0: { privateKey: <...>, index: 0 }, 1: { privateKey: <...>, index: 1 } } + * + * // individual accounts can be referenced using array index notation + * console.log(accounts[1]) + * // { privateKey: <...>, index: 1 } * ``` * * @param {number} from - Start index of secret keys. Default: 0 @@ -210,7 +209,7 @@ export class Ledger extends Wallet { } else { this.#status = 'BUSY' } - return this.status + return this.#status } /** @@ -407,28 +406,8 @@ export class Ledger extends Wallet { return await this.#version() } - /** - * Open the Nano app by launching a user flow. - * - * https://developers.ledger.com/docs/connectivity/ledgerJS/open-close-info-on-apps#open-application - * - * This command resets the internal USB connection of the device which can - * cause subsequent commands to fail if called too quickly. A one-second delay - * is implemented in this method to mitigate the issue. - * - * https://github.com/LedgerHQ/ledger-live/issues/4964#issuecomment-1878361157 - * - * @returns Status of command - */ - async #open (): Promise { - const name = new TextEncoder().encode('Nano') - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) - const response = await transport - .send(0xe0, 0xd8, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused, name as Buffer) - .then(res => bytes.toDec(res)) - .catch(err => err.statusCode) as number - return new Promise(r => setTimeout(r, 1000, { status: Ledger.#STATUS_CODES[response] })) - } + #accounts: AccountList + #status: DeviceStatus = 'DISCONNECTED' /** * Close the currently running app and return to the device dashboard. @@ -444,7 +423,7 @@ export class Ledger extends Wallet { * @returns Status of command */ async #close (): Promise { - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) const response = await transport .send(0xb0, 0xa7, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused) .then(res => bytes.toDec(res)) @@ -464,7 +443,7 @@ export class Ledger extends Wallet { const account = dec.toBytes(index + HARDENED_OFFSET, 4) const data = new Uint8Array([...Ledger.#DERIVATION_PATH, ...account]) - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) const response = await transport .send(Ledger.#ADPU_CODES.class, Ledger.#ADPU_CODES.account, show ? 1 : 0, Ledger.#ADPU_CODES.paramUnused, data as Buffer) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array @@ -521,7 +500,7 @@ export class Ledger extends Wallet { const signature = hex.toBytes(block.signature, 64) const data = new Uint8Array([Ledger.#ADPU_CODES.bip32DerivationLevel, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance, ...signature]) - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) const response = await transport .send(Ledger.#ADPU_CODES.class, Ledger.#ADPU_CODES.cacheBlock, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused, data as Buffer) .then(res => bytes.toDec(res)) @@ -531,6 +510,29 @@ export class Ledger extends Wallet { return { status: Ledger.#STATUS_CODES[response] } } + /** + * Open the Nano app by launching a user flow. + * + * https://developers.ledger.com/docs/connectivity/ledgerJS/open-close-info-on-apps#open-application + * + * This command resets the internal USB connection of the device which can + * cause subsequent commands to fail if called too quickly. A one-second delay + * is implemented in this method to mitigate the issue. + * + * https://github.com/LedgerHQ/ledger-live/issues/4964#issuecomment-1878361157 + * + * @returns Status of command + */ + async #open (): Promise { + const name = new TextEncoder().encode('Nano') + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) + const response = await transport + .send(0xe0, 0xd8, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused, name as Buffer) + .then(res => bytes.toDec(res)) + .catch(err => err.statusCode) as number + return new Promise(r => setTimeout(r, 1000, { status: Ledger.#STATUS_CODES[response] })) + } + /** * Sign a block with the Ledger device. * @@ -556,7 +558,7 @@ export class Ledger extends Wallet { const balance = hex.toBytes(BigInt(block.balance).toString(16), 16) const data = new Uint8Array([...Ledger.#DERIVATION_PATH, ...account, ...previous, ...link, ...representative, ...balance]) - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) const response = await transport .send(Ledger.#ADPU_CODES.class, Ledger.#ADPU_CODES.signBlock, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused, data as Buffer) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array @@ -597,7 +599,7 @@ export class Ledger extends Wallet { const derivationAccount = dec.toBytes(index + HARDENED_OFFSET, 4) const data = new Uint8Array([...Ledger.#DERIVATION_PATH, ...derivationAccount, ...nonce]) - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) const response = await transport .send(Ledger.#ADPU_CODES.class, Ledger.#ADPU_CODES.signNonce, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused, data as Buffer) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array @@ -626,7 +628,7 @@ export class Ledger extends Wallet { * @returns Status, process name, and version */ async #version (): Promise { - const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout) + const transport = await Ledger.DynamicTransport.create(Ledger.#openTimeout, Ledger.#listenTimeout) const response = await transport .send(0xb0, Ledger.#ADPU_CODES.version, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused) .catch(err => dec.toBytes(err.statusCode)) as Uint8Array -- 2.47.3