UNPKG

chaingate

Version:

Multi-chain cryptocurrency SDK for TypeScript — unified API for Bitcoin, Ethereum, Litecoin, Dogecoin, Bitcoin Cash, Polygon, Arbitrum, and any EVM-compatible chain. Create wallets, query balances, send transactions, and manage tokens and NFTs across UTXO

141 lines (140 loc) 5.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HDWallet = void 0; const bip32_1 = require("@scure/bip32"); const SigningWallet_1 = require("../SigningWallet"); const DerivedKey_1 = require("../../DerivedKey"); const DerivedPublicKey_1 = require("../../DerivedPublicKey"); const utils_1 = require("../../../utils"); const constants_1 = require("../../../constants"); const errors_1 = require("../../errors"); function requirePublicKey(key) { if (!key.publicKey) throw new errors_1.HDKeyNullError('publicKey'); return key.publicKey; } function requirePrivateKey(key) { if (!key.privateKey) throw new errors_1.HDKeyNullError('privateKey'); return key.privateKey; } /** * Base class for HD wallets. Derive unlimited child keys from a single secret. * * Common derivation paths are pre-computed and cached automatically. * * @typeParam T - The secret type (e.g. {@link Phrase}, {@link Seed}, {@link Xpriv}). * * @example * ```ts * const key = await wallet.derive("m/44'/60'/0'/0/0"); * const pubKey = await wallet.derivePublicKey("m/44'/0'/0'/0/0"); * ``` */ class HDWallet extends SigningWallet_1.SigningWallet { /** @internal */ constructor(secret, restoreData) { super(secret); this._derivationIndex = new Map((restoreData?.derivationIndex ?? []).map((e) => [e.derivationPath, e])); if (!secret.encrypted) { const master = this.createMasterKey(); this._publicKey = (0, utils_1.bytesToHex)(requirePublicKey(master)); for (const path of constants_1.commonDerivationPaths) { if (!this._derivationIndex.has(path)) { const derived = master.derive(path); this._derivationIndex.set(path, { derivationPath: path, xpub: derived.publicExtendedKey, publicKey: (0, utils_1.bytesToHex)(requirePublicKey(derived)), }); } } } else { this._publicKey = restoreData?.masterPublicKey ?? ''; } } createMasterKey() { const source = this.getKeySource(); return 'seed' in source ? bip32_1.HDKey.fromMasterSeed(source.seed) : bip32_1.HDKey.fromExtendedKey(source.xpriv); } /** The master public key as a hex string. */ get publicKey() { return this._publicKey; } /** All derivation paths that have been used, with their cached public keys. */ get derivationIndex() { return [...this._derivationIndex.values()]; } /** * Derives only the public key at a given path. Returns cached results when available. * * @param derivationPath - e.g. `"m/44'/60'/0'/0/0"`. */ async derivePublicKey(derivationPath) { const cached = this._derivationIndex.get(derivationPath); if (cached) { return new DerivedPublicKey_1.DerivedPublicKey({ publicKey: (0, utils_1.hexToBytes)(cached.publicKey), xpub: cached.xpub, }); } return this.secret.withDecrypted(() => { const master = this.createMasterKey(); const derived = derivationPath ? master.derive(derivationPath) : master; if (derivationPath) { this._derivationIndex.set(derivationPath, { derivationPath, xpub: derived.publicExtendedKey, publicKey: (0, utils_1.bytesToHex)(requirePublicKey(derived)), }); } if (!this._publicKey) { this._publicKey = (0, utils_1.bytesToHex)(requirePublicKey(master)); } return new DerivedPublicKey_1.DerivedPublicKey({ publicKey: requirePublicKey(derived), xpub: derived.publicExtendedKey, }); }); } /** * Derives a full key pair (public + private) at a given path. * * @param derivationPath - e.g. `"m/44'/60'/0'/0/0"`. */ async derive(derivationPath) { return this.secret.withDecrypted(() => { const master = this.createMasterKey(); const derived = derivationPath ? master.derive(derivationPath) : master; if (derivationPath && !this._derivationIndex.has(derivationPath)) { this._derivationIndex.set(derivationPath, { derivationPath, xpub: derived.publicExtendedKey, publicKey: (0, utils_1.bytesToHex)(requirePublicKey(derived)), }); } if (!this._publicKey) { this._publicKey = (0, utils_1.bytesToHex)(requirePublicKey(master)); } return new DerivedKey_1.DerivedKey({ privateKey: requirePrivateKey(derived), publicKey: requirePublicKey(derived), xpriv: derived.privateExtendedKey, xpub: derived.publicExtendedKey, }); }); } /** @inheritdoc */ async serialize(options) { const base = await super.serialize(options); return { ...base, derivationIndex: this.derivationIndex, masterPublicKey: this._publicKey || undefined, }; } } exports.HDWallet = HDWallet;