From: Chris Duncan Date: Tue, 12 May 2026 18:36:30 +0000 (-0700) Subject: Update Ledger dependencies and install standard Ledger error codes. Fix lock status... X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=e52e58a066ed771a39929689aa44f26dac0d63e1;p=libnemo.git Update Ledger dependencies and install standard Ledger error codes. Fix lock status using new LOCKED messaging from Ledger. --- diff --git a/package-lock.json b/package-lock.json index 6762c94..2a96404 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,10 @@ "version": "0.12.1", "license": "(GPL-3.0-or-later AND MIT AND ISC)", "dependencies": { - "@ledgerhq/hw-transport-web-ble": "^6.33.1", - "@ledgerhq/hw-transport-webhid": "^6.34.0", - "@ledgerhq/hw-transport-webusb": "^6.33.0", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/hw-transport-web-ble": "^6.34.2", + "@ledgerhq/hw-transport-webhid": "^6.35.2", + "@ledgerhq/hw-transport-webusb": "^6.34.2", "@noble/secp256k1": "^3.0.0", "nano-pow": "^5.1.14", "nano25519": "^1.0.2" @@ -499,76 +500,76 @@ } }, "node_modules/@ledgerhq/devices": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.13.0.tgz", - "integrity": "sha512-hgGn1kpe/rT0EJ0Qs7rG+1TXA4g6HN2t3dB4DndRTqVqC9aSSbME+ajA0QWLZisxOD3zkwvO4Q0mJ2zARAKyag==", + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.14.2.tgz", + "integrity": "sha512-T3pnfrsQEC/eJU0XHIqWI6qww+CL1k3NumR2XGWlMz8lVpoZ9HhcuGoCkMevp+8SWmymgyNIIFue3jlNA5KiMw==", "license": "Apache-2.0", "dependencies": { - "@ledgerhq/errors": "^6.32.0", - "@ledgerhq/logs": "^6.16.0", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/logs": "^6.17.0", "rxjs": "7.8.2", "semver": "7.7.3" } }, "node_modules/@ledgerhq/errors": { - "version": "6.32.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.32.0.tgz", - "integrity": "sha512-BjjvhLM6UXYUbhllqAduo9PSneLt9FXZ3TBEUFQ3MMSZOCHt0gAgDySLwul99R8fdYWkXBza4DYQjUNckpN2lg==", + "version": "6.34.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.34.1.tgz", + "integrity": "sha512-Atkim7yM9bbfWN7OikiE1vbtRLABRz6rDayTHkX0rkPTs6EkMVZSgoNNDGhcYQRlUXrTz9Eko+5ixCLpJQpEWg==", "license": "Apache-2.0" }, "node_modules/@ledgerhq/hw-transport": { - "version": "6.34.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.34.1.tgz", - "integrity": "sha512-Bg9Qk2vtm0m0cZn9prZV2Hbvh3b42KBh4uomO00derh+eiwsdg5AXBBptAJiREkew1RVtETRdWxrKchUJfeWvA==", + "version": "6.35.2", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.35.2.tgz", + "integrity": "sha512-eSXFFqMDAB2Ra/5uqmlru0cUyc2XDQPEKf4ITWHeMms2fHhETw9lcgAEl61vszkiz0RLUVB4VQsLJjj7O8kCvg==", "license": "Apache-2.0", "dependencies": { - "@ledgerhq/devices": "8.13.0", - "@ledgerhq/errors": "^6.32.0", - "@ledgerhq/logs": "^6.16.0", + "@ledgerhq/devices": "8.14.2", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/logs": "^6.17.0", "events": "^3.3.0" } }, "node_modules/@ledgerhq/hw-transport-web-ble": { - "version": "6.33.1", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-6.33.1.tgz", - "integrity": "sha512-ao/brcjeUUYyUXulT+uRtlyWxBrxGn6YGqwNi4l2qAs0A3zuE6QSnQMiRhhSrZ22SKT3caUarqK5s4GTml65wg==", + "version": "6.34.2", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-web-ble/-/hw-transport-web-ble-6.34.2.tgz", + "integrity": "sha512-u45djrQFh4WC0uCZj8i0Z5OK11m1+t8oYlkQkhDazrQ4bEzZmJqAtQR3jDmxQs3u2gqEMmE8tSuRfYoSCvLsKA==", "license": "Apache-2.0", "dependencies": { - "@ledgerhq/devices": "8.13.0", - "@ledgerhq/errors": "^6.32.0", - "@ledgerhq/hw-transport": "6.34.1", - "@ledgerhq/logs": "^6.16.0", + "@ledgerhq/devices": "8.14.2", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/hw-transport": "6.35.2", + "@ledgerhq/logs": "^6.17.0", "rxjs": "7.8.2" } }, "node_modules/@ledgerhq/hw-transport-webhid": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.34.0.tgz", - "integrity": "sha512-SG+UnZXyUzrJBSkZnRYGaaZV+C8yiu+pF69Mzw4AKOX6TG8RZ1tOvly8hhnRQ2/gXSiTgbc07N4T8ne2eFei3A==", + "version": "6.35.2", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.35.2.tgz", + "integrity": "sha512-gPqOIVW0cn5WjL23EtO+h9hD12mDIKS/buha3YJkzdxVBJufobc1N8a8CdtOcFoe53o0i1mTdHqo8MJzzueQCw==", "license": "Apache-2.0", "dependencies": { - "@ledgerhq/devices": "8.13.0", - "@ledgerhq/errors": "^6.32.0", - "@ledgerhq/hw-transport": "6.34.1", - "@ledgerhq/logs": "^6.16.0" + "@ledgerhq/devices": "8.14.2", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/hw-transport": "6.35.2", + "@ledgerhq/logs": "^6.17.0" } }, "node_modules/@ledgerhq/hw-transport-webusb": { - "version": "6.33.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.33.0.tgz", - "integrity": "sha512-/CSDMzBykihqumItyRxmrmqvBHIBRO9eQlHk2Xvrok6X09EF8ENglcITmEiyqvtDQEofD9A0+tdUhWgV9z82fg==", + "version": "6.34.2", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.34.2.tgz", + "integrity": "sha512-2nRe72vfUsxWkIFSgV8b/RR8BXA27284Uy5Yx+JJnxs1D5bCdvO4WDYg1kXsDd2E3Q1eCZBvV5gSHQbi+uKsvA==", "license": "Apache-2.0", "dependencies": { - "@ledgerhq/devices": "8.13.0", - "@ledgerhq/errors": "^6.32.0", - "@ledgerhq/hw-transport": "6.34.1", - "@ledgerhq/logs": "^6.16.0" + "@ledgerhq/devices": "8.14.2", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/hw-transport": "6.35.2", + "@ledgerhq/logs": "^6.17.0" } }, "node_modules/@ledgerhq/logs": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.16.0.tgz", - "integrity": "sha512-v/PLfb1dq1En35kkpbfRWp8jLYgbPUXxGhmd4pmvPSIe0nRGkNTomsZASmWQAv6pRonVGqHIBVlte7j1MBbOww==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.17.0.tgz", + "integrity": "sha512-yra33g5q/AU7+PwAws+GaVpQGUuxnDREjVBnviJjcaJLVKuLzI4pnj8Bd3nY3fypM5k1yZEYKEXfUuGFUjP2+w==", "license": "Apache-2.0" }, "node_modules/@noble/secp256k1": { @@ -853,9 +854,9 @@ "license": "MIT" }, "node_modules/basic-ftp": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz", - "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", "license": "MIT", "optional": true, "engines": { @@ -1353,9 +1354,9 @@ } }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "license": "MIT", "optional": true, "engines": { diff --git a/package.json b/package.json index 6999fb0..2dfe69b 100644 --- a/package.json +++ b/package.json @@ -55,9 +55,10 @@ "test:prod": "npm run build:prod && npm run test:node" }, "dependencies": { - "@ledgerhq/hw-transport-web-ble": "^6.33.1", - "@ledgerhq/hw-transport-webhid": "^6.34.0", - "@ledgerhq/hw-transport-webusb": "^6.33.0", + "@ledgerhq/errors": "^6.34.1", + "@ledgerhq/hw-transport-web-ble": "^6.34.2", + "@ledgerhq/hw-transport-webhid": "^6.35.2", + "@ledgerhq/hw-transport-webusb": "^6.34.2", "@noble/secp256k1": "^3.0.0", "nano-pow": "^5.1.14", "nano25519": "^1.0.2" diff --git a/src/lib/ledger.ts b/src/lib/ledger.ts index 72fd3b6..d3487af 100644 --- a/src/lib/ledger.ts +++ b/src/lib/ledger.ts @@ -1,6 +1,7 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later +import { StatusCodes } from '@ledgerhq/errors' import { default as TransportBLE } from '@ledgerhq/hw-transport-web-ble' import { default as TransportHID } from '@ledgerhq/hw-transport-webhid' import { default as TransportUSB } from '@ledgerhq/hw-transport-webusb' @@ -63,18 +64,12 @@ export class Ledger { ...dec.toBytes(BIP44_PURPOSE + HARDENED_OFFSET, 4), ...dec.toBytes(BIP44_COIN_NANO + HARDENED_OFFSET, 4) ]) - static #STATUS_CODES: { [key: number]: string } = Object.freeze({ - 0x6700: 'INCORRECT_LENGTH', - 0x670a: 'NO_APPLICATION_SPECIFIED', + static #STATUS_CODES: Readonly> = Object.freeze({ + ...Object.fromEntries(Object.entries(StatusCodes).map(([k, v]) => [+v, k])), 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' + 0x6a82: 'CACHE_MISS' }) // Compose event emission for status changes @@ -196,7 +191,7 @@ export class Ledger { } } try { - return await this.#connect() + return this.#connect() } catch (err) { throw new Error('Ledger.connect()', { cause: err }) } finally { @@ -461,21 +456,21 @@ export class Ledger { static async #connect (): Promise { try { const version = await this.#version() - if (version.status !== 'OK') { + if (version.status === 'LOCKED_DEVICE') { + this.#setStatus('LOCKED') + } else if (version.status !== 'OK') { this.#setStatus('DISCONNECTED') - } else { - if (version.name === 'Nano') { - const { status } = await this.account() - if (status === 'OK') { - this.#setStatus('CONNECTED') - } else if (status === 'SECURITY_STATUS_NOT_SATISFIED') { - this.#setStatus('LOCKED') - } else { - this.#setStatus('DISCONNECTED') - } + } else if (version.name === 'Nano') { + const { status } = await this.account() + if (status === 'OK') { + this.#setStatus('CONNECTED') + } else if (status === 'SECURITY_STATUS_NOT_SATISFIED') { + this.#setStatus('LOCKED') } else { - this.#setStatus('BUSY') + this.#setStatus('DISCONNECTED') } + } else { + this.#setStatus('BUSY') } } catch (err) { console.error('Ledger.#connect()', err)