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