UNPKG

@btc-vision/transaction

Version:

OPNet transaction library allows you to create and sign transactions for the OPNet network.

168 lines 7.41 kB
import * as bip39 from 'bip39'; import { BIP32Factory, MLDSASecurityLevel, QuantumBIP32Factory, } from '@btc-vision/bip32'; import { networks, toHex } from '@btc-vision/bitcoin'; import { backend } from '../ecc/backend.js'; import { Wallet } from '../keypair/Wallet.js'; import { MnemonicStrength } from './MnemonicStrength.js'; import { BIPStandard, buildBIPPath } from './BIPStandard.js'; import { AddressTypes } from '../keypair/AddressVerificator.js'; const bip32 = BIP32Factory(backend); export { BIPStandard, getBIPDescription } from './BIPStandard.js'; /** * Mnemonic class for managing BIP39 mnemonic phrases with BIP360 quantum support */ export class Mnemonic { _phrase; _passphrase; _network; _securityLevel; _seed; _classicalRoot; _quantumRoot; constructor(phrase, passphrase = '', network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2) { if (!bip39.validateMnemonic(phrase)) { throw new Error('Invalid mnemonic phrase'); } this._phrase = phrase; this._passphrase = passphrase; this._network = network; this._securityLevel = securityLevel; // Derive the seed from the mnemonic this._seed = bip39.mnemonicToSeedSync(this._phrase, this._passphrase); // Create the classical BIP32 root this._classicalRoot = bip32.fromSeed(this._seed, this._network); // Create the quantum BIP32 root with network parameter this._quantumRoot = QuantumBIP32Factory.fromSeed(this._seed, this._network, this._securityLevel); } get phrase() { return this._phrase; } get network() { return this._network; } get securityLevel() { return this._securityLevel; } get seed() { return new Uint8Array(this._seed); } static generatePhrase(strength = MnemonicStrength.MAXIMUM) { return bip39.generateMnemonic(strength); } static generate(strength = MnemonicStrength.MAXIMUM, passphrase = '', network = networks.bitcoin, securityLevel = MLDSASecurityLevel.LEVEL2) { const phrase = bip39.generateMnemonic(strength); return new Mnemonic(phrase, passphrase, network, securityLevel); } static validate(phrase) { return bip39.validateMnemonic(phrase); } /** * Best-effort zeroing of secret material held by this mnemonic. * * Zeros the seed buffer and root private keys in-place. * The mnemonic phrase and passphrase are JS strings and cannot be zeroed. */ zeroize() { this._seed.fill(0); this._classicalRoot.privateKey?.fill(0); this._quantumRoot.privateKey?.fill(0); } [Symbol.dispose]() { this.zeroize(); } derive(index = 0, account = 0, isChange = false, bipStandard = BIPStandard.BIP84) { const classicalPath = this.buildClassicalPath(account, index, isChange, bipStandard); const classicalChild = this._classicalRoot.derivePath(classicalPath); if (!classicalChild.privateKey) { throw new Error(`Failed to derive classical private key at index ${index}`); } const quantumPath = this.buildQuantumPath(account, index, isChange); const quantumChild = this._quantumRoot.derivePath(quantumPath); if (!quantumChild.privateKey) { throw new Error(`Failed to derive quantum private key at index ${index}`); } return new Wallet(toHex(new Uint8Array(classicalChild.privateKey)), toHex(new Uint8Array(quantumChild.privateKey)), this._network, this._securityLevel, new Uint8Array(this._quantumRoot.chainCode)); } deriveOPWallet(addressType = AddressTypes.P2TR, index = 0, account = 0, isChange = false) { let purpose; switch (addressType) { case AddressTypes.P2PKH: purpose = 44; break; case AddressTypes.P2SH_OR_P2SH_P2WPKH: purpose = 49; break; case AddressTypes.P2WPKH: purpose = 84; break; case AddressTypes.P2TR: purpose = 86; break; default: throw new Error(`Unsupported address type: ${addressType}`); } const coinType = this.getCoinType(); const change = isChange ? 1 : 0; const classicalPath = `m/${purpose}'/0'/${account}'/${change}/${index}`; const classicalChild = this._classicalRoot.derivePath(classicalPath); if (!classicalChild.privateKey) { throw new Error(`Failed to derive classical private key at path ${classicalPath}`); } const quantumPath = `m/360'/${coinType}'/${account}'/${change}/${index}`; const quantumChild = this._quantumRoot.derivePath(quantumPath); if (!quantumChild.privateKey) { throw new Error(`Failed to derive quantum private key at path ${quantumPath}`); } return new Wallet(toHex(new Uint8Array(classicalChild.privateKey)), toHex(new Uint8Array(quantumChild.privateKey)), this._network, this._securityLevel, new Uint8Array(this._quantumRoot.chainCode)); } deriveMultipleOPWallet(addressType = AddressTypes.P2TR, count = 5, startIndex = 0, account = 0, isChange = false) { const wallets = []; for (let i = 0; i < count; i++) { wallets.push(this.deriveOPWallet(addressType, startIndex + i, account, isChange)); } return wallets; } deriveMultiple(count, startIndex = 0, account = 0, isChange = false, bipStandard = BIPStandard.BIP84) { const wallets = []; for (let i = 0; i < count; i++) { wallets.push(this.derive(startIndex + i, account, isChange, bipStandard)); } return wallets; } deriveCustomPath(classicalPath, quantumPath) { const classicalChild = this._classicalRoot.derivePath(classicalPath); const quantumChild = this._quantumRoot.derivePath(quantumPath); if (!classicalChild.privateKey) { throw new Error(`Failed to derive classical private key at path ${classicalPath}`); } if (!quantumChild.privateKey) { throw new Error(`Failed to derive quantum private key at path ${quantumPath}`); } return new Wallet(toHex(new Uint8Array(classicalChild.privateKey)), toHex(new Uint8Array(quantumChild.privateKey)), this._network, this._securityLevel, new Uint8Array(this._quantumRoot.chainCode)); } getClassicalRoot() { return this._classicalRoot; } getQuantumRoot() { return this._quantumRoot; } buildClassicalPath(account, index, isChange, bipStandard = BIPStandard.BIP84) { const coinType = this.getCoinType(); const change = isChange ? 1 : 0; return buildBIPPath(bipStandard, coinType, account, change, index); } buildQuantumPath(account, index, isChange) { const coinType = this.getCoinType(); const change = isChange ? 1 : 0; return `m/360'/${coinType}'/${account}'/${change}/${index}`; } getCoinType() { if (this._network.bech32 === networks.testnet.bech32 || this._network.bech32 === networks.opnetTestnet.bech32 || this._network.bech32 === networks.regtest.bech32) { return 1; } return 0; } } //# sourceMappingURL=Mnemonic.js.map