From: Chris Duncan Date: Thu, 10 Jul 2025 16:04:09 +0000 (-0700) Subject: Update wallet parent to support Ledger public-only keypairs, and deprecate Ledger... X-Git-Tag: v0.10.5~65 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=08b3c6acd563476b042913fe84a2ebd89c2f7de7;p=libnemo.git Update wallet parent to support Ledger public-only keypairs, and deprecate Ledger account method overrides. --- diff --git a/src/lib/wallets/ledger-wallet.ts b/src/lib/wallets/ledger-wallet.ts index ec25851..d3a9773 100644 --- a/src/lib/wallets/ledger-wallet.ts +++ b/src/lib/wallets/ledger-wallet.ts @@ -5,7 +5,7 @@ import { ledgerUSBVendorId } from '@ledgerhq/devices' import { default as TransportBLE } from '@ledgerhq/hw-transport-web-ble' import { default as TransportUSB } from '@ledgerhq/hw-transport-webusb' import { default as TransportHID } from '@ledgerhq/hw-transport-webhid' -import { Account } from '#src/lib/account.js' +import { Account, AccountList } from '#src/lib/account.js' import { ChangeBlock, ReceiveBlock, SendBlock } from '#src/lib/block.js' import { BIP44_COIN_NANO, BIP44_PURPOSE, HARDENED_OFFSET, LEDGER_ADPU_CODES, LEDGER_STATUS_CODES } from '#src/lib/constants.js' import { bytes, dec, hex } from '#src/lib/convert.js' @@ -69,33 +69,6 @@ export class LedgerWallet extends Wallet { super(id) } - /** - * Since the Ledger device can only return one account per request, this - * overrides the default behavior of calling `accounts()` to instead - * directly derive and return a single account at the specified index. - * - * @returns Account - */ - async account (index: number = 0, show: boolean = false): Promise { - const { status, publicKey } = await this.#account(index, show) - if (publicKey == null) { - throw new Error('Failed to get account from device', { cause: status }) - } - const account = await Account.fromPublicKey(publicKey) - return account - } - - /** - * Since the Ledger device can only return one account per request, this - * overrides the default behavior of returning multiple accounts to instead - * return a single account at the specified index. - * - * @returns Account - */ - async accounts (): Promise { - throw new Error(`Ledger device only supports 'account()' calls`) - } - /** * Check which transport protocols are supported by the browser and set the * transport type according to the following priorities: Bluetooth, USB, HID. diff --git a/src/lib/wallets/wallet.ts b/src/lib/wallets/wallet.ts index d81d3a8..e35b808 100644 --- a/src/lib/wallets/wallet.ts +++ b/src/lib/wallets/wallet.ts @@ -111,10 +111,15 @@ export abstract class Wallet { if (indexes.length > 0) { const keypairs = await this.ckd(indexes) for (const keypair of keypairs) { - const { privateKey, index } = keypair - if (privateKey == null) throw new RangeError('Account private key missing') + const { privateKey, publicKey, index } = keypair if (index == null) throw new RangeError('Account keys derived but index missing') - output[index] = await Account.fromPrivateKey(privateKey, index) + if (privateKey != null && privateKey) { + output[index] = await Account.fromPrivateKey(privateKey, index) + } else if (publicKey != null) { + output[index] = await Account.fromPublicKey(publicKey, index) + } else { + throw new RangeError('Account keys missing') + } this.#accounts[index] = output[index] } } diff --git a/test/test.ledger.mjs b/test/test.ledger.mjs index a18d7a1..2ee701e 100644 --- a/test/test.ledger.mjs +++ b/test/test.ledger.mjs @@ -62,6 +62,20 @@ await suite('Ledger hardware wallet', { skip: false || isNode }, async () => { assert.equals(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000') }) + await test('get second and third accounts', async () => { + const accounts = await wallet.accounts(1, 2) + + assert.exists(accounts) + assert.equals(accounts.length, 2) + for (const account of accounts) { + assert.ok(account instanceof Account) + assert.exists(account.address) + assert.exists(account.publicKey) + assert.exists(account.privateKey) + assert.equals(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000') + } + }) + await test('sign open block from block', async () => { openBlock = new ReceiveBlock( account, @@ -136,10 +150,7 @@ await suite('Ledger hardware wallet', { skip: false || isNode }, async () => { }) await test('destroy wallet', async () => { - const { status } = await wallet.close() - - assert.equals(status, 'OK') - await wallet.destroy() + await assert.resolves(wallet.destroy()) }) // nonce signing is currently broken: https://github.com/LedgerHQ/app-nano/pull/14