UNPKG

@hdwallet/core

Version:

A complete Hierarchical Deterministic (HD) Wallet generator for 200+ cryptocurrencies, built with TypeScript.

1,378 lines (1,366 loc) 1.86 MB
const __$G = (typeof globalThis !== 'undefined' ? globalThis: typeof window !== 'undefined' ? window: typeof global !== 'undefined' ? global: typeof self !== 'undefined' ? self: {}); // SPDX-License-Identifier: MIT const __name__ = 'hdwallet'; const __version__ = '1.0.0-beta.10'; const __license__ = 'MIT'; const __author__ = 'Meheret Tesfaye Batu'; const __email__ = 'meherett.batu@gmail.com'; // export const __documentation__: string = '...'; const __description__ = 'A complete Hierarchical Deterministic (HD) Wallet generator for 200+ cryptocurrencies, built with TypeScript.'; const __url__ = 'https://hdwallet.io'; const __source__ = 'https://github.com/hdwallet-io/hdwallet.js'; const __changelog__ = `${__source__}/blob/master/CHANGELOG.md`; const __tracker__ = `${__source__}/issues`; const __keywords__ = [ 'ecc', 'kholaw', 'slip10', 'ed25519', 'nist256p1', 'secp256k1', 'hd', 'bip32', 'bip44', 'bip49', 'bip84', 'bip86', 'bip141', 'monero', 'cardano', 'entropy', 'mnemonic', 'seed', 'bip39', 'algorand', 'electrum', 'cryptocurrencies', 'bitcoin', 'ethereum', 'cryptography', 'cli', 'cip1852' ]; const __websites__ = [ 'https://talonlab.org', 'https://talonlab.gitbook.io/hdwallet', // __documentation__, 'https://hdwallet.online', 'https://hd.wallet', __url__ ]; var info = /*#__PURE__*/Object.freeze({ __proto__: null, __name__: __name__, __version__: __version__, __license__: __license__, __author__: __author__, __email__: __email__, __description__: __description__, __url__: __url__, __source__: __source__, __changelog__: __changelog__, __tracker__: __tracker__, __keywords__: __keywords__, __websites__: __websites__ }); // SPDX-License-Identifier: MIT class BaseError extends Error { constructor(message, options) { if ((options?.expected || options?.got) && options?.detail) { super(`${message}, (expected: ${options?.expected} | got: ${options?.got}) ${options?.detail}`); } else if (options?.expected || options?.got) { super(`${message}, (expected: ${options?.expected} | got: ${options?.got})`); } else if (options?.detail) { super(`${message} ${options?.detail}`); } else { super(`${message}`); } } } class TypeError$1 extends BaseError { } class EntropyError extends BaseError { } class MnemonicError extends BaseError { } class SeedError extends BaseError { } class ECCError extends BaseError { } class ExtendedKeyError extends BaseError { } class XPrivateKeyError extends BaseError { } class XPublicKeyError extends BaseError { } class PrivateKeyError extends BaseError { } class WIFError extends BaseError { } class PublicKeyError extends BaseError { } class ChecksumError extends BaseError { } class SemanticError extends BaseError { } class NetworkError extends BaseError { } class AddressError extends BaseError { } class CryptocurrencyError extends BaseError { } class SymbolError extends BaseError { } class HDError extends BaseError { } class DerivationError extends BaseError { } const crypto$2 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined; /** * Utilities for hex, bytes, CSPRNG. * @module */ /** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */ function isBytes(a) { return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array'); } /** Asserts something is positive integer. */ function anumber(n) { if (!Number.isSafeInteger(n) || n < 0) throw new Error('positive integer expected, got ' + n); } /** Asserts something is Uint8Array. */ function abytes(b, ...lengths) { if (!isBytes(b)) throw new Error('Uint8Array expected'); if (lengths.length > 0 && !lengths.includes(b.length)) throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length); } /** Asserts something is hash */ function ahash(h) { if (typeof h !== 'function' || typeof h.create !== 'function') throw new Error('Hash should be wrapped by utils.createHasher'); anumber(h.outputLen); anumber(h.blockLen); } /** Asserts a hash instance has not been destroyed / finished */ function aexists(instance, checkFinished = true) { if (instance.destroyed) throw new Error('Hash instance has been destroyed'); if (checkFinished && instance.finished) throw new Error('Hash#digest() has already been called'); } /** Asserts output is properly-sized byte array */ function aoutput(out, instance) { abytes(out); const min = instance.outputLen; if (out.length < min) { throw new Error('digestInto() expects output buffer of length at least ' + min); } } /** Cast u8 / u16 / u32 to u32. */ function u32(arr) { return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); } /** Zeroize a byte array. Warning: JS provides no guarantees. */ function clean(...arrays) { for (let i = 0; i < arrays.length; i++) { arrays[i].fill(0); } } /** Create DataView of an array for easy byte-level manipulation. */ function createView(arr) { return new DataView(arr.buffer, arr.byteOffset, arr.byteLength); } /** The rotate right (circular right shift) operation for uint32 */ function rotr(word, shift) { return (word << (32 - shift)) | (word >>> shift); } /** The rotate left (circular left shift) operation for uint32 */ function rotl(word, shift) { return (word << shift) | ((word >>> (32 - shift)) >>> 0); } /** Is current platform little-endian? Most are. Big-Endian platform: IBM */ const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)(); /** The byte swap operation for uint32 */ function byteSwap(word) { return (((word << 24) & 0xff000000) | ((word << 8) & 0xff0000) | ((word >>> 8) & 0xff00) | ((word >>> 24) & 0xff)); } /** Conditionally byte swap if on a big-endian platform */ const swap8IfBE = isLE ? (n) => n : (n) => byteSwap(n); /** In place byte swap for Uint32Array */ function byteSwap32(arr) { for (let i = 0; i < arr.length; i++) { arr[i] = byteSwap(arr[i]); } return arr; } const swap32IfBE = isLE ? (u) => u : byteSwap32; // Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex const hasHexBuiltin = /* @__PURE__ */ (() => // @ts-ignore typeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')(); // Array where index 0xf0 (240) is mapped to string 'f0' const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')); /** * Convert byte array to hex string. Uses built-in function, when available. * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' */ function bytesToHex$1(bytes) { abytes(bytes); // @ts-ignore if (hasHexBuiltin) return bytes.toHex(); // pre-caching improves the speed 6x let hex = ''; for (let i = 0; i < bytes.length; i++) { hex += hexes[bytes[i]]; } return hex; } // We use optimized technique to convert hex string to byte array const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 }; function asciiToBase16(ch) { if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; // '2' => 50-48 if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); // 'B' => 66-(65-10) if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); // 'b' => 98-(97-10) return; } /** * Convert hex string to byte array. Uses built-in function, when available. * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23]) */ function hexToBytes$1(hex) { if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex); // @ts-ignore if (hasHexBuiltin) return Uint8Array.fromHex(hex); const hl = hex.length; const al = hl / 2; if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl); const array = new Uint8Array(al); for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { const n1 = asciiToBase16(hex.charCodeAt(hi)); const n2 = asciiToBase16(hex.charCodeAt(hi + 1)); if (n1 === undefined || n2 === undefined) { const char = hex[hi] + hex[hi + 1]; throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi); } array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163 } return array; } /** * Converts string to bytes using UTF8 encoding. * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99]) */ function utf8ToBytes(str) { if (typeof str !== 'string') throw new Error('string expected'); return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809 } /** * Normalizes (non-hex) string or Uint8Array to Uint8Array. * Warning: when Uint8Array is passed, it would NOT get copied. * Keep in mind for future mutable operations. */ function toBytes(data) { if (typeof data === 'string') data = utf8ToBytes(data); abytes(data); return data; } /** * Helper for KDFs: consumes uint8array or string. * When string is passed, does utf8 decoding, using TextDecoder. */ function kdfInputToBytes(data) { if (typeof data === 'string') data = utf8ToBytes(data); abytes(data); return data; } /** Copies several Uint8Arrays into one. */ function concatBytes$1(...arrays) { let sum = 0; for (let i = 0; i < arrays.length; i++) { const a = arrays[i]; abytes(a); sum += a.length; } const res = new Uint8Array(sum); for (let i = 0, pad = 0; i < arrays.length; i++) { const a = arrays[i]; res.set(a, pad); pad += a.length; } return res; } function checkOpts(defaults, opts) { if (opts !== undefined && {}.toString.call(opts) !== '[object Object]') throw new Error('options should be object or undefined'); const merged = Object.assign(defaults, opts); return merged; } /** For runtime check if class implements interface */ class Hash { } /** Wraps hash function, creating an interface on top of it */ function createHasher(hashCons) { const hashC = (msg) => hashCons().update(toBytes(msg)).digest(); const tmp = hashCons(); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; hashC.create = () => hashCons(); return hashC; } function createOptHasher(hashCons) { const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest(); const tmp = hashCons({}); hashC.outputLen = tmp.outputLen; hashC.blockLen = tmp.blockLen; hashC.create = (opts) => hashCons(opts); return hashC; } /** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */ function randomBytes$1(bytesLength = 32) { if (crypto$2 && typeof crypto$2.getRandomValues === 'function') { return crypto$2.getRandomValues(new Uint8Array(bytesLength)); } // Legacy Node.js compatibility if (crypto$2 && typeof crypto$2.randomBytes === 'function') { return Uint8Array.from(crypto$2.randomBytes(bytesLength)); } throw new Error('crypto.getRandomValues must be defined'); } // SPDX-License-Identifier: MIT function getBytes(data, encoding = 'hex') { if (data == null) { return new Uint8Array(); } // Already a Uint8Array? if (data instanceof Uint8Array) { return data; } // Array of numbers? if (Array.isArray(data)) { return new Uint8Array(data); } // From here on: data is a string const str = data; switch (encoding) { case 'hex': { // Strip optional 0x/0X let s = str.startsWith('0x') || str.startsWith('0X') ? str.slice(2) : str; // Pad odd length if (s.length % 2 === 1) s = '0' + s; // Split into byte-pairs and parse return Uint8Array.from(s.match(/.{1,2}/g).map(b => parseInt(b, 16))); } case 'utf8': return new TextEncoder().encode(str); case 'base64': // atob → binary-string → map char codes return Uint8Array.from(atob(str), c => c.charCodeAt(0)); default: throw new Error(`Unsupported encoding: ${encoding}`); } } function toBuffer(input, encoding = 'utf8') { if (typeof input === 'string') { switch (encoding) { case 'utf8': // UTF-8 encode a string return new TextEncoder().encode(input); case 'base64': // atob gives a binary‐string; map char→byte return Uint8Array.from(atob(input), c => c.charCodeAt(0)); case 'hex': // split every two hex digits → parse → byte return Uint8Array.from(input.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); default: throw new Error(`Unsupported encoding: ${encoding}`); } } // If it's already an ArrayBuffer or TypedArray if (input instanceof ArrayBuffer) { return new Uint8Array(input); } if (ArrayBuffer.isView(input)) { return new Uint8Array(input.buffer, input.byteOffset, input.byteLength); } // Fallback: try Array-like (e.g. number[]) return Uint8Array.from(input); } function hexToBytes(hex) { const normalized = hex.startsWith('0x') ? hex.slice(2) : hex; if (normalized.length % 2 !== 0) { throw new Error(`Invalid hex string length: ${normalized.length}`); } const bytes = new Uint8Array(normalized.length / 2); for (let i = 0; i < bytes.length; i++) { bytes[i] = parseInt(normalized.substr(i * 2, 2), 16); } return bytes; } function bytesToHex(bytes, prefix = false) { const hex = Array.from(bytes) .map(b => b.toString(16).padStart(2, '0')) .join(''); return prefix ? `0x${hex}` : hex; } function bytesToString(data) { if (data == null || (typeof data === 'string' && data.length === 0) || (data instanceof Uint8Array && data.length === 0)) { return ''; } if (typeof data === 'string') { // If it’s a valid even-length hex string (0–9, A–F, a–f), return it lowercased: if (data.length % 2 === 0 && /^[0-9A-Fa-f]+$/.test(data)) { return data.toLowerCase(); } // Otherwise treat `data` as UTF-8 text: encode to Uint8Array then to hex const encoder = new TextEncoder(); const bytes = encoder.encode(data); return bytesToHex(bytes); } // Uint8Array case: just convert those bytes to hex return bytesToHex(data); } function randomBytes(len) { if (!Number.isInteger(len) || len <= 0) { throw new Error('randomBytes: length must be a positive integer'); } return randomBytes$1(len); } function bytesToInteger(bytes, littleEndian = false) { // if little-endian, reverse into a new array const data = littleEndian ? bytes.slice().reverse() : bytes; return data.reduce((acc, b) => (acc << BigInt(8)) + BigInt(b), BigInt(0)); } function ensureString(data) { if (data instanceof Uint8Array) { return new TextDecoder().decode(data); } if (typeof data === 'string') { return data; } throw new TypeError$1('Invalid value for string'); } function stringToInteger(data) { let buf; if (typeof data === 'string') { // treat string as hex (even-length hex string) buf = hexToBytes(data); } else { buf = data; } let val = BigInt(0); for (let i = 0; i < buf.length; i++) { val = (val << BigInt(8)) + BigInt(buf[i]); } return val; } function equalBytes(a, b) { if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; } function integerToBytes(value, length, endianness = 'big') { // coerce to BigInt without using 0n let val = typeof value === 'number' ? BigInt(value) : value; if (val < BigInt(0)) { throw new Error(`Cannot convert negative integers: ${val}`); } // build big-endian array const bytes = []; const ZERO = BigInt(0); const SHIFT = BigInt(8); const MASK = BigInt(0xff); while (val > ZERO) { // val & 0xffn → val & MASK bytes.unshift(Number(val & MASK)); // val >>= 8n → val = val >> SHIFT val = val >> SHIFT; } if (bytes.length === 0) { bytes.push(0); } // pad/truncate if (length !== undefined) { if (bytes.length > length) { throw new Error(`Integer too large to fit in ${length} bytes`); } while (bytes.length < length) { bytes.unshift(0); } } const result = new Uint8Array(bytes); return endianness === 'little' ? result.reverse() : result; } function concatBytes(...chunks) { const totalLength = chunks.reduce((sum, arr) => sum + arr.length, 0); const result = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { result.set(chunk, offset); offset += chunk.length; } return result; } function bytesToBinaryString(data, zeroPadBits = 0) { const bits = Array.from(data) .map((b) => b.toString(2).padStart(8, '0')) .join(''); return bits.length < zeroPadBits ? bits.padStart(zeroPadBits, '0') : bits; } function binaryStringToInteger(data) { const bin = typeof data === 'string' ? data : bytesToBinaryString(data); const clean = bin.trim(); return BigInt('0b' + clean); } function integerToBinaryString(data, zeroPadBits = 0) { const big = typeof data === 'bigint' ? data : BigInt(data); const bits = big.toString(2); return bits.length < zeroPadBits ? bits.padStart(zeroPadBits, '0') : bits; } function binaryStringToBytes(data, zeroPadByteLen = 0) { const bits = typeof data === 'string' ? data.trim() : bytesToBinaryString(data); const bitLen = bits.length; const val = BigInt('0b' + bits); let hex = val.toString(16); if (hex.length % 2 === 1) { hex = '0' + hex; } const byteLen = zeroPadByteLen > 0 ? zeroPadByteLen : Math.ceil(bitLen / 8); const expectedHexLen = byteLen * 2; if (hex.length < expectedHexLen) { hex = hex.padStart(expectedHexLen, '0'); } return hexToBytes(hex); } function isAllEqual(...inputs) { if (inputs.length < 2) return true; const getTag = (v) => { if (typeof v === 'string') return 'string'; if (typeof v === 'number') return 'number'; if (typeof v === 'boolean') return 'boolean'; if (Array.isArray(v)) { if (v.every(i => typeof i === 'number')) return 'array:number'; if (v.every(i => typeof i === 'string')) return 'array:string'; if (v.every(i => typeof i === 'boolean')) return 'array:boolean'; return 'array:unknown'; } if (v instanceof Uint8Array) return 'uint8array'; if (v instanceof ArrayBuffer) return 'arraybuffer'; if (ArrayBuffer.isView(v)) return 'view'; return 'unknown'; }; const firstTag = getTag(inputs[0]); if (firstTag === 'unknown' || firstTag === 'array:unknown') return false; for (const v of inputs.slice(1)) { if (getTag(v) !== firstTag) return false; } if (firstTag === 'string' || firstTag === 'number' || firstTag === 'boolean') { const first = inputs[0]; return inputs.every(v => v === first); } if (firstTag.startsWith('array:')) { const firstArr = inputs[0]; const len = firstArr.length; return inputs.slice(1).every(item => { const arr = item; if (arr.length !== len) return false; for (let i = 0; i < len; i++) { if (arr[i] !== firstArr[i]) return false; } return true; }); } const normalize = (v) => { if (v instanceof Uint8Array) return v; if (v instanceof ArrayBuffer) return new Uint8Array(v); return new Uint8Array(v.buffer, v.byteOffset, v.byteLength); }; const firstArr = normalize(inputs[0]); const len = firstArr.byteLength; return inputs.slice(1).every(item => { const arr = normalize(item); if (arr.byteLength !== len) return false; for (let i = 0; i < len; i++) { if (arr[i] !== firstArr[i]) return false; } return true; }); } function generatePassphrase(length = 32, chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') { const bytes = randomBytes(length); let result = ''; for (let i = 0; i < length; i++) { result += chars[bytes[i] % chars.length]; } return result; } function getHmac(eccName) { const encoder = new TextEncoder(); if ([ 'Kholaw-Ed25519', 'SLIP10-Ed25519', 'SLIP10-Ed25519-Blake2b', 'SLIP10-Ed25519-Monero', ].includes(eccName)) { return encoder.encode('ed25519 seed'); } else if (eccName === 'SLIP10-Nist256p1') { return encoder.encode('Nist256p1 seed'); } else if (eccName === 'SLIP10-Secp256k1') { return encoder.encode('Bitcoin seed'); } throw new DerivationError('Unknown ECC name'); } function excludeKeys(nested, keys) { const out = {}; const keySet = new Set(keys); // optional optimization for (const [k, v] of Object.entries(nested)) { const normKey = k.replace(/-/g, '_'); if (keySet.has(normKey)) continue; if (v && typeof v === 'object' && !Array.isArray(v) && !(v instanceof Uint8Array) && !(v instanceof Uint8Array)) { out[k] = excludeKeys(v, keys); } else { out[k] = v; } } return out; } function pathToIndexes(path) { if (path === 'm' || path === 'm/') return []; if (!path.startsWith('m/')) { throw new DerivationError(`Bad path format, expected 'm/0'/0', got '${path}'`); } return path .slice(2) .split('/') .map(i => i.endsWith("'") ? parseInt(i.slice(0, -1), 10) + 0x80000000 : parseInt(i, 10)); } function indexesToPath(indexes) { return ('m' + indexes .map(i => i & 0x80000000 ? `/${(i & ~0x80000000).toString()}'` : `/${i.toString()}`) .join('')); } function normalizeIndex(index, hardened = false) { if (typeof index === 'number') { if (index < 0) throw new DerivationError(`Bad index: ${index}`); return [index, hardened]; } if (typeof index === 'string') { const m = index.match(/^(\d+)(?:-(\d+))?$/); if (!m) { throw new DerivationError(`Bad index format, got '${index}'`); } const from = parseInt(m[1], 10); const to = m[2] ? parseInt(m[2], 10) : undefined; if (to === undefined) return [from, hardened]; if (from > to) { throw new DerivationError(`Range start ${from} > end ${to}`); } return [from, to, hardened]; } if (Array.isArray(index)) { const [a, b] = index; if (index.length !== 2 || typeof a !== 'number' || typeof b !== 'number') { throw new DerivationError(`Bad index tuple: ${JSON.stringify(index)}`); } if (a < 0 || b < 0) { throw new DerivationError(`Negative in tuple: ${index}`); } if (a > b) { throw new DerivationError(`Range start ${a} > end ${b}`); } return [a, b, hardened]; } throw new DerivationError(`Invalid index instance, got ${typeof index}`); } function normalizeDerivation(path, indexes) { let _path = 'm'; const _indexes = []; const _deriv = []; if (indexes && path) { throw new DerivationError('Provide either path or indexes, not both'); } if (indexes) { path = indexesToPath(indexes); } if (!path || path === 'm' || path === 'm/') { return [`${_path}/`, _indexes, _deriv]; } if (!path.startsWith('m/')) { throw new DerivationError(`Bad path format, got '${path}'`); } for (const seg of path.slice(2).split('/')) { const hardened = seg.endsWith("'"); const core = hardened ? seg.slice(0, -1) : seg; const parts = core.split('-').map(x => parseInt(x, 10)); if (parts.length === 2) { const [from, to] = parts; if (from > to) { throw new DerivationError(`Range start ${from} > end ${to}`); } _deriv.push([from, to, hardened]); _indexes.push(to + (hardened ? 0x80000000 : 0)); _path += hardened ? `/${to}'` : `/${to}`; } else { const idx = parts[0]; _deriv.push([idx, hardened]); _indexes.push(idx + (hardened ? 0x80000000 : 0)); _path += hardened ? `/${idx}'` : `/${idx}`; } } return [_path, _indexes, _deriv]; } function indexTupleToInteger(idx) { if (idx.length === 2) { const [i, h] = idx; return i + (h ? 0x80000000 : 0); } else { const [from, to, h] = idx; return to + (h ? 0x80000000 : 0); } } function indexTupleToString(idx) { if (idx.length === 2) { const [i, h] = idx; return `${i}${h ? "'" : ''}`; } else { const [from, to, h] = idx; return `${from}-${to}${h ? "'" : ''}`; } } function indexStringToTuple(i) { const hardened = i.endsWith("'"); const num = parseInt(hardened ? i.slice(0, -1) : i, 10); return [num, hardened]; } function xor(a, b) { if (a.length !== b.length) throw new DerivationError('Uint8Arrays must match length for XOR'); return getBytes(a.map((x, i) => x ^ b[i])); } function addNoCarry(a, b) { if (a.length !== b.length) throw new DerivationError('Uint8Arrays must match length for addNoCarry'); return getBytes(a.map((x, i) => (x + b[i]) & 0xff)); } function multiplyScalarNoCarry(data, scalar) { return getBytes(data.map(x => (x * scalar) & 0xff)); } function isBitsSet(value, bitNum) { return (value & (1 << bitNum)) !== 0; } function areBitsSet(value, mask) { return (value & mask) !== 0; } function setBit(value, bitNum) { return value | (1 << bitNum); } function setBits(value, mask) { return value | mask; } function resetBit(value, bitNum) { return value & ~(1 << bitNum); } function resetBits(value, mask) { return value & ~mask; } function bytesReverse(data) { return getBytes(data).reverse(); } function convertBits$2(data, fromBits, toBits) { const input = Array.isArray(data) ? data : Array.from(data); const maxVal = (1 << toBits) - 1; let acc = 0; let bits = 0; const out = []; for (const val of input) { if (val < 0 || val >> fromBits) { return null; } acc |= val << bits; bits += fromBits; while (bits >= toBits) { out.push(acc & maxVal); acc >>= toBits; bits -= toBits; } } if (bits > 0) { out.push(acc & maxVal); } return out; } function bytesChunkToWords(bytesChunk, wordsList, endianness) { const len = BigInt(wordsList.length); let chunkNum = bytesToInteger(new Uint8Array(bytesChunk), endianness !== 'big'); const i1 = Number(chunkNum % len); const i2 = Number(((chunkNum / len) + BigInt(i1)) % len); const i3 = Number(((chunkNum / len / len) + BigInt(i2)) % len); return [wordsList[i1], wordsList[i2], wordsList[i3]]; } function wordsToBytesChunk(w1, w2, w3, wordsList, endianness) { const len = BigInt(wordsList.length); const idxMap = new Map(wordsList.map((w, i) => [w, BigInt(i)])); const i1 = idxMap.get(w1); const i2 = idxMap.get(w2); const i3 = idxMap.get(w3); const chunk = i1 + len * ((i2 - i1 + len) % len) + len * len * ((i3 - i2 + len) % len); const u8 = integerToBytes(chunk, 4, endianness); return getBytes(u8); } function toCamelCase(input) { return input.toLowerCase().replace(/-([a-z])/g, (_, char) => char.toUpperCase()); } function ensureTypeMatch(instanceOrClass, expectedType, options = {}) { const tryMatch = (type) => { if (type === 'any') return true; if (type === 'null') return instanceOrClass === null; if (type === 'array') return Array.isArray(instanceOrClass); if (typeof type === 'string') return typeof instanceOrClass === type; if (typeof type === 'function') { if (typeof instanceOrClass === 'function') { let proto = instanceOrClass; while (proto && proto !== Function.prototype) { if (proto === type) return true; proto = Object.getPrototypeOf(proto); } return false; } return options.strict ? instanceOrClass?.constructor === type : instanceOrClass instanceof type; } return false; }; const allExpectedTypes = [expectedType, ...(options.otherTypes || [])]; const matched = allExpectedTypes.find(tryMatch); if (!matched && (options.errorClass || options.otherTypes)) { const expectedNames = allExpectedTypes.map((type) => typeof type === 'function' ? type.name : String(type)); const gotName = typeof instanceOrClass === 'function' ? instanceOrClass.name : instanceOrClass?.constructor?.name ?? typeof instanceOrClass; if (options.errorClass) { throw new options.errorClass(`Invalid type`, { expected: expectedNames, got: gotName }); } else { throw new TypeError$1(`Invalid type`, { expected: expectedNames, got: gotName }); } } return matched && options.errorClass ? instanceOrClass : { value: instanceOrClass, isValid: tryMatch(expectedType) }; } var utils = /*#__PURE__*/Object.freeze({ __proto__: null, getBytes: getBytes, toBuffer: toBuffer, hexToBytes: hexToBytes, bytesToHex: bytesToHex, bytesToString: bytesToString, randomBytes: randomBytes, bytesToInteger: bytesToInteger, ensureString: ensureString, stringToInteger: stringToInteger, equalBytes: equalBytes, integerToBytes: integerToBytes, concatBytes: concatBytes, bytesToBinaryString: bytesToBinaryString, binaryStringToInteger: binaryStringToInteger, integerToBinaryString: integerToBinaryString, binaryStringToBytes: binaryStringToBytes, isAllEqual: isAllEqual, generatePassphrase: generatePassphrase, getHmac: getHmac, excludeKeys: excludeKeys, pathToIndexes: pathToIndexes, indexesToPath: indexesToPath, normalizeIndex: normalizeIndex, normalizeDerivation: normalizeDerivation, indexTupleToInteger: indexTupleToInteger, indexTupleToString: indexTupleToString, indexStringToTuple: indexStringToTuple, xor: xor, addNoCarry: addNoCarry, multiplyScalarNoCarry: multiplyScalarNoCarry, isBitsSet: isBitsSet, areBitsSet: areBitsSet, setBit: setBit, setBits: setBits, resetBit: resetBit, resetBits: resetBits, bytesReverse: bytesReverse, convertBits: convertBits$2, bytesChunkToWords: bytesChunkToWords, wordsToBytesChunk: wordsToBytesChunk, toCamelCase: toCamelCase, ensureTypeMatch: ensureTypeMatch }); // SPDX-License-Identifier: MIT class NestedNamespace { constructor(data) { if (data instanceof Set) { data.forEach(item => { this[item] = item; }); } else if (Array.isArray(data)) { data.forEach(item => { if (item != null && typeof item === 'object' && !Array.isArray(item)) { Object.entries(item).forEach(([key, value]) => { this[key] = (value != null && typeof value === 'object') ? new NestedNamespace(value) : value; }); } else { this[item] = item; } }); } else { Object.entries(data).forEach(([key, value]) => { this[key] = (value != null && typeof value === 'object') ? new NestedNamespace(value) : value; }); } } } const SLIP10_ED25519_CONST = { PRIVATE_KEY_BYTE_LENGTH: 32, PUBLIC_KEY_PREFIX: integerToBytes(0x00), PUBLIC_KEY_BYTE_LENGTH: 32 }; const KHOLAW_ED25519_CONST = { ...SLIP10_ED25519_CONST, PRIVATE_KEY_BYTE_LENGTH: 64 }; const SLIP10_SECP256K1_CONST = { POINT_COORDINATE_BYTE_LENGTH: 32, PRIVATE_KEY_BYTE_LENGTH: 32, PRIVATE_KEY_UNCOMPRESSED_PREFIX: 0x00, PRIVATE_KEY_COMPRESSED_PREFIX: 0x01, PUBLIC_KEY_UNCOMPRESSED_PREFIX: integerToBytes(0x04), PUBLIC_KEY_COMPRESSED_BYTE_LENGTH: 33, PUBLIC_KEY_UNCOMPRESSED_BYTE_LENGTH: 65, CHECKSUM_BYTE_LENGTH: 4 }; class Info extends NestedNamespace { SOURCE_CODE; WHITEPAPER; WEBSITES; constructor(data) { super(data); } } class WitnessVersions extends NestedNamespace { getWitnessVersion(address) { return this[address.toUpperCase()]; } } class Entropies extends NestedNamespace { isEntropy(entropy) { return this.getEntropies().includes(entropy); } getEntropies() { return Object.values(this); } } class Mnemonics extends NestedNamespace { isMnemonic(mnemonic) { return this.getMnemonics().includes(mnemonic); } getMnemonics() { return Object.values(this); } } class Seeds extends NestedNamespace { isSeed(seed) { return this.getSeeds().includes(seed); } getSeeds() { return Object.values(this); } } class HDs extends NestedNamespace { isHD(hd) { return this.getHDS().includes(hd); } getHDS() { return Object.values(this); } } class Addresses extends NestedNamespace { isAddress(address) { return this.getAddresses().includes(address); } getAddresses() { return Object.values(this); } length() { return this.getAddresses().length; } } class AddressTypes extends NestedNamespace { isAddressType(addressType) { return this.getAddressTypes().includes(addressType); } getAddressTypes() { return Object.values(this); } } class AddressPrefixes extends NestedNamespace { isAddressPrefix(addressPrefix) { return this.getAddressPrefixes().includes(addressPrefix); } getAddressPrefixes() { return Object.values(this); } } class Networks extends NestedNamespace { isNetwork(network) { return this.getNetworks().includes(network.toLowerCase()); } getNetworks() { return Object.keys(this).map(k => k.toLowerCase()); } getNetwork(network) { if (!this.isNetwork(network)) { throw new NetworkError(`${network} network is not available`); } return this[network.toUpperCase()]; } } class Params extends NestedNamespace { } class ExtendedKeyVersions extends NestedNamespace { isVersion(version) { return Object.values(this).includes(Number(bytesToInteger(version))); } getVersions() { return Object.keys(this).map(k => k.toLowerCase().replace(/_/g, '-')); } getVersion(name) { return this[name.toUpperCase().replace(/-/g, '_')]; } getName(version) { const intVer = bytesToInteger(version); return Object.entries(this).find(([, v]) => v === intVer)?.[0]; } } class XPrivateKeyVersions extends ExtendedKeyVersions { } class XPublicKeyVersions extends ExtendedKeyVersions { } class PUBLIC_KEY_TYPES { static UNCOMPRESSED = 'uncompressed'; static COMPRESSED = 'compressed'; static getTypes() { return [this.UNCOMPRESSED, this.COMPRESSED]; } } class WIF_TYPES { static WIF = 'wif'; static WIF_COMPRESSED = 'wif-compressed'; static getTypes() { return [this.WIF, this.WIF_COMPRESSED]; } } class SEMANTICS { static P2WPKH = 'p2wpkh'; static P2WPKH_IN_P2SH = 'p2wpkh-in-p2sh'; static P2WSH = 'p2wsh'; static P2WSH_IN_P2SH = 'p2wsh-in-p2sh'; static getTypes() { return [this.P2WPKH, this.P2WPKH_IN_P2SH, this.P2WSH, this.P2WSH_IN_P2SH]; } } class MODES { static STANDARD = 'standard'; static SEGWIT = 'segwit'; static getTypes() { return [this.STANDARD, this.SEGWIT]; } } var consts = /*#__PURE__*/Object.freeze({ __proto__: null, NestedNamespace: NestedNamespace, SLIP10_ED25519_CONST: SLIP10_ED25519_CONST, KHOLAW_ED25519_CONST: KHOLAW_ED25519_CONST, SLIP10_SECP256K1_CONST: SLIP10_SECP256K1_CONST, Info: Info, WitnessVersions: WitnessVersions, Entropies: Entropies, Mnemonics: Mnemonics, Seeds: Seeds, HDs: HDs, Addresses: Addresses, AddressTypes: AddressTypes, AddressPrefixes: AddressPrefixes, Networks: Networks, Params: Params, ExtendedKeyVersions: ExtendedKeyVersions, XPrivateKeyVersions: XPrivateKeyVersions, XPublicKeyVersions: XPublicKeyVersions, PUBLIC_KEY_TYPES: PUBLIC_KEY_TYPES, WIF_TYPES: WIF_TYPES, SEMANTICS: SEMANTICS, MODES: MODES }); /** * HMAC: RFC2104 message authentication code. * @module */ class HMAC extends Hash { constructor(hash, _key) { super(); this.finished = false; this.destroyed = false; ahash(hash); const key = toBytes(_key); this.iHash = hash.create(); if (typeof this.iHash.update !== 'function') throw new Error('Expected instance of class which extends utils.Hash'); this.blockLen = this.iHash.blockLen; this.outputLen = this.iHash.outputLen; const blockLen = this.blockLen; const pad = new Uint8Array(blockLen); // blockLen can be bigger than outputLen pad.set(key.length > blockLen ? hash.create().update(key).digest() : key); for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36; this.iHash.update(pad); // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone this.oHash = hash.create(); // Undo internal XOR && apply outer XOR for (let i = 0; i < pad.length; i++) pad[i] ^= 0x36 ^ 0x5c; this.oHash.update(pad); clean(pad); } update(buf) { aexists(this); this.iHash.update(buf); return this; } digestInto(out) { aexists(this); abytes(out, this.outputLen); this.finished = true; this.iHash.digestInto(out); this.oHash.update(out); this.oHash.digestInto(out); this.destroy(); } digest() { const out = new Uint8Array(this.oHash.outputLen); this.digestInto(out); return out; } _cloneInto(to) { // Create new instance without calling constructor since key already in state and we don't know it. to || (to = Object.create(Object.getPrototypeOf(this), {})); const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this; to = to; to.finished = finished; to.destroyed = destroyed; to.blockLen = blockLen; to.outputLen = outputLen; to.oHash = oHash._cloneInto(to.oHash); to.iHash = iHash._cloneInto(to.iHash); return to; } clone() { return this._cloneInto(); } destroy() { this.destroyed = true; this.oHash.destroy(); this.iHash.destroy(); } } /** * HMAC: RFC2104 message authentication code. * @param hash - function that would be used e.g. sha256 * @param key - message key * @param message - message data * @example * import { hmac } from '@noble/hashes/hmac'; * import { sha256 } from '@noble/hashes/sha2'; * const mac1 = hmac(sha256, 'key', 'message'); */ const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest(); hmac.create = (hash, key) => new HMAC(hash, key); var D$1=new Uint32Array(1);var n$1=new Uint32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117]);function t$2(x=new Uint8Array,B=0){D$1[0]=B^4294967295;for(let A of x)D$1[0]=n$1[(D$1[0]^A)&255]^D$1[0]>>>8;return (D$1[0]^4294967295)>>>0} var B$1=new Uint16Array(1);var n=new Uint16Array([0,4129,8258,12387,16516,20645,24774,28903,33032,37161,41290,45419,49548,53677,57806,61935,4657,528,12915,8786,21173,17044,29431,25302,37689,33560,45947,41818,54205,50076,62463,58334,9314,13379,1056,5121,25830,29895,17572,21637,42346,46411,34088,38153,58862,62927,50604,54669,13907,9842,5649,1584,30423,26358,22165,18100,46939,42874,38681,34616,63455,59390,55197,51132,18628,22757,26758,30887,2112,6241,10242,14371,51660,55789,59790,63919,35144,39273,43274,47403,23285,19156,31415,27286,6769,2640,14899,10770,56317,52188,64447,60318,39801,35672,47931,43802,27814,31879,19684,23749,11298,15363,3168,7233,60846,64911,52716,56781,44330,48395,36200,40265,32407,28342,24277,20212,15891,11826,7761,3696,65439,61374,57309,53244,48923,44858,40793,36728,37256,33193,45514,41451,53516,49453,61774,57711,4224,161,12482,8419,20484,16421,28742,24679,33721,37784,41979,46042,49981,54044,58239,62302,689,4752,8947,13010,16949,21012,25207,29270,46570,42443,38312,34185,62830,58703,54572,50445,13538,9411,5280,1153,29798,25671,21540,17413,42971,47098,34713,38840,59231,63358,50973,55100,9939,14066,1681,5808,26199,30326,17941,22068,55628,51565,63758,59695,39368,35305,47498,43435,22596,18533,30726,26663,6336,2273,14466,10403,52093,56156,60223,64286,35833,39896,43963,48026,19061,23124,27191,31254,2801,6864,10931,14994,64814,60687,56684,52557,48554,44427,40424,36297,31782,27655,23652,19525,15522,11395,7392,3265,61215,65342,53085,57212,44955,49082,36825,40952,28183,32310,20053,24180,11923,16050,3793,7920]);function t$1(x=new Uint8Array,A=0){B$1[0]=A;for(let C of x)B$1[0]=n[B$1[0]>>>8^C]^B$1[0]<<8;return B$1[0]} /** * Internal Merkle-Damgard hash utils. * @module */ /** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */ function setBigUint64(view, byteOffset, value, isLE) { if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE); const _32n = BigInt(32); const _u32_max = BigInt(0xffffffff); const wh = Number((value >> _32n) & _u32_max); const wl = Number(value & _u32_max); const h = isLE ? 4 : 0; const l = isLE ? 0 : 4; view.setUint32(byteOffset + h, wh, isLE); view.setUint32(byteOffset + l, wl, isLE); } /** Choice: a ? b : c */ function Chi(a, b, c) { return (a & b) ^ (~a & c); } /** Majority function, true if any two inputs is true. */ function Maj(a, b, c) { return (a & b) ^ (a & c) ^ (b & c); } /** * Merkle-Damgard hash construction base class. * Could be used to create MD5, RIPEMD, SHA1, SHA2. */ class HashMD extends Hash { constructor(blockLen, outputLen, padOffset, isLE) { super(); this.finished = false; this.length = 0; this.pos = 0; this.destroyed = false; this.blockLen = blockLen; this.outputLen = outputLen; this.padOffset = padOffset; this.isLE = isLE; this.buffer = new Uint8Array(blockLen); this.view = createView(this.buffer); } update(data) { aexists(this); data = toBytes(data); abytes(data); const { view, buffer, blockLen } = this; const len = data.length; for (let pos = 0; pos < len;) { const take = Math.min(blockLen - this.pos, len - pos); // Fast path: we have at least one block in input, cast it to view and process if (take === blockLen) { const dataView = createView(data); for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos); continue; } buffer.set(data.subarray(pos, pos + take), this.pos); this.pos += take; pos += take; if (this.pos === blockLen) { this.process(view, 0); this.pos = 0; } } this.length += data.length; this.roundClean(); return this; } digestInto(out) { aexists(this); aoutput(out, this); this.finished = true; // Padding // We can avoid allocation of buffer for padding completely if it // was previously not allocated here. But it won't change performance. const { buffer, view, blockLen, isLE } = this; let { pos } = this; // append the bit '1' to the message buffer[pos++] = 0b10000000; clean(this.buffer.subarray(pos)); // we have less than padOffset left in buffer, so we cannot put length in // current block, need process it and pad again if (this.padOffset > blockLen - pos) { this.process(view, 0); pos = 0; } // Pad until full block byte with zeros for (let i = pos; i < blockLen; i++) buffer[i] = 0; // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen. // So we just write lowest 64 bits of that value. setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE); this.process(view, 0); const oview = createView(out); const len = this.outputLen; // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit'); const outLen = len / 4; const state = this.get(); if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state'); for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE); } digest() { const { buffer, outputLen } = this; this.digestInto(buffer); const res = buffer.slice(0, outputLen); this.de