/**\r
* Represents a mnemonic phrase that identifies a wallet as defined by BIP-39.\r
*/\r
-export class Bip39Mnemonic {\r
+export class Bip39 {\r
static #isInternal: boolean = false\r
\r
/**\r
* @param {(string|ArrayBuffer|Uint8Array<ArrayBuffer>)} entropy - Cryptographically secure random value\r
* @returns {string} Mnemonic phrase created using the BIP-39 wordlist\r
*/\r
- static async fromEntropy (entropy: string | ArrayBuffer | Uint8Array<ArrayBuffer>): Promise<Bip39Mnemonic> {\r
+ static async fromEntropy (entropy: string | ArrayBuffer | Uint8Array<ArrayBuffer>): Promise<Bip39> {\r
const e = new Entropy(entropy)\r
const phraseLength = 0.75 * e.byteLength\r
const checksum = await this.#checksum(e.bytes)\r
* @param {string} phrase - String of 12, 15, 18, 21, or 24 words\r
* @returns {string} Mnemonic phrase validated using the BIP-39 wordlist\r
*/\r
- static async fromPhrase (phrase: string): Promise<Bip39Mnemonic> {\r
+ static async fromPhrase (phrase: string): Promise<Bip39> {\r
this.#isInternal = true\r
const self = new this()\r
const isValid = await this.validate(phrase)\r
get phrase (): string | undefined { return this.#phrase?.join(' ').normalize('NFKD') }\r
\r
private constructor () {\r
- if (!Bip39Mnemonic.#isInternal) {\r
+ if (!Bip39.#isInternal) {\r
throw new Error(`Bip39Mnemonic must be created with async methods 'fromPhrase()' or 'fromEntropy().`)\r
}\r
- Bip39Mnemonic.#isInternal = false\r
+ Bip39.#isInternal = false\r
}\r
\r
/**\r
if (this.#blake2bSeed == null) {\r
let bits = 0n\r
for (const word of this.#phrase) {\r
- const wordIndex = Bip39Mnemonic.wordlist.indexOf(word)\r
+ const wordIndex = Bip39.wordlist.indexOf(word)\r
if (wordIndex === -1) {\r
throw new RangeError('Word not found in BIP-39 list')\r
}\r
- bits = (bits << 11n) | BigInt(Bip39Mnemonic.wordlist.indexOf(word))\r
+ bits = (bits << 11n) | BigInt(Bip39.wordlist.indexOf(word))\r
}\r
bits >>= 8n\r
this.#blake2bSeed = new Uint8Array(32)\r
'use strict'
import { parentPort } from 'node:worker_threads'
-import { Bip39Mnemonic } from './bip39'
-import { Bip44Ckd } from './bip44'
+import { Bip39 } from './bip39'
+import { Bip44 } from './bip44'
import { Blake2b } from './blake2b'
import { default as Constants, BIP44_COIN_NANO } from './constants'
import { default as Convert, bytes, hex, utf8 } from './convert'
static #locked: boolean = true
static #type?: 'BIP-44' | 'BLAKE2b'
static #seed?: ArrayBuffer
- static #mnemonic?: Bip39Mnemonic
+ static #mnemonic?: Bip39
static #parentPort?: any
static {
NODE: this.#parentPort = parentPort
static async create (type?: 'BIP-44' | 'BLAKE2b', key?: CryptoKey, keySalt?: ArrayBuffer, mnemonicSalt?: string): Promise<NamedData<ArrayBuffer>> {
try {
const entropy = new Entropy()
- const { phrase: mnemonicPhrase } = await Bip39Mnemonic.fromEntropy(entropy.bytes)
+ const { phrase: mnemonicPhrase } = await Bip39.fromEntropy(entropy.bytes)
const record = await this.import(type, key, keySalt, mnemonicPhrase, mnemonicSalt)
if (this.#seed == null || this.#mnemonic?.phrase == null) {
throw new Error('Failed to generate seed and mnemonic')
throw new Error('Invalid wallet account index')
}
const prv = this.#type === 'BIP-44'
- ? await Bip44Ckd.ckd(this.#seed, BIP44_COIN_NANO, index)
+ ? await Bip44.ckd(this.#seed, BIP44_COIN_NANO, index)
: await this.#deriveBlake2bPrivateKey(this.#seed, index)
const pub = await NanoNaCl.convert(new Uint8Array(prv))
return { index, publicKey: pub.buffer }
if (secret instanceof ArrayBuffer) {
this.#seed = secret
if (type === 'BLAKE2b') {
- this.#mnemonic = await Bip39Mnemonic.fromEntropy(new Uint8Array(secret))
+ this.#mnemonic = await Bip39.fromEntropy(new Uint8Array(secret))
}
} else {
- this.#mnemonic = await Bip39Mnemonic.fromPhrase(secret)
+ this.#mnemonic = await Bip39.fromPhrase(secret)
this.#seed = type === 'BIP-44'
? (await this.#mnemonic.toBip39Seed(mnemonicSalt ?? '')).buffer
: (await this.#mnemonic.toBlake2bSeed()).buffer
if (data == null) {
throw new Error('Data to sign not found')
}
- const prv = await Bip44Ckd.ckd(this.#seed, BIP44_COIN_NANO, index)
+ const prv = await Bip44.ckd(this.#seed, BIP44_COIN_NANO, index)
const sig = await NanoNaCl.detached(new Uint8Array(data), new Uint8Array(prv))
return { signature: sig.buffer }
} catch (err) {
throw new TypeError('Invalid seed')
}
this.#seed = seed
- if (mnemonic != null) this.#mnemonic = await Bip39Mnemonic.fromPhrase(mnemonic)
+ if (mnemonic != null) this.#mnemonic = await Bip39.fromPhrase(mnemonic)
this.#locked = false
return { isUnlocked: !this.#locked }
} catch (err) {
${importWorkerThreads}
${Convert}
${Constants}
- const Bip39Mnemonic = ${Bip39Mnemonic}
- const Bip44Ckd = ${Bip44Ckd}
+ const Bip39 = ${Bip39}
+ const Bip44 = ${Bip44}
const Blake2b = ${Blake2b}
const Entropy = ${Entropy}
const NanoNaCl = ${NanoNaCl}
//! SPDX-License-Identifier: GPL-3.0-or-later\r
\r
import { Account, AccountList } from './account'\r
-import { Bip39Mnemonic } from './bip39'\r
+import { Bip39 } from './bip39'\r
import { Block } from './block'\r
import { ADDRESS_GAP } from './constants'\r
import { bytes, hex, utf8 } from './convert'\r
}\r
if (/^(?:[A-F0-9]{64}){1,2}$/i.test(secret)) {\r
data.seed = hex.toBuffer(secret)\r
- } else if (await Bip39Mnemonic.validate(secret)) {\r
+ } else if (await Bip39.validate(secret)) {\r
data.mnemonicPhrase = secret.toLowerCase()\r
if (mnemonicSalt != null) data.mnemonicSalt = mnemonicSalt\r
} else {\r