From: Chris Duncan Date: Sat, 26 Jul 2025 06:20:55 +0000 (-0700) Subject: Refactor Ledger transport as static member. X-Git-Tag: v0.10.5~50^2~17 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=37f3d11e5b62550f30f5a84910e4075fb0ccb6fc;p=libnemo.git Refactor Ledger transport as static member. --- diff --git a/src/lib/wallets/ledger-wallet.ts b/src/lib/wallets/ledger-wallet.ts index 839294e..4eb2552 100644 --- a/src/lib/wallets/ledger-wallet.ts +++ b/src/lib/wallets/ledger-wallet.ts @@ -27,21 +27,9 @@ export class LedgerWallet extends Wallet { ...dec.toBytes(BIP44_COIN_NANO + HARDENED_OFFSET, 4) ]) - #status: DeviceStatus = 'DISCONNECTED' - - get listenTimeout (): 30000 { return 30000 } - get openTimeout (): 3000 { return 3000 } - get status (): DeviceStatus { return this.#status } - - DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID = TransportHID - - private constructor (id: Entropy) { - if (!LedgerWallet.#isInternal) { - throw new Error(`LedgerWallet cannot be instantiated directly. Use 'await LedgerWallet.create()' instead.`) - } - LedgerWallet.#isInternal = false - super(id, 'Ledger') - } + static DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID = this.checkBrowserSupport() + static get listenTimeout (): 30000 { return 30000 } + static get openTimeout (): 3000 { return 3000 } /** * Check which transport protocols are supported by the browser and return the @@ -71,17 +59,26 @@ export class LedgerWallet extends Wallet { */ static async create (): Promise { try { - const transport = LedgerWallet.checkBrowserSupport() const id = await Entropy.create(16) LedgerWallet.#isInternal = true const wallet = new this(id) - wallet.DynamicTransport = transport return wallet } catch (err) { throw new Error('failed to initialize Ledger wallet', { cause: err }) } } + #status: DeviceStatus = 'DISCONNECTED' + get status (): DeviceStatus { return this.#status } + + private constructor (id: Entropy) { + if (!LedgerWallet.#isInternal) { + throw new Error(`LedgerWallet cannot be instantiated directly. Use 'await LedgerWallet.create()' instead.`) + } + LedgerWallet.#isInternal = false + super(id, 'Ledger') + } + /** * Check if the Nano app is currently open and set device status accordingly. * @@ -96,7 +93,7 @@ export class LedgerWallet extends Wallet { if (version.status !== 'OK') { this.#status = 'DISCONNECTED' } else if (version.name === 'Nano') { - const { status } = await this.#account() + const { status } = await LedgerWallet.#account() if (status === 'OK') { this.#status = 'CONNECTED' } else if (status === 'SECURITY_STATUS_NOT_SATISFIED') { @@ -275,7 +272,7 @@ export class LedgerWallet extends Wallet { */ async #open (): Promise { const name = new TextEncoder().encode('Nano') - const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout) const response = await transport .send(0xe0, 0xd8, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, name as Buffer) .then(res => bytes.toDec(res)) @@ -297,7 +294,7 @@ export class LedgerWallet extends Wallet { * @returns Status of command */ async #close (): Promise { - const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout) const response = await transport .send(0xb0, 0xa7, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused) .then(res => bytes.toDec(res)) @@ -310,14 +307,14 @@ export class LedgerWallet extends Wallet { * * @returns Response object containing command status, public key, and address */ - async #account (index: number = 0, show: boolean = false): Promise { + static async #account (index: number = 0, show: boolean = false): Promise { if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) { throw new TypeError('Invalid account index') } const account = dec.toBytes(index + HARDENED_OFFSET, 4) const data = new Uint8Array([...LedgerWallet.#derivationPath, ...account]) - const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.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 @@ -368,7 +365,7 @@ export class LedgerWallet 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 this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.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)) @@ -397,7 +394,7 @@ export class LedgerWallet extends Wallet { const balance = hex.toBytes(BigInt(block.balance).toString(16), 16) const data = new Uint8Array([...LedgerWallet.#derivationPath, ...account, ...previous, ...link, ...representative, ...balance]) - const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.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 await transport.close() @@ -437,7 +434,7 @@ export class LedgerWallet extends Wallet { const derivationAccount = dec.toBytes(index + HARDENED_OFFSET, 4) const data = new Uint8Array([...LedgerWallet.#derivationPath, ...derivationAccount, ...nonce]) - const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.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 @@ -466,7 +463,7 @@ export class LedgerWallet extends Wallet { * @returns Status, process name, and version */ async #version (): Promise { - const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout) + const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.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