import { CUSTOM_TEST_VECTORS, NANO_TEST_VECTORS } from './VECTORS.mjs'
const rpc = new Rpc(env.NODE_URL ?? '', env.API_KEY_NAME)
+const isUnsupported = isNode || navigator?.usb == null
/**
* HID interactions require user gestures, so to reduce clicks, the variables
* addresses from their own Ledger hardware wallets.
*/
await Promise.all([
- suite('Ledger unsupported', { skip: !(isNode || navigator?.usb == null) }, async () => {
+ suite('Ledger unsupported', { skip: !isUnsupported }, async () => {
await test('status UNSUPPORTED', async () => {
assert.equal(Ledger.status, 'UNSUPPORTED')
})
}),
- suite('Ledger hardware wallet', { skip: isNode || navigator?.usb == null }, async () => {
+ suite('Ledger hardware wallet', { skip: isUnsupported }, async () => {
const { LEDGER_NANOS, LEDGER_NANOSP } = CUSTOM_TEST_VECTORS
const { OPEN_BLOCK, RECEIVE_BLOCK, SEND_BLOCK } = NANO_TEST_VECTORS
/** @type {Block} */ openBlock,
/** @type {Block} */ sendBlock,
/** @type {Block} */ receiveBlock,
- restored
+ /** @type {Wallet} */ restored
try {
wallet = await Wallet.create('Ledger')
} catch {
return
}
- await test('request permissions', { skip: true }, async () => {
+ await test('request permissions', { skip: isUnsupported }, async () => {
let status = Ledger.status
Ledger.addEventListener('ledgerstatuschanged', (event) => {
assert.equal(status, 'CONNECTED')
})
- await test('switch between interfaces', { skip: false || isNode || navigator?.usb == null }, async () => {
+ await test('switch between interfaces', { skip: isUnsupported }, async () => {
await assert.resolves(click(
'Verify current interface is HID, switch to unlocked Bluetooth device, then click to continue',
async () => wallet.config({ connection: 'ble' })
await test('verify mnemonic', async () => {
await click(
- 'Open Nano app, then click to continue',
- async () => wallet.unlock()
+ 'Open Nano app, then click to verify mnemonic',
+ async () => {
+ await wallet.config({ connection: 'hid' })
+ await wallet.unlock()
+ const isVerified = await wallet.verify(LEDGER_NANOS.MNEMONIC)
+ // const isVerified = await wallet.verify(LEDGER_NANOSP.MNEMONIC)
+ assert.exists(isVerified)
+ assert.equal(typeof isVerified, 'boolean')
+ assert.equal(isVerified, true)
+ }
)
- const isVerified = await wallet.verify(LEDGER_NANOS.MNEMONIC)
- // const isVerified = await wallet.verify(LEDGER_NANOSP.MNEMONIC)
-
- assert.exists(isVerified)
- assert.equal(typeof isVerified, 'boolean')
- assert.equal(isVerified, true)
})
await test('verify seed', async () => {
- const isVerified = await wallet.verify(LEDGER_NANOS.SEED)
- // const isVerified = await wallet.verify(LEDGER_NANOSP.SEED)
-
- assert.exists(isVerified)
- assert.equal(typeof isVerified, 'boolean')
- assert.equal(isVerified, true)
+ await click(
+ 'Click to verify seed',
+ async () => {
+ const isVerified = await wallet.verify(LEDGER_NANOS.SEED)
+ // const isVerified = await wallet.verify(LEDGER_NANOSP.SEED)
+ assert.exists(isVerified)
+ assert.equal(typeof isVerified, 'boolean')
+ assert.equal(isVerified, true)
+ }
+ )
})
await test('get first account', async () => {
account = await wallet.account()
-
assert.exists(account)
assert.ok(account instanceof Account)
assert.exists(account.publicKey)
await test('get second and third accounts', async () => {
const accounts = await wallet.accounts(1, 2)
-
assert.exists(accounts)
assert.equal(accounts.size, 2)
for (const account of accounts.values()) {
// skip since accounts must already be opened to be refreshed
await test('refresh first three accounts', { skip: true }, async () => {
const accounts = await wallet.refresh(rpc, 0, 2)
-
assert.exists(accounts)
for (const account of accounts.values()) {
assert.ok(account instanceof Account)
assert.nullish(openBlock.signature)
assert.equal(openBlock.account.publicKey, account.publicKey)
- await wallet.sign(0, openBlock)
+ await click(
+ 'Click to sign open block from Ledger wallet',
+ async () => wallet.sign(0, openBlock)
+ )
+ const { signature } = openBlock
- assert.ok(/^[A-F0-9]{128}$/i.test(openBlock.signature ?? ''))
+ assert.ok(/^[A-F0-9]{128}$/i.test(signature ?? ''))
+ openBlock.signature = undefined
- await openBlock.sign(wallet, 0)
+ await click(
+ 'Click to sign open block from block using Ledger',
+ async () => openBlock.sign(wallet, 0)
+ )
assert.exists(openBlock.signature)
assert.ok(/^[A-F0-9]{128}$/i.test(openBlock.signature ?? ''))
+ assert.equal(signature, openBlock.signature)
})
await test('sign send block from wallet which requires cache to be up-to-date', async () => {
assert.nullish(sendBlock.signature)
assert.equal(sendBlock.account.publicKey, account.publicKey)
- await wallet.sign(0, sendBlock, openBlock)
+ await click(
+ 'Click to sign send block which requires up-to-date cache',
+ async () => wallet.sign(0, sendBlock, openBlock)
+ )
assert.ok(/^[A-F0-9]{128}$/i.test(sendBlock.signature ?? ''))
})
assert.nullish(receiveBlock.signature)
assert.equal(receiveBlock.account.publicKey, account.publicKey)
- await receiveBlock.sign(wallet, 0, sendBlock)
+ await click(
+ 'Click to sign receive block from block passing previous block for cache',
+ async () => receiveBlock.sign(wallet, 0, sendBlock)
+ )
assert.exists(receiveBlock.signature)
assert.ok(/^[A-F0-9]{128}$/i.test(receiveBlock.signature ?? ''))
assert.nullish(sendBlock.signature)
assert.equal(sendBlock.account.publicKey, account.publicKey)
- await wallet.sign(0, sendBlock, receiveBlock)
+ await click(
+ 'Click to sign send block from Ledger including frontier block for cache',
+ async () => wallet.sign(0, sendBlock, receiveBlock)
+ )
assert.exists(sendBlock.signature)
assert.ok(/^[A-F0-9]{128}$/i.test(sendBlock.signature ?? ''))
await test('sign a 16-byte nonce', async () => {
const nonce = 'hello nano world'
- const signature = await wallet.sign(0, nonce)
-
- assert.exists(signature)
- assert.ok(/^[A-F0-9]{128}$/i.test(signature))
+ await click(
+ 'Click to sign send block from Ledger including frontier block for cache',
+ async () => {
+ const signature = await wallet.sign(0, nonce)
+ assert.exists(signature)
+ assert.ok(/^[A-F0-9]{128}$/i.test(signature))
+ }
+ )
})
await test('fail to sign invalid length nonces', async () => {
const nonceShort = 'hello world'
const nonceLong = 'hello world foobar'
- await assert.rejects(wallet.sign(0, nonceShort))
- await assert.rejects(wallet.sign(0, nonceLong))
+ await assert.rejects(click(
+ 'fail to sign short nonce',
+ async () => wallet.sign(0, nonceShort)
+ ))
+ await assert.rejects(click(
+ 'fail to sign long nonce',
+ async () => wallet.sign(0, nonceLong)
+ ))
})
await test('fail when using new', async () => {
await test('fail to sign a block without caching frontier', async () => {
sendBlock = new Block(account, receiveBlock.balance, receiveBlock.hash, SEND_BLOCK.representative)
.send(account.address, '0')
- await assert.rejects(sendBlock.sign(wallet, 0))
+ await assert.rejects(click(
+ 'fail to sign without frontier cache',
+ async () => sendBlock.sign(wallet, 0)
+ ))
})
await test('restore from db then destroy', async () => {
assert.exists(restored)
await assert.resolves(restored.unlock())
- assert.equal(await restored.verify(LEDGER_NANOS.MNEMONIC), true)
+ await assert.resolves(click(
+ 'Click to verify Ledger mnemonic',
+ async () => {
+ const verification = await restored.verify(LEDGER_NANOS.MNEMONIC)
+ assert.equal(verification, true)
+ }
+ ))
// assert.equal(await restored.verify(LEDGER_NANOSP.MNEMONIC), true)
await click(