UNPKG

@bsv/sdk

Version:

BSV Blockchain Software Development Kit

354 lines 15.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); // @ts-nocheck const utils_js_1 = require("../primitives/utils.js"); const Hash = __importStar(require("../primitives/Hash.js")); const Curve_js_1 = __importDefault(require("../primitives/Curve.js")); const PrivateKey_js_1 = __importDefault(require("../primitives/PrivateKey.js")); const PublicKey_js_1 = __importDefault(require("../primitives/PublicKey.js")); const Random_js_1 = __importDefault(require("../primitives/Random.js")); const BigNumber_js_1 = __importDefault(require("../primitives/BigNumber.js")); /** * @deprecated * The HD class implements the Bitcoin Improvement Proposal 32 (BIP32) hierarchical deterministic wallets. * It allows the generation of child keys from a master key, ensuring a tree-like structure of keys and addresses. * This class is deprecated due to the introduction of BRC-42, which offers an enhanced key derivation scheme. * BRC-42 uses invoice numbers for key derivation, improving privacy and scalability compared to BIP32. * * @class HD * @deprecated Replaced by BRC-42 which uses invoice numbers and supports private derivation. */ class HD { /** * Constructor for the BIP32 HD wallet. * Initializes an HD wallet with optional parameters for version bytes, depth, parent fingerprint, child index, chain code, private key, and public key. * @param versionBytesNum - Version bytes number for the wallet. * @param depth - Depth of the key in the hierarchy. * @param parentFingerPrint - Fingerprint of the parent key. * @param childIndex - Index of the child key. * @param chainCode - Chain code for key derivation. * @param privKey - Private key of the wallet. * @param pubKey - Public key of the wallet. */ constructor(versionBytesNum, depth, parentFingerPrint, childIndex, chainCode, privKey, pubKey) { this.constants = { pubKey: 0x0488b21e, privKey: 0x0488ade4 }; this.versionBytesNum = versionBytesNum; this.depth = depth; this.parentFingerPrint = parentFingerPrint; this.childIndex = childIndex; this.chainCode = chainCode; this.privKey = privKey; this.pubKey = pubKey; } /** * Generates a new HD wallet with random keys. * This method creates a root HD wallet with randomly generated private and public keys. * @returns {HD} The current HD instance with generated keys. */ fromRandom() { this.versionBytesNum = this.constants.privKey; this.depth = 0x00; this.parentFingerPrint = [0, 0, 0, 0]; this.childIndex = 0; this.chainCode = (0, Random_js_1.default)(32); this.privKey = PrivateKey_js_1.default.fromRandom(); this.pubKey = this.privKey.toPublicKey(); return this; } /** * Generates a new HD wallet with random keys. * This method creates a root HD wallet with randomly generated private and public keys. * @returns {HD} A new HD instance with generated keys. * @static */ static fromRandom() { return new this().fromRandom(); } /** * Initializes the HD wallet from a given base58 encoded string. * This method decodes a provided string to set up the HD wallet's properties. * @param str - A base58 encoded string representing the wallet. * @returns {HD} The new instance with properties set from the string. */ static fromString(str) { return new this().fromString(str); } /** * Initializes the HD wallet from a given base58 encoded string. * This method decodes a provided string to set up the HD wallet's properties. * @param str - A base58 encoded string representing the wallet. * @returns {HD} The current instance with properties set from the string. */ fromString(str) { const decoded = (0, utils_js_1.fromBase58Check)(str); return this.fromBinary([...decoded.prefix, ...decoded.data]); } /** * Initializes the HD wallet from a seed. * This method generates keys and other properties from a given seed, conforming to the BIP32 specification. * @param bytes - An array of bytes representing the seed. * @returns {HD} The current instance with properties set from the seed. */ static fromSeed(bytes) { return new this().fromSeed(bytes); } /** * Initializes the HD wallet from a seed. * This method generates keys and other properties from a given seed, conforming to the BIP32 specification. * @param bytes - An array of bytes representing the seed. * @returns {HD} The current instance with properties set from the seed. */ fromSeed(bytes) { if (bytes.length < 128 / 8) { throw new Error('Need more than 128 bits of entropy'); } if (bytes.length > 512 / 8) { throw new Error('More than 512 bits of entropy is nonstandard'); } const hash = Hash.sha512hmac((0, utils_js_1.toArray)('Bitcoin seed', 'utf8'), bytes); this.depth = 0x00; this.parentFingerPrint = [0, 0, 0, 0]; this.childIndex = 0; this.chainCode = hash.slice(32, 64); this.versionBytesNum = this.constants.privKey; this.privKey = new PrivateKey_js_1.default(hash.slice(0, 32)); this.pubKey = this.privKey.toPublicKey(); return this; } /** * Initializes the HD wallet from a binary buffer. * Parses a binary buffer to set up the wallet's properties. * @param buf - A buffer containing the wallet data. * @returns {HD} The new instance with properties set from the buffer. */ static fromBinary(buf) { return new this().fromBinary(buf); } /** * Initializes the HD wallet from a binary buffer. * Parses a binary buffer to set up the wallet's properties. * @param buf - A buffer containing the wallet data. * @returns {HD} The current instance with properties set from the buffer. */ fromBinary(buf) { // Both pub and private extended keys are 78 buf if (buf.length !== 78) { throw new Error('incorrect bip32 data length'); } const reader = new utils_js_1.Reader(buf); this.versionBytesNum = reader.readUInt32BE(); this.depth = reader.readUInt8(); this.parentFingerPrint = reader.read(4); this.childIndex = reader.readUInt32BE(); this.chainCode = reader.read(32); const keyBytes = reader.read(33); const isPrivate = this.versionBytesNum === this.constants.privKey; const isPublic = this.versionBytesNum === this.constants.pubKey; if (isPrivate && keyBytes[0] === 0) { this.privKey = new PrivateKey_js_1.default(keyBytes.slice(1, 33)); this.pubKey = this.privKey.toPublicKey(); } else if (isPublic && (keyBytes[0] === 0x02 || keyBytes[0] === 0x03)) { this.pubKey = PublicKey_js_1.default.fromString((0, utils_js_1.toHex)(keyBytes)); } else { throw new Error('Invalid key'); } return this; } /** * Converts the HD wallet to a base58 encoded string. * This method provides a string representation of the HD wallet's current state. * @returns {string} A base58 encoded string of the HD wallet. */ toString() { const bin = this.toBinary(); return (0, utils_js_1.toBase58Check)(bin, []); } /** * Derives a child HD wallet based on a given path. * The path specifies the hierarchy of the child key to be derived. * @param path - A string representing the derivation path (e.g., 'm/0'/1). * @returns {HD} A new HD instance representing the derived child wallet. */ derive(path) { if (path === 'm') { return this; } const e = path.split('/'); // eslint-disable-next-line @typescript-eslint/no-this-alias let bip32 = this; for (const [i, c] of e.entries()) { if (i === 0) { // Since `i` is now a number, compare it to 0 if (c !== 'm') { throw new Error('invalid path'); } continue; } if (parseInt(c.replace("'", ''), 10).toString() !== c.replace("'", '')) { throw new Error('invalid path'); } const usePrivate = c.length > 1 && c[c.length - 1] === "'"; let childIndex = parseInt(usePrivate ? c.slice(0, c.length - 1) : c, 10) & 0x7fffffff; if (usePrivate) { childIndex += 0x80000000; } bip32 = bip32.deriveChild(childIndex); } return bip32; } /** * Derives a child HD wallet from the current wallet based on an index. * This method generates either a private or public child key depending on the current wallet's state. * @param i - The index of the child key to derive. * @returns {HD} A new HD instance representing the derived child wallet. */ deriveChild(i) { if (typeof i !== 'number') { throw new Error('i must be a number'); } const ibc = []; ibc.push((i >> 24) & 0xff); ibc.push((i >> 16) & 0xff); ibc.push((i >> 8) & 0xff); ibc.push(i & 0xff); const ib = [...ibc]; const usePrivate = (i & 0x80000000) !== 0; const isPrivate = this.versionBytesNum === this.constants.privKey; if (usePrivate && (this.privKey === null || this.privKey === undefined || !isPrivate)) { throw new Error('Cannot do private key derivation without private key'); } let ret = null; if (this.privKey !== null && this.privKey !== undefined) { let data = null; if (usePrivate) { data = [0, ...this.privKey.toArray('be', 32), ...ib]; } else { data = [...this.pubKey.encode(true), ...ib]; } const hash = Hash.sha512hmac(this.chainCode, data); const il = new BigNumber_js_1.default(hash.slice(0, 32)); const ir = hash.slice(32, 64); // ki = IL + kpar (mod n). const k = il.add(this.privKey).mod(new Curve_js_1.default().n); ret = new HD(); ret.chainCode = ir; ret.privKey = new PrivateKey_js_1.default(k.toArray()); ret.pubKey = ret.privKey.toPublicKey(); } else { const data = [...this.pubKey.encode(true), ...ib]; const hash = Hash.sha512hmac(this.chainCode, data); const il = new BigNumber_js_1.default(hash.slice(0, 32)); const ir = hash.slice(32, 64); // Ki = (IL + kpar)*G = IL*G + Kpar const ilG = new Curve_js_1.default().g.mul(il); const Kpar = this.pubKey; const Ki = ilG.add(Kpar); const newpub = new PublicKey_js_1.default(Ki.x, Ki.y); ret = new HD(); ret.chainCode = ir; ret.pubKey = newpub; } ret.childIndex = i; const pubKeyhash = Hash.hash160(this.pubKey.encode(true)); ret.parentFingerPrint = pubKeyhash.slice(0, 4); ret.versionBytesNum = this.versionBytesNum; ret.depth = this.depth + 1; return ret; } /** * Converts the current HD wallet to a public-only wallet. * This method strips away the private key information, leaving only the public part. * @returns {HD} A new HD instance representing the public-only wallet. */ toPublic() { const bip32 = new HD(this.versionBytesNum, this.depth, this.parentFingerPrint, this.childIndex, this.chainCode, this.privKey, this.pubKey); bip32.versionBytesNum = this.constants.pubKey; bip32.privKey = undefined; return bip32; } /** * Converts the HD wallet into a binary representation. * This method serializes the wallet's properties into a binary format. * @returns {number[]} An array of numbers representing the binary data of the wallet. */ toBinary() { const isPrivate = this.versionBytesNum === this.constants.privKey; const isPublic = this.versionBytesNum === this.constants.pubKey; if (isPrivate) { return new utils_js_1.Writer() .writeUInt32BE(this.versionBytesNum) .writeUInt8(this.depth) .write(this.parentFingerPrint) .writeUInt32BE(this.childIndex) .write(this.chainCode) .writeUInt8(0) .write(this.privKey.toArray('be', 32)) .toArray(); } else if (isPublic) { return new utils_js_1.Writer() .writeUInt32BE(this.versionBytesNum) .writeUInt8(this.depth) .write(this.parentFingerPrint) .writeUInt32BE(this.childIndex) .write(this.chainCode) .write(this.pubKey.encode(true)) .toArray(); } else { throw new Error('bip32: invalid versionBytesNum byte'); } } /** * Checks if the HD wallet contains a private key. * This method determines whether the wallet is a private key wallet or a public key only wallet. * @returns {boolean} A boolean value indicating whether the wallet has a private key (true) or not (false). */ isPrivate() { return this.versionBytesNum === this.constants.privKey; } } exports.default = HD; //# sourceMappingURL=HD.js.map