]> zoso.dev Git - libnemo.git/commitdiff
Expand implementation of bespoke test suite.
authorChris Duncan <chris@zoso.dev>
Sun, 8 Dec 2024 03:27:42 +0000 (19:27 -0800)
committerChris Duncan <chris@zoso.dev>
Sun, 8 Dec 2024 03:27:42 +0000 (19:27 -0800)
GLOBALS.mjs
test/create-wallet.test.mjs
test/derive-accounts.test.mjs
test/import-wallet.test.mjs
test/lock-unlock-wallet.mjs
test/manage-rolodex.mjs
test/refresh-accounts.test.mjs
test/sign-blocks.test.mjs
test/tools.test.mjs

index 7e7d4e808c21e7c8ebd83271a91a11e10e905a29..37c6c5f10cf4478d74be97ef3909368fca35a50c 100644 (file)
@@ -62,14 +62,21 @@ console.log(`> TEST RUNNER CHECK DONE <`)
 console.log(` `)
 
 export function skip (name) {
-       console.log(`%cSKIP `, 'color:blue', name)
+       return new Promise(resolve => {
+               console.log(`%cSKIP `, 'color:blue', name)
+               resolve()
+       })
 }
 
 export function suite (name, fn) {
-       console.group(`%c=>%c ${name}`, 'font-weight:bold;color:green', 'font-weight:bold;color:unset')
        if (fn.constructor.name === 'AsyncFunction') fn = fn()
        if (typeof fn === 'function') fn = new Promise(resolve => resolve(fn()))
-       fn.then(console.groupEnd)
+       return new Promise(async (resolve) => {
+               console.group(`%c${name}`, 'font-weight:bold')
+               await fn
+               console.groupEnd()
+               resolve()
+       })
 }
 
 export function test (name, fn) {
index dc051efcec241f32f466b33d19a9cce41923b6e1..f0feaabd86e8f42f4205dd0cbf8e851c53c1e8f4 100644 (file)
@@ -3,59 +3,61 @@
 \r
 'use strict'\r
 \r
-import { assert, skip, test } from '#GLOBALS.mjs'\r
+import { assert, skip, suite, test } from '#GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '#dist/main.js'\r
 \r
-await test('BIP-44 wallet with random entropy', async () => {\r
-       const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       assert.ok('id' in wallet)\r
-       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
-       assert.ok('seed' in wallet)\r
-       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
-})\r
-\r
-await test('BLAKE2b wallet with random entropy', async () => {\r
-       const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       assert.ok('id' in wallet)\r
-       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
-       assert.ok('seed' in wallet)\r
-       assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
-})\r
-\r
-await test('BIP-44 replace invalid salt with empty string', async () => {\r
-       const invalidArgs = [null, true, false, 0, 1, 2, { "foo": "bar" }]\r
-       for (const arg of invalidArgs) {\r
+await suite('Create wallets', async () => {\r
+       await test('BIP-44 wallet with random entropy', async () => {\r
+               const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               assert.ok('id' in wallet)\r
+               assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
+               assert.ok('seed' in wallet)\r
+               assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
+       })\r
+\r
+       await test('BLAKE2b wallet with random entropy', async () => {\r
+               const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               assert.ok('id' in wallet)\r
+               assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.id))\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic))\r
+               assert.ok('seed' in wallet)\r
+               assert.ok(/[A-Fa-f0-9]{32,64}/.test(wallet.seed))\r
+       })\r
+\r
+       await test('BIP-44 replace invalid salt with empty string', async () => {\r
+               const invalidArgs = [null, true, false, 0, 1, 2, { "foo": "bar" }]\r
+               for (const arg of invalidArgs) {\r
+                       //@ts-expect-error\r
+                       await assert.resolves(Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg))\r
+               }\r
+       })\r
+\r
+       await test('fail when using new', async () => {\r
                //@ts-expect-error\r
-               await assert.resolves(Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg))\r
-       }\r
-})\r
-\r
-await test('fail when using new', () => {\r
-       //@ts-expect-error\r
-       assert.throws(() => new Bip44Wallet())\r
-       //@ts-expect-error\r
-       assert.throws(() => new Blake2bWallet())\r
-       //@ts-expect-error\r
-       assert.throws(() => new LedgerWallet())\r
-})\r
+               assert.throws(() => new Bip44Wallet())\r
+               //@ts-expect-error\r
+               assert.throws(() => new Blake2bWallet())\r
+               //@ts-expect-error\r
+               assert.throws(() => new LedgerWallet())\r
+       })\r
 \r
-await test('fail without a password', async () => {\r
-       //@ts-expect-error\r
-       await assert.rejects(Bip44Wallet.create())\r
-       //@ts-expect-error\r
-       await assert.rejects(Blake2bWallet.create())\r
+       await test('fail without a password', async () => {\r
+               //@ts-expect-error\r
+               await assert.rejects(Bip44Wallet.create())\r
+               //@ts-expect-error\r
+               await assert.rejects(Blake2bWallet.create())\r
+       })\r
 })\r
 \r
-skip('connect to ledger', async () => {\r
+await skip('connect to ledger', async () => {\r
        const wallet = await LedgerWallet.create()\r
        assert.ok(wallet)\r
 })\r
index ecbea6a7a785ad045f252fbf2590bd5da098acae..dca775f16ba4c8f452ffe849cc94be137a7d8842 100644 (file)
@@ -3,79 +3,81 @@
 \r
 'use strict'\r
 \r
-import { assert, skip, test } from '#GLOBALS.mjs'\r
+import { assert, skip, suite, test } from '#GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet, LedgerWallet } from '#dist/main.js'\r
 \r
-await test('should derive the first account from the given BIP-44 seed', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
+await suite('Account derivation', async () => {\r
+       await test('should derive the first account from the given BIP-44 seed', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
 \r
-       assert.equals(accounts.length, 1)\r
-       assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-       assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-       assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
-})\r
+               assert.equals(accounts.length, 1)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
+       })\r
 \r
-await test('should derive low indexed accounts from the given BIP-44 seed', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(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
+       await test('should derive low indexed accounts from the given BIP-44 seed', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(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
-       assert.equals(accounts.length, 2)\r
-       assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_1)\r
-       assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
-       assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_1)\r
-       assert.equals(accounts[1].privateKey, NANO_TEST_VECTORS.PRIVATE_2)\r
-       assert.equals(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
-       assert.equals(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_2)\r
-})\r
+               assert.equals(accounts.length, 2)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_1)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_1)\r
+               assert.equals(accounts[1].privateKey, NANO_TEST_VECTORS.PRIVATE_2)\r
+               assert.equals(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
+               assert.equals(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_2)\r
+       })\r
 \r
-await test('should derive high indexed accounts from the given seed', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts(0x70000000, 0x700000ff)\r
+       await test('should derive high indexed accounts from the given seed', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts(0x70000000, 0x700000ff)\r
 \r
-       assert.equals(accounts.length, 0x100)\r
-       for (let i = 0; i < accounts.length; i++) {\r
-               const a = accounts[i]\r
-               assert.exists(a)\r
-               assert.exists(a.address)\r
-               assert.exists(a.publicKey)\r
-               assert.exists(a.privateKey)\r
-               assert.exists(a.index)\r
-               assert.equals(a.index, i + 0x70000000)\r
-       }\r
-})\r
+               assert.equals(accounts.length, 0x100)\r
+               for (let i = 0; i < accounts.length; i++) {\r
+                       const a = accounts[i]\r
+                       assert.exists(a)\r
+                       assert.exists(a.address)\r
+                       assert.exists(a.publicKey)\r
+                       assert.exists(a.privateKey)\r
+                       assert.exists(a.index)\r
+                       assert.equals(a.index, i + 0x70000000)\r
+               }\r
+       })\r
 \r
-await test('should derive accounts for a BLAKE2b wallet', async () => {\r
-       const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const lowAccounts = await wallet.accounts(0, 2)\r
+       await test('should derive accounts for a BLAKE2b wallet', async () => {\r
+               const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const lowAccounts = await wallet.accounts(0, 2)\r
 \r
-       assert.equals(lowAccounts.length, 3)\r
-       for (const a of lowAccounts) {\r
-               assert.exists(a)\r
-               assert.exists(a.address)\r
-               assert.exists(a.publicKey)\r
-               assert.exists(a.privateKey)\r
-               assert.exists(a.index)\r
-       }\r
+               assert.equals(lowAccounts.length, 3)\r
+               for (const a of lowAccounts) {\r
+                       assert.exists(a)\r
+                       assert.exists(a.address)\r
+                       assert.exists(a.publicKey)\r
+                       assert.exists(a.privateKey)\r
+                       assert.exists(a.index)\r
+               }\r
 \r
-       const highAccounts = await wallet.accounts(0x70000000, 0x700000ff)\r
+               const highAccounts = await wallet.accounts(0x70000000, 0x700000ff)\r
 \r
-       assert.equals(highAccounts.length, 0x100)\r
-       for (const a of highAccounts) {\r
-               assert.exists(a)\r
-               assert.exists(a.address)\r
-               assert.exists(a.publicKey)\r
-               assert.exists(a.privateKey)\r
-               assert.exists(a.index)\r
-       }\r
+               assert.equals(highAccounts.length, 0x100)\r
+               for (const a of highAccounts) {\r
+                       assert.exists(a)\r
+                       assert.exists(a.address)\r
+                       assert.exists(a.publicKey)\r
+                       assert.exists(a.privateKey)\r
+                       assert.exists(a.index)\r
+               }\r
+       })\r
 })\r
 \r
-skip('fetch the first account from a Ledger device', async () => {\r
+await skip('fetch the first account from a Ledger device', async () => {\r
        const wallet = await LedgerWallet.create()\r
        const accounts = await wallet.accounts()\r
 \r
index b0690a9c8f5d544ad1dc3533f48c16002af4ff3d..e8187c3a6dcc16de520db2202ebc794ce2d26d83 100644 (file)
 \r
 'use strict'\r
 \r
-import { assert, test } from '#GLOBALS.mjs'\r
+import { assert, suite, test } from '#GLOBALS.mjs'\r
 import { BIP32_TEST_VECTORS, CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Account, Bip44Wallet, Blake2bWallet } from '#dist/main.js'\r
 \r
-await test('import a wallet with the official Nano test vectors mnemonic', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.ok(accounts[0] instanceof Account)\r
-       assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-       assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-       assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-       assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
-})\r
-\r
-await test('import a wallet with the checksum starting with a zero', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, 'food define cancel major spoon trash cigar basic aim bless wolf win ability seek paddle bench seed century group they mercy address monkey cake')\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       assert.equals(wallet.seed, 'F665F804E5907985455D1E5A7AD344843A2ED4179A7E06EEF263DE925FF6F4C0991B0A9344FCEE939FE0F1B1841B8C9B20FEACF6B954B74B2D26A01906B758E2')\r
-})\r
-\r
-await test('import a wallet with a 12-word phrase', async () => {\r
-       const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_0)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-       const account = accounts[0]\r
-\r
-       assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
-       assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0)\r
-       assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0)\r
-       assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0)\r
-       assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0)\r
-})\r
-\r
-await test('import a wallet with a 15-word phrase', async () => {\r
-       const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_1)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-       const account = accounts[0]\r
-\r
-       assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
-       assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1)\r
-       assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1)\r
-       assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1)\r
-       assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1)\r
-})\r
-\r
-await test('import a wallet with a 18-word phrase', async () => {\r
-       const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_2)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-       const account = accounts[0]\r
-\r
-       assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
-       assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2)\r
-       assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2)\r
-       assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2)\r
-       assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2)\r
-})\r
-\r
-await test('import a wallet with a 21-word phrase', async () => {\r
-       const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_3)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-       const account = accounts[0]\r
-\r
-       assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
-       assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3)\r
-       assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3)\r
-       assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3)\r
-       assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3)\r
-})\r
-\r
-await test('import a wallet with the official Nano test vectors seed', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.ok(accounts[0] instanceof Account)\r
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-       assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-       assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-       assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
-})\r
-\r
-await test('import a BIP-44 wallet with the zero seed', async () => {\r
-       const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0, TREZOR_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts(0, 3)\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase())\r
-       assert.equals(accounts.length, 4)\r
-       for (let i = 0; i < accounts.length; i++) {\r
-               assert.exists(accounts[i])\r
-               assert.exists(accounts[i].address)\r
-               assert.exists(accounts[i].publicKey)\r
-               assert.exists(accounts[i].privateKey)\r
-               assert.equals(accounts[i].index, i)\r
-       }\r
-})\r
-\r
-await test('import a BLAKE2b wallet with the zero seed', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts(0, 3)\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-       assert.equals(accounts.length, 4)\r
-\r
-       for (let i = 0; i < accounts.length; i++) {\r
-               assert.exists(accounts[i])\r
-               assert.exists(accounts[i].address)\r
-               assert.exists(accounts[i].publicKey)\r
-               assert.exists(accounts[i].privateKey)\r
-               assert.equals(accounts[i].index, i)\r
-       }\r
-})\r
-\r
-await test('import a BLAKE2b wallet with Trezor test vectors', async () => {\r
-       const wallet = await Blake2bWallet.fromMnemonic(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
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-       assert.ok(accounts[0] instanceof Account)\r
-       assert.equals(accounts[0].index, 0)\r
-       assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0)\r
-       assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0)\r
-       assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0)\r
-       assert.ok(accounts[1] instanceof Account)\r
-       assert.equals(accounts[1].index, 1)\r
-       assert.equals(accounts[1].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1)\r
-       assert.equals(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1)\r
-       assert.equals(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1)\r
-})\r
-\r
-await test('get identical BLAKE2b wallets when created with a seed versus with its derived mnemonic', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_2)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const walletAccounts = await wallet.accounts()\r
-       const walletAccount = walletAccounts[0]\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.exists(walletAccount)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
-\r
-       const imported = await Blake2bWallet.fromMnemonic(TREZOR_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
-       await imported.unlock(TREZOR_TEST_VECTORS.PASSWORD)\r
-       const importedAccounts = await imported.accounts()\r
-       const importedAccount = importedAccounts[0]\r
-\r
-       assert.equals(imported.mnemonic, wallet.mnemonic)\r
-       assert.equals(imported.seed, wallet.seed)\r
-       assert.equals(importedAccount.privateKey, walletAccount.privateKey)\r
-       assert.equals(importedAccount.publicKey, walletAccount.publicKey)\r
-})\r
-\r
-await test('get identical BLAKE2b wallets when created with max entropy value', async () => {\r
-       const wallet = await Blake2bWallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.ok(accounts[0] instanceof Account)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3)\r
-       assert.equals(accounts[0].index, 0)\r
-       assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0)\r
-       assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0)\r
-       assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0)\r
-})\r
-\r
-await test('reject when given invalid entropy', async () => {\r
-       await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797'))\r
-       await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701'))\r
-       await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0.replaceAll(/./g, 'x')))\r
-})\r
-\r
-await test('reject when given a seed with an invalid length', async () => {\r
-       await assert.rejects(Bip44Wallet.fromSeed(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(Bip44Wallet.fromSeed(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 when given a seed containing non-hex characters', async () => {\r
-       await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')),\r
-               'Seed contains invalid hexadecimal characters.')\r
-       await assert.rejects(Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')),\r
-               'Seed contains invalid hexadecimal characters.')\r
-})\r
-\r
-\r
-await test('retrieve a Bip44Wallet from storage using an ID', async () => {\r
-       const id = (await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)).id\r
-       const wallet = await Bip44Wallet.restore(id)\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, '')\r
-\r
-       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       assert.equals(unlockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('retrieve a Blake2bWallet from storage using an ID', async () => {\r
-       const id = (await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)).id\r
-       const wallet = await Blake2bWallet.restore(id)\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, '')\r
-\r
-       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       assert.equals(unlockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+await suite('Import wallets', async () => {\r
+       await test('import a wallet with the official Nano test vectors mnemonic', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.ok(accounts[0] instanceof Account)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
+       })\r
+\r
+       await test('import a wallet with the checksum starting with a zero', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, 'food define cancel major spoon trash cigar basic aim bless wolf win ability seek paddle bench seed century group they mercy address monkey cake')\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               assert.equals(wallet.seed, 'F665F804E5907985455D1E5A7AD344843A2ED4179A7E06EEF263DE925FF6F4C0991B0A9344FCEE939FE0F1B1841B8C9B20FEACF6B954B74B2D26A01906B758E2')\r
+       })\r
+\r
+       await test('import a wallet with a 12-word phrase', async () => {\r
+               const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_0)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+               const account = accounts[0]\r
+\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0)\r
+       })\r
+\r
+       await test('import a wallet with a 15-word phrase', async () => {\r
+               const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_1)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+               const account = accounts[0]\r
+\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1)\r
+       })\r
+\r
+       await test('import a wallet with a 18-word phrase', async () => {\r
+               const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_2)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+               const account = accounts[0]\r
+\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2)\r
+       })\r
+\r
+       await test('import a wallet with a 21-word phrase', async () => {\r
+               const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_3)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+               const account = accounts[0]\r
+\r
+               assert.equals(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
+               assert.equals(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3)\r
+               assert.equals(account.privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3)\r
+               assert.equals(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3)\r
+               assert.equals(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3)\r
+       })\r
+\r
+       await test('import a wallet with the official Nano test vectors seed', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.ok(accounts[0] instanceof Account)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+               assert.equals(accounts[0].privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+               assert.equals(accounts[0].address, NANO_TEST_VECTORS.ADDRESS_0)\r
+       })\r
+\r
+       await test('import a BIP-44 wallet with the zero seed', async () => {\r
+               const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0, TREZOR_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts(0, 3)\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase())\r
+               assert.equals(accounts.length, 4)\r
+               for (let i = 0; i < accounts.length; i++) {\r
+                       assert.exists(accounts[i])\r
+                       assert.exists(accounts[i].address)\r
+                       assert.exists(accounts[i].publicKey)\r
+                       assert.exists(accounts[i].privateKey)\r
+                       assert.equals(accounts[i].index, i)\r
+               }\r
+       })\r
+\r
+       await test('import a BLAKE2b wallet with the zero seed', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts(0, 3)\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+               assert.equals(accounts.length, 4)\r
+\r
+               for (let i = 0; i < accounts.length; i++) {\r
+                       assert.exists(accounts[i])\r
+                       assert.exists(accounts[i].address)\r
+                       assert.exists(accounts[i].publicKey)\r
+                       assert.exists(accounts[i].privateKey)\r
+                       assert.equals(accounts[i].index, i)\r
+               }\r
+       })\r
+\r
+       await test('import a BLAKE2b wallet with Trezor test vectors', async () => {\r
+               const wallet = await Blake2bWallet.fromMnemonic(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
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               assert.ok(accounts[0] instanceof Account)\r
+               assert.equals(accounts[0].index, 0)\r
+               assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0)\r
+               assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0)\r
+               assert.ok(accounts[1] instanceof Account)\r
+               assert.equals(accounts[1].index, 1)\r
+               assert.equals(accounts[1].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1)\r
+               assert.equals(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1)\r
+               assert.equals(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1)\r
+       })\r
+\r
+       await test('get identical BLAKE2b wallets when created with a seed versus with its derived mnemonic', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_2)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const walletAccounts = await wallet.accounts()\r
+               const walletAccount = walletAccounts[0]\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.exists(walletAccount)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
+\r
+               const imported = await Blake2bWallet.fromMnemonic(TREZOR_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_2)\r
+               await imported.unlock(TREZOR_TEST_VECTORS.PASSWORD)\r
+               const importedAccounts = await imported.accounts()\r
+               const importedAccount = importedAccounts[0]\r
+\r
+               assert.equals(imported.mnemonic, wallet.mnemonic)\r
+               assert.equals(imported.seed, wallet.seed)\r
+               assert.equals(importedAccount.privateKey, walletAccount.privateKey)\r
+               assert.equals(importedAccount.publicKey, walletAccount.publicKey)\r
+       })\r
+\r
+       await test('get identical BLAKE2b wallets when created with max entropy value', async () => {\r
+               const wallet = await Blake2bWallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.ok(accounts[0] instanceof Account)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3)\r
+               assert.equals(accounts[0].index, 0)\r
+               assert.equals(accounts[0].privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0)\r
+               assert.equals(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0)\r
+               assert.equals(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0)\r
+       })\r
+\r
+       await test('reject when given invalid entropy', async () => {\r
+               await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797'))\r
+               await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701'))\r
+               await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0.replaceAll(/./g, 'x')))\r
+       })\r
+\r
+       await test('reject when given a seed with an invalid length', async () => {\r
+               await assert.rejects(Bip44Wallet.fromSeed(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(Bip44Wallet.fromSeed(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 when given a seed containing non-hex characters', async () => {\r
+               await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')),\r
+                       'Seed contains invalid hexadecimal characters.')\r
+               await assert.rejects(Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')),\r
+                       'Seed contains invalid hexadecimal characters.')\r
+       })\r
+\r
+\r
+       await test('retrieve a Bip44Wallet from storage using an ID', async () => {\r
+               const id = (await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)).id\r
+               const wallet = await Bip44Wallet.restore(id)\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
+\r
+               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               assert.equals(unlockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('retrieve a Blake2bWallet from storage using an ID', async () => {\r
+               const id = (await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)).id\r
+               const wallet = await Blake2bWallet.restore(id)\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
+\r
+               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               assert.equals(unlockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+       })\r
 })\r
index 85a55aba11ddd581140ffb5ca9ebdc8227cfb419..5ec6ec28ebfa467bff96972d714560e380281e0f 100644 (file)
 \r
 'use strict'\r
 \r
-import { assert, test } from '#GLOBALS.mjs'\r
+import { assert, suite, test } from '#GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet } from '#dist/main.js'\r
 \r
-await test('locking and unlocking a Bip44Wallet with a password', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(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
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, '')\r
-\r
-       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       assert.equals(unlockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('locking and unlocking a Bip44Wallet with a random CryptoKey', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-       const lockResult = await wallet.lock(key)\r
-\r
-       assert.ok(lockResult)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, '')\r
-\r
-       const unlockResult = await wallet.unlock(key)\r
-\r
-       assert.equals(unlockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('fail to unlock a Bip44Wallet with different passwords', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(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(TREZOR_TEST_VECTORS.PASSWORD)\r
-\r
-       await assert.rejects(wallet.unlock(NANO_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' })\r
-       assert.equals(lockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('fail to unlock a Bip44Wallet with different keys', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const rightKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-       const wrongKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-       const lockResult = await wallet.lock(rightKey)\r
-\r
-       await assert.rejects(wallet.unlock(wrongKey), { message: 'Failed to unlock wallet' })\r
-       assert.equals(lockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('fail to unlock a Bip44Wallet with different valid inputs', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
-       const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-\r
-       await assert.rejects(wallet.unlock(key), { message: 'Failed to unlock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('fail to unlock a Bip44Wallet with no input', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(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
-       await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-       await wallet.lock('password')\r
-\r
-       //@ts-expect-error\r
-       await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('fail to unlock a Bip44Wallet with invalid input', async () => {\r
-       const wallet = await Bip44Wallet.fromMnemonic(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
-       await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-       await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       //@ts-expect-error\r
-       await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-})\r
-\r
-await test('locking and unlocking a Blake2bWallet with a password', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, '')\r
-\r
-       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       assert.equals(unlockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-})\r
-\r
-await test('locking and unlocking a Blake2bWallet with a random CryptoKey', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-       const lockResult = await wallet.lock(key)\r
-\r
-       assert.equals(lockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, '')\r
-       assert.equals(wallet.seed, '')\r
-\r
-       const unlockResult = await wallet.unlock(key)\r
-\r
-       assert.equals(lockResult, true)\r
-       assert.equals(unlockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-})\r
-\r
-await test('fail to unlock a Blake2bWallet with different passwords', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(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
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-})\r
-\r
-await test('fail to unlock a Blake2bWallet with different keys', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const rightKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-       const wrongKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-       const lockResult = await wallet.lock(rightKey)\r
-\r
-       await assert.rejects(wallet.unlock(wrongKey), { message: 'Failed to unlock wallet' })\r
-       assert.equals(lockResult, true)\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-})\r
-\r
-await test('fail to unlock a Blake2bWallet with different valid inputs', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-       const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
-\r
-       await assert.rejects(wallet.unlock(key), { message: 'Failed to unlock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-})\r
-\r
-await test('fail to unlock a Blake2bWallet with no input', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       //@ts-expect-error\r
-       await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-       await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       //@ts-expect-error\r
-       await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-})\r
-\r
-await test('fail to unlock a Blake2bWallet with invalid input', async () => {\r
-       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       //@ts-expect-error\r
-       await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-       await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-       //@ts-expect-error\r
-       await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' })\r
-       assert.ok('mnemonic' in wallet)\r
-       assert.ok('seed' in wallet)\r
-       assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+await suite('Lock and unlock wallets', async () => {\r
+       await test('locking and unlocking a Bip44Wallet with a password', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(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
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
+\r
+               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               assert.equals(unlockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('locking and unlocking a Bip44Wallet with a random CryptoKey', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+               const lockResult = await wallet.lock(key)\r
+\r
+               assert.ok(lockResult)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
+\r
+               const unlockResult = await wallet.unlock(key)\r
+\r
+               assert.equals(unlockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('fail to unlock a Bip44Wallet with different passwords', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(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(TREZOR_TEST_VECTORS.PASSWORD)\r
+\r
+               await assert.rejects(wallet.unlock(NANO_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' })\r
+               assert.equals(lockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('fail to unlock a Bip44Wallet with different keys', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const rightKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+               const wrongKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+               const lockResult = await wallet.lock(rightKey)\r
+\r
+               await assert.rejects(wallet.unlock(wrongKey), { message: 'Failed to unlock wallet' })\r
+               assert.equals(lockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('fail to unlock a Bip44Wallet with different valid inputs', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)\r
+               const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+\r
+               await assert.rejects(wallet.unlock(key), { message: 'Failed to unlock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('fail to unlock a Bip44Wallet with no input', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(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
+               await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+               await wallet.lock('password')\r
+\r
+               //@ts-expect-error\r
+               await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('fail to unlock a Bip44Wallet with invalid input', async () => {\r
+               const wallet = await Bip44Wallet.fromMnemonic(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
+               await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.equals(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+               await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               //@ts-expect-error\r
+               await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+       })\r
+\r
+       await test('locking and unlocking a Blake2bWallet with a password', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
+\r
+               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               assert.equals(unlockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+       })\r
+\r
+       await test('locking and unlocking a Blake2bWallet with a random CryptoKey', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+               const lockResult = await wallet.lock(key)\r
+\r
+               assert.equals(lockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, '')\r
+               assert.equals(wallet.seed, '')\r
+\r
+               const unlockResult = await wallet.unlock(key)\r
+\r
+               assert.equals(lockResult, true)\r
+               assert.equals(unlockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+       })\r
+\r
+       await test('fail to unlock a Blake2bWallet with different passwords', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(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
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+       })\r
+\r
+       await test('fail to unlock a Blake2bWallet with different keys', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const rightKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+               const wrongKey = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+               const lockResult = await wallet.lock(rightKey)\r
+\r
+               await assert.rejects(wallet.unlock(wrongKey), { message: 'Failed to unlock wallet' })\r
+               assert.equals(lockResult, true)\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+       })\r
+\r
+       await test('fail to unlock a Blake2bWallet with different valid inputs', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               const key = await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\r
+\r
+               await assert.rejects(wallet.unlock(key), { message: 'Failed to unlock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+       })\r
+\r
+       await test('fail to unlock a Blake2bWallet with no input', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               //@ts-expect-error\r
+               await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+               await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               //@ts-expect-error\r
+               await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+       })\r
+\r
+       await test('fail to unlock a Blake2bWallet with invalid input', async () => {\r
+               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               //@ts-expect-error\r
+               await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.equals(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.equals(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+               await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+               //@ts-expect-error\r
+               await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' })\r
+               assert.ok('mnemonic' in wallet)\r
+               assert.ok('seed' in wallet)\r
+               assert.notEqual(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+       })\r
 })\r
index 206aa51ddedd781f6043983fe47e8d34929a444a..29c5005dc96ae74f4b67e877aaa1de2cc3e3f252 100644 (file)
 
 'use strict'
 
-import { assert, test } from '#GLOBALS.mjs'
+import { assert, suite, test } from '#GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'
 import { Rolodex, Tools } from '#dist/main.js'
 
-console.log('> rolodex valid contact management <')
-
-await test('should create a rolodex and add two contacts', async () => {
-       const rolodex = new Rolodex()
-       assert.equals(rolodex.constructor, Rolodex)
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
-
-       assert.equals(rolodex.getAllNames().length, 2)
-       assert.equals(rolodex.getAllNames()[0], 'JohnDoe')
-       assert.equals(rolodex.getAllNames()[1], 'JaneSmith')
-       assert.equals(rolodex.getAddresses('JohnDoe').length, 1)
-       assert.equals(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_0)
-       assert.equals(rolodex.getAddresses('JaneSmith').length, 1)
-       assert.equals(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_1)
+await suite('Rolodex valid contact management', async () => {
+       await test('should create a rolodex and add two contacts', async () => {
+               const rolodex = new Rolodex()
+               assert.equals(rolodex.constructor, Rolodex)
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
+
+               assert.equals(rolodex.getAllNames().length, 2)
+               assert.equals(rolodex.getAllNames()[0], 'JohnDoe')
+               assert.equals(rolodex.getAllNames()[1], 'JaneSmith')
+               assert.equals(rolodex.getAddresses('JohnDoe').length, 1)
+               assert.equals(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getAddresses('JaneSmith').length, 1)
+               assert.equals(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_1)
+       })
+
+       await test('should get a name from an address', async () => {
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0), 'JohnDoe')
+       })
+
+       await test('should add three addresses to the same contact', async () => {
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1)
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2)
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getAddresses('JohnDoe').length, 3)
+               assert.equals(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(rolodex.getAddresses('JohnDoe')[1], NANO_TEST_VECTORS.ADDRESS_2)
+               assert.equals(rolodex.getAddresses('JohnDoe')[2], NANO_TEST_VECTORS.ADDRESS_0)
+       })
+
+       await test('should update the name on an existing entry', async () => {
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(rolodex.getAddresses('JohnDoe').length, 0)
+               assert.equals(rolodex.getAddresses('JaneSmith').length, 1)
+               assert.equals(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_0)
+       })
+
+       await test('should return empty address array for an unknown contact', async () => {
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               assert.equals(Array.isArray(rolodex.getAddresses('JaneSmith')), true)
+               assert.equals(rolodex.getAddresses('JaneSmith').length, 0)
+       })
+
+       await test('should return empty address array for blank contact names', () => {
+               const rolodex = new Rolodex()
+               //@ts-expect-error
+               assert.equals(Array.isArray(rolodex.getAddresses(undefined)), true)
+               //@ts-expect-error
+               assert.equals(rolodex.getAddresses(undefined).length, 0)
+               //@ts-expect-error
+               assert.equals(Array.isArray(rolodex.getAddresses(null)), true)
+               //@ts-expect-error
+               assert.equals(rolodex.getAddresses(null).length, 0)
+               assert.equals(Array.isArray(rolodex.getAddresses('')), true)
+               assert.equals(rolodex.getAddresses('').length, 0)
+       })
+
+       await test('should return null for an unknown address', async () => {
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               assert.ok(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1) === null)
+               assert.ok(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1) !== undefined)
+       })
+
+       await test('should return null for a blank address', async () => {
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               //@ts-expect-error
+               assert.ok(rolodex.getName(undefined) === null)
+               //@ts-expect-error
+               assert.ok(rolodex.getName(undefined) !== undefined)
+               //@ts-expect-error
+               assert.ok(rolodex.getName(null) === null)
+               //@ts-expect-error
+               assert.ok(rolodex.getName(null) !== undefined)
+               assert.ok(rolodex.getName('') === null)
+               assert.ok(rolodex.getName('') !== undefined)
+       })
 })
 
-await test('should get a name from an address', async () => {
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       assert.equals(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0), 'JohnDoe')
+await suite('Rolodex exceptions', async () => {
+       await test('should throw if adding no data', async () => {
+               const rolodex = new Rolodex()
+               //@ts-expect-error
+               await assert.rejects(rolodex.add())
+       })
+
+       await test('should throw if passed no address', async () => {
+               const rolodex = new Rolodex()
+               //@ts-expect-error
+               await assert.rejects(rolodex.add('JohnDoe'))
+               //@ts-expect-error
+               await assert.rejects(rolodex.add('JohnDoe', undefined))
+               //@ts-expect-error
+               await assert.rejects(rolodex.add('JohnDoe', null))
+               await assert.rejects(rolodex.add('JohnDoe', ''))
+       })
+
+       await test('should throw if name is blank', async () => {
+               const rolodex = new Rolodex()
+               //@ts-expect-error
+               await assert.rejects(rolodex.add(undefined, NANO_TEST_VECTORS.ADDRESS_0))
+               //@ts-expect-error
+               await assert.rejects(rolodex.add(null, NANO_TEST_VECTORS.ADDRESS_0))
+               await assert.rejects(rolodex.add('', NANO_TEST_VECTORS.ADDRESS_0))
+       })
 })
 
-await test('should add three addresses to the same contact', async () => {
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1)
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2)
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       assert.equals(rolodex.getAddresses('JohnDoe').length, 3)
-       assert.equals(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_1)
-       assert.equals(rolodex.getAddresses('JohnDoe')[1], NANO_TEST_VECTORS.ADDRESS_2)
-       assert.equals(rolodex.getAddresses('JohnDoe')[2], NANO_TEST_VECTORS.ADDRESS_0)
-})
-
-await test('should update the name on an existing entry', async () => {
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0)
-       assert.equals(rolodex.getAddresses('JohnDoe').length, 0)
-       assert.equals(rolodex.getAddresses('JaneSmith').length, 1)
-       assert.equals(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_0)
-})
-
-await test('should return empty address array for an unknown contact', async () => {
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       assert.equals(Array.isArray(rolodex.getAddresses('JaneSmith')), true)
-       assert.equals(rolodex.getAddresses('JaneSmith').length, 0)
-})
-
-await test('should return empty address array for blank contact names', () => {
-       const rolodex = new Rolodex()
-       //@ts-expect-error
-       assert.equals(Array.isArray(rolodex.getAddresses(undefined)), true)
-       //@ts-expect-error
-       assert.equals(rolodex.getAddresses(undefined).length, 0)
-       //@ts-expect-error
-       assert.equals(Array.isArray(rolodex.getAddresses(null)), true)
-       //@ts-expect-error
-       assert.equals(rolodex.getAddresses(null).length, 0)
-       assert.equals(Array.isArray(rolodex.getAddresses('')), true)
-       assert.equals(rolodex.getAddresses('').length, 0)
-})
-
-await test('should return null for an unknown address', async () => {
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       assert.ok(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1) === null)
-       assert.ok(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1) !== undefined)
-})
-
-await test('should return null for a blank address', async () => {
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       //@ts-expect-error
-       assert.ok(rolodex.getName(undefined) === null)
-       //@ts-expect-error
-       assert.ok(rolodex.getName(undefined) !== undefined)
-       //@ts-expect-error
-       assert.ok(rolodex.getName(null) === null)
-       //@ts-expect-error
-       assert.ok(rolodex.getName(null) !== undefined)
-       assert.ok(rolodex.getName('') === null)
-       assert.ok(rolodex.getName('') !== undefined)
-})
-
-console.log('> rolodex exceptions <')
-
-await test('should throw if adding no data', async () => {
-       const rolodex = new Rolodex()
-       //@ts-expect-error
-       await assert.rejects(rolodex.add())
-})
-
-await test('should throw if passed no address', async () => {
-       const rolodex = new Rolodex()
-       //@ts-expect-error
-       await assert.rejects(rolodex.add('JohnDoe'))
-       //@ts-expect-error
-       await assert.rejects(rolodex.add('JohnDoe', undefined))
-       //@ts-expect-error
-       await assert.rejects(rolodex.add('JohnDoe', null))
-       await assert.rejects(rolodex.add('JohnDoe', ''))
-})
-
-await test('should throw if name is blank', async () => {
-       const rolodex = new Rolodex()
-       //@ts-expect-error
-       await assert.rejects(rolodex.add(undefined, NANO_TEST_VECTORS.ADDRESS_0))
-       //@ts-expect-error
-       await assert.rejects(rolodex.add(null, NANO_TEST_VECTORS.ADDRESS_0))
-       await assert.rejects(rolodex.add('', NANO_TEST_VECTORS.ADDRESS_0))
-})
-
-console.log('> rolodex data signature verification <')
-
-await test('should verify valid data and signature', async () => {
-       const data = 'Test data'
-       const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
-       const rolodex = new Rolodex()
-       await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
-       const result = await rolodex.verify('JohnDoe', signature, data)
-       assert.equals(result, true)
-})
-
-await test('should reject incorrect contact for signature', async () => {
-       const data = 'Test data'
-       const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
-       const rolodex = new Rolodex()
-       await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
-       const result = await rolodex.verify('JaneSmith', signature, data)
-       assert.equals(result, false)
+await suite('Rolodex data signature verification', async () => {
+       await test('should verify valid data and signature', async () => {
+               const data = 'Test data'
+               const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
+               const rolodex = new Rolodex()
+               await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
+               const result = await rolodex.verify('JohnDoe', signature, data)
+               assert.equals(result, true)
+       })
+
+       await test('should reject incorrect contact for signature', async () => {
+               const data = 'Test data'
+               const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
+               const rolodex = new Rolodex()
+               await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
+               const result = await rolodex.verify('JaneSmith', signature, data)
+               assert.equals(result, false)
+       })
 })
index b2870b9786bfb1bf095fbf58c95ba1a27e2f0e5d..ad40a39b9e6edf929dcc4dc496d770078db568ec 100644 (file)
@@ -3,7 +3,7 @@
 
 'use strict'
 
-import { assert, skip, test } from '#GLOBALS.mjs'
+import { assert, skip, suite, test } from '#GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'
 import { Account, Bip44Wallet, Rpc } from '#dist/main.js'
 
@@ -15,144 +15,144 @@ if (process) {
        rpc = new Rpc(process?.env?.NODE_URL ?? '', process?.env?.API_KEY_NAME)
 }
 
-console.log('refreshing account info')
-
-await test('fetch balance, frontier, and representative', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const accounts = await wallet.accounts()
-       const account = accounts[0]
-       await account.refresh(rpc)
-
-       assert.equals(typeof account.balance, 'bigint')
-       assert.notEqual(account.balance, undefined)
-       assert.notEqual(account.balance, null)
-       assert.notEqual(account.balance, '')
-       assert.notEqual(account.balance && account.balance < 0, true)
-
-       assert.equals(typeof account.frontier, 'string')
-       assert.notEqual(account.frontier, undefined)
-       assert.notEqual(account.frontier, null)
-       assert.notEqual(account.frontier, '')
-       assert.match(account.frontier ?? '', /^[0-9A-F]{64}$/i)
-
-       assert.equals(account.representative && account.representative.constructor, Account)
-       assert.notEqual(account.representative, undefined)
-       assert.notEqual(account.representative, null)
-       assert.notEqual(account.representative, '')
-       assert.notEqual(account.representative?.address, undefined)
-       assert.notEqual(account.representative?.address, null)
-       assert.notEqual(account.representative?.address, '')
+await suite('refreshing account info', async () => {
+       await test('fetch balance, frontier, and representative', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const accounts = await wallet.accounts()
+               const account = accounts[0]
+               await account.refresh(rpc)
+
+               assert.equals(typeof account.balance, 'bigint')
+               assert.notEqual(account.balance, undefined)
+               assert.notEqual(account.balance, null)
+               assert.notEqual(account.balance, '')
+               assert.notEqual(account.balance && account.balance < 0, true)
+
+               assert.equals(typeof account.frontier, 'string')
+               assert.notEqual(account.frontier, undefined)
+               assert.notEqual(account.frontier, null)
+               assert.notEqual(account.frontier, '')
+               assert.match(account.frontier ?? '', /^[0-9A-F]{64}$/i)
+
+               assert.equals(account.representative && account.representative.constructor, Account)
+               assert.notEqual(account.representative, undefined)
+               assert.notEqual(account.representative, null)
+               assert.notEqual(account.representative, '')
+               assert.notEqual(account.representative?.address, undefined)
+               assert.notEqual(account.representative?.address, null)
+               assert.notEqual(account.representative?.address, '')
+       })
+
+       await test('throw when refreshing unopened account', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const accounts = await wallet.accounts(0x7fffffff)
+               const account = accounts[0]
+               await assert.rejects(account.refresh(rpc),
+                       { message: 'Account not found' })
+       })
+
+       await test('throw when referencing invalid account index', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               await assert.rejects(wallet.accounts(0x80000000),
+                       { message: 'Invalid child key index 0x80000000' })
+       })
+
+       await test('throw with invalid node', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const invalidNode = new Rpc('http://invalid.com')
+               const accounts = await wallet.accounts()
+               const account = accounts[0]
+               await assert.rejects(account.refresh(invalidNode),
+                       { message: 'Account not found' })
+       })
 })
 
-await test('throw when refreshing unopened account', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const accounts = await wallet.accounts(0x7fffffff)
-       const account = accounts[0]
-       await assert.rejects(account.refresh(rpc),
-               { message: 'Account not found' })
+await suite('finding next unopened account', async () => {
+       await test('return correct account from test vector', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const account = await wallet.getNextNewAccount(rpc)
+               assert.ok(account)
+               assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+       })
+
+       await test('return successfully for small batch size', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const account = await wallet.getNextNewAccount(rpc, 1)
+               assert.ok(account)
+               assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+       })
+
+       await test('return successfully for large batch size', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const account = await wallet.getNextNewAccount(rpc, 100)
+               assert.ok(account)
+               assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+               assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+       })
+
+       await test('should throw on invalid node URL', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount())
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(null))
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(1))
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(''))
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount('foo'))
+       })
+
+       await test('should throw on invalid batch size', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(rpc, null))
+               await assert.rejects(wallet.getNextNewAccount(rpc, -1))
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(rpc, ''))
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(rpc, 'foo'))
+               //@ts-expect-error
+               await assert.rejects(wallet.getNextNewAccount(rpc, { 'foo': 'bar' }))
+       })
 })
 
-await test('throw when referencing invalid account index', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       await assert.rejects(wallet.accounts(0x80000000),
-               { message: 'Invalid child key index 0x80000000' })
-})
-
-await test('throw with invalid node', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const invalidNode = new Rpc('http://invalid.com')
-       const accounts = await wallet.accounts()
-       const account = accounts[0]
-       await assert.rejects(account.refresh(invalidNode),
-               { message: 'Account not found' })
-})
-
-console.log('finding next unopened account')
-
-await test('return correct account from test vector', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const account = await wallet.getNextNewAccount(rpc)
-       assert.ok(account)
-       assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-       assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
-})
-
-await test('return successfully for small batch size', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const account = await wallet.getNextNewAccount(rpc, 1)
-       assert.ok(account)
-       assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-       assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
-})
-
-await test('return successfully for large batch size', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const account = await wallet.getNextNewAccount(rpc, 100)
-       assert.ok(account)
-       assert.equals(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-       assert.equals(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
-})
-
-await test('should throw on invalid node URL', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount())
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(null))
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(1))
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(''))
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount('foo'))
-})
-
-await test('should throw on invalid batch size', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(rpc, null))
-       await assert.rejects(wallet.getNextNewAccount(rpc, -1))
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(rpc, ''))
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(rpc, 'foo'))
-       //@ts-expect-error
-       await assert.rejects(wallet.getNextNewAccount(rpc, { 'foo': 'bar' }))
-})
-
-console.log('> refreshing wallet accounts <')
-
-skip('should get balance, frontier, and representative for one account', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const accounts = await wallet.refresh(rpc)
-       const account = accounts[0]
-       assert.ok(account instanceof Account)
-       assert.equals(typeof account.balance, 'bigint')
-       assert.notEqual(account.frontier, undefined)
-       assert.notEqual(account.frontier, null)
-       assert.equals(typeof account.frontier, 'string')
-})
-
-skip('should get balance, frontier, and representative for multiple accounts', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       const accounts = await wallet.refresh(rpc, 0, 2)
-       assert.equals(accounts.length, 1)
-       assert.ok(accounts[0] instanceof Account)
-})
-
-skip('should handle failure gracefully', async () => {
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-       await assert.doesNotReject(wallet.refresh(rpc, 0, 20))
+await suite('Refreshing wallet accounts', async () => {
+       skip('should get balance, frontier, and representative for one account', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const accounts = await wallet.refresh(rpc)
+               const account = accounts[0]
+               assert.ok(account instanceof Account)
+               assert.equals(typeof account.balance, 'bigint')
+               assert.notEqual(account.frontier, undefined)
+               assert.notEqual(account.frontier, null)
+               assert.equals(typeof account.frontier, 'string')
+       })
+
+       skip('should get balance, frontier, and representative for multiple accounts', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               const accounts = await wallet.refresh(rpc, 0, 2)
+               assert.equals(accounts.length, 1)
+               assert.ok(accounts[0] instanceof Account)
+       })
+
+       skip('should handle failure gracefully', async () => {
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+               await assert.doesNotReject(wallet.refresh(rpc, 0, 20))
+       })
 })
index 12c8227136a664375ca9273ebf36604572baaca3..f13abb6da21e7d765d7770a0ab213d53da3f4cd8 100644 (file)
 \r
 'use strict'\r
 \r
-import { assert, test } from '#GLOBALS.mjs'\r
+import { assert, suite, test } from '#GLOBALS.mjs'\r
 import { NANO_TEST_VECTORS } from '#test/TEST_VECTORS.js'\r
 import { SendBlock, ReceiveBlock, ChangeBlock } from '#dist/main.js'\r
 \r
-console.log('> valid blocks <')\r
+await suite('Valid blocks', async () => {\r
+       await test('should not allow negative balances', async () => {\r
+               assert.throws(() => {\r
+                       const block = new SendBlock(\r
+                               NANO_TEST_VECTORS.ADDRESS_0,\r
+                               '7000000000000000000000000000000',\r
+                               NANO_TEST_VECTORS.ADDRESS_1,\r
+                               '12000000000000000000000000000000',\r
+                               NANO_TEST_VECTORS.ADDRESS_2,\r
+                               '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
+                       )\r
+               }, { message: 'Negative balance' })\r
+       })\r
 \r
-await test('should not allow negative balances', async () => {\r
-       assert.throws(() => {\r
+       await test('should allow zero balances', async () => {\r
                const block = new SendBlock(\r
                        NANO_TEST_VECTORS.ADDRESS_0,\r
-                       '7000000000000000000000000000000',\r
+                       '9007199254740991',\r
                        NANO_TEST_VECTORS.ADDRESS_1,\r
-                       '12000000000000000000000000000000',\r
+                       '9007199254740991',\r
                        NANO_TEST_VECTORS.ADDRESS_2,\r
                        '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
                )\r
-       }, { message: 'Negative balance' })\r
-})\r
-\r
-await test('should allow zero balances', async () => {\r
-       const block = new SendBlock(\r
-               NANO_TEST_VECTORS.ADDRESS_0,\r
-               '9007199254740991',\r
-               NANO_TEST_VECTORS.ADDRESS_1,\r
-               '9007199254740991',\r
-               NANO_TEST_VECTORS.ADDRESS_2,\r
-               '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
-       )\r
-       assert.notEqual(block.balance, 0)\r
-       assert.equals(block.balance, BigInt(0))\r
-})\r
+               assert.notEqual(block.balance, 0)\r
+               assert.equals(block.balance, BigInt(0))\r
+       })\r
 \r
-await test('should subtract balance from SendBlock correctly', async () => {\r
-       const block = new SendBlock(\r
-               NANO_TEST_VECTORS.ADDRESS_0,\r
-               '3000000000000000000000000000000',\r
-               NANO_TEST_VECTORS.ADDRESS_1,\r
-               '2000000000000000000000000000000',\r
-               NANO_TEST_VECTORS.ADDRESS_2,\r
-               '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
-       )\r
-       assert.equals(block.balance, 1000000000000000000000000000000n)\r
-})\r
+       await test('should subtract balance from SendBlock correctly', async () => {\r
+               const block = new SendBlock(\r
+                       NANO_TEST_VECTORS.ADDRESS_0,\r
+                       '3000000000000000000000000000000',\r
+                       NANO_TEST_VECTORS.ADDRESS_1,\r
+                       '2000000000000000000000000000000',\r
+                       NANO_TEST_VECTORS.ADDRESS_2,\r
+                       '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
+               )\r
+               assert.equals(block.balance, 1000000000000000000000000000000n)\r
+       })\r
 \r
-await test('should add balance from ReceiveBlock correctly', async () => {\r
-       const block = new ReceiveBlock(\r
-               NANO_TEST_VECTORS.ADDRESS_0,\r
-               '2000000000000000000000000000000',\r
-               NANO_TEST_VECTORS.ADDRESS_1,\r
-               '1000000000000000000000000000000',\r
-               NANO_TEST_VECTORS.ADDRESS_2,\r
-               '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
-       )\r
-       assert.equals(block.balance, 3000000000000000000000000000000n)\r
+       await test('should add balance from ReceiveBlock correctly', async () => {\r
+               const block = new ReceiveBlock(\r
+                       NANO_TEST_VECTORS.ADDRESS_0,\r
+                       '2000000000000000000000000000000',\r
+                       NANO_TEST_VECTORS.ADDRESS_1,\r
+                       '1000000000000000000000000000000',\r
+                       NANO_TEST_VECTORS.ADDRESS_2,\r
+                       '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D'\r
+               )\r
+               assert.equals(block.balance, 3000000000000000000000000000000n)\r
+       })\r
 })\r
 \r
-console.log('> block signing tests using official test vectors <')\r
-\r
-await test('should create a valid signature for an open block', async () => {\r
-       const block = new ReceiveBlock(\r
-               NANO_TEST_VECTORS.OPEN_BLOCK.account,\r
-               '0',\r
-               NANO_TEST_VECTORS.OPEN_BLOCK.link,\r
-               NANO_TEST_VECTORS.OPEN_BLOCK.balance,\r
-               NANO_TEST_VECTORS.OPEN_BLOCK.representative,\r
-               NANO_TEST_VECTORS.OPEN_BLOCK.previous,\r
-               NANO_TEST_VECTORS.OPEN_BLOCK.work\r
-       )\r
-       await block.sign(NANO_TEST_VECTORS.OPEN_BLOCK.key)\r
-       assert.equals(await block.hash(), NANO_TEST_VECTORS.OPEN_BLOCK.hash)\r
-       assert.equals(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature)\r
-})\r
+await suite('Block signing tests using official test vectors', async () => {\r
+       await test('should create a valid signature for an open block', async () => {\r
+               const block = new ReceiveBlock(\r
+                       NANO_TEST_VECTORS.OPEN_BLOCK.account,\r
+                       '0',\r
+                       NANO_TEST_VECTORS.OPEN_BLOCK.link,\r
+                       NANO_TEST_VECTORS.OPEN_BLOCK.balance,\r
+                       NANO_TEST_VECTORS.OPEN_BLOCK.representative,\r
+                       NANO_TEST_VECTORS.OPEN_BLOCK.previous,\r
+                       NANO_TEST_VECTORS.OPEN_BLOCK.work\r
+               )\r
+               await block.sign(NANO_TEST_VECTORS.OPEN_BLOCK.key)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.OPEN_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature)\r
+       })\r
 \r
-await test('should create a valid signature for a receive block', async () => {\r
-       const block = new ReceiveBlock(\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.account,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.balance,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.link,\r
-               '0',\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.previous,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.work\r
-       )\r
-       await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key)\r
-       assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
-       assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
-})\r
+       await test('should create a valid signature for a receive block', async () => {\r
+               const block = new ReceiveBlock(\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.account,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.balance,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.link,\r
+                       '0',\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.previous,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.work\r
+               )\r
+               await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
+       })\r
 \r
-await test('should create a valid signature for a receive block without work', async () => {\r
-       const block = new ReceiveBlock(\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.account,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.balance,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.link,\r
-               '0',\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,\r
-               NANO_TEST_VECTORS.RECEIVE_BLOCK.previous\r
-       )\r
-       await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key)\r
-       assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
-       assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
-       assert.equals(block.work, '')\r
-})\r
+       await test('should create a valid signature for a receive block without work', async () => {\r
+               const block = new ReceiveBlock(\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.account,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.balance,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.link,\r
+                       '0',\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,\r
+                       NANO_TEST_VECTORS.RECEIVE_BLOCK.previous\r
+               )\r
+               await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
+               assert.equals(block.work, '')\r
+       })\r
 \r
-await test('should create a valid signature for a send block', async () => {\r
-       const block = new SendBlock(\r
-               NANO_TEST_VECTORS.SEND_BLOCK.account,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.balance,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.link,\r
-               '0',\r
-               NANO_TEST_VECTORS.SEND_BLOCK.representative,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.previous,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.work\r
-       )\r
-       await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key)\r
-       assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
-       assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
-})\r
+       await test('should create a valid signature for a send block', async () => {\r
+               const block = new SendBlock(\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.account,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.balance,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.link,\r
+                       '0',\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.representative,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.previous,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.work\r
+               )\r
+               await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
+       })\r
 \r
-await test('should create a valid signature for a send block without work', async () => {\r
-       const block = new SendBlock(\r
-               NANO_TEST_VECTORS.SEND_BLOCK.account,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.balance,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.link,\r
-               '0',\r
-               NANO_TEST_VECTORS.SEND_BLOCK.representative,\r
-               NANO_TEST_VECTORS.SEND_BLOCK.previous\r
-       )\r
-       await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key)\r
-       assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
-       assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
-       assert.equals(block.work, '')\r
-})\r
+       await test('should create a valid signature for a send block without work', async () => {\r
+               const block = new SendBlock(\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.account,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.balance,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.link,\r
+                       '0',\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.representative,\r
+                       NANO_TEST_VECTORS.SEND_BLOCK.previous\r
+               )\r
+               await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key)\r
+               assert.equals(await block.hash(), NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
+               assert.equals(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
+               assert.equals(block.work, '')\r
+       })\r
 \r
-await test('should create a valid signature for a change rep block', async () => {\r
-       const work = '0000000000000000'\r
-       const block = new ChangeBlock(\r
-               'nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php',\r
-               '3000000000000000000000000000000',\r
-               'nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs',\r
-               '128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4',\r
-               work,\r
-       )\r
-       await block.sign('781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3') // Did not find a private key at nano docs for this address\r
-       assert.equals(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D')\r
-       assert.equals(block.work, work)\r
-})\r
+       await test('should create a valid signature for a change rep block', async () => {\r
+               const work = '0000000000000000'\r
+               const block = new ChangeBlock(\r
+                       'nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php',\r
+                       '3000000000000000000000000000000',\r
+                       'nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs',\r
+                       '128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4',\r
+                       work,\r
+               )\r
+               await block.sign('781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3') // Did not find a private key at nano docs for this address\r
+               assert.equals(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D')\r
+               assert.equals(block.work, work)\r
+       })\r
 \r
-await test('should create a valid signature for a change rep block without work', async () => {\r
-       const block = new ChangeBlock(\r
-               NANO_TEST_VECTORS.ADDRESS_0,\r
-               '0',\r
-               'nano_34amtofxstsfyqcgphp8piij9u33widykq9wbz6ysjpxhbgmqu8btu1eexer',\r
-               'F3C1D7B6EE97DA09D4C00538CEA93CBA5F74D78FD3FBE71347D2DFE7E53DF327'\r
-       )\r
-       await block.sign(NANO_TEST_VECTORS.PRIVATE_0)\r
-       assert.equals(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305')\r
-       assert.equals(block.work, '')\r
+       await test('should create a valid signature for a change rep block without work', async () => {\r
+               const block = new ChangeBlock(\r
+                       NANO_TEST_VECTORS.ADDRESS_0,\r
+                       '0',\r
+                       'nano_34amtofxstsfyqcgphp8piij9u33widykq9wbz6ysjpxhbgmqu8btu1eexer',\r
+                       'F3C1D7B6EE97DA09D4C00538CEA93CBA5F74D78FD3FBE71347D2DFE7E53DF327'\r
+               )\r
+               await block.sign(NANO_TEST_VECTORS.PRIVATE_0)\r
+               assert.equals(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305')\r
+               assert.equals(block.work, '')\r
+       })\r
 })\r
index 3187802ea5f2fd55b78fbb179108b5cc76c2e591..eabbb9f04252f06daba6dcae60e457cc1a0bdeab 100644 (file)
@@ -15,11 +15,10 @@ if (process) {
        rpc = new Rpc(process?.env?.NODE_URL ?? '', process?.env?.API_KEY_NAME)\r
 }\r
 \r
-suite('unit conversion tests', async () => {\r
-\r
+await suite('unit conversion tests', async () => {\r
        await test('should convert nano to raw', async () => {\r
                const result = await Tools.convert('1', 'NANO', 'RAW')\r
-               assert.equals(result, '100000000000000000000000000000')\r
+               assert.equals(result, '1000000000000000000000000000000')\r
        })\r
 \r
        await test('should convert raw to nano', async () => {\r
@@ -78,77 +77,77 @@ suite('unit conversion tests', async () => {
        })\r
 })\r
 \r
-console.log('> signature tests <')\r
-\r
-await test('should sign data with a single parameter', async () => {\r
-       const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi')\r
-       assert.equals(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C')\r
-})\r
+await suite('signature tests', async () => {\r
+       await test('should sign data with a single parameter', async () => {\r
+               const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi')\r
+               assert.equals(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C')\r
+       })\r
 \r
-await test('should sign data with multiple parameters', async () => {\r
-       const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi', 'somePassword')\r
-       assert.equals(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804')\r
-})\r
+       await test('should sign data with multiple parameters', async () => {\r
+               const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi', 'somePassword')\r
+               assert.equals(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804')\r
+       })\r
 \r
-await test('should verify a signature using the public key', async () => {\r
-       const result = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
-       assert.equals(result, true)\r
+       await test('should verify a signature using the public key', async () => {\r
+               const result = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
+               assert.equals(result, true)\r
 \r
-       const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi')\r
-       assert.equals(result2, false)\r
+               const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi')\r
+               assert.equals(result2, false)\r
 \r
-       const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
-       assert.equals(result3, false)\r
-})\r
+               const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
+               assert.equals(result3, false)\r
+       })\r
 \r
-await test('should verify a block using the public key', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-       const account = accounts[0]\r
-       const sendBlock = new SendBlock(\r
-               account.address,\r
-               '5618869000000000000000000000000',\r
-               'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p',\r
-               '2000000000000000000000000000000',\r
-               'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',\r
-               '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',\r
-       )\r
-       await sendBlock.sign(account.privateKey ?? '')\r
-       const valid = await sendBlock.verify(account.publicKey)\r
-       assert.equals(valid, true)\r
-})\r
+       await test('should verify a block using the public key', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+               const account = accounts[0]\r
+               const sendBlock = new SendBlock(\r
+                       account.address,\r
+                       '5618869000000000000000000000000',\r
+                       'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p',\r
+                       '2000000000000000000000000000000',\r
+                       'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',\r
+                       '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',\r
+               )\r
+               await sendBlock.sign(account.privateKey ?? '')\r
+               const valid = await sendBlock.verify(account.publicKey)\r
+               assert.equals(valid, true)\r
+       })\r
 \r
-await test('should reject a block using the wrong public key', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
-       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-       const accounts = await wallet.accounts()\r
-       const account = accounts[0]\r
-       const sendBlock = new SendBlock(\r
-               account.address,\r
-               '5618869000000000000000000000000',\r
-               'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p',\r
-               '2000000000000000000000000000000',\r
-               'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',\r
-               '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',\r
-       )\r
-       await sendBlock.sign(account.privateKey ?? '')\r
-\r
-       sendBlock.account = Account.fromAddress('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
-       const valid = await sendBlock.verify(account.publicKey)\r
-       assert.equals(valid, false)\r
-})\r
+       await test('should reject a block using the wrong public key', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
+               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+               const accounts = await wallet.accounts()\r
+               const account = accounts[0]\r
+               const sendBlock = new SendBlock(\r
+                       account.address,\r
+                       '5618869000000000000000000000000',\r
+                       'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p',\r
+                       '2000000000000000000000000000000',\r
+                       'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou',\r
+                       '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D',\r
+               )\r
+               await sendBlock.sign(account.privateKey ?? '')\r
+\r
+               sendBlock.account = Account.fromAddress('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
+               const valid = await sendBlock.verify(account.publicKey)\r
+               assert.equals(valid, false)\r
+       })\r
 \r
-await test('sweeper throws without required parameters', async () => {\r
-       //@ts-expect-error\r
-       await assert.rejects(Tools.sweep(),\r
-               'Missing required sweep arguments')\r
-})\r
+       await test('sweeper throws without required parameters', async () => {\r
+               //@ts-expect-error\r
+               await assert.rejects(Tools.sweep(),\r
+                       'Missing required sweep arguments')\r
+       })\r
 \r
-skip('sweeper fails gracefully for ineligible accounts', async () => {\r
-       const wallet = await Bip44Wallet.fromSeed(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
-       assert.ok(results)\r
-       assert.equals(results.length, 1)\r
+       await skip('sweeper fails gracefully for ineligible accounts', async () => {\r
+               const wallet = await Bip44Wallet.fromSeed(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
+               assert.ok(results)\r
+               assert.equals(results.length, 1)\r
+       })\r
 })\r