--- /dev/null
+// SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import blake2b from 'blake2b-wasm'
+import { nanoCKD } from './bip32-key-derivation.js'
+
+let addEventListener = globalThis.addEventListener
+let postMessage = globalThis.postMessage
+if (addEventListener == null || postMessage == null) {
+ const { isMainThread, parentPort } = await import('node:worker_threads')
+ if (!isMainThread && parentPort) {
+ addEventListener = Object.getPrototypeOf(parentPort).addListener.bind(parentPort)
+ postMessage = Object.getPrototypeOf(parentPort).postMessage.bind(parentPort)
+ }
+}
+
+/**
+* Derives BIP-44 Nano account private keys.
+*
+* @param {number} index - Index of the account
+* @returns {Promise<Account>}
+*/
+addEventListener('message', (message) => {
+ const { type, seed, index } = message.data ?? message
+ switch (type) {
+ case 'bip44': {
+ ckdBip44(seed, index).then(postMessage)
+ break
+ }
+ case 'blake2b': {
+ ckdBlake2b(seed, index).then(postMessage)
+ break
+ }
+ }
+})
+
+/**
+* Derives BIP-44 Nano account private keys.
+*
+* @param {number} index - Index of the account
+* @returns {Promise<Account>}
+*/
+async function ckdBip44 (seed: string, index: number): Promise<string> {
+ return nanoCKD(seed, index)
+}
+
+/**
+* Derives BLAKE2b account private keys.
+*
+* @param {number} index - Index of the account
+* @returns {Promise<Account>}
+*/
+async function ckdBlake2b (seed: string, index: number): Promise<string> {
+ const indexHex = index.toString(16).padStart(8, '0').toUpperCase()
+ const inputHex = `${seed}${indexHex}`.padStart(72, '0')
+ const inputArray = (inputHex.match(/.{1,2}/g) ?? []).map(h => parseInt(h, 16))
+ const inputBytes = Uint8Array.from(inputArray)
+ const hash = blake2b().update(inputBytes).digest('hex')
+ return hash
+}