]> git.codecow.com Git - libnemo.git/commitdiff
Move data validation for wallet load into separate load module. Refactor how Ledger...
authorChris Duncan <chris@zoso.dev>
Sun, 10 Aug 2025 20:22:08 +0000 (13:22 -0700)
committerChris Duncan <chris@zoso.dev>
Sun, 10 Aug 2025 20:22:08 +0000 (13:22 -0700)
12 files changed:
README.md
src/lib/wallet/index.ts
src/lib/wallet/ledger.ts
src/lib/wallet/load.ts
test/perf.account.mjs
test/perf.wallet.mjs
test/test.blocks.mjs
test/test.create-wallet.mjs
test/test.derive-accounts.mjs
test/test.import-wallet.mjs
test/test.lock-unlock.mjs
test/test.tools.mjs

index 56a38ee03b56b43ddb7e46bb09c7cd196c6492e8..9b8572a97720e7a8983b2611adc27d251d533afd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -68,13 +68,13 @@ usage.
 ```javascript
 import { Wallet } from 'libnemo'
 
-const wallet = await Wallet.create(password)
-const wallet = await Wallet.load(password, mnemonic, salt?)
-const wallet = await Wallet.load(password, seed)
+const wallet = await Wallet.create('BIP-44', password)
+const wallet = await Wallet.load('BIP-44', password, mnemonic, salt?)
+const wallet = await Wallet.load('BIP-44', password, seed)
 
-const wallet = await Wallet.create(password)
-const wallet = await Wallet.load(password, seed)
-const wallet = await Wallet.load(password, mnemonic)
+const wallet = await Wallet.create('BLAKE2b', password)
+const wallet = await Wallet.load('BLAKE2b', password, seed)
+const wallet = await Wallet.load('BLAKE2b', password, mnemonic)
 ```
 
 ```javascript
index 2c2f29ae0530ce491daf36227f7b984f796a0af3..8ff2325c0466cd2420ff3202cab7867355efdf4b 100644 (file)
@@ -42,16 +42,20 @@ export class Wallet {
        * @param {string} [salt=''] - Used when generating the final seed\r
        * @returns {Wallet} A newly instantiated Wallet\r
        */\r
-       static async create (password: string, type: 'BIP-44' | 'BLAKE2b', mnemonicSalt?: string): Promise<Wallet>\r
-       static async create (password: unknown, type: unknown, mnemonicSalt?: unknown): Promise<Wallet> {\r
-               if (typeof password !== 'string') {\r
-                       throw new TypeError('Password must be a string')\r
+       static async create (type: WalletType, password: string, mnemonicSalt?: string): Promise<Wallet>\r
+       static async create (type: unknown, password: unknown, mnemonicSalt?: unknown): Promise<Wallet> {\r
+               if (type === 'Ledger') {\r
+                       Wallet.#isInternal = true\r
+                       return new this(type)\r
                }\r
-               const passwordBuffer = utf8.toBuffer(password)\r
-               password = undefined\r
                if (type !== 'BIP-44' && type !== 'BLAKE2b') {\r
                        throw new TypeError('Invalid wallet type')\r
                }\r
+               if (typeof password !== 'string') {\r
+                       throw new TypeError('Invalid password', { cause: typeof password })\r
+               }\r
+               const passwordBuffer = utf8.toBuffer(password)\r
+               password = undefined\r
                if (mnemonicSalt !== undefined && typeof mnemonicSalt !== 'string') {\r
                        throw new TypeError('Mnemonic salt must be a string')\r
                }\r
@@ -83,41 +87,27 @@ export class Wallet {
        * Imports an existing HD wallet by using an entropy value generated using a\r
        * cryptographically strong pseudorandom number generator.NamedD\r
        *\r
-       * @param {string} password - Encrypts the wallet to lock and unlock it. Discard as soon as possible after loading the wallet.\r
        * @param {string} type - Algorithm used to generate wallet and child accounts\r
+       * @param {string} password - Encrypts the wallet to lock and unlock it. Discard as soon as possible after loading the wallet.\r
        * @param {string} seed - Used to derive child accounts\r
        * @returns Wallet in a locked state\r
        */\r
-       static async load (password: string, type: 'BIP-44' | 'BLAKE2b', seed: string): Promise<Wallet>\r
+       static async load (type: 'BIP-44' | 'BLAKE2b', password: string, seed: string): Promise<Wallet>\r
        /**\r
        * Imports an existing HD wallet by using an entropy value generated using a\r
        * cryptographically strong pseudorandom number generator.\r
        *\r
-       * @param {string} password - Encrypts the wallet to lock and unlock it. Discard as soon as possible after loading the wallet.\r
        * @param {string} type - Algorithm used to generate wallet and child accounts\r
+       * @param {string} password - Encrypts the wallet to lock and unlock it. Discard as soon as possible after loading the wallet.\r
        * @param {string} mnemonicPhrase - Used to derive the wallet seed\r
        * @param {string} [mnemonicSalt] - Used to alter the seed derived from the mnemonic phrase\r
        * @returns Wallet in a locked state\r
        */\r
-       static async load (password: string, type: 'BIP-44' | 'BLAKE2b', mnemonicPhrase: string, mnemonicSalt?: string): Promise<Wallet>\r
-       static async load (password: unknown, type: unknown, secret: unknown, mnemonicSalt?: unknown): Promise<Wallet> {\r
-               if (typeof password !== 'string') {\r
-                       throw new TypeError('Password must be a string')\r
-               }\r
-               const passwordBuffer = utf8.toBuffer(password)\r
-               password = undefined\r
-               if (type !== 'BIP-44' && type !== 'BLAKE2b') {\r
-                       throw new TypeError('Invalid wallet type', { cause: type })\r
-               }\r
-               if (typeof secret !== 'string') {\r
-                       throw new TypeError('Wallet secret must be a string')\r
-               }\r
-               if (mnemonicSalt !== undefined && typeof mnemonicSalt !== 'string') {\r
-                       throw new TypeError('Mnemonic salt must be a string')\r
-               }\r
+       static async load (type: 'BIP-44' | 'BLAKE2b', password: string, mnemonicPhrase: string, mnemonicSalt?: string): Promise<Wallet>\r
+       static async load (type: WalletType, password: string, secret: string, mnemonicSalt?: string): Promise<Wallet> {\r
                Wallet.#isInternal = true\r
                const self = new this(type)\r
-               await _load(self, passwordBuffer, secret, mnemonicSalt)\r
+               await _load(self, password, secret, mnemonicSalt)\r
                return self\r
        }\r
 \r
@@ -185,10 +175,14 @@ export class Wallet {
                }\r
        }\r
 \r
-       constructor (type: WalletType, id?: string) {\r
-               if (!Wallet.#isInternal && type !== 'Ledger') {\r
+       constructor (type: WalletType, id?: string)\r
+       constructor (type: unknown, id?: string) {\r
+               if (!Wallet.#isInternal) {\r
                        throw new Error(`Wallet cannot be instantiated directly. Use 'await Wallet.create()' instead.`)\r
                }\r
+               if (type !== 'BIP-44' && type !== 'BLAKE2b' && type !== 'Ledger') {\r
+                       throw new TypeError('Invalid wallet type', { cause: type })\r
+               }\r
                Wallet.#isInternal = false\r
                this.#accounts = new AccountList()\r
                this.#id = id ?? crypto.randomUUID()\r
index 98e93d267c6331f2acb725a70919fa5a11a9fccc..773a02894714a586a12163ed2c0836bea206e612 100644 (file)
@@ -21,12 +21,13 @@ 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 #isInternal: boolean = false\r
        static #derivationPath: 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
 \r
        static DynamicTransport: typeof TransportBLE | typeof TransportUSB | typeof TransportHID\r
        static get listenTimeout (): 30000 { return 30000 }\r
@@ -62,7 +63,7 @@ export class Ledger extends Wallet {
        static async create (): Promise<Ledger> {\r
                try {\r
                        if (this.isUnsupported) throw new Error('Browser is unsupported')\r
-                       Ledger.#isInternal = true\r
+                       this.#isInternal = true\r
                        const self = new this()\r
                        await Database.add({ [self.id]: { id: self.id, type: 'Ledger' } }, Wallet.DB_NAME)\r
                        return self\r
@@ -80,7 +81,6 @@ export class Ledger extends Wallet {
        }\r
 \r
        #accounts: AccountList\r
-       #vault: undefined\r
        #status: DeviceStatus = 'DISCONNECTED'\r
        get status (): DeviceStatus { return this.#status }\r
 \r
@@ -91,7 +91,6 @@ export class Ledger extends Wallet {
                Ledger.#isInternal = false\r
                super('Ledger')\r
                this.#accounts = new AccountList()\r
-               this.#vault = undefined\r
        }\r
 \r
        /**\r
@@ -354,7 +353,7 @@ export class Ledger extends Wallet {
        */\r
        async verify (mnemonic: string): Promise<boolean>\r
        async verify (secret: string): Promise<boolean> {\r
-               const testWallet = await Wallet.load('', 'BIP-44', secret)\r
+               const testWallet = await Wallet.load('BIP-44', '', secret)\r
                await testWallet.unlock('')\r
                const testAccount = await testWallet.account(0)\r
                const testOpenBlock = await new Block(testAccount.address, '0', testAccount.publicKey, testAccount.address)\r
index 2a2a0745a3519cd4797a69eb0c9339b642a74800..b4d7bad687ec230bb3cc5f484a05941fd794893b 100644 (file)
@@ -3,7 +3,7 @@
 
 import { Bip39 } from '#crypto'
 import { NamedData } from '#types'
-import { hex } from '../convert'
+import { hex, utf8 } from '../convert'
 import { Database } from '../database'
 import { Wallet } from '.'
 
@@ -15,13 +15,24 @@ import { Wallet } from '.'
 * @param {string} [salt=''] - Used when generating the final seed
 * @returns {Wallet} A newly instantiated Wallet
 */
-export async function _load (wallet: Wallet, password: ArrayBuffer, secret: string, mnemonicSalt?: string): Promise<void> {
+export async function _load (wallet: Wallet, password: string, secret: string, mnemonicSalt?: string): Promise<void>
+export async function _load (wallet: Wallet, password: unknown, secret: unknown, mnemonicSalt?: unknown): Promise<void> {
+       if (typeof password !== 'string') {
+               throw new TypeError('Password must be a string')
+       }
+       if (typeof secret !== 'string') {
+               throw new TypeError('Wallet secret must be a string')
+       }
+       if (mnemonicSalt !== undefined && typeof mnemonicSalt !== 'string') {
+               throw new TypeError('Mnemonic salt must be a string')
+       }
        try {
                const data: NamedData = {
                        action: 'load',
                        type: wallet.type,
-                       password
+                       password: utf8.toBuffer(password)
                }
+               password = undefined
                if (/^(?:[A-F0-9]{64}){1,2}$/i.test(secret)) {
                        data.seed = hex.toBuffer(secret)
                } else if (await Bip39.validate(secret)) {
@@ -30,6 +41,8 @@ export async function _load (wallet: Wallet, password: ArrayBuffer, secret: stri
                } else {
                        throw new TypeError('Invalid wallet data')
                }
+               secret = undefined
+               mnemonicSalt = undefined
                const result = wallet.vault.request<ArrayBuffer>(data)
                const { iv, salt, encrypted } = await result
                const record = {
index 0e5919a71f1756bb602c83e6352514f66742ca41..90d8384e8aa564114105710a49dd6335724e0837 100644 (file)
@@ -21,7 +21,7 @@ await Promise.all([
                const COUNT = 0x200
 
                await test(`Time to create ${COUNT} BIP-44 accounts`, async () => {
-                       const wallet = await Wallet.create(NANO_TEST_VECTORS.PASSWORD, 'BIP-44')
+                       const wallet = await Wallet.create('BIP-44', NANO_TEST_VECTORS.PASSWORD)
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
 
                        const start = performance.now()
@@ -35,7 +35,7 @@ await Promise.all([
                })
 
                await test(`Time to create ${COUNT} BLAKE2b accounts`, async () => {
-                       const wallet = await Wallet.create(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b')
+                       const wallet = await Wallet.create('BLAKE2b', NANO_TEST_VECTORS.PASSWORD)
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
 
                        const start = performance.now()
@@ -49,7 +49,7 @@ await Promise.all([
                })
 
                await test(`Time to create 1 BIP-44 account ${COUNT} times`, async () => {
-                       const wallet = await Wallet.create(NANO_TEST_VECTORS.PASSWORD, 'BIP-44')
+                       const wallet = await Wallet.create('BIP-44', NANO_TEST_VECTORS.PASSWORD)
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
 
                        const times = []
@@ -65,7 +65,7 @@ await Promise.all([
                })
 
                await test(`Time to create 1 BLAKE2b account ${COUNT} times`, async () => {
-                       const wallet = await Wallet.create(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b')
+                       const wallet = await Wallet.create('BLAKE2b', NANO_TEST_VECTORS.PASSWORD)
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
 
                        const times = []
index 30e1a0a3162b4a67d65f0c2b2313554684bfe96d..6764e9ee58a3ae083ee0c4a7a95399abdb613b03 100644 (file)
@@ -24,7 +24,7 @@ await Promise.all([
                        const times = []
                        for (let i = 0; i < COUNT; i++) {
                                const start = performance.now()
-                               const wallet = await Wallet.create(NANO_TEST_VECTORS.PASSWORD, 'BIP-44')
+                               const wallet = await Wallet.create('BIP-44', NANO_TEST_VECTORS.PASSWORD)
                                const end = performance.now()
                                times.push(end - start)
                                await wallet.destroy()
@@ -36,7 +36,7 @@ await Promise.all([
                        const times = []
                        for (let i = 0; i < COUNT; i++) {
                                const start = performance.now()
-                               const wallet = await Wallet.create(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b')
+                               const wallet = await Wallet.create('BLAKE2b', NANO_TEST_VECTORS.PASSWORD)
                                const end = performance.now()
                                times.push(end - start)
                                await wallet.destroy()
index 900b55e21582816289e8d5e0ccd17b55cac432d0..81fe264a8c7ce5126bf0643d94b3c1cf68290a74 100644 (file)
@@ -98,7 +98,7 @@ await Promise.all([
                const { ADDRESS_0, BIP39_SEED, BLAKE2B_ADDRESS_1, BLAKE2B_PUBLIC_1, BLAKE2B_SEED, OPEN_BLOCK, PASSWORD, PRIVATE_0, RECEIVE_BLOCK, SEND_BLOCK } = NANO_TEST_VECTORS\r
 \r
                await test('sign open block with BLAKE2b wallet', async () => {\r
-                       const wallet = await Wallet.load(PASSWORD, 'BLAKE2b', BLAKE2B_SEED)\r
+                       const wallet = await Wallet.load('BLAKE2b', PASSWORD, BLAKE2B_SEED)\r
                        await assert.resolves(wallet.unlock(PASSWORD))\r
 \r
                        const block = new Block(BLAKE2B_ADDRESS_1, '0', OPEN_BLOCK.previous, OPEN_BLOCK.representative)\r
@@ -111,7 +111,7 @@ await Promise.all([
                })\r
 \r
                await test('sign open block with BIP-44 wallet', async () => {\r
-                       const wallet = await Wallet.load(PASSWORD, 'BIP-44', BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', PASSWORD, BIP39_SEED)\r
                        await assert.resolves(wallet.unlock(PASSWORD))\r
 \r
                        const block = new Block(ADDRESS_0, '0', OPEN_BLOCK.previous, OPEN_BLOCK.representative)\r
@@ -123,7 +123,7 @@ await Promise.all([
                })\r
 \r
                await test('fail to sign open block with wallet when locked', async () => {\r
-                       const wallet = await Wallet.load(PASSWORD, 'BIP-44', BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', PASSWORD, BIP39_SEED)\r
                        const block = new Block(ADDRESS_0, '0', OPEN_BLOCK.previous, OPEN_BLOCK.representative)\r
                                .receive(OPEN_BLOCK.link, OPEN_BLOCK.balance)\r
 \r
index 980c56b6720c7994307e458cafa5256cda6499c1..4b009a26094567c018f2db6586d00d3f0f76fad2 100644 (file)
@@ -21,14 +21,14 @@ await Promise.all([
                const { PASSWORD } = NANO_TEST_VECTORS\r
 \r
                await test('destroy BIP-44 wallet before unlocking', async () => {\r
-                       const wallet = await Wallet.create(PASSWORD, 'BIP-44')\r
+                       const wallet = await Wallet.create('BIP-44', PASSWORD)\r
 \r
                        await assert.resolves(wallet.destroy())\r
                        await assert.rejects(wallet.unlock(PASSWORD))\r
                })\r
 \r
                await test('BIP-44 wallet with random entropy', async () => {\r
-                       const wallet = await Wallet.create(PASSWORD, 'BIP-44')\r
+                       const wallet = await Wallet.create('BIP-44', PASSWORD)\r
                        await wallet.unlock(PASSWORD)\r
 \r
                        assert.ok('id' in wallet)\r
@@ -49,7 +49,7 @@ await Promise.all([
                })\r
 \r
                await test('BLAKE2b wallet with random entropy', async () => {\r
-                       const wallet = await Wallet.create(PASSWORD, 'BLAKE2b')\r
+                       const wallet = await Wallet.create('BLAKE2b', PASSWORD)\r
                        await wallet.unlock(PASSWORD)\r
 \r
                        assert.ok('id' in wallet)\r
@@ -73,7 +73,7 @@ await Promise.all([
                        const invalidArgs = [null, true, false, 0, 1, 2, { foo: 'bar' }]\r
                        for (const arg of invalidArgs) {\r
                                //@ts-expect-error\r
-                               await assert.rejects(Wallet.create(PASSWORD, 'BIP-44', arg))\r
+                               await assert.rejects(Wallet.create('BIP-44', PASSWORD, arg))\r
                        }\r
                })\r
 \r
index dda65fbe2dada4fac9d9bccc97b86b18451ad72a..1fee8fd04d74bad78a0d84138b9aeb2a3b2bdc8a 100644 (file)
@@ -20,7 +20,7 @@ await Promise.all([
        suite('Derive accounts from BIP-44 wallet', async () => {\r
 \r
                await test('derive the first account from the given BIP-44 seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -36,7 +36,7 @@ await Promise.all([
                })\r
 \r
                await test('derive low indexed accounts from the given BIP-44 seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(1, 2)\r
 \r
@@ -52,7 +52,7 @@ await Promise.all([
                })\r
 \r
                await test('derive high indexed accounts from the given seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(0x70000000, 0x7000000f)\r
 \r
@@ -72,7 +72,7 @@ await Promise.all([
        suite('Derive accounts from BLAKE2b wallet', async () => {\r
 \r
                await test('derive the second account from the given BLAKE2b seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', NANO_TEST_VECTORS.BLAKE2B_SEED)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account(1)\r
 \r
@@ -90,7 +90,7 @@ await Promise.all([
                })\r
 \r
                await test('derive low indexed accounts from the given BLAKE2B seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', NANO_TEST_VECTORS.BLAKE2B_SEED)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(2, 3)\r
 \r
@@ -106,7 +106,7 @@ await Promise.all([
                })\r
 \r
                await test('derive high indexed accounts from the given seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', NANO_TEST_VECTORS.BLAKE2B_SEED)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(0x70000000, 0x7000000f)\r
 \r
index 925f7974964a69fc1d57d66a45242ae8fe7418ac..784199c5ffe9b29a261ca8d55409e6fed9ca5fce 100644 (file)
@@ -24,7 +24,7 @@ await Promise.all([
        suite('Import wallets', async () => {\r
 \r
                await test('nano.org BIP-44 test vector mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -38,7 +38,7 @@ await Promise.all([
                })\r
 \r
                await test('nano.org BIP-44 test vector seed with no mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -54,7 +54,7 @@ await Promise.all([
                })\r
 \r
                await test('Trezor-derived BIP-44 entropy for 12-word mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -67,7 +67,7 @@ await Promise.all([
                })\r
 \r
                await test('Trezor-derived BIP-44 entropy for 15-word mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -80,7 +80,7 @@ await Promise.all([
                })\r
 \r
                await test('Trezor-derived BIP-44 entropy for 18-word mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -93,7 +93,7 @@ await Promise.all([
                })\r
 \r
                await test('Trezor-derived BIP-44 entropy for 21-word mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -106,7 +106,7 @@ await Promise.all([
                })\r
 \r
                await test('BIP-44 zero-string entropy', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', TREZOR_TEST_VECTORS.MNEMONIC_0, TREZOR_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_0, TREZOR_TEST_VECTORS.PASSWORD)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(0, 3)\r
 \r
@@ -126,7 +126,7 @@ await Promise.all([
                })\r
 \r
                await test('BLAKE2b zero-string seed', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(0, 3)\r
 \r
@@ -148,7 +148,7 @@ await Promise.all([
                })\r
 \r
                await test('Trezor-derived BLAKE2b test vectors verified with third-party libraries', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const accounts = await wallet.accounts(0, 1)\r
 \r
@@ -167,14 +167,14 @@ await Promise.all([
                })\r
 \r
                await test('BLAKE2b seed creates identical wallet as its derived mnemonic', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.ENTROPY_2)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_2)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const walletAccount = await wallet.account()\r
 \r
                        assert.ok(await wallet.verify(TREZOR_TEST_VECTORS.MNEMONIC_2))\r
                        assert.ok(await wallet.verify(TREZOR_TEST_VECTORS.ENTROPY_2))\r
 \r
-                       const imported = await Wallet.load(TREZOR_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.MNEMONIC_2)\r
+                       const imported = await Wallet.load('BLAKE2b', TREZOR_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
                        await imported.unlock(TREZOR_TEST_VECTORS.PASSWORD)\r
                        const importedAccount = await imported.account()\r
 \r
@@ -187,7 +187,7 @@ await Promise.all([
                })\r
 \r
                await test('BLAKE2b mnemonic for maximum seed value', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.MNEMONIC_3)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
 \r
@@ -201,27 +201,27 @@ await Promise.all([
                })\r
 \r
                await test('Reject invalid seed', async () => {\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797'))\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701'))\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', TREZOR_TEST_VECTORS.ENTROPY_0.replaceAll(/./g, 'x')))\r
+                       await assert.rejects(Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797'))\r
+                       await assert.rejects(Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701'))\r
+                       await assert.rejects(Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0.replaceAll(/./g, 'x')))\r
                })\r
 \r
                await test('Reject invalid length seed', async () => {\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED + 'f'),\r
+                       await assert.rejects(Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED + 'f'),\r
                                `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length + 1}-character string.`)\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED.slice(0, -1)),\r
+                       await assert.rejects(Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED.slice(0, -1)),\r
                                `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length - 1}-character string.`)\r
                })\r
 \r
                await test('Reject seed containing non-hex characters', async () => {\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')),\r
+                       await assert.rejects(Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')),\r
                                'Seed contains invalid hexadecimal characters.')\r
-                       await assert.rejects(Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')),\r
+                       await assert.rejects(Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')),\r
                                'Seed contains invalid hexadecimal characters.')\r
                })\r
 \r
                await test('Import BIP-44 wallet from storage using a wallet-generated ID', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                        const restored = await Wallet.restore(wallet.id)\r
 \r
                        assert.ok('mnemonic' in restored)\r
@@ -242,7 +242,7 @@ await Promise.all([
                })\r
 \r
                await test('Import BLAKE2B wallet from storage using a wallet-generated ID', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.ENTROPY_0)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
                        const restored = await Wallet.restore(wallet.id)\r
 \r
                        assert.ok('mnemonic' in restored)\r
@@ -263,7 +263,7 @@ await Promise.all([
                })\r
 \r
                await test('export wallet IDs from storage and reimport them', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                        const backups = await Wallet.export()\r
 \r
                        assert.ok(backups.some(record => record.id === wallet.id))\r
index e15b0f62039685c501fb814daec3f820495f997e..727cf0252d1fd314e62dbf08ce037a798e3413cd 100644 (file)
@@ -24,7 +24,7 @@ await Promise.all([
        suite('Lock and unlock wallets', async () => {\r
 \r
                await test('locking and unlocking a Bip44Wallet with a password', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
 \r
                        assert.ok('mnemonic' in wallet)\r
                        assert.ok('seed' in wallet)\r
@@ -41,7 +41,7 @@ await Promise.all([
                })\r
 \r
                await test('fail to unlock a Bip44Wallet with different passwords', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const lockResult = await wallet.lock()\r
 \r
@@ -58,7 +58,7 @@ await Promise.all([
                })\r
 \r
                await test('fail to unlock a Bip44Wallet with invalid input', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
 \r
                        //@ts-expect-error\r
@@ -70,7 +70,7 @@ await Promise.all([
                })\r
 \r
                await test('locking and unlocking a Blake2bWallet with a password', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.ENTROPY_0)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
 \r
                        assert.ok('mnemonic' in wallet)\r
                        assert.ok('seed' in wallet)\r
@@ -87,7 +87,7 @@ await Promise.all([
                })\r
 \r
                await test('fail to unlock a Blake2bWallet with different passwords', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.ENTROPY_1)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
 \r
                        await assert.rejects(wallet.unlock(TREZOR_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' })\r
                        assert.ok('mnemonic' in wallet)\r
@@ -101,7 +101,7 @@ await Promise.all([
                })\r
 \r
                await test('fail to unlock a Blake2bWallet with no input', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BLAKE2b', TREZOR_TEST_VECTORS.ENTROPY_1)\r
+                       const wallet = await Wallet.load('BLAKE2b', NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
 \r
                        //@ts-expect-error\r
                        await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' })\r
index fa8ae1812aba97c302b9cdf098f735493e6cebf2..b9b1f5c65b9661dc6011a0fa5e808733e2edf32d 100644 (file)
@@ -137,7 +137,7 @@ await Promise.all([
                })\r
 \r
                await test('should verify a block using the public key', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
                        if (account.index == null) {\r
@@ -152,7 +152,7 @@ await Promise.all([
                })\r
 \r
                await test('should reject a block using the wrong public key', async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const account = await wallet.account()\r
                        if (account.index == null) {\r
@@ -178,7 +178,7 @@ await Promise.all([
                })\r
 \r
                await test('sweeper fails gracefully for ineligible accounts', { skip: true }, async () => {\r
-                       const wallet = await Wallet.load(NANO_TEST_VECTORS.PASSWORD, 'BIP-44', NANO_TEST_VECTORS.BIP39_SEED)\r
+                       const wallet = await Wallet.load('BIP-44', NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
                        await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
                        const results = await Tools.sweep(rpc, wallet, NANO_TEST_VECTORS.ADDRESS_1)\r
 \r