]> git.codecow.com Git - libnemo.git/commitdiff
Refactor Ledger transport as static member.
authorChris Duncan <chris@zoso.dev>
Sat, 26 Jul 2025 06:20:55 +0000 (23:20 -0700)
committerChris Duncan <chris@zoso.dev>
Sat, 26 Jul 2025 06:20:55 +0000 (23:20 -0700)
src/lib/wallets/ledger-wallet.ts

index 839294efa58e617fd50a8f9fad41ed26313c3d0b..4eb2552aaf2d9014e096f4b4b3e5bf9edce82402 100644 (file)
@@ -27,21 +27,9 @@ export class LedgerWallet extends Wallet {
                ...dec.toBytes(BIP44_COIN_NANO + HARDENED_OFFSET, 4)\r
        ])\r
 \r
-       #status: DeviceStatus = 'DISCONNECTED'\r
-\r
-       get listenTimeout (): 30000 { return 30000 }\r
-       get openTimeout (): 3000 { return 3000 }\r
-       get status (): DeviceStatus { return this.#status }\r
-\r
-       DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID = TransportHID\r
-\r
-       private constructor (id: Entropy) {\r
-               if (!LedgerWallet.#isInternal) {\r
-                       throw new Error(`LedgerWallet cannot be instantiated directly. Use 'await LedgerWallet.create()' instead.`)\r
-               }\r
-               LedgerWallet.#isInternal = false\r
-               super(id, 'Ledger')\r
-       }\r
+       static DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID = this.checkBrowserSupport()\r
+       static get listenTimeout (): 30000 { return 30000 }\r
+       static get openTimeout (): 3000 { return 3000 }\r
 \r
        /**\r
        * Check which transport protocols are supported by the browser and return the\r
@@ -71,17 +59,26 @@ export class LedgerWallet extends Wallet {
        */\r
        static async create (): Promise<LedgerWallet> {\r
                try {\r
-                       const transport = LedgerWallet.checkBrowserSupport()\r
                        const id = await Entropy.create(16)\r
                        LedgerWallet.#isInternal = true\r
                        const wallet = new this(id)\r
-                       wallet.DynamicTransport = transport\r
                        return wallet\r
                } catch (err) {\r
                        throw new Error('failed to initialize Ledger wallet', { cause: err })\r
                }\r
        }\r
 \r
+       #status: DeviceStatus = 'DISCONNECTED'\r
+       get status (): DeviceStatus { return this.#status }\r
+\r
+       private constructor (id: Entropy) {\r
+               if (!LedgerWallet.#isInternal) {\r
+                       throw new Error(`LedgerWallet cannot be instantiated directly. Use 'await LedgerWallet.create()' instead.`)\r
+               }\r
+               LedgerWallet.#isInternal = false\r
+               super(id, 'Ledger')\r
+       }\r
+\r
        /**\r
        * Check if the Nano app is currently open and set device status accordingly.\r
        *\r
@@ -96,7 +93,7 @@ export class LedgerWallet extends Wallet {
                if (version.status !== 'OK') {\r
                        this.#status = 'DISCONNECTED'\r
                } else if (version.name === 'Nano') {\r
-                       const { status } = await this.#account()\r
+                       const { status } = await LedgerWallet.#account()\r
                        if (status === 'OK') {\r
                                this.#status = 'CONNECTED'\r
                        } else if (status === 'SECURITY_STATUS_NOT_SATISFIED') {\r
@@ -275,7 +272,7 @@ export class LedgerWallet extends Wallet {
        */\r
        async #open (): Promise<LedgerResponse> {\r
                const name = new TextEncoder().encode('Nano')\r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport\r
                        .send(0xe0, 0xd8, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, name as Buffer)\r
                        .then(res => bytes.toDec(res))\r
@@ -297,7 +294,7 @@ export class LedgerWallet extends Wallet {
        * @returns Status of command\r
        */\r
        async #close (): Promise<LedgerResponse> {\r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport\r
                        .send(0xb0, 0xa7, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused)\r
                        .then(res => bytes.toDec(res))\r
@@ -310,14 +307,14 @@ export class LedgerWallet extends Wallet {
        *\r
        * @returns Response object containing command status, public key, and address\r
        */\r
-       async #account (index: number = 0, show: boolean = false): Promise<LedgerAccountResponse> {\r
+       static async #account (index: number = 0, show: boolean = false): Promise<LedgerAccountResponse> {\r
                if (typeof index !== 'number' || index < 0 || index >= HARDENED_OFFSET) {\r
                        throw new TypeError('Invalid account index')\r
                }\r
                const account = dec.toBytes(index + HARDENED_OFFSET, 4)\r
                const data = new Uint8Array([...LedgerWallet.#derivationPath, ...account])\r
 \r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport\r
                        .send(LEDGER_ADPU_CODES.class, LEDGER_ADPU_CODES.account, show ? 1 : 0, LEDGER_ADPU_CODES.paramUnused, data as Buffer)\r
                        .catch(err => dec.toBytes(err.statusCode)) as Uint8Array\r
@@ -368,7 +365,7 @@ export class LedgerWallet extends Wallet {
                const signature = hex.toBytes(block.signature, 64)\r
                const data = new Uint8Array([LEDGER_ADPU_CODES.bip32DerivationLevel, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance, ...signature])\r
 \r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport\r
                        .send(LEDGER_ADPU_CODES.class, LEDGER_ADPU_CODES.cacheBlock, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, data as Buffer)\r
                        .then(res => bytes.toDec(res))\r
@@ -397,7 +394,7 @@ export class LedgerWallet extends Wallet {
                const balance = hex.toBytes(BigInt(block.balance).toString(16), 16)\r
                const data = new Uint8Array([...LedgerWallet.#derivationPath, ...account, ...previous, ...link, ...representative, ...balance])\r
 \r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport.send(LEDGER_ADPU_CODES.class, LEDGER_ADPU_CODES.signBlock, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, data as Buffer)\r
                        .catch(err => dec.toBytes(err.statusCode)) as Uint8Array\r
                await transport.close()\r
@@ -437,7 +434,7 @@ export class LedgerWallet extends Wallet {
                const derivationAccount = dec.toBytes(index + HARDENED_OFFSET, 4)\r
                const data = new Uint8Array([...LedgerWallet.#derivationPath, ...derivationAccount, ...nonce])\r
 \r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport\r
                        .send(LEDGER_ADPU_CODES.class, LEDGER_ADPU_CODES.signNonce, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, data as Buffer)\r
                        .catch(err => dec.toBytes(err.statusCode)) as Uint8Array\r
@@ -466,7 +463,7 @@ export class LedgerWallet extends Wallet {
        * @returns Status, process name, and version\r
        */\r
        async #version (): Promise<LedgerVersionResponse> {\r
-               const transport = await this.DynamicTransport.create(this.openTimeout, this.listenTimeout)\r
+               const transport = await LedgerWallet.DynamicTransport.create(LedgerWallet.openTimeout, LedgerWallet.listenTimeout)\r
                const response = await transport\r
                        .send(0xb0, LEDGER_ADPU_CODES.version, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused)\r
                        .catch(err => dec.toBytes(err.statusCode)) as Uint8Array\r