From: Chris Duncan Date: Mon, 21 Jul 2025 20:05:40 +0000 (-0700) Subject: Fix test suites to work with Node test runner by collecting all promises at once... X-Git-Tag: v0.10.5~55^2~42 X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=5921a5c2b48cc068d0629a269fdb05865f15b8bb;p=libnemo.git Fix test suites to work with Node test runner by collecting all promises at once per file. --- diff --git a/test/perf.account.js b/test/perf.account.js index 1e1b948..a0c5262 100644 --- a/test/perf.account.js +++ b/test/perf.account.js @@ -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)) + }) }) -}) +]) diff --git a/test/perf.block.js b/test/perf.block.js index 20b8350..9d12c32 100644 --- a/test/perf.block.js +++ b/test/perf.block.js @@ -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)) + }) }) -}) +]) diff --git a/test/perf.wallet.js b/test/perf.wallet.js index b58adc7..f0817df 100644 --- a/test/perf.wallet.js +++ b/test/perf.wallet.js @@ -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)) + }) }) -}) +]) diff --git a/test/test.blake2b.mjs b/test/test.blake2b.mjs index 220610d..4f89e47 100644 --- a/test/test.blake2b.mjs +++ b/test/test.blake2b.mjs @@ -7,85 +7,87 @@ import { assert, suite, test } from './GLOBALS.mjs' import { BLAKE2B_TEST_VECTORS } from './VECTORS.js' import { Blake2b } from '../dist/main.min.js' -await suite('BLAKE2b test vectors', async () => { +await Promise.all([ + suite('BLAKE2b test vectors', async () => { - await test('check 512 reference test vectors', async () => { - for (let i = 0; i < BLAKE2B_TEST_VECTORS.REFERENCE.length; i++) { - const test = BLAKE2B_TEST_VECTORS.REFERENCE[i] - if (test.in.length % 2 === 1) test.in = `0${test.in}` - const input = Uint8Array.from(test.in - .split(/(.{2})/) - .filter(v => v.length > 0) - .map(v => parseInt(v, 16)) - ) - let key - if (test.key.length > 0) { - if (test.key.length % 2 === 1) { - test.key = `0${test.key}` - } - key = Uint8Array.from(test.key + await test('check 512 reference test vectors', async () => { + for (let i = 0; i < BLAKE2B_TEST_VECTORS.REFERENCE.length; i++) { + const test = BLAKE2B_TEST_VECTORS.REFERENCE[i] + if (test.in.length % 2 === 1) test.in = `0${test.in}` + const input = Uint8Array.from(test.in .split(/(.{2})/) .filter(v => v.length > 0) .map(v => parseInt(v, 16)) ) + let key + if (test.key.length > 0) { + if (test.key.length % 2 === 1) { + test.key = `0${test.key}` + } + key = Uint8Array.from(test.key + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + try { + const output = new Blake2b(64, key).update(input).digest('hex') + assert.equal(output, test.out) + } catch (err) { + console.error(`blake2b reference test vector ${i} failed`, { cause: err }) + } } - try { - const output = new Blake2b(64, key).update(input).digest('hex') - assert.equal(output, test.out) - } catch (err) { - console.error(`blake2b reference test vector ${i} failed`, { cause: err }) - } - } - }) + }) - await test('check 64 libsodium test vectors', async () => { - for (let i = 0; i < BLAKE2B_TEST_VECTORS.LIBSODIUM.length; i++) { - const test = BLAKE2B_TEST_VECTORS.LIBSODIUM[i] - if (test.in.length % 2 === 1) test.in = `0${test.in}` - const input = Uint8Array.from(test.in - .split(/(.{2})/) - .filter(v => v.length > 0) - .map(v => parseInt(v, 16)) - ) - let key - if (test.key.length > 0) { - if (test.key.length % 2 === 1) { - test.key = `0${test.key}` - } - key = Uint8Array.from(test.key + await test('check 64 libsodium test vectors', async () => { + for (let i = 0; i < BLAKE2B_TEST_VECTORS.LIBSODIUM.length; i++) { + const test = BLAKE2B_TEST_VECTORS.LIBSODIUM[i] + if (test.in.length % 2 === 1) test.in = `0${test.in}` + const input = Uint8Array.from(test.in .split(/(.{2})/) .filter(v => v.length > 0) .map(v => parseInt(v, 16)) ) - } - let salt - if (test.salt && test.salt.length > 0) { - if (test.salt.length % 2 === 1) { - test.salt = `0${test.salt}` + let key + if (test.key.length > 0) { + if (test.key.length % 2 === 1) { + test.key = `0${test.key}` + } + key = Uint8Array.from(test.key + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) } - salt = Uint8Array.from(test.salt - .split(/(.{2})/) - .filter(v => v.length > 0) - .map(v => parseInt(v, 16)) - ) - } - let personal - if (test.personal && test.personal.length > 0) { - if (test.personal.length % 2 === 1) { - test.personal = `0${test.personal}` + let salt + if (test.salt && test.salt.length > 0) { + if (test.salt.length % 2 === 1) { + test.salt = `0${test.salt}` + } + salt = Uint8Array.from(test.salt + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + let personal + if (test.personal && test.personal.length > 0) { + if (test.personal.length % 2 === 1) { + test.personal = `0${test.personal}` + } + personal = Uint8Array.from(test.personal + .split(/(.{2})/) + .filter(v => v.length > 0) + .map(v => parseInt(v, 16)) + ) + } + try { + const output = new Blake2b(test.outlen ?? 64, key, salt, personal).update(input).digest('hex') + assert.equal(output, test.out) + } catch (err) { + console.error(`blake2b libsodium test vector ${i} failed`, { cause: err }) } - personal = Uint8Array.from(test.personal - .split(/(.{2})/) - .filter(v => v.length > 0) - .map(v => parseInt(v, 16)) - ) - } - try { - const output = new Blake2b(test.outlen ?? 64, key, salt, personal).update(input).digest('hex') - assert.equal(output, test.out) - } catch (err) { - console.error(`blake2b libsodium test vector ${i} failed`, { cause: err }) } - } + }) }) -}) +]) diff --git a/test/test.blocks.mjs b/test/test.blocks.mjs index 53fc076..91f8d77 100644 --- a/test/test.blocks.mjs +++ b/test/test.blocks.mjs @@ -7,159 +7,161 @@ import { assert, suite, test } from './GLOBALS.mjs' import { NANO_TEST_VECTORS } from './VECTORS.js' import { SendBlock, ReceiveBlock, ChangeBlock } from '../dist/main.min.js' -await suite('Block format', async () => { +await Promise.all([ + suite('Block format', async () => { - await test('throw on negative balances', async () => { - assert.throws(() => { - new SendBlock( + await test('throw on negative balances', async () => { + assert.throws(() => { + new SendBlock( + NANO_TEST_VECTORS.ADDRESS_0, + '7000000000000000000000000000000', + NANO_TEST_VECTORS.ADDRESS_1, + '12000000000000000000000000000000', + NANO_TEST_VECTORS.ADDRESS_2, + '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' + ) + }, { message: 'Negative balance' }) + }) + + await test('allow zero balances', async () => { + const block = new SendBlock( NANO_TEST_VECTORS.ADDRESS_0, - '7000000000000000000000000000000', + '9007199254740991', NANO_TEST_VECTORS.ADDRESS_1, - '12000000000000000000000000000000', + '9007199254740991', NANO_TEST_VECTORS.ADDRESS_2, '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' ) - }, { message: 'Negative balance' }) - }) - - await test('allow zero balances', async () => { - const block = new SendBlock( - NANO_TEST_VECTORS.ADDRESS_0, - '9007199254740991', - NANO_TEST_VECTORS.ADDRESS_1, - '9007199254740991', - NANO_TEST_VECTORS.ADDRESS_2, - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' - ) - assert.notEqual(block.balance, 0) - assert.equal(block.balance, BigInt(0)) - }) + assert.notEqual(block.balance, 0) + assert.equal(block.balance, BigInt(0)) + }) - await test('subtract balance from SendBlock correctly', async () => { - const block = new SendBlock( - NANO_TEST_VECTORS.ADDRESS_0, - '3000000000000000000000000000000', - NANO_TEST_VECTORS.ADDRESS_1, - '2000000000000000000000000000000', - NANO_TEST_VECTORS.ADDRESS_2, - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' - ) - assert.equal(block.balance, 1000000000000000000000000000000n) - }) + await test('subtract balance from SendBlock correctly', async () => { + const block = new SendBlock( + NANO_TEST_VECTORS.ADDRESS_0, + '3000000000000000000000000000000', + NANO_TEST_VECTORS.ADDRESS_1, + '2000000000000000000000000000000', + NANO_TEST_VECTORS.ADDRESS_2, + '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' + ) + assert.equal(block.balance, 1000000000000000000000000000000n) + }) - await test('add balance from ReceiveBlock correctly', async () => { - const block = new ReceiveBlock( - NANO_TEST_VECTORS.ADDRESS_0, - '2000000000000000000000000000000', - NANO_TEST_VECTORS.ADDRESS_1, - '1000000000000000000000000000000', - NANO_TEST_VECTORS.ADDRESS_2, - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' - ) - assert.equal(block.balance, 3000000000000000000000000000000n) - }) -}) + await test('add balance from ReceiveBlock correctly', async () => { + const block = new ReceiveBlock( + NANO_TEST_VECTORS.ADDRESS_0, + '2000000000000000000000000000000', + NANO_TEST_VECTORS.ADDRESS_1, + '1000000000000000000000000000000', + NANO_TEST_VECTORS.ADDRESS_2, + '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D' + ) + assert.equal(block.balance, 3000000000000000000000000000000n) + }) + }), -await suite('Block signing using official test vectors', async () => { + suite('Block signing using official test vectors', async () => { - await test('sign open block', async () => { - const block = new ReceiveBlock( - NANO_TEST_VECTORS.OPEN_BLOCK.account, - '0', - NANO_TEST_VECTORS.OPEN_BLOCK.link, - NANO_TEST_VECTORS.OPEN_BLOCK.balance, - NANO_TEST_VECTORS.OPEN_BLOCK.representative, - NANO_TEST_VECTORS.OPEN_BLOCK.previous, - NANO_TEST_VECTORS.OPEN_BLOCK.work - ) - await block.sign(NANO_TEST_VECTORS.OPEN_BLOCK.key) - assert.equal(block.hash, NANO_TEST_VECTORS.OPEN_BLOCK.hash) - assert.equal(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature) - }) + await test('sign open block', async () => { + const block = new ReceiveBlock( + NANO_TEST_VECTORS.OPEN_BLOCK.account, + '0', + NANO_TEST_VECTORS.OPEN_BLOCK.link, + NANO_TEST_VECTORS.OPEN_BLOCK.balance, + NANO_TEST_VECTORS.OPEN_BLOCK.representative, + NANO_TEST_VECTORS.OPEN_BLOCK.previous, + NANO_TEST_VECTORS.OPEN_BLOCK.work + ) + await block.sign(NANO_TEST_VECTORS.OPEN_BLOCK.key) + assert.equal(block.hash, NANO_TEST_VECTORS.OPEN_BLOCK.hash) + assert.equal(block.signature, NANO_TEST_VECTORS.OPEN_BLOCK.signature) + }) - await test('sign receive block', async () => { - const block = new ReceiveBlock( - NANO_TEST_VECTORS.RECEIVE_BLOCK.account, - NANO_TEST_VECTORS.RECEIVE_BLOCK.balance, - NANO_TEST_VECTORS.RECEIVE_BLOCK.link, - '0', - NANO_TEST_VECTORS.RECEIVE_BLOCK.representative, - NANO_TEST_VECTORS.RECEIVE_BLOCK.previous, - NANO_TEST_VECTORS.RECEIVE_BLOCK.work - ) - await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key) - assert.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) - assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature) - }) + await test('sign receive block', async () => { + const block = new ReceiveBlock( + NANO_TEST_VECTORS.RECEIVE_BLOCK.account, + NANO_TEST_VECTORS.RECEIVE_BLOCK.balance, + NANO_TEST_VECTORS.RECEIVE_BLOCK.link, + '0', + NANO_TEST_VECTORS.RECEIVE_BLOCK.representative, + NANO_TEST_VECTORS.RECEIVE_BLOCK.previous, + NANO_TEST_VECTORS.RECEIVE_BLOCK.work + ) + await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key) + assert.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) + assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature) + }) - await test('sign receive block without work', async () => { - const block = new ReceiveBlock( - NANO_TEST_VECTORS.RECEIVE_BLOCK.account, - NANO_TEST_VECTORS.RECEIVE_BLOCK.balance, - NANO_TEST_VECTORS.RECEIVE_BLOCK.link, - '0', - NANO_TEST_VECTORS.RECEIVE_BLOCK.representative, - NANO_TEST_VECTORS.RECEIVE_BLOCK.previous - ) - await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key) - assert.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) - assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature) - assert.equal(block.work, '') - }) + await test('sign receive block without work', async () => { + const block = new ReceiveBlock( + NANO_TEST_VECTORS.RECEIVE_BLOCK.account, + NANO_TEST_VECTORS.RECEIVE_BLOCK.balance, + NANO_TEST_VECTORS.RECEIVE_BLOCK.link, + '0', + NANO_TEST_VECTORS.RECEIVE_BLOCK.representative, + NANO_TEST_VECTORS.RECEIVE_BLOCK.previous + ) + await block.sign(NANO_TEST_VECTORS.RECEIVE_BLOCK.key) + assert.equal(block.hash, NANO_TEST_VECTORS.RECEIVE_BLOCK.hash) + assert.equal(block.signature, NANO_TEST_VECTORS.RECEIVE_BLOCK.signature) + assert.equal(block.work, '') + }) - await test('sign send block', async () => { - 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, - NANO_TEST_VECTORS.SEND_BLOCK.work - ) - await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key) - assert.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash) - assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature) - }) + await test('sign send block', async () => { + 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, + NANO_TEST_VECTORS.SEND_BLOCK.work + ) + await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key) + assert.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash) + assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature) + }) - await test('sign send block without work', async () => { - 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 - ) - await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key) - assert.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash) - assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature) - assert.equal(block.work, '') - }) + await test('sign send block without work', async () => { + 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 + ) + await block.sign(NANO_TEST_VECTORS.SEND_BLOCK.key) + assert.equal(block.hash, NANO_TEST_VECTORS.SEND_BLOCK.hash) + assert.equal(block.signature, NANO_TEST_VECTORS.SEND_BLOCK.signature) + assert.equal(block.work, '') + }) - await test('sign change rep block', async () => { - const work = '0000000000000000' - const block = new ChangeBlock( - 'nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php', - '3000000000000000000000000000000', - 'nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs', - '128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4', - work, - ) - await block.sign('781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3') // Did not find a private key at nano docs for this address - assert.equal(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D') - assert.equal(block.work, work) - }) + await test('sign change rep block', async () => { + const work = '0000000000000000' + const block = new ChangeBlock( + 'nano_3igf8hd4sjshoibbbkeitmgkp1o6ug4xads43j6e4gqkj5xk5o83j8ja9php', + '3000000000000000000000000000000', + 'nano_1anrzcuwe64rwxzcco8dkhpyxpi8kd7zsjc1oeimpc3ppca4mrjtwnqposrs', + '128106287002E595F479ACD615C818117FCB3860EC112670557A2467386249D4', + work, + ) + await block.sign('781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3') // Did not find a private key at nano docs for this address + assert.equal(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D') + assert.equal(block.work, work) + }) - await test('sign change rep block without work', async () => { - const block = new ChangeBlock( - NANO_TEST_VECTORS.ADDRESS_0, - '0', - 'nano_34amtofxstsfyqcgphp8piij9u33widykq9wbz6ysjpxhbgmqu8btu1eexer', - 'F3C1D7B6EE97DA09D4C00538CEA93CBA5F74D78FD3FBE71347D2DFE7E53DF327' - ) - await block.sign(NANO_TEST_VECTORS.PRIVATE_0) - assert.equal(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305') - assert.equal(block.work, '') + await test('sign change rep block without work', async () => { + const block = new ChangeBlock( + NANO_TEST_VECTORS.ADDRESS_0, + '0', + 'nano_34amtofxstsfyqcgphp8piij9u33widykq9wbz6ysjpxhbgmqu8btu1eexer', + 'F3C1D7B6EE97DA09D4C00538CEA93CBA5F74D78FD3FBE71347D2DFE7E53DF327' + ) + await block.sign(NANO_TEST_VECTORS.PRIVATE_0) + assert.equal(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305') + assert.equal(block.work, '') + }) }) -}) +]) diff --git a/test/test.calculate-pow.mjs b/test/test.calculate-pow.mjs index 29b6bdb..bff769b 100644 --- a/test/test.calculate-pow.mjs +++ b/test/test.calculate-pow.mjs @@ -7,41 +7,43 @@ import { assert, isNode, suite, test } from './GLOBALS.mjs' import { NANO_TEST_VECTORS } from './VECTORS.js' import { SendBlock, Blake2b } from '../dist/main.min.js' -await suite('Calculate proof-of-work', { skip: isNode }, async () => { - - await test('SendBlock PoW', async () => { - 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 - ) - await block.pow() - - assert.equal(block.previous.length, 64) - assert.equal(block.work?.length, 16) - - const work = block.work - ?.match(/.{2}/g) - ?.map(hex => parseInt(hex, 16)) - .reverse() - if (work == null) throw new Error('Work invalid') - const previous = block.previous - ?.match(/.{2}/g) - ?.map(hex => parseInt(hex, 16)) - if (previous == null) throw new Error('Previous block hash invalid') - - const bytes = new Uint8Array([...work, ...previous]) - assert.equal(bytes.byteLength, 40) - - const hash = new Blake2b(8) - .update(bytes) - .digest('hex') - .slice(8, 16) - - assert.ok(parseInt(hash.slice(0, 2), 16) > 0xf0) - assert.equal(parseInt(hash.slice(2, 8), 16), 0xffffff) +await Promise.all([ + suite('Calculate proof-of-work', { skip: isNode }, async () => { + + await test('SendBlock PoW', async () => { + 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 + ) + await block.pow() + + assert.equal(block.previous.length, 64) + assert.equal(block.work?.length, 16) + + const work = block.work + ?.match(/.{2}/g) + ?.map(hex => parseInt(hex, 16)) + .reverse() + if (work == null) throw new Error('Work invalid') + const previous = block.previous + ?.match(/.{2}/g) + ?.map(hex => parseInt(hex, 16)) + if (previous == null) throw new Error('Previous block hash invalid') + + const bytes = new Uint8Array([...work, ...previous]) + assert.equal(bytes.byteLength, 40) + + const hash = new Blake2b(8) + .update(bytes) + .digest('hex') + .slice(8, 16) + + assert.ok(parseInt(hash.slice(0, 2), 16) > 0xf0) + assert.equal(parseInt(hash.slice(2, 8), 16), 0xffffff) + }) }) -}) +]) diff --git a/test/test.create-wallet.mjs b/test/test.create-wallet.mjs index 2253f0c..6209492 100644 --- a/test/test.create-wallet.mjs +++ b/test/test.create-wallet.mjs @@ -7,52 +7,54 @@ import { assert, suite, test } from './GLOBALS.mjs' import { NANO_TEST_VECTORS } from './VECTORS.js' import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' -await suite('Create wallets', async () => { - - await test('BIP-44 wallet with random entropy', async () => { - const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - assert.ok('id' in wallet) - assert.ok(/^libnemo_[A-Fa-f0-9]{32,64}$/.test(wallet.id)) - assert.ok('mnemonic' in wallet) - assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)) - assert.ok('seed' in wallet) - assert.ok(/^[A-Fa-f0-9]{128}$/.test(wallet.seed)) - - await wallet.destroy() - }) - - await test('BLAKE2b wallet with random entropy', async () => { - const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - assert.ok('id' in wallet) - assert.ok(/^libnemo_[A-Fa-f0-9]{32,64}$/.test(wallet.id)) - assert.ok('mnemonic' in wallet) - assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)) - assert.ok('seed' in wallet) - assert.ok(/^[A-Fa-f0-9]{64}$/.test(wallet.seed)) - - await wallet.destroy() - }) - - await test('BIP-44 replace invalid salt with empty string', async () => { - const invalidArgs = [null, true, false, 0, 1, 2, { foo: 'bar' }] - for (const arg of invalidArgs) { - const wallet = Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg) - await assert.resolves(wallet); - (await wallet).destroy() - } - }) - - await test('fail when using new', async () => { - assert.throws(() => new Bip44Wallet()) - assert.throws(() => new Blake2bWallet()) - }) - - await test('fail without a password', async () => { - await assert.rejects(Bip44Wallet.create()) - await assert.rejects(Blake2bWallet.create()) +await Promise.all([ + suite('Create wallets', async () => { + + await test('BIP-44 wallet with random entropy', async () => { + const wallet = await Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + assert.ok('id' in wallet) + assert.ok(/^libnemo_[A-Fa-f0-9]{32,64}$/.test(wallet.id)) + assert.ok('mnemonic' in wallet) + assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)) + assert.ok('seed' in wallet) + assert.ok(/^[A-Fa-f0-9]{128}$/.test(wallet.seed)) + + await wallet.destroy() + }) + + await test('BLAKE2b wallet with random entropy', async () => { + const wallet = await Blake2bWallet.create(NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + assert.ok('id' in wallet) + assert.ok(/^libnemo_[A-Fa-f0-9]{32,64}$/.test(wallet.id)) + assert.ok('mnemonic' in wallet) + assert.ok(/^(?:[a-z]{3,} ){11,23}[a-z]{3,}$/.test(wallet.mnemonic)) + assert.ok('seed' in wallet) + assert.ok(/^[A-Fa-f0-9]{64}$/.test(wallet.seed)) + + await wallet.destroy() + }) + + await test('BIP-44 replace invalid salt with empty string', async () => { + const invalidArgs = [null, true, false, 0, 1, 2, { foo: 'bar' }] + for (const arg of invalidArgs) { + const wallet = Bip44Wallet.create(NANO_TEST_VECTORS.PASSWORD, arg) + await assert.resolves(wallet); + (await wallet).destroy() + } + }) + + await test('fail when using new', async () => { + assert.throws(() => new Bip44Wallet()) + assert.throws(() => new Blake2bWallet()) + }) + + await test('fail without a password', async () => { + await assert.rejects(Bip44Wallet.create()) + await assert.rejects(Blake2bWallet.create()) + }) }) -}) +]) diff --git a/test/test.derive-accounts.mjs b/test/test.derive-accounts.mjs index e287265..2cbf6ae 100644 --- a/test/test.derive-accounts.mjs +++ b/test/test.derive-accounts.mjs @@ -7,122 +7,124 @@ import { assert, suite, test } from './GLOBALS.mjs' import { NANO_TEST_VECTORS } from './VECTORS.js' import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' -await suite('Derive accounts from BIP-44 wallet', async () => { - - await test('derive the first account from the given BIP-44 seed', 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() - const privateKey = await account.export(wallet.seed, 'hex') - - assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) - assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) - assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0) - assert.equal(account.index, 0) - - const accounts = await wallet.accounts() - assert.exists(accounts[0]) - assert.equal(account, accounts[0]) - - await wallet.destroy() - }) - - await test('derive low indexed accounts from the given BIP-44 seed', async () => { - const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(1, 2) - const privateKey1 = await accounts[1].export(wallet.seed, 'hex') - const privateKey2 = await accounts[2].export(wallet.seed, 'hex') - - assert.equal(accounts.length, 2) - assert.equal(privateKey1, NANO_TEST_VECTORS.PRIVATE_1) - assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_1) - assert.equal(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_1) - assert.equal(accounts[1].index, 1) - assert.equal(privateKey2, NANO_TEST_VECTORS.PRIVATE_2) - assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.PUBLIC_2) - assert.equal(accounts[2].address, NANO_TEST_VECTORS.ADDRESS_2) - assert.equal(accounts[2].index, 2) - - await wallet.destroy() - }) - - await test('derive high indexed accounts from the given seed', async () => { - const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(0x70000000, 0x7000000f) - - assert.equal(accounts.length, 0x10) - for (let i = 0x70000000; i < 0x7000000f; i++) { - const a = accounts[i] - assert.exists(a) - assert.equal(a.index, i) - assert.exists(a.address) - assert.exists(a.publicKey) - const privateKey = await a.export(wallet.seed, 'hex') - assert.exists(privateKey) - } - - await wallet.destroy() - }) -}) - -await suite('Derive accounts from BLAKE2b wallet', async () => { - - await test('derive the second account from the given BLAKE2b seed', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account(1) - const privateKey = await account.export(wallet.seed, 'hex') - - assert.equal(privateKey, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1) - // assert.equal(account.publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_0) - // assert.equal(account.address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_0) - assert.equal(account.index, 1) - - const accounts = await wallet.accounts(1) - assert.exists(accounts[1]) - assert.equal(account, accounts[1]) - - await wallet.destroy() - }) - - await test('derive low indexed accounts from the given BLAKE2B seed', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(1, 2) - // const privateKey1 = await accounts[1].export(wallet.seed, 'hex') - // const privateKey2 = await accounts[2].export(wallet.seed, 'hex') - - assert.equal(accounts.length, 2) - // assert.equal(privateKey1, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1) - // assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_1) - // assert.equal(accounts[1].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_1) - assert.equal(accounts[1].index, 1) - // assert.equal(privateKey2, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_2) - // assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_2) - // assert.equal(accounts[2].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_2) - assert.equal(accounts[2].index, 2) - - await wallet.destroy() - }) - - await test('derive high indexed accounts from the given seed', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(0x70000000, 0x7000000f) - - assert.equal(accounts.length, 0x10) - for (let i = 0x70000000; i < 0x7000000f; i++) { - const a = accounts[i] - assert.exists(a) - assert.equal(a.index, i) - assert.exists(a.address) - assert.exists(a.publicKey) - const privateKey = await a.export(wallet.seed, 'hex') - assert.exists(privateKey) - } - - await wallet.destroy() +await Promise.all([ + suite('Derive accounts from BIP-44 wallet', async () => { + + await test('derive the first account from the given BIP-44 seed', 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() + const privateKey = await account.export(wallet.seed, 'hex') + + assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) + assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) + assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0) + assert.equal(account.index, 0) + + const accounts = await wallet.accounts() + assert.exists(accounts[0]) + assert.equal(account, accounts[0]) + + await wallet.destroy() + }) + + await test('derive low indexed accounts from the given BIP-44 seed', async () => { + const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(1, 2) + const privateKey1 = await accounts[1].export(wallet.seed, 'hex') + const privateKey2 = await accounts[2].export(wallet.seed, 'hex') + + assert.equal(accounts.length, 2) + assert.equal(privateKey1, NANO_TEST_VECTORS.PRIVATE_1) + assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.PUBLIC_1) + assert.equal(accounts[1].address, NANO_TEST_VECTORS.ADDRESS_1) + assert.equal(accounts[1].index, 1) + assert.equal(privateKey2, NANO_TEST_VECTORS.PRIVATE_2) + assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.PUBLIC_2) + assert.equal(accounts[2].address, NANO_TEST_VECTORS.ADDRESS_2) + assert.equal(accounts[2].index, 2) + + await wallet.destroy() + }) + + await test('derive high indexed accounts from the given seed', async () => { + const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(0x70000000, 0x7000000f) + + assert.equal(accounts.length, 0x10) + for (let i = 0x70000000; i < 0x7000000f; i++) { + const a = accounts[i] + assert.exists(a) + assert.equal(a.index, i) + assert.exists(a.address) + assert.exists(a.publicKey) + const privateKey = await a.export(wallet.seed, 'hex') + assert.exists(privateKey) + } + + await wallet.destroy() + }) + }), + + suite('Derive accounts from BLAKE2b wallet', async () => { + + await test('derive the second account from the given BLAKE2b seed', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account(1) + const privateKey = await account.export(wallet.seed, 'hex') + + assert.equal(privateKey, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1) + // assert.equal(account.publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_0) + // assert.equal(account.address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_0) + assert.equal(account.index, 1) + + const accounts = await wallet.accounts(1) + assert.exists(accounts[1]) + assert.equal(account, accounts[1]) + + await wallet.destroy() + }) + + await test('derive low indexed accounts from the given BLAKE2B seed', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(1, 2) + // const privateKey1 = await accounts[1].export(wallet.seed, 'hex') + // const privateKey2 = await accounts[2].export(wallet.seed, 'hex') + + assert.equal(accounts.length, 2) + // assert.equal(privateKey1, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_1) + // assert.equal(accounts[1].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_1) + // assert.equal(accounts[1].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_1) + assert.equal(accounts[1].index, 1) + // assert.equal(privateKey2, NANO_TEST_VECTORS.BLAKE2B_PRIVATE_2) + // assert.equal(accounts[2].publicKey, NANO_TEST_VECTORS.BLAKE2B_PUBLIC_2) + // assert.equal(accounts[2].address, NANO_TEST_VECTORS.BLAKE2B_ADDRESS_2) + assert.equal(accounts[2].index, 2) + + await wallet.destroy() + }) + + await test('derive high indexed accounts from the given seed', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BLAKE2B_SEED) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(0x70000000, 0x7000000f) + + assert.equal(accounts.length, 0x10) + for (let i = 0x70000000; i < 0x7000000f; i++) { + const a = accounts[i] + assert.exists(a) + assert.equal(a.index, i) + assert.exists(a.address) + assert.exists(a.publicKey) + const privateKey = await a.export(wallet.seed, 'hex') + assert.exists(privateKey) + } + + await wallet.destroy() + }) }) -}) +]) diff --git a/test/test.import-wallet.mjs b/test/test.import-wallet.mjs index 80cb5b2..3c1cd1c 100644 --- a/test/test.import-wallet.mjs +++ b/test/test.import-wallet.mjs @@ -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' import { Account, Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' -await suite('Import wallets', async () => { - - await test('nano.org BIP-44 test vector mnemonic', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.ok(account instanceof Account) - assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) - assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) - - await wallet.destroy() - }) - - await test('nano.org BIP-44 test vector seed with no mnemonic', 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() - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.ok(account instanceof Account) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) - assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) - - await wallet.destroy() - }) - - await test('Trezor-derived BIP-44 entropy for 12-word mnemonic', async () => { - const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_0) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - - assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0) - assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0) - assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0) - assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0) - - await wallet.destroy() - }) - - await test('Trezor-derived BIP-44 entropy for 15-word mnemonic', async () => { - const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_1) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - - assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1) - assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1) - assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1) - assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1) - - await wallet.destroy() - }) - - await test('Trezor-derived BIP-44 entropy for 18-word mnemonic', async () => { - const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_2) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - - assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2) - assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2) - assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2) - assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2) - - await wallet.destroy() - }) - - await test('Trezor-derived BIP-44 entropy for 21-word mnemonic', async () => { - const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_3) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - - assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3) - assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3) - assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3) - assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3) - - await wallet.destroy() - }) - - await test('BIP-44 zero-string entropy', async () => { - const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0, TREZOR_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(0, 3) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase()) - assert.equal(accounts.length, 4) - - for (let i = 0; i < accounts.length; i++) { - assert.exists(accounts[i]) - assert.exists(accounts[i].address) - assert.exists(accounts[i].publicKey) - const privateKey = await accounts[i].export(wallet.seed, 'hex') - assert.exists(privateKey) - } - - await wallet.destroy() - }) - - await test('BLAKE2b zero-string seed', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(0, 3) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) - assert.equal(accounts.length, 4) - - for (let i = 0; i < accounts.length; i++) { - assert.exists(accounts[i]) - assert.exists(accounts[i].address) - assert.exists(accounts[i].publicKey) - const privateKey = await accounts[i].export(wallet.seed, 'hex') - assert.exists(privateKey) - } - - await wallet.destroy() - }) - - await test('Trezor-derived BLAKE2b test vectors verified with third-party libraries', async () => { - const wallet = await Blake2bWallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_1) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const accounts = await wallet.accounts(0, 1) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - assert.ok(accounts[0] instanceof Account) - assert.equal(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0) - assert.equal(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0) - const privateKey0 = await accounts[0].export(wallet.seed, 'hex') - assert.equal(privateKey0, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0) - - assert.ok(accounts[1] instanceof Account) - assert.equal(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1) - assert.equal(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1) - const privateKey1 = await accounts[1].export(wallet.seed, 'hex') - assert.equal(privateKey1, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1) - - await wallet.destroy() - }) - - await test('BLAKE2b seed creates identical wallet as its derived mnemonic', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_2) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const walletAccount = await wallet.account() - const walletAccountPrivateKey = await walletAccount.export(wallet.seed, 'hex') - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.exists(walletAccount) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_2) - - const imported = await Blake2bWallet.fromMnemonic(TREZOR_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_2) - await imported.unlock(TREZOR_TEST_VECTORS.PASSWORD) - const importedAccount = await imported.account() - const importedAccountPrivateKey = await importedAccount.export(imported.seed, 'hex') - - assert.equal(imported.mnemonic, wallet.mnemonic) - assert.equal(imported.seed, wallet.seed) - assert.equal(importedAccount.publicKey, walletAccount.publicKey) - assert.equal(importedAccountPrivateKey, walletAccountPrivateKey) - - await wallet.destroy() - }) - - await test('BLAKE2b mnemonic for maximum seed value', async () => { - const wallet = await Blake2bWallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_3) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.ok(account instanceof Account) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3) - assert.equal(account.publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0) - assert.equal(account.address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0) - - const privateKey = await account.export(wallet.seed, 'hex') - assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0) - - await wallet.destroy() - }) - - await test('Reject invalid entropy', async () => { - await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797')) - await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701')) - await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0.replaceAll(/./g, 'x'))) - }) - - await test('Reject invalid length seed', async () => { - await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED + 'f'), - `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length + 1}-character string.`) - await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED.slice(0, -1)), - `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length - 1}-character string.`) - }) - - await test('Reject seed containing non-hex characters', async () => { - await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')), - 'Seed contains invalid hexadecimal characters.') - await assert.rejects(Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')), - 'Seed contains invalid hexadecimal characters.') - }) - - await test('Import BIP-44 wallet from session storage using a wallet-generated ID', async () => { - const id = (await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)).id - const wallet = await Bip44Wallet.restore(id) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, '') - - const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - assert.equal(unlockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('Import BLAKE2B wallet from session storage using a wallet-generated ID', async () => { - const id = (await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)).id - const wallet = await Blake2bWallet.restore(id) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, '') - - const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - assert.equal(unlockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) - - await wallet.destroy() +await Promise.all([ + suite('Import wallets', async () => { + + await test('nano.org BIP-44 test vector mnemonic', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.ok(account instanceof Account) + assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) + assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) + + await wallet.destroy() + }) + + await test('nano.org BIP-44 test vector seed with no mnemonic', 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() + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.ok(account instanceof Account) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + assert.equal(account.publicKey, NANO_TEST_VECTORS.PUBLIC_0) + assert.equal(account.address, NANO_TEST_VECTORS.ADDRESS_0) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) + + await wallet.destroy() + }) + + await test('Trezor-derived BIP-44 entropy for 12-word mnemonic', async () => { + const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_0) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_0) + assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_0) + assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_0) + assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_0) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_0) + + await wallet.destroy() + }) + + await test('Trezor-derived BIP-44 entropy for 15-word mnemonic', async () => { + const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_1) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_1) + assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_1) + assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_1) + assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_1) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_1) + + await wallet.destroy() + }) + + await test('Trezor-derived BIP-44 entropy for 18-word mnemonic', async () => { + const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_2) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_2) + assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_2) + assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_2) + assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_2) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_2) + + await wallet.destroy() + }) + + await test('Trezor-derived BIP-44 entropy for 21-word mnemonic', async () => { + const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, CUSTOM_TEST_VECTORS.ENTROPY_3) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.equal(wallet.mnemonic, CUSTOM_TEST_VECTORS.MNEMONIC_3) + assert.equal(wallet.seed, CUSTOM_TEST_VECTORS.SEED_3) + assert.equal(account.publicKey, CUSTOM_TEST_VECTORS.PUBLIC_3) + assert.equal(account.address, CUSTOM_TEST_VECTORS.ADDRESS_3) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, CUSTOM_TEST_VECTORS.PRIVATE_3) + + await wallet.destroy() + }) + + await test('BIP-44 zero-string entropy', async () => { + const wallet = await Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0, TREZOR_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(0, 3) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.SEED_0.toUpperCase()) + assert.equal(accounts.length, 4) + + for (let i = 0; i < accounts.length; i++) { + assert.exists(accounts[i]) + assert.exists(accounts[i].address) + assert.exists(accounts[i].publicKey) + const privateKey = await accounts[i].export(wallet.seed, 'hex') + assert.exists(privateKey) + } + + await wallet.destroy() + }) + + await test('BLAKE2b zero-string seed', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(0, 3) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) + assert.equal(accounts.length, 4) + + for (let i = 0; i < accounts.length; i++) { + assert.exists(accounts[i]) + assert.exists(accounts[i].address) + assert.exists(accounts[i].publicKey) + const privateKey = await accounts[i].export(wallet.seed, 'hex') + assert.exists(privateKey) + } + + await wallet.destroy() + }) + + await test('Trezor-derived BLAKE2b test vectors verified with third-party libraries', async () => { + const wallet = await Blake2bWallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_1) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const accounts = await wallet.accounts(0, 1) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + assert.ok(accounts[0] instanceof Account) + assert.equal(accounts[0].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_0) + assert.equal(accounts[0].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_0) + const privateKey0 = await accounts[0].export(wallet.seed, 'hex') + assert.equal(privateKey0, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_0) + + assert.ok(accounts[1] instanceof Account) + assert.equal(accounts[1].publicKey, TREZOR_TEST_VECTORS.BLAKE2B_1_PUBLIC_1) + assert.equal(accounts[1].address, TREZOR_TEST_VECTORS.BLAKE2B_1_ADDRESS_1) + const privateKey1 = await accounts[1].export(wallet.seed, 'hex') + assert.equal(privateKey1, TREZOR_TEST_VECTORS.BLAKE2B_1_PRIVATE_1) + + await wallet.destroy() + }) + + await test('BLAKE2b seed creates identical wallet as its derived mnemonic', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_2) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const walletAccount = await wallet.account() + const walletAccountPrivateKey = await walletAccount.export(wallet.seed, 'hex') + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.exists(walletAccount) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_2) + + const imported = await Blake2bWallet.fromMnemonic(TREZOR_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_2) + await imported.unlock(TREZOR_TEST_VECTORS.PASSWORD) + const importedAccount = await imported.account() + const importedAccountPrivateKey = await importedAccount.export(imported.seed, 'hex') + + assert.equal(imported.mnemonic, wallet.mnemonic) + assert.equal(imported.seed, wallet.seed) + assert.equal(importedAccount.publicKey, walletAccount.publicKey) + assert.equal(importedAccountPrivateKey, walletAccountPrivateKey) + + await wallet.destroy() + }) + + await test('BLAKE2b mnemonic for maximum seed value', async () => { + const wallet = await Blake2bWallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.MNEMONIC_3) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.ok(account instanceof Account) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_3) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_3) + assert.equal(account.publicKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PUBLIC_0) + assert.equal(account.address, TREZOR_TEST_VECTORS.BLAKE2B_3_ADDRESS_0) + + const privateKey = await account.export(wallet.seed, 'hex') + assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_3_PRIVATE_0) + + await wallet.destroy() + }) + + await test('Reject invalid entropy', async () => { + await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C797')) + await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, '6CAF5A42BB8074314AAE20295975ECE663BE7AAD945A73613D193B0CC41C79701')) + await assert.rejects(Bip44Wallet.fromEntropy(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0.replaceAll(/./g, 'x'))) + }) + + await test('Reject invalid length seed', async () => { + await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED + 'f'), + `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length + 1}-character string.`) + await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED.slice(0, -1)), + `Expected a ${NANO_TEST_VECTORS.BIP39_SEED.length}-character seed, but received ${NANO_TEST_VECTORS.BIP39_SEED.length - 1}-character string.`) + }) + + await test('Reject seed containing non-hex characters', async () => { + await assert.rejects(Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.SEED_0.replace(/./, 'g')), + 'Seed contains invalid hexadecimal characters.') + await assert.rejects(Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1.replace(/./, 'g')), + 'Seed contains invalid hexadecimal characters.') + }) + + await test('Import BIP-44 wallet from session storage using a wallet-generated ID', async () => { + const id = (await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD)).id + const wallet = await Bip44Wallet.restore(id) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, '') + + const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + assert.equal(unlockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('Import BLAKE2B wallet from session storage using a wallet-generated ID', async () => { + const id = (await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0)).id + const wallet = await Blake2bWallet.restore(id) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, '') + + const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + assert.equal(unlockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) + + await wallet.destroy() + }) }) -}) +]) diff --git a/test/test.ledger.mjs b/test/test.ledger.mjs index 812dda7..aa878f5 100644 --- a/test/test.ledger.mjs +++ b/test/test.ledger.mjs @@ -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)) + }) }) -}) +]) diff --git a/test/test.lock-unlock.mjs b/test/test.lock-unlock.mjs index 9a56aba..2a9141a 100644 --- a/test/test.lock-unlock.mjs +++ b/test/test.lock-unlock.mjs @@ -7,295 +7,297 @@ import { assert, suite, test } from './GLOBALS.mjs' import { NANO_TEST_VECTORS, TREZOR_TEST_VECTORS } from './VECTORS.js' import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js' -await suite('Lock and unlock wallets', async () => { - - await test('locking and unlocking a Bip44Wallet with a password', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, '') - - const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - assert.equal(unlockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('locking and unlocking a Bip44Wallet with random bytes', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) - - const lockResult = await wallet.lock(new Uint8Array(key)) - assert.ok(lockResult) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, '') - - const unlockResult = await wallet.unlock(new Uint8Array(key)) - - assert.equal(unlockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('locking and unlocking a Bip44Wallet Account with a password', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - - assert.equal(lockResult, true) - - const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const privateKey = await account.export(wallet.seed, 'hex') - - assert.equal(unlockResult, true) - assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) - - await wallet.destroy() - }) - - await test('fail to unlock a Bip44Wallet with different passwords', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const lockResult = await wallet.lock(TREZOR_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.unlock(NANO_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' }) - assert.equal(lockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('fail to unlock a Bip44Wallet with different random bytes', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const rightKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) - const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) - const lockResult = await wallet.lock(new Uint8Array(rightKey)) - - await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' }) - assert.equal(lockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('fail to unlock a Bip44Wallet with different valid inputs', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) - - await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('fail to unlock a Bip44Wallet with no input', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.lock('password') - - await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('fail to unlock a Bip44Wallet with invalid input', async () => { - const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) - assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) - - await wallet.destroy() - }) - - await test('locking and unlocking a Blake2bWallet with a password', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0) - - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, '') - - const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - assert.equal(unlockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) - - await wallet.destroy() - }) - - await test('locking and unlocking a Blake2bWallet with random bytes', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) - const lockResult = await wallet.lock(new Uint8Array(key)) - - assert.equal(lockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.equal(wallet.seed, '') - - const unlockResult = await wallet.unlock(new Uint8Array(key)) - - assert.equal(lockResult, true) - assert.equal(unlockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.destroy() - }) - - await test('locking and unlocking a Blake2bWallet Account with a password', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const account = await wallet.account() - const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - - assert.equal(lockResult, true) - - const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const privateKey = await account.export(wallet.seed, 'hex') - - assert.equal(unlockResult, true) - assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_PRIVATE_0) - - await wallet.destroy() - }) - - await test('fail to unlock a Blake2bWallet with different passwords', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) - - await assert.rejects(wallet.unlock(TREZOR_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.destroy() - }) - - await test('fail to unlock a Blake2bWallet with different keys', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const rightKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) - const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) - const lockResult = await wallet.lock(new Uint8Array(rightKey)) - - await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' }) - assert.equal(lockResult, true) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.destroy() - }) - - await test('fail to unlock a Blake2bWallet with different valid inputs', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) - const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) - - await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.destroy() - }) - - await test('fail to unlock a Blake2bWallet with no input', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.destroy() - }) - - await test('fail to unlock a Blake2bWallet with invalid input', async () => { - const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) - assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.lock(NANO_TEST_VECTORS.PASSWORD) - - await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' }) - assert.ok('mnemonic' in wallet) - assert.ok('seed' in wallet) - assert.nullish(wallet.mnemonic) - assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) - - await wallet.destroy() +await Promise.all([ + suite('Lock and unlock wallets', async () => { + + await test('locking and unlocking a Bip44Wallet with a password', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, '') + + const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + assert.equal(unlockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('locking and unlocking a Bip44Wallet with random bytes', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) + + const lockResult = await wallet.lock(new Uint8Array(key)) + assert.ok(lockResult) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, '') + + const unlockResult = await wallet.unlock(new Uint8Array(key)) + + assert.equal(unlockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('locking and unlocking a Bip44Wallet Account with a password', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD) + + assert.equal(lockResult, true) + + const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const privateKey = await account.export(wallet.seed, 'hex') + + assert.equal(unlockResult, true) + assert.equal(privateKey, NANO_TEST_VECTORS.PRIVATE_0) + + await wallet.destroy() + }) + + await test('fail to unlock a Bip44Wallet with different passwords', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const lockResult = await wallet.lock(TREZOR_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.unlock(NANO_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' }) + assert.equal(lockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('fail to unlock a Bip44Wallet with different random bytes', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const rightKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) + const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) + const lockResult = await wallet.lock(new Uint8Array(rightKey)) + + await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' }) + assert.equal(lockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('fail to unlock a Bip44Wallet with different valid inputs', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) + + await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('fail to unlock a Bip44Wallet with no input', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.lock('password') + + await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('fail to unlock a Bip44Wallet with invalid input', async () => { + const wallet = await Bip44Wallet.fromMnemonic(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.MNEMONIC, NANO_TEST_VECTORS.PASSWORD) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, NANO_TEST_VECTORS.MNEMONIC) + assert.equal(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.lock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, NANO_TEST_VECTORS.BIP39_SEED) + + await wallet.destroy() + }) + + await test('locking and unlocking a Blake2bWallet with a password', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0) + + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, '') + + const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + assert.equal(unlockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_0) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_0) + + await wallet.destroy() + }) + + await test('locking and unlocking a Blake2bWallet with random bytes', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) + const lockResult = await wallet.lock(new Uint8Array(key)) + + assert.equal(lockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.equal(wallet.seed, '') + + const unlockResult = await wallet.unlock(new Uint8Array(key)) + + assert.equal(lockResult, true) + assert.equal(unlockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.destroy() + }) + + await test('locking and unlocking a Blake2bWallet Account with a password', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_0) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const account = await wallet.account() + const lockResult = await wallet.lock(NANO_TEST_VECTORS.PASSWORD) + + assert.equal(lockResult, true) + + const unlockResult = await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const privateKey = await account.export(wallet.seed, 'hex') + + assert.equal(unlockResult, true) + assert.equal(privateKey, TREZOR_TEST_VECTORS.BLAKE2B_PRIVATE_0) + + await wallet.destroy() + }) + + await test('fail to unlock a Blake2bWallet with different passwords', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) + + await assert.rejects(wallet.unlock(TREZOR_TEST_VECTORS.PASSWORD), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.destroy() + }) + + await test('fail to unlock a Blake2bWallet with different keys', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const rightKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) + const wrongKey = globalThis.crypto.getRandomValues(new Uint8Array(64)) + const lockResult = await wallet.lock(new Uint8Array(rightKey)) + + await assert.rejects(wallet.unlock(new Uint8Array(wrongKey)), { message: 'Failed to unlock wallet' }) + assert.equal(lockResult, true) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.destroy() + }) + + await test('fail to unlock a Blake2bWallet with different valid inputs', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) + const key = globalThis.crypto.getRandomValues(new Uint8Array(64)) + + await assert.rejects(wallet.unlock(new Uint8Array(key)), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.destroy() + }) + + await test('fail to unlock a Blake2bWallet with no input', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.lock(), { message: 'Failed to lock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.lock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.unlock(), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.destroy() + }) + + await test('fail to unlock a Blake2bWallet with invalid input', async () => { + const wallet = await Blake2bWallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, TREZOR_TEST_VECTORS.ENTROPY_1) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.lock(1), { message: 'Failed to lock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.equal(wallet.mnemonic, TREZOR_TEST_VECTORS.MNEMONIC_1) + assert.equal(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.lock(NANO_TEST_VECTORS.PASSWORD) + + await assert.rejects(wallet.unlock(1), { message: 'Failed to unlock wallet' }) + assert.ok('mnemonic' in wallet) + assert.ok('seed' in wallet) + assert.nullish(wallet.mnemonic) + assert.notEqual(wallet.seed, TREZOR_TEST_VECTORS.ENTROPY_1) + + await wallet.destroy() + }) }) -}) +]) diff --git a/test/test.manage-rolodex.mjs b/test/test.manage-rolodex.mjs index b05394b..31a09be 100644 --- a/test/test.manage-rolodex.mjs +++ b/test/test.manage-rolodex.mjs @@ -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) + }) }) -}) +]) diff --git a/test/test.refresh-accounts.mjs b/test/test.refresh-accounts.mjs index 409a077..8bdeff9 100644 --- a/test/test.refresh-accounts.mjs +++ b/test/test.refresh-accounts.mjs @@ -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() + }) }) -}) +]) diff --git a/test/test.runner-check.mjs b/test/test.runner-check.mjs index 1f2bd9e..1c731f4 100644 --- a/test/test.runner-check.mjs +++ b/test/test.runner-check.mjs @@ -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') } diff --git a/test/test.tools.mjs b/test/test.tools.mjs index e5a4599..1bd91ce 100644 --- a/test/test.tools.mjs +++ b/test/test.tools.mjs @@ -9,146 +9,148 @@ import { Bip44Wallet, Account, SendBlock, Rpc, Tools } from '../dist/main.min.js const rpc = new Rpc(env?.NODE_URL ?? '', env?.API_KEY_NAME) -await suite('unit conversion tests', async () => { - - await test('should convert nano to raw', async () => { - const result = await Tools.convert('1', 'NANO', 'RAW') - assert.equal(result, '1000000000000000000000000000000') - }) - - await test('should convert raw to nano', async () => { - const result = await Tools.convert('1000000000000000000000000000000', 'RAW', 'NANO') - assert.equal(result, '1') - }) - - await test('should convert 1 raw to 10^-29 nano', async () => { - const result = await Tools.convert('1', 'RAW', 'NANO') - assert.equal(result, '.000000000000000000000000000001') - }) - - await test('should ignore leading and trailing zeros', async () => { - const result = await Tools.convert('0011002200.0033004400', 'nano', 'nano') - assert.equal(result, '11002200.00330044') - }) - - await test('should convert raw to nyano', async () => { - const result = await Tools.convert(RAW_MAX, 'RAW', 'NYANO') - assert.equal(result, '340282366920938.463463374607431768211455') - }) - - await test('should convert case-insensitive nyano to raw', async () => { - const result = await Tools.convert('0.000000000000000123456789', 'nYaNo', 'rAw') - assert.equal(result, '123456789') - }) - - await test('should convert nano to pico', async () => { - const result = await Tools.convert('123.456', 'nano', 'pico') - assert.equal(result, '123456') - }) - - await test('should convert knano to pico', async () => { - const result = await Tools.convert('123.456', 'nano', 'pico') - assert.equal(result, '123456') - }) - - await test('should throw if amount exceeds raw max', async () => { - await assert.rejects(Tools.convert(RAW_MAX, 'NANO', 'RAW'), - { message: 'Amount exceeds Nano limits' }) - }) - - await test('should throw if amount exceeds raw min', async () => { - await assert.rejects(Tools.convert('0.1', 'RAW', 'NANO'), - { message: 'Amount must be at least 1 raw' }) - }) - - await test('should throw if amount is blank', async () => { - await assert.rejects(Tools.convert('', 'RAW', 'NANO'), - { message: 'Invalid amount' }) - }) - - await test('should throw if amount has non-digit characters', async () => { - await assert.rejects(Tools.convert('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'RAW', 'NANO'), - { message: 'Invalid amount' }) - }) -}) - -await suite('signature tests', async () => { - - await test('should sign data with a single parameter', async () => { - const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi') - assert.equal(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C') - }) - - await test('should sign data with multiple parameters', async () => { - const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi', 'somePassword') - assert.equal(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804') - }) - - await test('should verify a signature using the public key', async () => { - const result = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi') - assert.equal(result, true) - - const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi') - assert.equal(result2, false) - - const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi') - assert.equal(result3, false) - }) - - await test('should verify a block using the public key', 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() - const privateKey = await account.export(wallet.seed, 'hex') - const sendBlock = new SendBlock( - account.address, - '5618869000000000000000000000000', - 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', - '2000000000000000000000000000000', - 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou', - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', - ) - await sendBlock.sign(privateKey) - const valid = await sendBlock.verify(account.publicKey) - assert.equal(valid, true) - - await wallet.destroy() - }) - - await test('should reject a block using the wrong public key', 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() - const privateKey = await account.export(wallet.seed, 'hex') - const sendBlock = new SendBlock( - account.address, - '5618869000000000000000000000000', - 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', - '2000000000000000000000000000000', - 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou', - '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', - ) - await sendBlock.sign(privateKey) - - sendBlock.account = Account.import('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p') - const valid = await sendBlock.verify(account.publicKey) - assert.equal(valid, false) - - await wallet.destroy() - }) - - await test('sweeper throws without required parameters', async () => { - await assert.rejects(Tools.sweep(), - 'Missing required sweep arguments') - }) - - await test('sweeper fails gracefully for ineligible accounts', { skip: true }, async () => { - const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) - await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) - const results = await Tools.sweep(rpc, wallet, NANO_TEST_VECTORS.ADDRESS_1) - assert.ok(results) - assert.equal(results.length, 1) - - await wallet.destroy() - }) -}) +await Promise.all([ + suite('unit conversion tests', async () => { + + await test('should convert nano to raw', async () => { + const result = await Tools.convert('1', 'NANO', 'RAW') + assert.equal(result, '1000000000000000000000000000000') + }) + + await test('should convert raw to nano', async () => { + const result = await Tools.convert('1000000000000000000000000000000', 'RAW', 'NANO') + assert.equal(result, '1') + }) + + await test('should convert 1 raw to 10^-29 nano', async () => { + const result = await Tools.convert('1', 'RAW', 'NANO') + assert.equal(result, '.000000000000000000000000000001') + }) + + await test('should ignore leading and trailing zeros', async () => { + const result = await Tools.convert('0011002200.0033004400', 'nano', 'nano') + assert.equal(result, '11002200.00330044') + }) + + await test('should convert raw to nyano', async () => { + const result = await Tools.convert(RAW_MAX, 'RAW', 'NYANO') + assert.equal(result, '340282366920938.463463374607431768211455') + }) + + await test('should convert case-insensitive nyano to raw', async () => { + const result = await Tools.convert('0.000000000000000123456789', 'nYaNo', 'rAw') + assert.equal(result, '123456789') + }) + + await test('should convert nano to pico', async () => { + const result = await Tools.convert('123.456', 'nano', 'pico') + assert.equal(result, '123456') + }) + + await test('should convert knano to pico', async () => { + const result = await Tools.convert('123.456', 'nano', 'pico') + assert.equal(result, '123456') + }) + + await test('should throw if amount exceeds raw max', async () => { + await assert.rejects(Tools.convert(RAW_MAX, 'NANO', 'RAW'), + { message: 'Amount exceeds Nano limits' }) + }) + + await test('should throw if amount exceeds raw min', async () => { + await assert.rejects(Tools.convert('0.1', 'RAW', 'NANO'), + { message: 'Amount must be at least 1 raw' }) + }) + + await test('should throw if amount is blank', async () => { + await assert.rejects(Tools.convert('', 'RAW', 'NANO'), + { message: 'Invalid amount' }) + }) + + await test('should throw if amount has non-digit characters', async () => { + await assert.rejects(Tools.convert('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'RAW', 'NANO'), + { message: 'Invalid amount' }) + }) + }), + + suite('signature tests', async () => { + + await test('should sign data with a single parameter', async () => { + const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi') + assert.equal(result, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C') + }) + + await test('should sign data with multiple parameters', async () => { + const result = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, 'miro@metsanheimo.fi', 'somePassword') + assert.equal(result, 'BB534F9B469AF451B1941FFEF8EE461FC5D284B5D393140900C6E13A65EF08D0AE2BC77131EE182922F66C250C7237A83878160457D5C39A70E55F7FCE925804') + }) + + await test('should verify a signature using the public key', async () => { + const result = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi') + assert.equal(result, true) + + const result2 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'FECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'mir@metsanheimo.fi') + assert.equal(result2, false) + + const result3 = await Tools.verify(NANO_TEST_VECTORS.PUBLIC_0, 'AECB9B084065ADC969904B55A0099C63746B68DF41FECB713244D387EED83A80B9D4907278C5EBC0998A5FC8BA597FBAAABBFCE0ABD2CA2212ACFE788637040C', 'miro@metsanheimo.fi') + assert.equal(result3, false) + }) + + await test('should verify a block using the public key', 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() + const privateKey = await account.export(wallet.seed, 'hex') + const sendBlock = new SendBlock( + account.address, + '5618869000000000000000000000000', + 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', + '2000000000000000000000000000000', + 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou', + '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', + ) + await sendBlock.sign(privateKey) + const valid = await sendBlock.verify(account.publicKey) + assert.equal(valid, true) + + await wallet.destroy() + }) + + await test('should reject a block using the wrong public key', 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() + const privateKey = await account.export(wallet.seed, 'hex') + const sendBlock = new SendBlock( + account.address, + '5618869000000000000000000000000', + 'nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p', + '2000000000000000000000000000000', + 'nano_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou', + '92BA74A7D6DC7557F3EDA95ADC6341D51AC777A0A6FF0688A5C492AB2B2CB40D', + ) + await sendBlock.sign(privateKey) + + sendBlock.account = Account.import('nano_1q3hqecaw15cjt7thbtxu3pbzr1eihtzzpzxguoc37bj1wc5ffoh7w74gi6p') + const valid = await sendBlock.verify(account.publicKey) + assert.equal(valid, false) + + await wallet.destroy() + }) + + await test('sweeper throws without required parameters', async () => { + await assert.rejects(Tools.sweep(), + 'Missing required sweep arguments') + }) + + await test('sweeper fails gracefully for ineligible accounts', { skip: true }, async () => { + const wallet = await Bip44Wallet.fromSeed(NANO_TEST_VECTORS.PASSWORD, NANO_TEST_VECTORS.BIP39_SEED) + await wallet.unlock(NANO_TEST_VECTORS.PASSWORD) + const results = await Tools.sweep(rpc, wallet, NANO_TEST_VECTORS.ADDRESS_1) + assert.ok(results) + assert.equal(results.length, 1) + + await wallet.destroy() + }) + }) +])