]> git.codecow.com Git - libnemo.git/commitdiff
Fix test suites to work with Node test runner by collecting all promises at once...
authorChris Duncan <chris@zoso.dev>
Mon, 21 Jul 2025 20:05:40 +0000 (13:05 -0700)
committerChris Duncan <chris@zoso.dev>
Mon, 21 Jul 2025 20:05:40 +0000 (13:05 -0700)
15 files changed:
test/perf.account.js
test/perf.block.js
test/perf.wallet.js
test/test.blake2b.mjs
test/test.blocks.mjs
test/test.calculate-pow.mjs
test/test.create-wallet.mjs
test/test.derive-accounts.mjs
test/test.import-wallet.mjs
test/test.ledger.mjs
test/test.lock-unlock.mjs
test/test.manage-rolodex.mjs
test/test.refresh-accounts.mjs
test/test.runner-check.mjs
test/test.tools.mjs

index 1e1b9486e9ddb40641875040810a873525b4c1e3..a0c5262d329e3e8bee6c74556aaf3d79205347c2 100644 (file)
@@ -7,58 +7,60 @@ import { assert, stats, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'
 import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'
 
-await suite('Account performance', { skip: true }, async () => {
-       const COUNT = 0x200
+await Promise.all([
+       suite('Account performance', { skip: true }, async () => {
+               const COUNT = 0x200
 
-       await test(`Time to create ${COUNT} BIP-44 accounts`, async () => {
-               const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-               const start = performance.now()
-               const accounts = await wallet.accounts(0, COUNT - 1)
-               const end = performance.now()
-               console.log(`Total: ${end - start} ms`)
-               console.log(`Average: ${(end - start) / COUNT} ms`)
-               assert.equal(accounts.length, COUNT)
-               await wallet.destroy()
-       })
-
-       await test(`Time to create ${COUNT} BLAKE2b accounts`, async () => {
-               const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-               const start = performance.now()
-               const accounts = await wallet.accounts(0, COUNT - 1)
-               const end = performance.now()
-               console.log(`Total: ${end - start} ms`)
-               console.log(`Average: ${(end - start) / COUNT} ms`)
-               assert.equal(accounts.length, COUNT)
-               await wallet.destroy()
-       })
-
-       await test(`Time to create 1 BIP-44 account ${COUNT} times`, async () => {
-               const times = []
-               const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-               for (let i = 0; i < COUNT; i++) {
+               await test(`Time to create ${COUNT} BIP-44 accounts`, async () => {
+                       const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
                        const start = performance.now()
-                       await wallet.accounts(i)
+                       const accounts = await wallet.accounts(0, COUNT - 1)
                        const end = performance.now()
-                       times.push(end - start)
-               }
-               await wallet.destroy()
-               console.log(stats(times))
-       })
+                       console.log(`Total: ${end - start} ms`)
+                       console.log(`Average: ${(end - start) / COUNT} ms`)
+                       assert.equal(accounts.length, COUNT)
+                       await wallet.destroy()
+               })
 
-       await test(`Average time to create 1 BLAKE2b account ${COUNT} times`, async () => {
-               const times = []
-               const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
-               for (let i = 0; i < COUNT; i++) {
+               await test(`Time to create ${COUNT} BLAKE2b accounts`, async () => {
+                       const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
                        const start = performance.now()
-                       await wallet.accounts(i)
+                       const accounts = await wallet.accounts(0, COUNT - 1)
                        const end = performance.now()
-                       times.push(end - start)
-               }
-               await wallet.destroy()
-               console.log(stats(times))
+                       console.log(`Total: ${end - start} ms`)
+                       console.log(`Average: ${(end - start) / COUNT} ms`)
+                       assert.equal(accounts.length, COUNT)
+                       await wallet.destroy()
+               })
+
+               await test(`Time to create 1 BIP-44 account ${COUNT} times`, async () => {
+                       const times = []
+                       const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+                       for (let i = 0; i < COUNT; i++) {
+                               const start = performance.now()
+                               await wallet.accounts(i)
+                               const end = performance.now()
+                               times.push(end - start)
+                       }
+                       await wallet.destroy()
+                       console.log(stats(times))
+               })
+
+               await test(`Average time to create 1 BLAKE2b account ${COUNT} times`, async () => {
+                       const times = []
+                       const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)
+                       for (let i = 0; i < COUNT; i++) {
+                               const start = performance.now()
+                               await wallet.accounts(i)
+                               const end = performance.now()
+                               times.push(end - start)
+                       }
+                       await wallet.destroy()
+                       console.log(stats(times))
+               })
        })
-})
+])
index 20b83505104588ece4d60a6232a2452c8d44a6e7..9d12c32768df3a6c94db09c4f9c581144ae83cb2 100644 (file)
@@ -7,26 +7,28 @@ import { stats, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'
 import { SendBlock } from '../dist/main.min.js'
 
-await suite('Block performance', { skip: true }, async () => {
-       const COUNT = 0x200
+await Promise.all([
+       suite('Block performance', { skip: true }, async () => {
+               const COUNT = 0x200
 
-       await test(`libnemo: Time to calculate proof-of-work for a send block ${COUNT} times`, { skip: true }, async () => {
-               const times = []
-               const block = new SendBlock(
-                       NANO_TEST_VECTORS.SEND_BLOCK.account,
-                       NANO_TEST_VECTORS.SEND_BLOCK.balance,
-                       NANO_TEST_VECTORS.SEND_BLOCK.link,
-                       '0',
-                       NANO_TEST_VECTORS.SEND_BLOCK.representative,
-                       NANO_TEST_VECTORS.SEND_BLOCK.previous
-               )
-               for (let i = 0; i < COUNT; i++) {
-                       const start = performance.now()
-                       await block.pow()
-                       const end = performance.now()
-                       times.push(end - start)
-                       console.log(`${block.work} (${end - start} ms)`)
-               }
-               console.log(stats(times))
+               await test(`libnemo: Time to calculate proof-of-work for a send block ${COUNT} times`, { skip: true }, async () => {
+                       const times = []
+                       const block = new SendBlock(
+                               NANO_TEST_VECTORS.SEND_BLOCK.account,
+                               NANO_TEST_VECTORS.SEND_BLOCK.balance,
+                               NANO_TEST_VECTORS.SEND_BLOCK.link,
+                               '0',
+                               NANO_TEST_VECTORS.SEND_BLOCK.representative,
+                               NANO_TEST_VECTORS.SEND_BLOCK.previous
+                       )
+                       for (let i = 0; i < COUNT; i++) {
+                               const start = performance.now()
+                               await block.pow()
+                               const end = performance.now()
+                               times.push(end - start)
+                               console.log(`${block.work} (${end - start} ms)`)
+                       }
+                       console.log(stats(times))
+               })
        })
-})
+])
index b58adc75c7698063f49b1eadda80037f16347c31..f0817df29953a8f07ce1f3c2bfdae04d42042900 100644 (file)
@@ -7,30 +7,32 @@ import { stats, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'
 import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'
 
-await suite(`Wallet performance`, { skip: true }, async () => {
-       const COUNT = 0x20
+await Promise.all([
+       suite(`Wallet performance`, { skip: true }, async () => {
+               const COUNT = 0x20
 
-       await test(`Time to create ${COUNT} BIP-44 wallets`, async () => {
-               const times = []
-               for (let i = 0; i < COUNT; i++) {
-                       const start = performance.now()
-                       const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
-                       const end = performance.now()
-                       times.push(end - start)
-                       await wallet.destroy()
-               }
-               console.log(stats(times))
-       })
+               await test(`Time to create ${COUNT} BIP-44 wallets`, async () => {
+                       const times = []
+                       for (let i = 0; i < COUNT; i++) {
+                               const start = performance.now()
+                               const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD)
+                               const end = performance.now()
+                               times.push(end - start)
+                               await wallet.destroy()
+                       }
+                       console.log(stats(times))
+               })
 
-       await test(`Time to create ${COUNT} BLAKE2b wallets`, async () => {
-               const times = []
-               for (let i = 0; i < COUNT; i++) {
-                       const start = performance.now()
-                       const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
-                       const end = performance.now()
-                       times.push(end - start)
-                       await wallet.destroy()
-               }
-               console.log(stats(times))
+               await test(`Time to create ${COUNT} BLAKE2b wallets`, async () => {
+                       const times = []
+                       for (let i = 0; i < COUNT; i++) {
+                               const start = performance.now()
+                               const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD)
+                               const end = performance.now()
+                               times.push(end - start)
+                               await wallet.destroy()
+                       }
+                       console.log(stats(times))
+               })
        })
-})
+])
index 220610d440ec745eb3589acfb67b930519955b77..4f89e475df4242a66ae23fbe32873a7e68095767 100644 (file)
@@ -7,85 +7,87 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { BLAKE2B_TEST_VECTORS } from './VECTORS.js'\r
 import { Blake2b } from '../dist/main.min.js'\r
 \r
-await suite('BLAKE2b test vectors', async () => {\r
+await Promise.all([\r
+       suite('BLAKE2b test vectors', async () => {\r
 \r
-       await test('check 512 reference test vectors', async () => {\r
-               for (let i = 0; i < BLAKE2B_TEST_VECTORS.REFERENCE.length; i++) {\r
-                       const test = BLAKE2B_TEST_VECTORS.REFERENCE[i]\r
-                       if (test.in.length % 2 === 1) test.in = `0${test.in}`\r
-                       const input = Uint8Array.from(test.in\r
-                               .split(/(.{2})/)\r
-                               .filter(v => v.length > 0)\r
-                               .map(v => parseInt(v, 16))\r
-                       )\r
-                       let key\r
-                       if (test.key.length > 0) {\r
-                               if (test.key.length % 2 === 1) {\r
-                                       test.key = `0${test.key}`\r
-                               }\r
-                               key = Uint8Array.from(test.key\r
+               await test('check 512 reference test vectors', async () => {\r
+                       for (let i = 0; i < BLAKE2B_TEST_VECTORS.REFERENCE.length; i++) {\r
+                               const test = BLAKE2B_TEST_VECTORS.REFERENCE[i]\r
+                               if (test.in.length % 2 === 1) test.in = `0${test.in}`\r
+                               const input = Uint8Array.from(test.in\r
                                        .split(/(.{2})/)\r
                                        .filter(v => v.length > 0)\r
                                        .map(v => parseInt(v, 16))\r
                                )\r
+                               let key\r
+                               if (test.key.length > 0) {\r
+                                       if (test.key.length % 2 === 1) {\r
+                                               test.key = `0${test.key}`\r
+                                       }\r
+                                       key = Uint8Array.from(test.key\r
+                                               .split(/(.{2})/)\r
+                                               .filter(v => v.length > 0)\r
+                                               .map(v => parseInt(v, 16))\r
+                                       )\r
+                               }\r
+                               try {\r
+                                       const output = new Blake2b(64, key).update(input).digest('hex')\r
+                                       assert.equal(output, test.out)\r
+                               } catch (err) {\r
+                                       console.error(`blake2b reference test vector ${i} failed`, { cause: err })\r
+                               }\r
                        }\r
-                       try {\r
-                               const output = new Blake2b(64, key).update(input).digest('hex')\r
-                               assert.equal(output, test.out)\r
-                       } catch (err) {\r
-                               console.error(`blake2b reference test vector ${i} failed`, { cause: err })\r
-                       }\r
-               }\r
-       })\r
+               })\r
 \r
-       await test('check 64 libsodium test vectors', async () => {\r
-               for (let i = 0; i < BLAKE2B_TEST_VECTORS.LIBSODIUM.length; i++) {\r
-                       const test = BLAKE2B_TEST_VECTORS.LIBSODIUM[i]\r
-                       if (test.in.length % 2 === 1) test.in = `0${test.in}`\r
-                       const input = Uint8Array.from(test.in\r
-                               .split(/(.{2})/)\r
-                               .filter(v => v.length > 0)\r
-                               .map(v => parseInt(v, 16))\r
-                       )\r
-                       let key\r
-                       if (test.key.length > 0) {\r
-                               if (test.key.length % 2 === 1) {\r
-                                       test.key = `0${test.key}`\r
-                               }\r
-                               key = Uint8Array.from(test.key\r
+               await test('check 64 libsodium test vectors', async () => {\r
+                       for (let i = 0; i < BLAKE2B_TEST_VECTORS.LIBSODIUM.length; i++) {\r
+                               const test = BLAKE2B_TEST_VECTORS.LIBSODIUM[i]\r
+                               if (test.in.length % 2 === 1) test.in = `0${test.in}`\r
+                               const input = Uint8Array.from(test.in\r
                                        .split(/(.{2})/)\r
                                        .filter(v => v.length > 0)\r
                                        .map(v => parseInt(v, 16))\r
                                )\r
-                       }\r
-                       let salt\r
-                       if (test.salt && test.salt.length > 0) {\r
-                               if (test.salt.length % 2 === 1) {\r
-                                       test.salt = `0${test.salt}`\r
+                               let key\r
+                               if (test.key.length > 0) {\r
+                                       if (test.key.length % 2 === 1) {\r
+                                               test.key = `0${test.key}`\r
+                                       }\r
+                                       key = Uint8Array.from(test.key\r
+                                               .split(/(.{2})/)\r
+                                               .filter(v => v.length > 0)\r
+                                               .map(v => parseInt(v, 16))\r
+                                       )\r
                                }\r
-                               salt = Uint8Array.from(test.salt\r
-                                       .split(/(.{2})/)\r
-                                       .filter(v => v.length > 0)\r
-                                       .map(v => parseInt(v, 16))\r
-                               )\r
-                       }\r
-                       let personal\r
-                       if (test.personal && test.personal.length > 0) {\r
-                               if (test.personal.length % 2 === 1) {\r
-                                       test.personal = `0${test.personal}`\r
+                               let salt\r
+                               if (test.salt && test.salt.length > 0) {\r
+                                       if (test.salt.length % 2 === 1) {\r
+                                               test.salt = `0${test.salt}`\r
+                                       }\r
+                                       salt = Uint8Array.from(test.salt\r
+                                               .split(/(.{2})/)\r
+                                               .filter(v => v.length > 0)\r
+                                               .map(v => parseInt(v, 16))\r
+                                       )\r
+                               }\r
+                               let personal\r
+                               if (test.personal && test.personal.length > 0) {\r
+                                       if (test.personal.length % 2 === 1) {\r
+                                               test.personal = `0${test.personal}`\r
+                                       }\r
+                                       personal = Uint8Array.from(test.personal\r
+                                               .split(/(.{2})/)\r
+                                               .filter(v => v.length > 0)\r
+                                               .map(v => parseInt(v, 16))\r
+                                       )\r
+                               }\r
+                               try {\r
+                                       const output = new Blake2b(test.outlen ?? 64, key, salt, personal).update(input).digest('hex')\r
+                                       assert.equal(output, test.out)\r
+                               } catch (err) {\r
+                                       console.error(`blake2b libsodium test vector ${i} failed`, { cause: err })\r
                                }\r
-                               personal = Uint8Array.from(test.personal\r
-                                       .split(/(.{2})/)\r
-                                       .filter(v => v.length > 0)\r
-                                       .map(v => parseInt(v, 16))\r
-                               )\r
-                       }\r
-                       try {\r
-                               const output = new Blake2b(test.outlen ?? 64, key, salt, personal).update(input).digest('hex')\r
-                               assert.equal(output, test.out)\r
-                       } catch (err) {\r
-                               console.error(`blake2b libsodium test vector ${i} failed`, { cause: err })\r
                        }\r
-               }\r
+               })\r
        })\r
-})\r
+])\r
index 53fc076358655161a1f7a4bee430930754b9c81a..91f8d7718d584bc009586cd1207d9bf565f9b9ca 100644 (file)
@@ -7,159 +7,161 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'\r
 import { SendBlock, ReceiveBlock, ChangeBlock } from '../dist/main.min.js'\r
 \r
-await suite('Block format', async () => {\r
+await Promise.all([\r
+       suite('Block format', async () => {\r
 \r
-       await test('throw on negative balances', async () => {\r
-               assert.throws(() => {\r
-                       new SendBlock(\r
+               await test('throw on negative balances', async () => {\r
+                       assert.throws(() => {\r
+                               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('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('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.equal(block.balance, BigInt(0))\r
-       })\r
+                       assert.notEqual(block.balance, 0)\r
+                       assert.equal(block.balance, BigInt(0))\r
+               })\r
 \r
-       await test('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.equal(block.balance, 1000000000000000000000000000000n)\r
-       })\r
+               await test('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.equal(block.balance, 1000000000000000000000000000000n)\r
+               })\r
 \r
-       await test('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.equal(block.balance, 3000000000000000000000000000000n)\r
-       })\r
-})\r
+               await test('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.equal(block.balance, 3000000000000000000000000000000n)\r
+               })\r
+       }),\r
 \r
-await suite('Block signing using official test vectors', async () => {\r
+       suite('Block signing using official test vectors', async () => {\r
 \r
-       await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.OPEN_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature)\r
-       })\r
+               await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.OPEN_BLOCK.hash)\r
+                       assert.equal(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature)\r
+               })\r
 \r
-       await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
-       })\r
+               await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
+                       assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
+               })\r
 \r
-       await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
-               assert.equal(block.work, '')\r
-       })\r
+               await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash)\r
+                       assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature)\r
+                       assert.equal(block.work, '')\r
+               })\r
 \r
-       await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
-       })\r
+               await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
+                       assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
+               })\r
 \r
-       await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
-               assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
-               assert.equal(block.work, '')\r
-       })\r
+               await test('sign 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.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash)\r
+                       assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature)\r
+                       assert.equal(block.work, '')\r
+               })\r
 \r
-       await test('sign 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.equal(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D')\r
-               assert.equal(block.work, work)\r
-       })\r
+               await test('sign 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.equal(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D')\r
+                       assert.equal(block.work, work)\r
+               })\r
 \r
-       await test('sign 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.equal(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305')\r
-               assert.equal(block.work, '')\r
+               await test('sign 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.equal(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305')\r
+                       assert.equal(block.work, '')\r
+               })\r
        })\r
-})\r
+])\r
index 29b6bdbf94925ca8e8880a0e9d13e85d80a7c32b..bff769bbf9331f152643d08a7218c39ff8b10441 100644 (file)
@@ -7,41 +7,43 @@ import { assert, isNode, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'\r
 import { SendBlock, Blake2b } from '../dist/main.min.js'\r
 \r
-await suite('Calculate proof-of-work', { skip: isNode }, async () => {\r
-\r
-       await test('SendBlock PoW', 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.pow()\r
-\r
-               assert.equal(block.previous.length, 64)\r
-               assert.equal(block.work?.length, 16)\r
-\r
-               const work = block.work\r
-                       ?.match(/.{2}/g)\r
-                       ?.map(hex => parseInt(hex, 16))\r
-                       .reverse()\r
-               if (work == null) throw new Error('Work invalid')\r
-               const previous = block.previous\r
-                       ?.match(/.{2}/g)\r
-                       ?.map(hex => parseInt(hex, 16))\r
-               if (previous == null) throw new Error('Previous block hash invalid')\r
-\r
-               const bytes = new Uint8Array([...work, ...previous])\r
-               assert.equal(bytes.byteLength, 40)\r
-\r
-               const hash = new Blake2b(8)\r
-                       .update(bytes)\r
-                       .digest('hex')\r
-                       .slice(8, 16)\r
-\r
-               assert.ok(parseInt(hash.slice(0, 2), 16) > 0xf0)\r
-               assert.equal(parseInt(hash.slice(2, 8), 16), 0xffffff)\r
+await Promise.all([\r
+       suite('Calculate proof-of-work', { skip: isNode }, async () => {\r
+\r
+               await test('SendBlock PoW', 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.pow()\r
+\r
+                       assert.equal(block.previous.length, 64)\r
+                       assert.equal(block.work?.length, 16)\r
+\r
+                       const work = block.work\r
+                               ?.match(/.{2}/g)\r
+                               ?.map(hex => parseInt(hex, 16))\r
+                               .reverse()\r
+                       if (work == null) throw new Error('Work invalid')\r
+                       const previous = block.previous\r
+                               ?.match(/.{2}/g)\r
+                               ?.map(hex => parseInt(hex, 16))\r
+                       if (previous == null) throw new Error('Previous block hash invalid')\r
+\r
+                       const bytes = new Uint8Array([...work, ...previous])\r
+                       assert.equal(bytes.byteLength, 40)\r
+\r
+                       const hash = new Blake2b(8)\r
+                               .update(bytes)\r
+                               .digest('hex')\r
+                               .slice(8, 16)\r
+\r
+                       assert.ok(parseInt(hash.slice(0, 2), 16) > 0xf0)\r
+                       assert.equal(parseInt(hash.slice(2, 8), 16), 0xffffff)\r
+               })\r
        })\r
-})\r
+])\r
index 2253f0c56091ed3b0ff999eef4db170e3ea6b3df..620949214795fd5ea674e2d5014a891da2b7cc1c 100644 (file)
@@ -7,52 +7,54 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'\r
 \r
-await suite('Create wallets', async () => {\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(/^libnemo_[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]{128}$/.test(wallet.seed))\r
-\r
-               await wallet.destroy()\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(/^libnemo_[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]{64}$/.test(wallet.seed))\r
-\r
-               await wallet.destroy()\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
-                       const wallet = Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg)\r
-                       await assert.resolves(wallet);\r
-                       (await wallet).destroy()\r
-               }\r
-       })\r
-\r
-       await test('fail when using new', async () => {\r
-               assert.throws(() => new Bip44Wallet())\r
-               assert.throws(() => new Blake2bWallet())\r
-       })\r
-\r
-       await test('fail without a password', async () => {\r
-               await assert.rejects(Bip44Wallet.create())\r
-               await assert.rejects(Blake2bWallet.create())\r
+await Promise.all([\r
+       suite('Create wallets', async () => {\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(/^libnemo_[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]{128}$/.test(wallet.seed))\r
+\r
+                       await wallet.destroy()\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(/^libnemo_[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]{64}$/.test(wallet.seed))\r
+\r
+                       await wallet.destroy()\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
+                               const wallet = Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg)\r
+                               await assert.resolves(wallet);\r
+                               (await wallet).destroy()\r
+                       }\r
+               })\r
+\r
+               await test('fail when using new', async () => {\r
+                       assert.throws(() => new Bip44Wallet())\r
+                       assert.throws(() => new Blake2bWallet())\r
+               })\r
+\r
+               await test('fail without a password', async () => {\r
+                       await assert.rejects(Bip44Wallet.create())\r
+                       await assert.rejects(Blake2bWallet.create())\r
+               })\r
        })\r
-})\r
+])\r
index e2872656aa8594da3281568e6f0d546ec7c200dc..2cbf6ae65afcba47edb89cf9ba9c25e13869f50c 100644 (file)
@@ -7,122 +7,124 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'\r
 \r
-await suite('Derive accounts from BIP-44 wallet', async () => {\r
-\r
-       await test('derive the first account from the given BIP-44 seed', async () => {\r
-               const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               const account = await wallet.account()\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-\r
-               assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
-               assert.equal(account.index, 0)\r
-\r
-               const accounts = await wallet.accounts()\r
-               assert.exists(accounts[0])\r
-               assert.equal(account, accounts[0])\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('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
-               const privateKey1 = await accounts[1].export(wallet.seed, 'hex')\r
-               const privateKey2 = await accounts[2].export(wallet.seed, 'hex')\r
-\r
-               assert.equal(accounts.length, 2)\r
-               assert.equal(privateKey1, NANO_TEST_VECTORS.PRIVATE_1)\r
-               assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
-               assert.equal(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_1)\r
-               assert.equal(accounts[1].index, 1)\r
-               assert.equal(privateKey2, NANO_TEST_VECTORS.PRIVATE_2)\r
-               assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
-               assert.equal(accounts[2].address, NANO_TEST_VECTORS.ADDRESS_2)\r
-               assert.equal(accounts[2].index, 2)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('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, 0x7000000f)\r
-\r
-               assert.equal(accounts.length, 0x10)\r
-               for (let i = 0x70000000; i < 0x7000000f; i++) {\r
-                       const a = accounts[i]\r
-                       assert.exists(a)\r
-                       assert.equal(a.index, i)\r
-                       assert.exists(a.address)\r
-                       assert.exists(a.publicKey)\r
-                       const privateKey = await a.export(wallet.seed, 'hex')\r
-                       assert.exists(privateKey)\r
-               }\r
-\r
-               await wallet.destroy()\r
-       })\r
-})\r
-\r
-await suite('Derive accounts from BLAKE2b wallet', async () => {\r
-\r
-       await test('derive the second account from the given BLAKE2b seed', async () => {\r
-               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               const account = await wallet.account(1)\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-\r
-               assert.equal(privateKey, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1)\r
-               // assert.equal(account.publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_0)\r
-               // assert.equal(account.address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_0)\r
-               assert.equal(account.index, 1)\r
-\r
-               const accounts = await wallet.accounts(1)\r
-               assert.exists(accounts[1])\r
-               assert.equal(account, accounts[1])\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('derive low indexed accounts from the given BLAKE2B seed', async () => {\r
-               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               const accounts = await wallet.accounts(1, 2)\r
-               // const privateKey1 = await accounts[1].export(wallet.seed, 'hex')\r
-               // const privateKey2 = await accounts[2].export(wallet.seed, 'hex')\r
-\r
-               assert.equal(accounts.length, 2)\r
-               // assert.equal(privateKey1, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1)\r
-               // assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_1)\r
-               // assert.equal(accounts[1].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_1)\r
-               assert.equal(accounts[1].index, 1)\r
-               // assert.equal(privateKey2, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_2)\r
-               // assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_2)\r
-               // assert.equal(accounts[2].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_2)\r
-               assert.equal(accounts[2].index, 2)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('derive high indexed accounts from the given seed', async () => {\r
-               const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
-               await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               const accounts = await wallet.accounts(0x70000000, 0x7000000f)\r
-\r
-               assert.equal(accounts.length, 0x10)\r
-               for (let i = 0x70000000; i < 0x7000000f; i++) {\r
-                       const a = accounts[i]\r
-                       assert.exists(a)\r
-                       assert.equal(a.index, i)\r
-                       assert.exists(a.address)\r
-                       assert.exists(a.publicKey)\r
-                       const privateKey = await a.export(wallet.seed, 'hex')\r
-                       assert.exists(privateKey)\r
-               }\r
-\r
-               await wallet.destroy()\r
+await Promise.all([\r
+       suite('Derive accounts from BIP-44 wallet', async () => {\r
+\r
+               await test('derive the first account from the given BIP-44 seed', async () => {\r
+                       const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED)\r
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+                       const account = await wallet.account()\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+\r
+                       assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+                       assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+                       assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
+                       assert.equal(account.index, 0)\r
+\r
+                       const accounts = await wallet.accounts()\r
+                       assert.exists(accounts[0])\r
+                       assert.equal(account, accounts[0])\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('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
+                       const privateKey1 = await accounts[1].export(wallet.seed, 'hex')\r
+                       const privateKey2 = await accounts[2].export(wallet.seed, 'hex')\r
+\r
+                       assert.equal(accounts.length, 2)\r
+                       assert.equal(privateKey1, NANO_TEST_VECTORS.PRIVATE_1)\r
+                       assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_1)\r
+                       assert.equal(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_1)\r
+                       assert.equal(accounts[1].index, 1)\r
+                       assert.equal(privateKey2, NANO_TEST_VECTORS.PRIVATE_2)\r
+                       assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.PUBLIC_2)\r
+                       assert.equal(accounts[2].address, NANO_TEST_VECTORS.ADDRESS_2)\r
+                       assert.equal(accounts[2].index, 2)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('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, 0x7000000f)\r
+\r
+                       assert.equal(accounts.length, 0x10)\r
+                       for (let i = 0x70000000; i < 0x7000000f; i++) {\r
+                               const a = accounts[i]\r
+                               assert.exists(a)\r
+                               assert.equal(a.index, i)\r
+                               assert.exists(a.address)\r
+                               assert.exists(a.publicKey)\r
+                               const privateKey = await a.export(wallet.seed, 'hex')\r
+                               assert.exists(privateKey)\r
+                       }\r
+\r
+                       await wallet.destroy()\r
+               })\r
+       }),\r
+\r
+       suite('Derive accounts from BLAKE2b wallet', async () => {\r
+\r
+               await test('derive the second account from the given BLAKE2b seed', async () => {\r
+                       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+                       const account = await wallet.account(1)\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+\r
+                       assert.equal(privateKey, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1)\r
+                       // assert.equal(account.publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_0)\r
+                       // assert.equal(account.address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_0)\r
+                       assert.equal(account.index, 1)\r
+\r
+                       const accounts = await wallet.accounts(1)\r
+                       assert.exists(accounts[1])\r
+                       assert.equal(account, accounts[1])\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('derive low indexed accounts from the given BLAKE2B seed', async () => {\r
+                       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+                       const accounts = await wallet.accounts(1, 2)\r
+                       // const privateKey1 = await accounts[1].export(wallet.seed, 'hex')\r
+                       // const privateKey2 = await accounts[2].export(wallet.seed, 'hex')\r
+\r
+                       assert.equal(accounts.length, 2)\r
+                       // assert.equal(privateKey1, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1)\r
+                       // assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_1)\r
+                       // assert.equal(accounts[1].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_1)\r
+                       assert.equal(accounts[1].index, 1)\r
+                       // assert.equal(privateKey2, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_2)\r
+                       // assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_2)\r
+                       // assert.equal(accounts[2].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_2)\r
+                       assert.equal(accounts[2].index, 2)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('derive high indexed accounts from the given seed', async () => {\r
+                       const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED)\r
+                       await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+                       const accounts = await wallet.accounts(0x70000000, 0x7000000f)\r
+\r
+                       assert.equal(accounts.length, 0x10)\r
+                       for (let i = 0x70000000; i < 0x7000000f; i++) {\r
+                               const a = accounts[i]\r
+                               assert.exists(a)\r
+                               assert.equal(a.index, i)\r
+                               assert.exists(a.address)\r
+                               assert.exists(a.publicKey)\r
+                               const privateKey = await a.export(wallet.seed, 'hex')\r
+                               assert.exists(privateKey)\r
+                       }\r
+\r
+                       await wallet.destroy()\r
+               })\r
        })\r
-})\r
+])\r
index 80cb5b2309a6bf7c0551fbc78acfc36a14a3721c..3c1cd1c6c1c0774362f9db5c5617552005fe0e96 100644 (file)
@@ -7,279 +7,281 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { BIP32_TEST_VECTORS, CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.js'\r
 import { Account, Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'\r
 \r
-await suite('Import wallets', async () => {\r
-\r
-       await test('nano.org BIP-44 test vector 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 account = await wallet.account()\r
-\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.ok(account instanceof Account)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('nano.org BIP-44 test vector seed with no mnemonic', 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 account = await wallet.account()\r
-\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.ok(account instanceof Account)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Trezor-derived BIP-44 entropy for 12-word mnemonic', 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 account = await wallet.account()\r
-\r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Trezor-derived BIP-44 entropy for 15-word mnemonic', 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 account = await wallet.account()\r
-\r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Trezor-derived BIP-44 entropy for 18-word mnemonic', 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 account = await wallet.account()\r
-\r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Trezor-derived BIP-44 entropy for 21-word mnemonic', 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 account = await wallet.account()\r
-\r
-               assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
-               assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3)\r
-               assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3)\r
-               assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('BIP-44 zero-string entropy', 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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase())\r
-               assert.equal(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
-                       const privateKey = await accounts[i].export(wallet.seed, 'hex')\r
-                       assert.exists(privateKey)\r
-               }\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('BLAKE2b zero-string 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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-               assert.equal(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
-                       const privateKey = await accounts[i].export(wallet.seed, 'hex')\r
-                       assert.exists(privateKey)\r
-               }\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Trezor-derived BLAKE2b test vectors verified with third-party libraries', 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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               assert.ok(accounts[0] instanceof Account)\r
-               assert.equal(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0)\r
-               assert.equal(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0)\r
-               const privateKey0 = await accounts[0].export(wallet.seed, 'hex')\r
-               assert.equal(privateKey0, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0)\r
-\r
-               assert.ok(accounts[1] instanceof Account)\r
-               assert.equal(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1)\r
-               assert.equal(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1)\r
-               const privateKey1 = await accounts[1].export(wallet.seed, 'hex')\r
-               assert.equal(privateKey1, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('BLAKE2b seed creates identical wallet as 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 walletAccount = await wallet.account()\r
-               const walletAccountPrivateKey = await walletAccount.export(wallet.seed, 'hex')\r
-\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.exists(walletAccount)\r
-               assert.equal(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 importedAccount = await imported.account()\r
-               const importedAccountPrivateKey = await importedAccount.export(imported.seed, 'hex')\r
-\r
-               assert.equal(imported.mnemonic, wallet.mnemonic)\r
-               assert.equal(imported.seed, wallet.seed)\r
-               assert.equal(importedAccount.publicKey, walletAccount.publicKey)\r
-               assert.equal(importedAccountPrivateKey, walletAccountPrivateKey)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('BLAKE2b mnemonic for maximum seed 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 account = await wallet.account()\r
-\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.ok(account instanceof Account)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3)\r
-               assert.equal(account.publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0)\r
-               assert.equal(account.address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0)\r
-\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-               assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Reject 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 invalid length seed', 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 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
-       await test('Import BIP-44 wallet from session storage using a wallet-generated 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.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, '')\r
-\r
-               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('Import BLAKE2B wallet from session storage using a wallet-generated 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.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, '')\r
-\r
-               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-\r
-               await wallet.destroy()\r
+await Promise.all([\r
+       suite('Import wallets', async () => {\r
+\r
+               await test('nano.org BIP-44 test vector 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 account = await wallet.account()\r
+\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.ok(account instanceof Account)\r
+                       assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+                       assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+                       assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('nano.org BIP-44 test vector seed with no mnemonic', 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 account = await wallet.account()\r
+\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.ok(account instanceof Account)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+                       assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0)\r
+                       assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Trezor-derived BIP-44 entropy for 12-word mnemonic', 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 account = await wallet.account()\r
+\r
+                       assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0)\r
+                       assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0)\r
+                       assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0)\r
+                       assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Trezor-derived BIP-44 entropy for 15-word mnemonic', 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 account = await wallet.account()\r
+\r
+                       assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1)\r
+                       assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1)\r
+                       assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1)\r
+                       assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Trezor-derived BIP-44 entropy for 18-word mnemonic', 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 account = await wallet.account()\r
+\r
+                       assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2)\r
+                       assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2)\r
+                       assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2)\r
+                       assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Trezor-derived BIP-44 entropy for 21-word mnemonic', 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 account = await wallet.account()\r
+\r
+                       assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3)\r
+                       assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3)\r
+                       assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3)\r
+                       assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('BIP-44 zero-string entropy', 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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase())\r
+                       assert.equal(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
+                               const privateKey = await accounts[i].export(wallet.seed, 'hex')\r
+                               assert.exists(privateKey)\r
+                       }\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('BLAKE2b zero-string 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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+                       assert.equal(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
+                               const privateKey = await accounts[i].export(wallet.seed, 'hex')\r
+                               assert.exists(privateKey)\r
+                       }\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Trezor-derived BLAKE2b test vectors verified with third-party libraries', 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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       assert.ok(accounts[0] instanceof Account)\r
+                       assert.equal(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0)\r
+                       assert.equal(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0)\r
+                       const privateKey0 = await accounts[0].export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey0, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0)\r
+\r
+                       assert.ok(accounts[1] instanceof Account)\r
+                       assert.equal(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1)\r
+                       assert.equal(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1)\r
+                       const privateKey1 = await accounts[1].export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey1, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('BLAKE2b seed creates identical wallet as 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 walletAccount = await wallet.account()\r
+                       const walletAccountPrivateKey = await walletAccount.export(wallet.seed, 'hex')\r
+\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.exists(walletAccount)\r
+                       assert.equal(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 importedAccount = await imported.account()\r
+                       const importedAccountPrivateKey = await importedAccount.export(imported.seed, 'hex')\r
+\r
+                       assert.equal(imported.mnemonic, wallet.mnemonic)\r
+                       assert.equal(imported.seed, wallet.seed)\r
+                       assert.equal(importedAccount.publicKey, walletAccount.publicKey)\r
+                       assert.equal(importedAccountPrivateKey, walletAccountPrivateKey)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('BLAKE2b mnemonic for maximum seed 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 account = await wallet.account()\r
+\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.ok(account instanceof Account)\r
+                       assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3)\r
+                       assert.equal(account.publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0)\r
+                       assert.equal(account.address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0)\r
+\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+                       assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Reject 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 invalid length seed', 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 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
+               await test('Import BIP-44 wallet from session storage using a wallet-generated 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.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, '')\r
+\r
+                       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('Import BLAKE2B wallet from session storage using a wallet-generated 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.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, '')\r
+\r
+                       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+\r
+                       await wallet.destroy()\r
+               })\r
        })\r
-})\r
+])\r
index 812dda7fff537e4979bc875c8543ac866568d09e..aa878f5974c99ec2cb43c3331ff6281e446f9506 100644 (file)
@@ -13,186 +13,188 @@ const rpc = new Rpc(env.NODE_URL ?? '', env.API_KEY_NAME)
 * HID interactions require user gestures, so to reduce clicks, the variables
 * shared among tests like wallet and account are declared at the top-level.
 */
-await suite('Ledger hardware wallet', { skip: true || isNode }, async () => {
-
-       let wallet, account, openBlock, sendBlock, receiveBlock
-
-       await test('request permissions', async () => {
-               wallet = await LedgerWallet.create()
-               let status = wallet.status
-               assert.equal(status, 'DISCONNECTED')
-               assert.equal(status, wallet.status)
-
-               status = await click(
-                       'Reset permissions, unlock device, quit Nano app, then click to continue',
-                       async () => wallet.connect()
-               )
-               assert.equal(status, 'BUSY')
-               assert.equal(status, wallet.status)
-
-               status = await click(
-                       'Open Nano app on device, allow device to auto-lock, then click to continue',
-                       async () => wallet.connect()
-               )
-               assert.equal(status, 'LOCKED')
-               assert.equal(status, wallet.status)
-
-               status = await click(
-                       'Unlock device, verify Nano app is open, then click to continue',
-                       async () => wallet.connect()
-               )
-               assert.equal(status, 'CONNECTED')
-               assert.equal(status, wallet.status)
-       })
-
-       await test('get version', async () => {
-               const { status, name, version } = await wallet.version()
-
-               assert.equal(status, 'OK')
-               assert.equal(name, 'Nano')
-               assert.equal(version, '1.2.6')
-       })
-
-       await test('get first account', async () => {
-               account = await wallet.account()
-
-               assert.exists(account)
-               assert.ok(account instanceof Account)
-               assert.exists(account.address)
-               assert.exists(account.publicKey)
-               assert.exists(account.privateKey)
-               assert.equal(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000')
-       })
-
-       await test('get second and third accounts', async () => {
-               const accounts = await wallet.accounts(1, 2)
-
-               assert.exists(accounts)
-               assert.equal(accounts.length, 2)
-               for (const account of accounts) {
-                       assert.ok(account instanceof Account)
-                       assert.exists(account.address)
-                       assert.exists(account.publicKey)
-                       assert.exists(account.privateKey)
-                       assert.equal(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000')
-               }
-       })
-
-       await test('refresh first three accounts (must already be opened to be refreshed)', async () => {
-               const accounts = await wallet.refresh(rpc, 0, 2)
-
-               assert.exists(accounts)
-               for (const account of accounts) {
+await Promise.all([
+       suite('Ledger hardware wallet', { skip: true || isNode }, async () => {
+
+               let wallet, account, openBlock, sendBlock, receiveBlock
+
+               await test('request permissions', async () => {
+                       wallet = await LedgerWallet.create()
+                       let status = wallet.status
+                       assert.equal(status, 'DISCONNECTED')
+                       assert.equal(status, wallet.status)
+
+                       status = await click(
+                               'Reset permissions, unlock device, quit Nano app, then click to continue',
+                               async () => wallet.connect()
+                       )
+                       assert.equal(status, 'BUSY')
+                       assert.equal(status, wallet.status)
+
+                       status = await click(
+                               'Open Nano app on device, allow device to auto-lock, then click to continue',
+                               async () => wallet.connect()
+                       )
+                       assert.equal(status, 'LOCKED')
+                       assert.equal(status, wallet.status)
+
+                       status = await click(
+                               'Unlock device, verify Nano app is open, then click to continue',
+                               async () => wallet.connect()
+                       )
+                       assert.equal(status, 'CONNECTED')
+                       assert.equal(status, wallet.status)
+               })
+
+               await test('get version', async () => {
+                       const { status, name, version } = await wallet.version()
+
+                       assert.equal(status, 'OK')
+                       assert.equal(name, 'Nano')
+                       assert.equal(version, '1.2.6')
+               })
+
+               await test('get first account', async () => {
+                       account = await wallet.account()
+
+                       assert.exists(account)
                        assert.ok(account instanceof Account)
                        assert.exists(account.address)
-                       assert.exists(account.balance)
-                       assert.ok(account.balance >= 0)
                        assert.exists(account.publicKey)
                        assert.exists(account.privateKey)
                        assert.equal(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000')
-               }
-       })
-
-       await test('sign open block from block', async () => {
-               openBlock = new ReceiveBlock(
-                       account,
-                       '0',
-                       NANO_TEST_VECTORS.RECEIVE_BLOCK.link,
-                       NANO_TEST_VECTORS.RECEIVE_BLOCK.balance,
-                       NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,
-                       '0'
-               )
-
-               assert.ok(/^[A-Fa-f0-9]{64}$/.test(openBlock.hash))
-               assert.nullish(openBlock.signature)
-               assert.equal(openBlock.account.publicKey, account.publicKey)
-
-               const { status, hash, signature } = await wallet.sign(0, openBlock)
-
-               assert.equal(status, 'OK')
-               assert.ok(/^[A-Fa-f0-9]{64}$/.test(hash))
-               assert.ok(/^[A-Fa-f0-9]{128}$/.test(signature))
-
-               await openBlock.sign(0)
-
-               assert.ok(/^[A-Fa-f0-9]{128}$/.test(openBlock.signature))
-               assert.equal(signature, openBlock.signature)
-       })
-
-       await test('cache open block', async () => {
-               const { status } = await wallet.updateCache(0, openBlock)
-
-               assert.equal(status, 'OK')
-       })
-
-       await test('sign send block from wallet which requires cache to be up-to-date', async () => {
-               sendBlock = new SendBlock(
-                       account,
-                       openBlock.balance,
-                       account.address,
-                       '0',
-                       NANO_TEST_VECTORS.SEND_BLOCK.representative,
-                       openBlock.hash
-               )
-
-               assert.ok(/^[A-Fa-f0-9]{64}$/.test(sendBlock.hash))
-               assert.nullish(sendBlock.signature)
-               assert.equal(sendBlock.account.publicKey, account.publicKey)
-
-               const { status, hash, signature } = await wallet.sign(0, sendBlock)
-
-               assert.equal(status, 'OK')
-               assert.ok(/^[A-Fa-f0-9]{64}$/.test(hash))
-               assert.ok(/^[A-Fa-f0-9]{128}$/.test(signature))
-               sendBlock.signature = signature
-       })
-
-       await test('sign a receive block from block object which can accept previous block for cache', async () => {
-               receiveBlock = new ReceiveBlock(
-                       account,
-                       sendBlock.balance,
-                       sendBlock.hash,
-                       '0',
-                       NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,
-                       sendBlock.hash
-               )
-
-               assert.ok(/^[A-Fa-f0-9]{64}$/.test(sendBlock.hash))
-               assert.nullish(receiveBlock.signature)
-               assert.equal(receiveBlock.account.publicKey, account.publicKey)
-
-               await receiveBlock.sign(0, sendBlock)
-
-               assert.ok(/^[A-Fa-f0-9]{128}$/.test(receiveBlock.signature))
-       })
-
-       // nonce signing is currently broken: https://github.com/LedgerHQ/app-nano/pull/14
-       await test('sign a nonce', { skip: true }, async () => {
-               const nonce = new TextEncoder().encode('0123456789abcdef')
-               const { status, signature } = await click('Click to sign nonce', wallet.sign(0, nonce))
-
-               assert.equal(status, 'OK')
-               assert.OK(/^[A-Fa-f0-9]{128}$/.test(signature))
-       })
-
-       await test('destroy wallet', async () => {
-               await wallet.destroy()
-               await assert.rejects(wallet.version())
-       })
-
-       await test('fail when using new', async () => {
-               assert.throws(() => new LedgerWallet())
-       })
-
-       await test('fail to sign a block without caching frontier', async () => {
-               sendBlock = new SendBlock(
-                       account,
-                       receiveBlock.balance,
-                       account.address,
-                       '0',
-                       NANO_TEST_VECTORS.SEND_BLOCK.representative,
-                       receiveBlock.previous
-               )
-               await assert.rejects(sendBlock.sign(0))
+               })
+
+               await test('get second and third accounts', async () => {
+                       const accounts = await wallet.accounts(1, 2)
+
+                       assert.exists(accounts)
+                       assert.equal(accounts.length, 2)
+                       for (const account of accounts) {
+                               assert.ok(account instanceof Account)
+                               assert.exists(account.address)
+                               assert.exists(account.publicKey)
+                               assert.exists(account.privateKey)
+                               assert.equal(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000')
+                       }
+               })
+
+               await test('refresh first three accounts (must already be opened to be refreshed)', async () => {
+                       const accounts = await wallet.refresh(rpc, 0, 2)
+
+                       assert.exists(accounts)
+                       for (const account of accounts) {
+                               assert.ok(account instanceof Account)
+                               assert.exists(account.address)
+                               assert.exists(account.balance)
+                               assert.ok(account.balance >= 0)
+                               assert.exists(account.publicKey)
+                               assert.exists(account.privateKey)
+                               assert.equal(account.privateKey, '0000000000000000000000000000000000000000000000000000000000000000')
+                       }
+               })
+
+               await test('sign open block from block', async () => {
+                       openBlock = new ReceiveBlock(
+                               account,
+                               '0',
+                               NANO_TEST_VECTORS.RECEIVE_BLOCK.link,
+                               NANO_TEST_VECTORS.RECEIVE_BLOCK.balance,
+                               NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,
+                               '0'
+                       )
+
+                       assert.ok(/^[A-Fa-f0-9]{64}$/.test(openBlock.hash))
+                       assert.nullish(openBlock.signature)
+                       assert.equal(openBlock.account.publicKey, account.publicKey)
+
+                       const { status, hash, signature } = await wallet.sign(0, openBlock)
+
+                       assert.equal(status, 'OK')
+                       assert.ok(/^[A-Fa-f0-9]{64}$/.test(hash))
+                       assert.ok(/^[A-Fa-f0-9]{128}$/.test(signature))
+
+                       await openBlock.sign(0)
+
+                       assert.ok(/^[A-Fa-f0-9]{128}$/.test(openBlock.signature))
+                       assert.equal(signature, openBlock.signature)
+               })
+
+               await test('cache open block', async () => {
+                       const { status } = await wallet.updateCache(0, openBlock)
+
+                       assert.equal(status, 'OK')
+               })
+
+               await test('sign send block from wallet which requires cache to be up-to-date', async () => {
+                       sendBlock = new SendBlock(
+                               account,
+                               openBlock.balance,
+                               account.address,
+                               '0',
+                               NANO_TEST_VECTORS.SEND_BLOCK.representative,
+                               openBlock.hash
+                       )
+
+                       assert.ok(/^[A-Fa-f0-9]{64}$/.test(sendBlock.hash))
+                       assert.nullish(sendBlock.signature)
+                       assert.equal(sendBlock.account.publicKey, account.publicKey)
+
+                       const { status, hash, signature } = await wallet.sign(0, sendBlock)
+
+                       assert.equal(status, 'OK')
+                       assert.ok(/^[A-Fa-f0-9]{64}$/.test(hash))
+                       assert.ok(/^[A-Fa-f0-9]{128}$/.test(signature))
+                       sendBlock.signature = signature
+               })
+
+               await test('sign a receive block from block object which can accept previous block for cache', async () => {
+                       receiveBlock = new ReceiveBlock(
+                               account,
+                               sendBlock.balance,
+                               sendBlock.hash,
+                               '0',
+                               NANO_TEST_VECTORS.RECEIVE_BLOCK.representative,
+                               sendBlock.hash
+                       )
+
+                       assert.ok(/^[A-Fa-f0-9]{64}$/.test(sendBlock.hash))
+                       assert.nullish(receiveBlock.signature)
+                       assert.equal(receiveBlock.account.publicKey, account.publicKey)
+
+                       await receiveBlock.sign(0, sendBlock)
+
+                       assert.ok(/^[A-Fa-f0-9]{128}$/.test(receiveBlock.signature))
+               })
+
+               // nonce signing is currently broken: https://github.com/LedgerHQ/app-nano/pull/14
+               await test('sign a nonce', { skip: true }, async () => {
+                       const nonce = new TextEncoder().encode('0123456789abcdef')
+                       const { status, signature } = await click('Click to sign nonce', wallet.sign(0, nonce))
+
+                       assert.equal(status, 'OK')
+                       assert.OK(/^[A-Fa-f0-9]{128}$/.test(signature))
+               })
+
+               await test('destroy wallet', async () => {
+                       await wallet.destroy()
+                       await assert.rejects(wallet.version())
+               })
+
+               await test('fail when using new', async () => {
+                       assert.throws(() => new LedgerWallet())
+               })
+
+               await test('fail to sign a block without caching frontier', async () => {
+                       sendBlock = new SendBlock(
+                               account,
+                               receiveBlock.balance,
+                               account.address,
+                               '0',
+                               NANO_TEST_VECTORS.SEND_BLOCK.representative,
+                               receiveBlock.previous
+                       )
+                       await assert.rejects(sendBlock.sign(0))
+               })
        })
-})
+])
index 9a56aba2f2a31ac65ed312d7ffba46e0c1600441..2a9141a34acc9cde0f9aadbce117bea8c047c360 100644 (file)
@@ -7,295 +7,297 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.js'\r
 import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'\r
 \r
-await suite('Lock and unlock wallets', async () => {\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.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, '')\r
-\r
-               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('locking and unlocking a Bip44Wallet with random bytes', 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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-\r
-               const lockResult = await wallet.lock(new Uint8Array(key))\r
-               assert.ok(lockResult)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, '')\r
-\r
-               const unlockResult = await wallet.unlock(new Uint8Array(key))\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('locking and unlocking a Bip44Wallet Account with a password', 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 account = await wallet.account()\r
-               const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-               assert.equal(lockResult, true)\r
-\r
-               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
-\r
-               await wallet.destroy()\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.equal(lockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('fail to unlock a Bip44Wallet with different random bytes', 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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-               const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-               const lockResult = await wallet.lock(new Uint8Array(rightKey))\r
-\r
-               await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' })\r
-               assert.equal(lockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-\r
-               await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' })\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\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
-               await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.lock('password')\r
-\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.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\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
-               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.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
-               assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\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.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
-\r
-               await wallet.destroy()\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.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, '')\r
-\r
-               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('locking and unlocking a Blake2bWallet with random bytes', 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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-               const lockResult = await wallet.lock(new Uint8Array(key))\r
-\r
-               assert.equal(lockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.equal(wallet.seed, '')\r
-\r
-               const unlockResult = await wallet.unlock(new Uint8Array(key))\r
-\r
-               assert.equal(lockResult, true)\r
-               assert.equal(unlockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('locking and unlocking a Blake2bWallet Account with a password', 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 account = await wallet.account()\r
-               const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\r
-               assert.equal(lockResult, true)\r
-\r
-               const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
-               const privateKey = await account.export(wallet.seed, 'hex')\r
-\r
-               assert.equal(unlockResult, true)\r
-               assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_PRIVATE_0)\r
-\r
-               await wallet.destroy()\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.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.destroy()\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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-               const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-               const lockResult = await wallet.lock(new Uint8Array(rightKey))\r
-\r
-               await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' })\r
-               assert.equal(lockResult, true)\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.destroy()\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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
-\r
-               await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' })\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.destroy()\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
-               await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
-               assert.ok('mnemonic' in wallet)\r
-               assert.ok('seed' in wallet)\r
-               assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\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.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.destroy()\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
-               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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
-               assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
-\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.nullish(wallet.mnemonic)\r
-               assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
-\r
-               await wallet.destroy()\r
+await Promise.all([\r
+       suite('Lock and unlock wallets', async () => {\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.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, '')\r
+\r
+                       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('locking and unlocking a Bip44Wallet with random bytes', 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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+\r
+                       const lockResult = await wallet.lock(new Uint8Array(key))\r
+                       assert.ok(lockResult)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, '')\r
+\r
+                       const unlockResult = await wallet.unlock(new Uint8Array(key))\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('locking and unlocking a Bip44Wallet Account with a password', 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 account = await wallet.account()\r
+                       const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+                       assert.equal(lockResult, true)\r
+\r
+                       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0)\r
+\r
+                       await wallet.destroy()\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.equal(lockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('fail to unlock a Bip44Wallet with different random bytes', 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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+                       const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+                       const lockResult = await wallet.lock(new Uint8Array(rightKey))\r
+\r
+                       await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' })\r
+                       assert.equal(lockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+\r
+                       await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' })\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\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
+                       await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.lock('password')\r
+\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.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\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
+                       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.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC)\r
+                       assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\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.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED)\r
+\r
+                       await wallet.destroy()\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.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, '')\r
+\r
+                       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('locking and unlocking a Blake2bWallet with random bytes', 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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+                       const lockResult = await wallet.lock(new Uint8Array(key))\r
+\r
+                       assert.equal(lockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.equal(wallet.seed, '')\r
+\r
+                       const unlockResult = await wallet.unlock(new Uint8Array(key))\r
+\r
+                       assert.equal(lockResult, true)\r
+                       assert.equal(unlockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('locking and unlocking a Blake2bWallet Account with a password', 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 account = await wallet.account()\r
+                       const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\r
+                       assert.equal(lockResult, true)\r
+\r
+                       const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD)\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\r
+\r
+                       assert.equal(unlockResult, true)\r
+                       assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_PRIVATE_0)\r
+\r
+                       await wallet.destroy()\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.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.destroy()\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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+                       const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+                       const lockResult = await wallet.lock(new Uint8Array(rightKey))\r
+\r
+                       await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' })\r
+                       assert.equal(lockResult, true)\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.destroy()\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 = globalThis.crypto.getRandomValues(new Uint8Array(64))\r
+\r
+                       await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' })\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.destroy()\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
+                       await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' })\r
+                       assert.ok('mnemonic' in wallet)\r
+                       assert.ok('seed' in wallet)\r
+                       assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\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.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.destroy()\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
+                       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.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1)\r
+                       assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.lock(NANO_TEST_VECTORS.PASSWORD)\r
+\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.nullish(wallet.mnemonic)\r
+                       assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1)\r
+\r
+                       await wallet.destroy()\r
+               })\r
        })\r
-})\r
+])\r
index b05394bbf020d2a65c5f124e73e425f32dc90365..31a09be51b36219f11172454213e20afba911ee5 100644 (file)
@@ -7,196 +7,198 @@ import { assert, suite, test } from './GLOBALS.mjs'
 import { NANO_TEST_VECTORS } from './VECTORS.js'
 import { Rolodex, Tools } from '../dist/main.min.js'
 
-await suite('Rolodex valid contact management', async () => {
-
-       await test('export returns empty array for empty rolodex (delete db if not already empty)', async () => {
-               const result = await Rolodex.getAllNames()
-
-               assert.ok(Array.isArray(result))
-               assert.equal(result.length, 0)
-       })
-
-       await test('add two contacts, then delete them', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-               await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1))
-
-               let names = await Rolodex.getAllNames()
-               assert.ok(Array.isArray(names))
-               assert.equal(names.length, 2)
-               assert.equal(names[0], 'JaneSmith')
-               assert.equal(names[1], 'JohnDoe')
-
-               const addressesJohnDoe = await Rolodex.getAddresses('JohnDoe')
-               const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
-
-               assert.ok(Array.isArray(addressesJohnDoe))
-               assert.equal(addressesJohnDoe.length, 1)
-               assert.equal(addressesJohnDoe[0], NANO_TEST_VECTORS.ADDRESS_0)
-               assert.ok(Array.isArray(addressesJaneSmith))
-               assert.equal(addressesJaneSmith.length, 1)
-               assert.equal(addressesJaneSmith[0], NANO_TEST_VECTORS.ADDRESS_1)
-
-               const deleteJohnDoe = await Rolodex.deleteName('JohnDoe')
-               const deleteJaneSmith = await Rolodex.deleteName('JaneSmith')
-               assert.equal(deleteJohnDoe, true)
-               assert.equal(deleteJaneSmith, true)
-
-               names = await Rolodex.getAllNames()
-               assert.ok(Array.isArray(names))
-               assert.equal(names.length, 0)
-       })
-
-       await test('get a name from an address', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-
-               const name = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(name, 'JohnDoe')
-
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-       })
-
-       await test('add three addresses to the same contact, then delete one address, then delete the contact', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1))
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2))
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-
-               let addresses = await Rolodex.getAddresses('JohnDoe')
-               assert.ok(Array.isArray(addresses))
-               assert.equal(addresses.length, 3)
-               assert.equal(addresses[0], NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(addresses[1], NANO_TEST_VECTORS.ADDRESS_2)
-               assert.equal(addresses[2], NANO_TEST_VECTORS.ADDRESS_1)
-
-               await assert.resolves(Rolodex.deleteAddress(NANO_TEST_VECTORS.ADDRESS_1))
-               addresses = await Rolodex.getAddresses('JohnDoe')
-               assert.ok(Array.isArray(addresses))
-               assert.equal(addresses.length, 2)
-               assert.equal(addresses[0], NANO_TEST_VECTORS.ADDRESS_0)
-               assert.equal(addresses[1], NANO_TEST_VECTORS.ADDRESS_2)
-
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-               addresses = await Rolodex.getAddresses('JohnDoe')
-               const address0 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0)
-               const address1 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1)
-               const address2 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_2)
-
-               assert.ok(Array.isArray(addresses))
-               assert.equal(addresses.length, 0)
-               assert.nullish(address0)
-               assert.nullish(address1)
-               assert.nullish(address2)
-       })
-
-       await test('update the name on an existing address', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-               await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0))
-               const addressesJohnDoe = await Rolodex.getAddresses('JohnDoe')
-               const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
-
-               assert.ok(Array.isArray(addressesJohnDoe))
-               assert.equal(addressesJohnDoe.length, 0)
-               assert.ok(Array.isArray(addressesJaneSmith))
-               assert.equal(addressesJaneSmith.length, 1)
-               assert.equal(addressesJaneSmith[0], NANO_TEST_VECTORS.ADDRESS_0)
-
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-               await assert.resolves(Rolodex.deleteName('JaneSmith'))
-       })
-
-       await test('return empty address array for an unknown contact', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-               const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
-
-               assert.equal(Array.isArray(addressesJaneSmith), true)
-               assert.equal(addressesJaneSmith.length, 0)
-
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-       })
-
-       await test('return empty address array for blank contact names', async () => {
-               //@ts-expect-error
-               const addressesUndefined = await Rolodex.getAddresses(undefined)
-               //@ts-expect-error
-               const addressesNull = await Rolodex.getAddresses(null)
-               const addressesBlank = await Rolodex.getAddresses('')
-
-               assert.equal(Array.isArray(addressesUndefined), true)
-               assert.equal(addressesUndefined.length, 0)
-               assert.equal(Array.isArray(addressesNull), true)
-               assert.equal(addressesNull.length, 0)
-               assert.equal(Array.isArray(addressesBlank), true)
-               assert.equal(addressesBlank.length, 0)
-       })
-
-       await test('should return null for an unknown address', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-               const addressUnknown = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1)
-
-               assert.ok(addressUnknown === null)
-               assert.ok(addressUnknown !== undefined)
-
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-       })
-
-       await test('should return null for a blank address', async () => {
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-               //@ts-expect-error
-               const nameUndefined = await Rolodex.getName(undefined)
-               //@ts-expect-error
-               const nameNull = await Rolodex.getName(null)
-               const nameBlank = await Rolodex.getName('')
-
-               assert.ok(nameUndefined === null)
-               assert.ok(nameUndefined !== undefined)
-               assert.ok(nameNull === null)
-               assert.ok(nameNull !== undefined)
-               assert.ok(nameBlank === null)
-               assert.ok(nameBlank !== undefined)
-
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-       })
-
-       await test('throw if adding no data', async () => {
-               //@ts-expect-error
-               await assert.rejects(Rolodex.add())
-       })
-
-       await test('throw if passed no address', async () => {
-               //@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('throw if name is blank', async () => {
-               //@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 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)
-               await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
-               const result = await Rolodex.verify('JohnDoe', signature, data)
-               await assert.resolves(Rolodex.deleteName('JohnDoe'))
-               assert.equal(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)
-               await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1))
-               const result = await Rolodex.verify('JaneSmith', signature, data)
-               await assert.resolves(Rolodex.deleteName('JaneSmith'))
-               assert.equal(result, false)
+await Promise.all([
+       suite('Rolodex valid contact management', async () => {
+
+               await test('export returns empty array for empty rolodex (delete db if not already empty)', async () => {
+                       const result = await Rolodex.getAllNames()
+
+                       assert.ok(Array.isArray(result))
+                       assert.equal(result.length, 0)
+               })
+
+               await test('add two contacts, then delete them', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+                       await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1))
+
+                       let names = await Rolodex.getAllNames()
+                       assert.ok(Array.isArray(names))
+                       assert.equal(names.length, 2)
+                       assert.equal(names[0], 'JaneSmith')
+                       assert.equal(names[1], 'JohnDoe')
+
+                       const addressesJohnDoe = await Rolodex.getAddresses('JohnDoe')
+                       const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
+
+                       assert.ok(Array.isArray(addressesJohnDoe))
+                       assert.equal(addressesJohnDoe.length, 1)
+                       assert.equal(addressesJohnDoe[0], NANO_TEST_VECTORS.ADDRESS_0)
+                       assert.ok(Array.isArray(addressesJaneSmith))
+                       assert.equal(addressesJaneSmith.length, 1)
+                       assert.equal(addressesJaneSmith[0], NANO_TEST_VECTORS.ADDRESS_1)
+
+                       const deleteJohnDoe = await Rolodex.deleteName('JohnDoe')
+                       const deleteJaneSmith = await Rolodex.deleteName('JaneSmith')
+                       assert.equal(deleteJohnDoe, true)
+                       assert.equal(deleteJaneSmith, true)
+
+                       names = await Rolodex.getAllNames()
+                       assert.ok(Array.isArray(names))
+                       assert.equal(names.length, 0)
+               })
+
+               await test('get a name from an address', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+
+                       const name = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0)
+                       assert.equal(name, 'JohnDoe')
+
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+               })
+
+               await test('add three addresses to the same contact, then delete one address, then delete the contact', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1))
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2))
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+
+                       let addresses = await Rolodex.getAddresses('JohnDoe')
+                       assert.ok(Array.isArray(addresses))
+                       assert.equal(addresses.length, 3)
+                       assert.equal(addresses[0], NANO_TEST_VECTORS.ADDRESS_0)
+                       assert.equal(addresses[1], NANO_TEST_VECTORS.ADDRESS_2)
+                       assert.equal(addresses[2], NANO_TEST_VECTORS.ADDRESS_1)
+
+                       await assert.resolves(Rolodex.deleteAddress(NANO_TEST_VECTORS.ADDRESS_1))
+                       addresses = await Rolodex.getAddresses('JohnDoe')
+                       assert.ok(Array.isArray(addresses))
+                       assert.equal(addresses.length, 2)
+                       assert.equal(addresses[0], NANO_TEST_VECTORS.ADDRESS_0)
+                       assert.equal(addresses[1], NANO_TEST_VECTORS.ADDRESS_2)
+
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+                       addresses = await Rolodex.getAddresses('JohnDoe')
+                       const address0 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0)
+                       const address1 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1)
+                       const address2 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_2)
+
+                       assert.ok(Array.isArray(addresses))
+                       assert.equal(addresses.length, 0)
+                       assert.nullish(address0)
+                       assert.nullish(address1)
+                       assert.nullish(address2)
+               })
+
+               await test('update the name on an existing address', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+                       await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0))
+                       const addressesJohnDoe = await Rolodex.getAddresses('JohnDoe')
+                       const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
+
+                       assert.ok(Array.isArray(addressesJohnDoe))
+                       assert.equal(addressesJohnDoe.length, 0)
+                       assert.ok(Array.isArray(addressesJaneSmith))
+                       assert.equal(addressesJaneSmith.length, 1)
+                       assert.equal(addressesJaneSmith[0], NANO_TEST_VECTORS.ADDRESS_0)
+
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+                       await assert.resolves(Rolodex.deleteName('JaneSmith'))
+               })
+
+               await test('return empty address array for an unknown contact', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+                       const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
+
+                       assert.equal(Array.isArray(addressesJaneSmith), true)
+                       assert.equal(addressesJaneSmith.length, 0)
+
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+               })
+
+               await test('return empty address array for blank contact names', async () => {
+                       //@ts-expect-error
+                       const addressesUndefined = await Rolodex.getAddresses(undefined)
+                       //@ts-expect-error
+                       const addressesNull = await Rolodex.getAddresses(null)
+                       const addressesBlank = await Rolodex.getAddresses('')
+
+                       assert.equal(Array.isArray(addressesUndefined), true)
+                       assert.equal(addressesUndefined.length, 0)
+                       assert.equal(Array.isArray(addressesNull), true)
+                       assert.equal(addressesNull.length, 0)
+                       assert.equal(Array.isArray(addressesBlank), true)
+                       assert.equal(addressesBlank.length, 0)
+               })
+
+               await test('should return null for an unknown address', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+                       const addressUnknown = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1)
+
+                       assert.ok(addressUnknown === null)
+                       assert.ok(addressUnknown !== undefined)
+
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+               })
+
+               await test('should return null for a blank address', async () => {
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+                       //@ts-expect-error
+                       const nameUndefined = await Rolodex.getName(undefined)
+                       //@ts-expect-error
+                       const nameNull = await Rolodex.getName(null)
+                       const nameBlank = await Rolodex.getName('')
+
+                       assert.ok(nameUndefined === null)
+                       assert.ok(nameUndefined !== undefined)
+                       assert.ok(nameNull === null)
+                       assert.ok(nameNull !== undefined)
+                       assert.ok(nameBlank === null)
+                       assert.ok(nameBlank !== undefined)
+
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+               })
+
+               await test('throw if adding no data', async () => {
+                       //@ts-expect-error
+                       await assert.rejects(Rolodex.add())
+               })
+
+               await test('throw if passed no address', async () => {
+                       //@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('throw if name is blank', async () => {
+                       //@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))
+               })
+       }),
+
+       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)
+                       await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+                       const result = await Rolodex.verify('JohnDoe', signature, data)
+                       await assert.resolves(Rolodex.deleteName('JohnDoe'))
+                       assert.equal(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)
+                       await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1))
+                       const result = await Rolodex.verify('JaneSmith', signature, data)
+                       await assert.resolves(Rolodex.deleteName('JaneSmith'))
+                       assert.equal(result, false)
+               })
        })
-})
+])
index 409a0774df2dff731fafe005a0eaeed89197211e..8bdeff92714ee351eca776ae694de4a765e189a6 100644 (file)
@@ -9,165 +9,167 @@ import { Account, Bip44Wallet, Rpc } from '../dist/main.min.js'
 
 const rpc = new Rpc(env.NODE_URL ?? '', env.API_KEY_NAME)
 
-await suite('Refreshing account info', { skip: true }, 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 account = await wallet.account()
-               await account.refresh(rpc)
-
-               assert.exists(account.balance)
-               assert.notEqual(account.balance, '')
-               assert.equal(typeof account.balance, 'bigint')
-               assert.ok(account.balance >= 0)
-
-               assert.exists(account.frontier)
-               assert.equal(typeof account.frontier, 'string')
-               assert.notEqual(account.frontier, '')
-               assert.ok(/^[A-Fa-f0-9]{64}$/.test(account.frontier))
-
-               assert.exists(account.representative)
-               assert.notEqual(account.representative, '')
-               assert.equal(account.representative.constructor, Account)
-               assert.exists(account.representative?.address)
-               assert.notEqual(account.representative?.address, '')
-
-               await wallet.destroy()
-       })
-
-       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 account = await wallet.account(0x7fffffff)
+await Promise.all([
+       suite('Refreshing account info', { skip: true }, async () => {
 
-               await assert.rejects(account.refresh(rpc),
-                       { message: 'Account not found' })
+               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 account = await wallet.account()
+                       await account.refresh(rpc)
+
+                       assert.exists(account.balance)
+                       assert.notEqual(account.balance, '')
+                       assert.equal(typeof account.balance, 'bigint')
+                       assert.ok(account.balance >= 0)
 
-               await wallet.destroy()
-       })
+                       assert.exists(account.frontier)
+                       assert.equal(typeof account.frontier, 'string')
+                       assert.notEqual(account.frontier, '')
+                       assert.ok(/^[A-Fa-f0-9]{64}$/.test(account.frontier))
 
-       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)
+                       assert.exists(account.representative)
+                       assert.notEqual(account.representative, '')
+                       assert.equal(account.representative.constructor, Account)
+                       assert.exists(account.representative?.address)
+                       assert.notEqual(account.representative?.address, '')
+
+                       await wallet.destroy()
+               })
+
+               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 account = await wallet.account(0x7fffffff)
+
+                       await assert.rejects(account.refresh(rpc),
+                               { message: 'Account not found' })
+
+                       await wallet.destroy()
+               })
+
+               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.account(0x80000000),
-                       { message: 'Invalid child key index 0x80000000' })
+                       await assert.rejects(wallet.account(0x80000000),
+                               { message: 'Invalid child key index 0x80000000' })
+
+                       await wallet.destroy()
+               })
+
+               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 account = await wallet.account()
 
-               await wallet.destroy()
-       })
+                       await assert.rejects(account.refresh(invalidNode),
+                               { message: 'Account not found' })
 
-       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 account = await wallet.account()
-
-               await assert.rejects(account.refresh(invalidNode),
-                       { message: 'Account not found' })
-
-               await wallet.destroy()
-       })
-})
+                       await wallet.destroy()
+               })
+       }),
 
-await suite('Fetch next unopened account', { skip: true }, async () => {
+       suite('Fetch next unopened account', { skip: true }, 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.unopened(rpc)
+               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.unopened(rpc)
 
-               assert.exists(account)
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+                       assert.exists(account)
+                       assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+                       assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
 
-               await wallet.destroy()
-       })
+                       await wallet.destroy()
+               })
 
-       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.unopened(rpc, 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.unopened(rpc, 1)
 
-               assert.exists(account)
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+                       assert.exists(account)
+                       assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+                       assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
 
-               await wallet.destroy()
-       })
+                       await wallet.destroy()
+               })
 
-       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.unopened(rpc, 100)
+               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.unopened(rpc, 100)
 
-               assert.exists(account)
-               assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
-               assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
+                       assert.exists(account)
+                       assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_1)
+                       assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_1)
 
-               await wallet.destroy()
-       })
+                       await wallet.destroy()
+               })
 
-       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)
+               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)
 
-               await assert.rejects(wallet.unopened())
-               await assert.rejects(wallet.unopened(null))
-               await assert.rejects(wallet.unopened(1))
-               await assert.rejects(wallet.unopened(''))
-               await assert.rejects(wallet.unopened('foo'))
+                       await assert.rejects(wallet.unopened())
+                       await assert.rejects(wallet.unopened(null))
+                       await assert.rejects(wallet.unopened(1))
+                       await assert.rejects(wallet.unopened(''))
+                       await assert.rejects(wallet.unopened('foo'))
 
-               await wallet.destroy()
-       })
+                       await wallet.destroy()
+               })
 
-       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)
+               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)
 
-               await assert.rejects(wallet.unopened(rpc, null))
-               await assert.rejects(wallet.unopened(rpc, -1))
-               await assert.rejects(wallet.unopened(rpc, ''))
-               await assert.rejects(wallet.unopened(rpc, 'foo'))
-               await assert.rejects(wallet.unopened(rpc, { 'foo': 'bar' }))
+                       await assert.rejects(wallet.unopened(rpc, null))
+                       await assert.rejects(wallet.unopened(rpc, -1))
+                       await assert.rejects(wallet.unopened(rpc, ''))
+                       await assert.rejects(wallet.unopened(rpc, 'foo'))
+                       await assert.rejects(wallet.unopened(rpc, { 'foo': 'bar' }))
 
-               await wallet.destroy()
-       })
-})
+                       await wallet.destroy()
+               })
+       }),
 
-await suite('Refreshing wallet accounts', { skip: true }, async () => {
+       suite('Refreshing wallet accounts', { skip: true }, async () => {
 
-       await test('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]
+               await test('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.equal(typeof account.balance, 'bigint')
-               assert.exists(account.frontier)
-               assert.equal(typeof account.frontier, 'string')
+                       assert.ok(account instanceof Account)
+                       assert.equal(typeof account.balance, 'bigint')
+                       assert.exists(account.frontier)
+                       assert.equal(typeof account.frontier, 'string')
 
-               await wallet.destroy()
-       })
+                       await wallet.destroy()
+               })
 
-       await test('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)
+               await test('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.equal(accounts.length, 1)
-               assert.ok(accounts[0] instanceof Account)
+                       assert.equal(accounts.length, 1)
+                       assert.ok(accounts[0] instanceof Account)
 
-               await wallet.destroy()
-       })
+                       await wallet.destroy()
+               })
 
-       await test('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 test('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.resolves(wallet.refresh(rpc, 0, 20))
+                       await assert.resolves(wallet.refresh(rpc, 0, 20))
 
-               await wallet.destroy()
+                       await wallet.destroy()
+               })
        })
-})
+])
index 1f2bd9e81159315cfa1e8dc773594ae336ca2faa..1c731f437de9958d4572629665a95e9c7551d2b0 100644 (file)
@@ -4,42 +4,43 @@
 import { failures, isNode, passes, suite, test } from './GLOBALS.mjs'
 
 if (!isNode) {
-       await suite('TEST RUNNER CHECK', async () => {
-               await new Promise(r => setTimeout(r, 0))
-
-               console.assert(failures.length === 0)
-               console.assert(passes.length === 0)
-
-               //@ts-expect-error
-               await test('promise should pass', new Promise(resolve => resolve(null)))
-               console.assert(failures.some(call => /.*promise should pass.*/.test(call[0])) === false, `good promise errored`)
-               console.assert(passes.some(call => /.*promise should pass.*/.test(call)) === true, `good promise not logged`)
-
-               //@ts-expect-error
-               await test('promise should fail', new Promise((resolve, reject) => reject('FAILURE EXPECTED HERE')))
-               console.assert(failures.some(call => /.*promise should fail.*/.test(call)) === true, `bad promise not errored`)
-               console.assert(passes.some(call => /.*promise should fail.*/.test(call)) === false, 'bad promise logged')
-
-               await test('async should pass', async () => {})
-               console.assert(failures.some(call => /.*async should pass.*/.test(call)) === false, 'good async errored')
-               console.assert(passes.some(call => /.*async should pass.*/.test(call)) === true, 'good async not logged')
-
-               await test('async should fail', async () => { throw new Error('FAILURE EXPECTED HERE') })
-               console.assert(failures.some(call => /.*async should fail.*/.test(call)) === true, 'bad async not errored')
-               console.assert(passes.some(call => /.*async should fail.*/.test(call)) === false, 'bad async logged')
-
-               await test('function should pass', () => {})
-               console.assert(failures.some(call => /.*function should pass.*/.test(call)) === false, 'good function errored')
-               console.assert(passes.some(call => /.*function should pass.*/.test(call)) === true, 'good function not logged')
-
-               //@ts-expect-error
-               await test('function should fail', 'FAILURE EXPECTED HERE')
-               console.assert(failures.some(call => /.*function should fail.*/.test(call)) === true, 'bad function not errored')
-               console.assert(passes.some(call => /.*function should fail.*/.test(call)) === false, 'bad function logged')
-
-               failures.splice(0)
-               passes.splice(0)
-       })
-
+       await Promise.all([
+               suite('TEST RUNNER CHECK', async () => {
+                       await new Promise(r => setTimeout(r, 0))
+
+                       console.assert(failures.length === 0)
+                       console.assert(passes.length === 0)
+
+                       //@ts-expect-error
+                       await test('promise should pass', new Promise(resolve => resolve(null)))
+                       console.assert(failures.some(call => /.*promise should pass.*/.test(call[0])) === false, `good promise errored`)
+                       console.assert(passes.some(call => /.*promise should pass.*/.test(call)) === true, `good promise not logged`)
+
+                       //@ts-expect-error
+                       await test('promise should fail', new Promise((resolve, reject) => reject('FAILURE EXPECTED HERE')))
+                       console.assert(failures.some(call => /.*promise should fail.*/.test(call)) === true, `bad promise not errored`)
+                       console.assert(passes.some(call => /.*promise should fail.*/.test(call)) === false, 'bad promise logged')
+
+                       await test('async should pass', async () => {})
+                       console.assert(failures.some(call => /.*async should pass.*/.test(call)) === false, 'good async errored')
+                       console.assert(passes.some(call => /.*async should pass.*/.test(call)) === true, 'good async not logged')
+
+                       await test('async should fail', async () => { throw new Error('FAILURE EXPECTED HERE') })
+                       console.assert(failures.some(call => /.*async should fail.*/.test(call)) === true, 'bad async not errored')
+                       console.assert(passes.some(call => /.*async should fail.*/.test(call)) === false, 'bad async logged')
+
+                       await test('function should pass', () => {})
+                       console.assert(failures.some(call => /.*function should pass.*/.test(call)) === false, 'good function errored')
+                       console.assert(passes.some(call => /.*function should pass.*/.test(call)) === true, 'good function not logged')
+
+                       //@ts-expect-error
+                       await test('function should fail', 'FAILURE EXPECTED HERE')
+                       console.assert(failures.some(call => /.*function should fail.*/.test(call)) === true, 'bad function not errored')
+                       console.assert(passes.some(call => /.*function should fail.*/.test(call)) === false, 'bad function logged')
+
+                       failures.splice(0)
+                       passes.splice(0)
+               })
+       ])
        console.log(`%cTEST RUNNER CHECK DONE`, 'font-weight:bold')
 }
index e5a4599c89b7eee88bd604a30d2dbbf7af8da53f..1bd91ce690d820da47e0e996035a8247e57bedf4 100644 (file)
@@ -9,146 +9,148 @@ import { Bip44Wallet, Account, SendBlock, Rpc, Tools } from '../dist/main.min.js
 \r
 const rpc = new Rpc(env?.NODE_URL ?? '', env?.API_KEY_NAME)\r
 \r
-await suite('unit conversion tests', async () => {\r
-\r
-       await test('should convert nano to raw', async () => {\r
-               const result = await Tools.convert('1', 'NANO', 'RAW')\r
-               assert.equal(result, '1000000000000000000000000000000')\r
-       })\r
-\r
-       await test('should convert raw to nano', async () => {\r
-               const result = await Tools.convert('1000000000000000000000000000000', 'RAW', 'NANO')\r
-               assert.equal(result, '1')\r
-       })\r
-\r
-       await test('should convert 1 raw to 10^-29 nano', async () => {\r
-               const result = await Tools.convert('1', 'RAW', 'NANO')\r
-               assert.equal(result, '.000000000000000000000000000001')\r
-       })\r
-\r
-       await test('should ignore leading and trailing zeros', async () => {\r
-               const result = await Tools.convert('0011002200.0033004400', 'nano', 'nano')\r
-               assert.equal(result, '11002200.00330044')\r
-       })\r
-\r
-       await test('should convert raw to nyano', async () => {\r
-               const result = await Tools.convert(RAW_MAX, 'RAW', 'NYANO')\r
-               assert.equal(result, '340282366920938.463463374607431768211455')\r
-       })\r
-\r
-       await test('should convert case-insensitive nyano to raw', async () => {\r
-               const result = await Tools.convert('0.000000000000000123456789', 'nYaNo', 'rAw')\r
-               assert.equal(result, '123456789')\r
-       })\r
-\r
-       await test('should convert nano to pico', async () => {\r
-               const result = await Tools.convert('123.456', 'nano', 'pico')\r
-               assert.equal(result, '123456')\r
-       })\r
-\r
-       await test('should convert knano to pico', async () => {\r
-               const result = await Tools.convert('123.456', 'nano', 'pico')\r
-               assert.equal(result, '123456')\r
-       })\r
-\r
-       await test('should throw if amount exceeds raw max', async () => {\r
-               await assert.rejects(Tools.convert(RAW_MAX, 'NANO', 'RAW'),\r
-                       { message: 'Amount exceeds Nano limits' })\r
-       })\r
-\r
-       await test('should throw if amount exceeds raw min', async () => {\r
-               await assert.rejects(Tools.convert('0.1', 'RAW', 'NANO'),\r
-                       { message: 'Amount must be at least 1 raw' })\r
-       })\r
-\r
-       await test('should throw if amount is blank', async () => {\r
-               await assert.rejects(Tools.convert('', 'RAW', 'NANO'),\r
-                       { message: 'Invalid amount' })\r
-       })\r
-\r
-       await test('should throw if amount has non-digit characters', async () => {\r
-               await assert.rejects(Tools.convert('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'RAW', 'NANO'),\r
-                       { message: 'Invalid amount' })\r
-       })\r
-})\r
-\r
-await suite('signature tests', async () => {\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.equal(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.equal(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.equal(result, true)\r
-\r
-               const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi')\r
-               assert.equal(result2, false)\r
-\r
-               const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
-               assert.equal(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 account = await wallet.account()\r
-               const privateKey = await account.export(wallet.seed, 'hex')\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(privateKey)\r
-               const valid = await sendBlock.verify(account.publicKey)\r
-               assert.equal(valid, true)\r
-\r
-               await wallet.destroy()\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 account = await wallet.account()\r
-               const privateKey = await account.export(wallet.seed, 'hex')\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(privateKey)\r
-\r
-               sendBlock.account = Account.import('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
-               const valid = await sendBlock.verify(account.publicKey)\r
-               assert.equal(valid, false)\r
-\r
-               await wallet.destroy()\r
-       })\r
-\r
-       await test('sweeper throws without required parameters', async () => {\r
-               await assert.rejects(Tools.sweep(),\r
-                       'Missing required sweep arguments')\r
-       })\r
-\r
-       await test('sweeper fails gracefully for ineligible accounts', { skip: true }, 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.equal(results.length, 1)\r
-\r
-               await wallet.destroy()\r
-       })\r
-})\r
+await Promise.all([\r
+       suite('unit conversion tests', async () => {\r
+\r
+               await test('should convert nano to raw', async () => {\r
+                       const result = await Tools.convert('1', 'NANO', 'RAW')\r
+                       assert.equal(result, '1000000000000000000000000000000')\r
+               })\r
+\r
+               await test('should convert raw to nano', async () => {\r
+                       const result = await Tools.convert('1000000000000000000000000000000', 'RAW', 'NANO')\r
+                       assert.equal(result, '1')\r
+               })\r
+\r
+               await test('should convert 1 raw to 10^-29 nano', async () => {\r
+                       const result = await Tools.convert('1', 'RAW', 'NANO')\r
+                       assert.equal(result, '.000000000000000000000000000001')\r
+               })\r
+\r
+               await test('should ignore leading and trailing zeros', async () => {\r
+                       const result = await Tools.convert('0011002200.0033004400', 'nano', 'nano')\r
+                       assert.equal(result, '11002200.00330044')\r
+               })\r
+\r
+               await test('should convert raw to nyano', async () => {\r
+                       const result = await Tools.convert(RAW_MAX, 'RAW', 'NYANO')\r
+                       assert.equal(result, '340282366920938.463463374607431768211455')\r
+               })\r
+\r
+               await test('should convert case-insensitive nyano to raw', async () => {\r
+                       const result = await Tools.convert('0.000000000000000123456789', 'nYaNo', 'rAw')\r
+                       assert.equal(result, '123456789')\r
+               })\r
+\r
+               await test('should convert nano to pico', async () => {\r
+                       const result = await Tools.convert('123.456', 'nano', 'pico')\r
+                       assert.equal(result, '123456')\r
+               })\r
+\r
+               await test('should convert knano to pico', async () => {\r
+                       const result = await Tools.convert('123.456', 'nano', 'pico')\r
+                       assert.equal(result, '123456')\r
+               })\r
+\r
+               await test('should throw if amount exceeds raw max', async () => {\r
+                       await assert.rejects(Tools.convert(RAW_MAX, 'NANO', 'RAW'),\r
+                               { message: 'Amount exceeds Nano limits' })\r
+               })\r
+\r
+               await test('should throw if amount exceeds raw min', async () => {\r
+                       await assert.rejects(Tools.convert('0.1', 'RAW', 'NANO'),\r
+                               { message: 'Amount must be at least 1 raw' })\r
+               })\r
+\r
+               await test('should throw if amount is blank', async () => {\r
+                       await assert.rejects(Tools.convert('', 'RAW', 'NANO'),\r
+                               { message: 'Invalid amount' })\r
+               })\r
+\r
+               await test('should throw if amount has non-digit characters', async () => {\r
+                       await assert.rejects(Tools.convert('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'RAW', 'NANO'),\r
+                               { message: 'Invalid amount' })\r
+               })\r
+       }),\r
+\r
+       suite('signature tests', async () => {\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.equal(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.equal(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.equal(result, true)\r
+\r
+                       const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi')\r
+                       assert.equal(result2, false)\r
+\r
+                       const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi')\r
+                       assert.equal(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 account = await wallet.account()\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\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(privateKey)\r
+                       const valid = await sendBlock.verify(account.publicKey)\r
+                       assert.equal(valid, true)\r
+\r
+                       await wallet.destroy()\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 account = await wallet.account()\r
+                       const privateKey = await account.export(wallet.seed, 'hex')\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(privateKey)\r
+\r
+                       sendBlock.account = Account.import('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p')\r
+                       const valid = await sendBlock.verify(account.publicKey)\r
+                       assert.equal(valid, false)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+\r
+               await test('sweeper throws without required parameters', async () => {\r
+                       await assert.rejects(Tools.sweep(),\r
+                               'Missing required sweep arguments')\r
+               })\r
+\r
+               await test('sweeper fails gracefully for ineligible accounts', { skip: true }, 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.equal(results.length, 1)\r
+\r
+                       await wallet.destroy()\r
+               })\r
+       })\r
+])\r