]> git.codecow.com Git - libnemo.git/commitdiff
Move Ledger constants into Ledger class instead of shared constants file.
authorChris Duncan <chris@zoso.dev>
Mon, 11 Aug 2025 12:52:06 +0000 (05:52 -0700)
committerChris Duncan <chris@zoso.dev>
Mon, 11 Aug 2025 12:52:06 +0000 (05:52 -0700)
src/lib/constants.ts
src/lib/wallet/ledger.ts

index 48c67caf9ae727922e19706c408ba48309071c4d..31bbe041275e2cba8b175e70af841be98db0c878 100644 (file)
@@ -24,31 +24,6 @@ export const DIFFICULTY_RECEIVE = 0xfffffe0000000000n
 export const DIFFICULTY_SEND = 0xfffffff800000000n
 export const XNO = 'ΣΎ'
 
-export const LEDGER_STATUS_CODES: { [key: number]: string } = Object.freeze({
-       0x6700: 'INCORRECT_LENGTH',
-       0x670a: 'NO_APPLICATION_SPECIFIED',
-       0x6807: 'APPLICATION_NOT_INSTALLED',
-       0x6d00: 'APPLICATION_ALREADY_LAUNCHED',
-       0x6982: 'SECURITY_STATUS_NOT_SATISFIED',
-       0x6985: 'CONDITIONS_OF_USE_NOT_SATISFIED',
-       0x6a81: 'INVALID_SIGNATURE',
-       0x6a82: 'CACHE_MISS',
-       0x6b00: 'INCORRECT_PARAMETER',
-       0x6e01: 'TRANSPORT_STATUS_ERROR',
-       0x9000: 'OK'
-})
-
-export const LEDGER_ADPU_CODES: { [key: string]: number } = Object.freeze({
-       class: 0xa1,
-       bip32DerivationLevel: 0x03,
-       version: 0x01,
-       account: 0x02,
-       cacheBlock: 0x03,
-       signBlock: 0x04,
-       signNonce: 0x05,
-       paramUnused: 0x00
-})
-
 export const UNITS: { [key: string]: number } = Object.freeze({
        RAW: 0,
        RAI: 24,
@@ -84,7 +59,5 @@ export default `
        const DIFFICULTY_RECEIVE = ${DIFFICULTY_RECEIVE}
        const DIFFICULTY_SEND = ${DIFFICULTY_SEND}
        const XNO = '${XNO}'
-       const LEDGER_STATUS_CODES = ${JSON.stringify(LEDGER_STATUS_CODES)}
-       const LEDGER_ADPU_CODES = ${JSON.stringify(LEDGER_ADPU_CODES)}
        const UNITS = ${JSON.stringify(UNITS)}
 `
index 773a02894714a586a12163ed2c0836bea206e612..9f471c6944c74a7389f685fffc88a325900cf745 100644 (file)
@@ -7,7 +7,7 @@ import { default as TransportUSB } from '@ledgerhq/hw-transport-webusb'
 import { default as TransportHID } from '@ledgerhq/hw-transport-webhid'\r
 import { Account, AccountList } from '../account'\r
 import { Block } from '../block'\r
-import { BIP44_COIN_NANO, BIP44_PURPOSE, HARDENED_OFFSET, LEDGER_ADPU_CODES, LEDGER_STATUS_CODES } from '../constants'\r
+import { BIP44_COIN_NANO, BIP44_PURPOSE, HARDENED_OFFSET } from '../constants'\r
 import { bytes, dec, hex } from '../convert'\r
 import { Database } from '../database'\r
 import { Rpc } from '../rpc'\r
@@ -21,15 +21,40 @@ import { DeviceStatus, LedgerAccountResponse, LedgerResponse, LedgerSignResponse
 * is responsible for using Ledger technology to back up these pieces of data.\r
 */\r
 export class Ledger extends Wallet {\r
-       static #derivationPath: Uint8Array = new Uint8Array([\r
-               LEDGER_ADPU_CODES.bip32DerivationLevel,\r
+       static #isInternal: boolean = false\r
+\r
+       static #ADPU_CODES: { [key: string]: number } = Object.freeze({\r
+               class: 0xa1,\r
+               bip32DerivationLevel: 0x03,\r
+               version: 0x01,\r
+               account: 0x02,\r
+               cacheBlock: 0x03,\r
+               signBlock: 0x04,\r
+               signNonce: 0x05,\r
+               paramUnused: 0x00\r
+       })\r
+       static #DERIVATION_PATH: Uint8Array = new Uint8Array([\r
+               Ledger.#ADPU_CODES.bip32DerivationLevel,\r
                ...dec.toBytes(BIP44_PURPOSE + HARDENED_OFFSET, 4),\r
                ...dec.toBytes(BIP44_COIN_NANO + HARDENED_OFFSET, 4)\r
        ])\r
-       static #isInternal: boolean = false\r
-       static INTERNAL: Symbol = Symbol('Ledger')\r
+       static #STATUS_CODES: { [key: number]: string } = Object.freeze({\r
+               0x6700: 'INCORRECT_LENGTH',\r
+               0x670a: 'NO_APPLICATION_SPECIFIED',\r
+               0x6807: 'APPLICATION_NOT_INSTALLED',\r
+               0x6d00: 'APPLICATION_ALREADY_LAUNCHED',\r
+               0x6982: 'SECURITY_STATUS_NOT_SATISFIED',\r
+               0x6985: 'CONDITIONS_OF_USE_NOT_SATISFIED',\r
+               0x6a81: 'INVALID_SIGNATURE',\r
+               0x6a82: 'CACHE_MISS',\r
+               0x6b00: 'INCORRECT_PARAMETER',\r
+               0x6e01: 'TRANSPORT_STATUS_ERROR',\r
+               0x9000: 'OK'\r
+       })\r
 \r
        static DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID\r
+       static SYMBOL: Symbol = Symbol('Ledger')\r
+\r
        static get listenTimeout (): 30000 { return 30000 }\r
        static get openTimeout (): 3000 { return 3000 }\r
 \r
@@ -37,7 +62,7 @@ export class Ledger extends Wallet {
        * Check which transport protocols are supported by the browser and return the\r
        * transport type according to the following priorities: USB, Bluetooth, HID.\r
        */\r
-       static get isUnsupported (): boolean {\r
+       static get #isUnsupported (): boolean {\r
                console.log('Checking browser Ledger support...')\r
                if (typeof globalThis.navigator?.usb?.getDevices === 'function') {\r
                        this.DynamicTransport = TransportUSB\r
@@ -62,7 +87,7 @@ export class Ledger extends Wallet {
        */\r
        static async create (): Promise<Ledger> {\r
                try {\r
-                       if (this.isUnsupported) throw new Error('Browser is unsupported')\r
+                       if (this.#isUnsupported) throw new Error('Browser is unsupported')\r
                        this.#isInternal = true\r
                        const self = new this()\r
                        await Database.add({ [self.id]: { id: self.id, type: 'Ledger' } }, Wallet.DB_NAME)\r
@@ -399,10 +424,10 @@ export class Ledger extends Wallet {
                const name = new TextEncoder().encode('Nano')\r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout)\r
                const response = await transport\r
-                       .send(0xe0, 0xd8, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, name as Buffer)\r
+                       .send(0xe0, 0xd8, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused, name as Buffer)\r
                        .then(res => bytes.toDec(res))\r
                        .catch(err => err.statusCode) as number\r
-               return new Promise(r => setTimeout(r, 1000, { status: LEDGER_STATUS_CODES[response] }))\r
+               return new Promise(r => setTimeout(r, 1000, { status: Ledger.#STATUS_CODES[response] }))\r
        }\r
 \r
        /**\r
@@ -421,10 +446,10 @@ export class Ledger extends Wallet {
        async #close (): Promise<LedgerResponse> {\r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout)\r
                const response = await transport\r
-                       .send(0xb0, 0xa7, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused)\r
+                       .send(0xb0, 0xa7, Ledger.#ADPU_CODES.paramUnused, Ledger.#ADPU_CODES.paramUnused)\r
                        .then(res => bytes.toDec(res))\r
                        .catch(err => err.statusCode) as number\r
-               return new Promise(r => setTimeout(r, 1000, { status: LEDGER_STATUS_CODES[response] }))\r
+               return new Promise(r => setTimeout(r, 1000, { status: Ledger.#STATUS_CODES[response] }))\r
        }\r
 \r
        /**\r
@@ -437,16 +462,16 @@ export class Ledger extends Wallet {
                        throw new TypeError('Invalid account index')\r
                }\r
                const account = dec.toBytes(index + HARDENED_OFFSET, 4)\r
-               const data = new Uint8Array([...Ledger.#derivationPath, ...account])\r
+               const data = new Uint8Array([...Ledger.#DERIVATION_PATH, ...account])\r
 \r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.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
+                       .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
                await transport.close()\r
 \r
                const statusCode = bytes.toDec(response.slice(-2)) as number\r
-               const status = LEDGER_STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
+               const status = Ledger.#STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
                if (status !== 'OK') {\r
                        return { status, publicKey: null, address: null }\r
                }\r
@@ -494,16 +519,16 @@ export class Ledger extends Wallet {
                const representative = hex.toBytes(block.representative.publicKey, 32)\r
                const balance = hex.toBytes(block.balance.toString(16), 16)\r
                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
+               const data = new Uint8Array([Ledger.#ADPU_CODES.bip32DerivationLevel, ...purpose, ...coin, ...account, ...previous, ...link, ...representative, ...balance, ...signature])\r
 \r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.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
+                       .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
                        .catch(err => err.statusCode) as number\r
                await transport.close()\r
 \r
-               return { status: LEDGER_STATUS_CODES[response] }\r
+               return { status: Ledger.#STATUS_CODES[response] }\r
        }\r
 \r
        /**\r
@@ -529,16 +554,16 @@ export class Ledger extends Wallet {
                const link = block.link\r
                const representative = hex.toBytes(block.representative.publicKey, 32)\r
                const balance = hex.toBytes(BigInt(block.balance).toString(16), 16)\r
-               const data = new Uint8Array([...Ledger.#derivationPath, ...account, ...previous, ...link, ...representative, ...balance])\r
+               const data = new Uint8Array([...Ledger.#DERIVATION_PATH, ...account, ...previous, ...link, ...representative, ...balance])\r
 \r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout)\r
                const response = await transport\r
-                       .send(LEDGER_ADPU_CODES.class, LEDGER_ADPU_CODES.signBlock, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused, data as Buffer)\r
+                       .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
 \r
                const statusCode = bytes.toDec(response.slice(-2)) as number\r
-               const status = LEDGER_STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
+               const status = Ledger.#STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
 \r
                if (response.byteLength === 2) {\r
                        return { status, signature: null }\r
@@ -570,16 +595,16 @@ export class Ledger extends Wallet {
                }\r
 \r
                const derivationAccount = dec.toBytes(index + HARDENED_OFFSET, 4)\r
-               const data = new Uint8Array([...Ledger.#derivationPath, ...derivationAccount, ...nonce])\r
+               const data = new Uint8Array([...Ledger.#DERIVATION_PATH, ...derivationAccount, ...nonce])\r
 \r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.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
+                       .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
                await transport.close()\r
 \r
                const statusCode = bytes.toDec(response.slice(-2)) as number\r
-               const status = LEDGER_STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
+               const status = Ledger.#STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
 \r
                if (response.byteLength === 2) {\r
                        return { status, signature: null }\r
@@ -603,12 +628,12 @@ export class Ledger extends Wallet {
        async #version (): Promise<LedgerVersionResponse> {\r
                const transport = await Ledger.DynamicTransport.create(Ledger.openTimeout, Ledger.listenTimeout)\r
                const response = await transport\r
-                       .send(0xb0, LEDGER_ADPU_CODES.version, LEDGER_ADPU_CODES.paramUnused, LEDGER_ADPU_CODES.paramUnused)\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
                await transport.close()\r
 \r
                const statusCode = bytes.toDec(response.slice(-2)) as number\r
-               const status = LEDGER_STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
+               const status = Ledger.#STATUS_CODES[statusCode] ?? 'UNKNOWN_ERROR'\r
                if (status !== 'OK') {\r
                        return { status, name: null, version: null }\r
                }\r