import { ACCOUNT_KEY_BYTE_LENGTH, ACCOUNT_KEY_HEX_LENGTH, ALPHABET, PREFIX, PREFIX_LEGACY } from './constants'\r
import { base32, bytes, hex, utf8 } from './convert'\r
import { Rpc } from './rpc'\r
-import { Data, Key, KeyPair } from '#types'\r
+import { Key, KeyPair, NamedData } from '#types'\r
import { NanoNaClWorker, SafeWorker } from '#workers'\r
\r
/**\r
async sign (block: ChangeBlock | ReceiveBlock | SendBlock, password: Key): Promise<string> {\r
if (typeof password === 'string') password = utf8.toBytes(password)\r
try {\r
- const headers = {\r
- method: 'detached'\r
- }\r
- const result = await NanoNaClWorker.assign(headers, {\r
+ const { signature } = await NanoNaClWorker.assign<ArrayBuffer>({\r
+ method: 'detached',\r
privateKey: (await this.#export(password)).buffer,\r
msg: hex.toBytes(block.hash).buffer\r
})\r
- block.signature = result\r
- return result\r
+ block.signature = bytes.toHex(new Uint8Array(signature))\r
+ return block.signature\r
} catch (err) {\r
throw new Error(`Failed to sign block`, { cause: err })\r
} finally {\r
throw new Error('Password must be string or bytes')\r
}\r
try {\r
- const headers = {\r
+ const response = await SafeWorker.assign<ArrayBuffer>({\r
method: 'get',\r
name: this.publicKey,\r
- store: 'Account'\r
- }\r
- const response = await SafeWorker.assign(headers, {\r
+ store: 'Account',\r
password: password.buffer\r
})\r
- return new Uint8Array(response[this.publicKey] as ArrayBuffer)\r
+ return new Uint8Array(response[this.publicKey])\r
} catch (err) {\r
throw new Error(`Failed to export private key for Account ${this.address}`, { cause: err })\r
} finally {\r
}\r
\r
const accounts: Account[] = []\r
- const privateAccounts: Data = {}\r
+ const privateAccounts: NamedData = {\r
+ method: 'set',\r
+ store: 'Account',\r
+ password: password.buffer\r
+ }\r
for (let keypair of keypairs) {\r
let { index, privateKey } = keypair\r
if (index == null) {\r
this.#validateKey(privateKey)\r
if (typeof privateKey === 'string') privateKey = hex.toBytes(privateKey)\r
try {\r
- const headers = {\r
- method: 'convert'\r
- }\r
- const publicKey = await NanoNaClWorker.assign(headers, {\r
+ const result = await NanoNaClWorker.assign<ArrayBuffer>({\r
+ method: 'convert',\r
privateKey: new Uint8Array(privateKey).buffer\r
})\r
- privateAccounts[publicKey] = privateKey.buffer\r
- const address = this.#keyToAddress(hex.toBytes(publicKey))\r
+ const publicKey = new Uint8Array(result.publicKey)\r
+ privateAccounts[bytes.toHex(publicKey)] = privateKey.buffer\r
+ const address = this.#keyToAddress(publicKey)\r
this.#isInternal = true\r
accounts.push(new this(address, publicKey, index))\r
} catch (err) {\r
}\r
\r
try {\r
- const headers = {\r
- method: 'set',\r
- store: 'Account'\r
- }\r
- privateAccounts.password = password.buffer\r
- const isLocked = await SafeWorker.assign(headers, privateAccounts)\r
+ const isLocked = await SafeWorker.assign(privateAccounts)\r
if (!isLocked) {\r
throw null\r
}\r
return this
}
- digest (): Uint8Array
+ digest (): Uint8Array<ArrayBuffer>
digest (out: 'hex'): string
- digest (out: 'binary' | Uint8Array): Uint8Array
- digest (out?: 'binary' | 'hex' | Uint8Array): string | Uint8Array {
+ digest (out: 'binary' | Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
+ digest (out?: 'binary' | 'hex' | Uint8Array<ArrayBuffer>): string | Uint8Array<ArrayBuffer> {
const buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.#outlen) : out
if (!(buf instanceof Uint8Array)) throw new TypeError(`out must be "binary", "hex", Uint8Array, or Buffer`)
if (buf.length < this.#outlen) throw new RangeError(`out must have at least outlen bytes of space`)
throw new Error('Provide a key for block signature verification.')
}
try {
- const headers = {
- method: 'verify'
- }
- return await NanoNaClWorker.assign(headers, {
+ const { isVerified } = await NanoNaClWorker.assign<boolean>({
+ method: 'verify',
msg: hex.toBytes(this.hash).buffer,
signature: hex.toBytes(this.signature ?? '').buffer,
publicKey: hex.toBytes(key).buffer
})
+ return isVerified
} catch (err) {
throw new Error(`Failed to derive public key from private key`, { cause: err })
}
}
/**
- *
- * @param {string} action - Nano protocol RPC call to execute
- * @param {object} [data] - JSON to send to the node as defined by the action
- * @returns {Promise<any>} JSON-formatted RPC results from the node
- */
- async call (action: string, data?: { [key: string]: any }): Promise<any> {
+ * Sends a nano RPC call to a node endpoint.
+ *
+ * @param {string} action - Nano protocol RPC call to execute
+ * @param {object} [data] - JSON to send to the node as defined by the action
+ * @returns {Promise<any>} JSON-formatted RPC results from the node
+ */
+ async call (action: string, data?: { [key: string]: unknown }): Promise<any> {
var process: any = process || null
this.#validate(action)
const headers: { [key: string]: string } = {}
message: string
}
-function hash (data: string | string[], encoding?: 'hex', format?: 'hex'): string | Uint8Array {
+function hash (data: string | string[], encoding?: 'hex'): Uint8Array<ArrayBuffer>
+function hash (data: string | string[], encoding?: 'hex', format?: 'hex'): string | Uint8Array<ArrayBuffer> {
if (!Array.isArray(data)) data = [data]
const hash = new Blake2b(32)
if (encoding === 'hex') {
*/
export async function sign (key: Key, ...input: string[]): Promise<string> {
if (typeof key === 'string') key = hex.toBytes(key)
- let signature: string
try {
- const headers = {
- method: 'detached'
- }
- return await NanoNaClWorker.assign(headers, {
+ const { signature } = await NanoNaClWorker.assign<ArrayBuffer>({
+ method: 'detached',
privateKey: key.buffer,
- msg: (hash(input) as Uint8Array<ArrayBuffer>).buffer
+ msg: hash(input).buffer
})
+ return bytes.toHex(new Uint8Array(signature))
} catch (err) {
throw new Error(`Failed to sign message with private key`, { cause: err })
} finally {
export async function verify (key: Key, signature: string, ...input: string[]): Promise<boolean> {
if (typeof key === 'string') key = hex.toBytes(key)
try {
- const headers = {
- method: 'verify'
- }
- return await NanoNaClWorker.assign(headers, {
- msg: (hash(input) as Uint8Array<ArrayBuffer>).buffer,
+ const { isVerified } = await NanoNaClWorker.assign<boolean>({
+ method: 'verify',
+ msg: hash(input).buffer,
signature: hex.toBytes(signature).buffer,
publicKey: new Uint8Array(key).buffer
})
+ return isVerified
} catch (err) {
throw new Error('Failed to verify signature', { cause: err })
} finally {
* @returns {Promise<Account>}\r
*/\r
async ckd (indexes: number[]): Promise<KeyPair[]> {\r
- const headers = {\r
- indexes\r
- }\r
- const results = await Bip44CkdWorker.assign(headers, {\r
+ const results = await Bip44CkdWorker.assign({\r
+ indexes,\r
seed: hex.toBytes(this.seed).buffer\r
})\r
const privateKeys: KeyPair[] = []\r
import { bytes, hex, utf8 } from '#src/lib/convert.js'\r
import { Entropy } from '#src/lib/entropy.js'\r
import { Rpc } from '#src/lib/rpc.js'\r
-import { Key, KeyPair } from '#types'\r
+import { Key, KeyPair, NamedData } from '#types'\r
import { SafeWorker } from '#workers'\r
\r
/**\r
method: 'destroy',\r
name: this.id\r
})\r
+ // NODE: await SafeWorker.assign({ method: 'STOP' })\r
}\r
\r
/**\r
seed: this.seed\r
})\r
const encoded = utf8.toBytes(serialized)\r
- const headers = {\r
+ const success = await SafeWorker.assign({\r
method: 'set',\r
- store: 'Wallet'\r
- }\r
- const success = await SafeWorker.assign(headers, {\r
+ store: 'Wallet',\r
[this.id]: encoded.buffer,\r
password: password.buffer\r
})\r
throw new Error('Failed to unlock wallet')\r
}\r
try {\r
- const headers = {\r
+ const response = await SafeWorker.assign<ArrayBuffer>({\r
method: 'get',\r
name: this.id,\r
store: 'Wallet',\r
- }\r
- const response = await SafeWorker.assign(headers, {\r
password: password.buffer\r
})\r
- const decoded = bytes.toUtf8(response[this.id])\r
+ const decoded = bytes.toUtf8(new Uint8Array(response[this.id]))\r
const deserialized = JSON.parse(decoded)\r
let { id, mnemonic, seed } = deserialized\r
if (id == null) {\r
// SPDX-License-Identifier: GPL-3.0-or-later
import { WorkerInterface } from './worker-interface'
-import { Data, Headers } from '#types'
+import { Data, NamedData } from '#types'
type ExtendedKey = {
privateKey: DataView<ArrayBuffer>
this.listen()
}
- static async work (headers: Headers, data: Data): Promise<Data> {
- let { coin, indexes } = headers
- let { seed } = data
- if (coin != null && (typeof coin !== 'number' || !Number.isInteger(coin))) {
+ static async work (data: NamedData): Promise<NamedData<ArrayBuffer>> {
+ if (data.coin != null && (typeof data.coin !== 'number' || !Number.isInteger(data.coin))) {
throw new TypeError('BIP-44 coin derivation level must be an integer')
}
- if (!Array.isArray(indexes)) indexes = [indexes]
- const privateKeys: Data = {}
+ if (!Array.isArray(data.indexes) || data.indexes.some(i => !Number.isInteger(i))) {
+ throw new TypeError('BIP-44 account indexes must be an array of integers')
+ }
+ if (!(data.seed instanceof ArrayBuffer)) {
+ throw new TypeError('BIP-44 seed must be an ArrayBuffer')
+ }
+ const coin: number = data.coin
+ const indexes = Array.isArray(data.indexes)
+ ? data.indexes
+ : [data.indexes]
+ const seed = data.seed
+ const privateKeys: NamedData<ArrayBuffer> = {}
for (const i of indexes) {
if (typeof i !== 'number' || !Number.isInteger(i)) {
throw new TypeError('BIP-44 account derivation level must be an integer')
// SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
// SPDX-License-Identifier: GPL-3.0-or-later
-export { Bip44CkdWorker, NanoNaClWorker, SafeWorker } from './queue'
+export { Bip44CkdWorker, NanoNaClWorker, SafeWorker } from './worker-queue'
import { WorkerInterface } from './worker-interface'\r
import { Blake2b } from '#src/lib/blake2b.js'\r
import { default as Convert, bytes, hex } from '#src/lib/convert.js'\r
-import { Data, Headers, Key } from '#types'\r
+import { Data, NamedData, Key } from '#types'\r
\r
/**\r
* Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.\r
this.listen()\r
}\r
\r
- static async work (headers: Headers, data: Data): Promise<boolean | string> {\r
- const { method } = headers\r
+ static async work (data: NamedData<string | ArrayBuffer>): Promise<NamedData> {\r
+ if (typeof data.method !== 'string'\r
+ || !(data.msg == null || data.msg instanceof ArrayBuffer)\r
+ || !(data.privateKey == null || data.privateKey instanceof ArrayBuffer)\r
+ || !(data.publicKey == null || data.publicKey instanceof ArrayBuffer)\r
+ || !(data.signature == null || data.signature instanceof ArrayBuffer)\r
+ ) {\r
+ throw new TypeError('Invalid NanoNaCl input')\r
+ }\r
+ const method = data.method\r
const msg = new Uint8Array(data.msg)\r
const privateKey = new Uint8Array(data.privateKey)\r
const publicKey = new Uint8Array(data.publicKey)\r
try {\r
switch (method) {\r
case 'convert': {\r
- return bytes.toHex(await this.convert(privateKey))\r
+ return { publicKey: (await this.convert(privateKey)).buffer }\r
}\r
case 'detached': {\r
- return bytes.toHex(await this.detached(msg, privateKey))\r
+ return { signature: (await this.detached(msg, privateKey)).buffer }\r
}\r
case 'verify': {\r
- return await this.verify(msg, signature, publicKey)\r
+ return { isVerified: await this.verify(msg, signature, publicKey) }\r
}\r
default: {\r
throw new TypeError(`unknown NanoNaCl method ${method}`)\r
import { PBKDF2_ITERATIONS } from '#src/lib/constants.js'
import { default as Convert, bytes } from '#src/lib/convert.js'
import { Entropy } from '#src/lib/entropy.js'
-import { Data, Headers, SafeRecord } from '#types'
+import { NamedData, SafeRecord } from '#types'
/**
* Encrypts and stores data in the browser using IndexedDB.
this.listen()
}
- static async work (headers: Headers, data: Data): Promise<boolean | Data> {
- const { method, name, store } = headers
- const password = data?.password
- if (data != null) delete data.password
+ static async work (data: NamedData): Promise<NamedData<boolean | ArrayBuffer>> {
+ const { method, name, store } = data
+ if (typeof method !== 'string') {
+ throw new TypeError('Invalid method')
+ }
+ delete data.method
+ if (name != null && typeof name !== 'string') {
+ throw new TypeError('Invalid name')
+ }
+ delete data.name
+ if (typeof store !== 'string') {
+ throw new TypeError('Invalid store')
+ }
+ delete data.store
+ const password = data.password
+ delete data.password
this.#storage = await this.#open(this.DB_NAME)
- let result
try {
switch (method) {
case 'set': {
- result = await this.set(data, store, password)
- break
+ return { result: await this.set(data, store, password) }
}
case 'get': {
- result = await this.get(name, store, password)
- break
+ return await this.get(name, store, password)
}
case 'destroy': {
- result = await this.destroy(name, store)
- break
+ return { result: await this.destroy(name, store) }
}
default: {
throw new Error(`unknown Safe method ${method}`)
console.log(err)
throw new Error('Safe error', { cause: err })
}
- return result
}
/**
/**
* Encrypts data with a password byte array and stores it in the Safe.
*/
- static async set (data: Data | unknown, store: string | unknown, password: ArrayBuffer | unknown): Promise<boolean> {
+ static async set (data: NamedData | unknown, store: string | unknown, password: ArrayBuffer | unknown): Promise<boolean> {
this.#isDataValid(data)
if (typeof store !== 'string' || store === '') {
throw new Error('Invalid database store name')
/**
* Retrieves data from the Safe and decrypts it with a password byte array.
*/
- static async get (name: string | string[] | unknown, store: string | unknown, password: ArrayBuffer | unknown): Promise<Data> {
+ static async get (name: string | string[] | unknown, store: string | unknown, password: ArrayBuffer | unknown): Promise<NamedData<ArrayBuffer>> {
const names = Array.isArray(name) ? name : [name]
if (names.some(v => typeof v !== 'string')) {
throw new Error('Invalid fields')
throw new Error('Invalid password')
}
- const results: Data = {}
+ const results: NamedData<ArrayBuffer> = {}
try {
const records: SafeRecord[] = await this.#get(fields, store)
if (records == null || records.length === 0) {
})
}
- static #isDataValid (data: unknown): asserts data is Data {
+ static #isDataValid (data: unknown): asserts data is { [key: string]: ArrayBuffer } {
if (typeof data !== 'object') {
throw new Error('Invalid data')
}
// SPDX-License-Identifier: GPL-3.0-or-later
import { parentPort } from 'node:worker_threads'
-import { Data, Headers } from '#types'
+import { Data, NamedData } from '#types'
/**
* Provides basic worker event messaging to extending classes.
* function signature and providing their own processing call in the try-catch
* block.
*
- * @param {Header} headers - Flat object of header data
- * @param {Data} data - String keys for ArrayBuffer values to transfer and process
+ * @param {NamedData} data - Flat object of data key-value pairs
* @returns Promise for processed data
*/
- static async work (headers: Headers | null, data?: Data): Promise<any> {
- return new Promise(async (resolve, reject): Promise<void> => {
+ static work (data: NamedData): Promise<NamedData> {
+ return new Promise((resolve, reject): void => {
try {
- let x, y = new ArrayBuffer(0)
- if (headers != null) {
- const { sample } = headers
- x = sample
- }
- if (data != null) {
- const { buf } = data
- y = buf
+ if (data == null) {
+ throw new Error('Missing data')
}
+ const { x, y } = data
resolve({ x, y })
} catch (err) {
reject(err)
/**
* Transfers buffers of worker results back to the main thread.
*
- * @param {Headers} results - Key-value pairs of processed data
+ * @param {NamedData} data - Key-value pairs of processed data
*/
- static report (results: Headers): void {
+ static report (data: NamedData): void {
const buffers = []
try {
- if (typeof results === 'object') {
- for (const d of Object.keys(results)) {
- if (results[d] instanceof ArrayBuffer) {
- buffers.push(results[d])
+ if (typeof data === 'object') {
+ for (const d of Object.keys(data)) {
+ if (data[d] instanceof ArrayBuffer) {
+ buffers.push(data[d])
}
}
}
throw new Error('Failed to report results', { cause: err })
}
//@ts-expect-error
- BROWSER: postMessage(results, buffers)
- NODE: parentPort?.postMessage(results, buffers)
+ BROWSER: postMessage(data, buffers)
+ NODE: parentPort?.postMessage({ data }, buffers)
}
/**
*/
static listen (): void {
const listener = async (message: MessageEvent<any>): Promise<void> => {
- const { name, headers, data } = message.data
- if (name === 'STOP') {
- close()
+ // console.log(message)
+ const { data } = message
+ if (data.method === 'STOP') {
this.report({})
+ BROWSER: close()
+ NODE: process.exit()
} else {
- this.work(headers, data).then(this.report).catch(this.report)
+ this.work(data).then(this.report).catch(this.report)
}
}
BROWSER: addEventListener('message', listener)
import { default as bip44 } from './bip44-ckd'
import { default as nacl } from './nano-nacl'
import { default as safe } from './safe'
-import { Data, Headers } from '#types'
+import { Data, NamedData } from '#types'
type Task = {
id: number
- headers: Headers | null
- data?: Data
+ data: NamedData
reject: (value: any) => void
resolve: (value: any) => void
}
/**
* Processes a queue of tasks using Web Workers.
*/
-export class Queue {
- static #instances: Queue[] = []
- static get instances (): Queue[] { return this.#instances }
+export class WorkerQueue {
+ static #instances: WorkerQueue[] = []
+ static get instances (): WorkerQueue[] { return this.#instances }
#job?: Task
#isIdle: boolean
NODE: this.#worker.on('message', message => {
this.#report(message)
})
- Queue.#instances.push(this)
+ WorkerQueue.#instances.push(this)
}
- async assign (headers: Headers | null, data?: Data): Promise<any> {
- return this.#assign(task => this.#queue.push(task), headers, data)
+ async assign<T extends Data> (data: NamedData): Promise<NamedData<T>> {
+ return this.#assign<T>(data, task => this.#queue.push(task))
}
- async prioritize (headers: Headers | null, data?: Data): Promise<any> {
- return this.#assign(task => this.#queue.unshift(task), headers, data)
+ async prioritize<T extends Data> (data: NamedData): Promise<NamedData<T>> {
+ return this.#assign<T>(data, task => this.#queue.unshift(task))
}
terminate (): void {
this.#worker.terminate()
}
- async #assign (enqueue: (task: Task) => number, headers: Headers | null, data?: Data): Promise<Data> {
+ async #assign<T extends Data> (data: NamedData, enqueue: (task: Task) => number): Promise<NamedData<T>> {
return new Promise(async (resolve, reject): Promise<void> => {
const task: Task = {
id: performance.now(),
- headers,
data,
resolve,
reject
this.#job = this.#queue.shift()
this.#isIdle = this.#job == null
if (this.#job != null) {
- const { id, headers, data, reject } = this.#job
+ const { data, reject } = this.#job
try {
const buffers: ArrayBuffer[] = []
- if (data != null) {
- for (let d of Object.keys(data)) {
+ for (let d of Object.keys(data)) {
+ if (data[d] instanceof ArrayBuffer) {
buffers.push(data[d])
}
}
- BROWSER: this.#worker.postMessage({ headers, data }, buffers)
- NODE: this.#worker.postMessage({ data: { headers, data } }, buffers)
+ BROWSER: this.#worker.postMessage(data, buffers)
+ NODE: this.#worker.postMessage({ data }, buffers)
} catch (err) {
reject(err)
}
}
}
-export const Bip44CkdWorker = new Queue(bip44)
-export const NanoNaClWorker = new Queue(nacl)
-export const SafeWorker = new Queue(safe)
+export const Bip44CkdWorker = new WorkerQueue(bip44)
+export const NanoNaClWorker = new WorkerQueue(nacl)
+export const SafeWorker = new WorkerQueue(safe)
constructor (account: Account | string, balance: string, representative: Account | string, frontier: string, work?: string)
}
-export type Data = {
- [key: string]: ArrayBuffer
-}
+export type Data = boolean | number[] | string | ArrayBuffer
-export type Headers = {
- [key: string]: any
+export type NamedData<T extends Data = Data> = {
+ [key: string]: T
}
export type Key = string | Uint8Array<ArrayBuffer>
* @param {number} [count=1] - Integer between 1 and CPU thread count shared among all Pools
*/
constructor (worker: string)
- assign (headers: Headers | null, data?: Data): Promise<any>
- prioritize (headers: Headers | null, data?: Data): Promise<any>
+ assign (data: NamedData): Promise<NamedData>
+ prioritize (data: NamedData): Promise<NamedData>
terminate (): void
}
export declare const Bip44CkdWorker: Queue
// SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
// SPDX-License-Identifier: GPL-3.0-or-later
+export { env } from '../env.mjs'
import { Queue } from './QUEUE.mjs'
-import { process } from '../env.mjs'
const queue = new Queue()
-export { process }
-export const isNode = process.versions?.node != null
+export const isNode = globalThis !== globalThis.window
let NodeTestSuite, NodeTestTest
if (isNode) {
import { NANO_TEST_VECTORS } from './VECTORS.js'
import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'
-await suite('Account performance', async () => {
+await suite('Account performance', { skip: true }, async () => {
const COUNT = 0x200
await test(`Time to create ${COUNT} BIP-44 accounts`, async () => {
const end = performance.now()
console.log(`Total: ${end - start} ms`)
console.log(`Average: ${(end - start) / COUNT} ms`)
- assert.equals(accounts.length, COUNT)
+ assert.equal(accounts.length, COUNT)
await wallet.destroy()
})
const end = performance.now()
console.log(`Total: ${end - start} ms`)
console.log(`Average: ${(end - start) / COUNT} ms`)
- assert.equals(accounts.length, COUNT)
+ assert.equal(accounts.length, COUNT)
await wallet.destroy()
})
'use strict'
-import { assert, stats, suite, test } from './GLOBALS.mjs'
+import { stats, suite, test } from './GLOBALS.mjs'
import { NANO_TEST_VECTORS } from './VECTORS.js'
import { SendBlock } from '../dist/main.min.js'
-await suite('Block performance', async () => {
+await 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 () => {
'use strict'
-import { assert, stats, suite, test } from './GLOBALS.mjs'
+import { stats, suite, test } from './GLOBALS.mjs'
import { NANO_TEST_VECTORS } from './VECTORS.js'
import { Bip44Wallet, Blake2bWallet } from '../dist/main.min.js'
-await suite(`Wallet performance`, async () => {
+await suite(`Wallet performance`, { skip: true }, async () => {
const COUNT = 0x20
await test(`Time to create ${COUNT} BIP-44 wallets`, async () => {
\r
'use strict'\r
\r
-import { assert, suite, test } from './GLOBALS.mjs'\r
+import { assert, isNode, suite, test } from './GLOBALS.mjs'\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', async () => {\r
+await suite('Calculate proof-of-work', { skip: isNode }, async () => {\r
\r
await test('SendBlock PoW', async () => {\r
const block = new SendBlock(\r
'use strict'
-import { assert, click, isNode, process, suite, test } from './GLOBALS.mjs'
+import { assert, click, env, isNode, suite, test } from './GLOBALS.mjs'
import { NANO_TEST_VECTORS } from './VECTORS.js'
import { Account, LedgerWallet, ReceiveBlock, Rpc, SendBlock } from '../dist/main.min.js'
-const rpc = new Rpc(process.env.NODE_URL ?? '', process.env.API_KEY_NAME)
+const rpc = new Rpc(env.NODE_URL ?? '', env.API_KEY_NAME)
/**
* HID interactions require user gestures, so to reduce clicks, the variables
'use strict'
-import { assert, process, suite, test } from './GLOBALS.mjs'
+import { assert, env, suite, test } from './GLOBALS.mjs'
import { NANO_TEST_VECTORS } from './VECTORS.js'
import { Account, Bip44Wallet, Rpc } from '../dist/main.min.js'
-const rpc = new Rpc(process.env.NODE_URL ?? '', process.env.API_KEY_NAME)
+const rpc = new Rpc(env.NODE_URL ?? '', env.API_KEY_NAME)
await suite('Refreshing account info', { skip: true }, async () => {
// SPDX-FileCopyrightText: 2025 Chris Duncan <chris@zoso.dev>
// SPDX-License-Identifier: GPL-3.0-or-later
-import { failures, passes, suite, test } from './GLOBALS.mjs'
+import { failures, isNode, passes, suite, test } from './GLOBALS.mjs'
-await suite('TEST RUNNER CHECK', async () => {
- await new Promise(r => setTimeout(r, 0))
+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)
+ 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 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')
+ //@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 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('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')
+ 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')
+ //@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')
+ failures.splice(0)
+ passes.splice(0)
+ })
+
+ console.log(`%cTEST RUNNER CHECK DONE`, 'font-weight:bold')
+}
\r
'use strict'\r
\r
-import { assert, suite, test } from './GLOBALS.mjs'\r
+import { assert, env, suite, test } from './GLOBALS.mjs'\r
import { RAW_MAX, NANO_TEST_VECTORS } from './VECTORS.js'\r
import { Bip44Wallet, Account, SendBlock, Rpc, Tools } from '../dist/main.min.js'\r
\r
-let rpc\r
-//@ts-ignore\r
-var process = process || null\r
-if (process) {\r
- //@ts-expect-error\r
- rpc = new Rpc(process?.env?.NODE_URL ?? '', process?.env?.API_KEY_NAME)\r
-}\r
+const rpc = new Rpc(env?.NODE_URL ?? '', env?.API_KEY_NAME)\r
\r
await suite('unit conversion tests', async () => {\r
\r