Wallet Management
Deriving Wallets
Once a mnemonic is created or restored, derive a wallet using the derive() method on the Mnemonic instance. This method generates the corresponding private key, public key, and address from the mnemonic phrase. To derive multiple wallets from the same mnemonic, use the deriveMultiple() method. The derivation process is deterministic, meaning the same mnemonic always produces the same wallets.
For advanced use cases, the Mnemonic class provides additional derivation methods. Use deriveCustomPath() to derive a wallet using a custom BIP32 derivation path. The deriveOPWallet() method derives a wallet compatible with the Unisat wallet format, while deriveMultipleUnisat() generates multiple Unisat-compatible wallets from the same mnemonic.
Single Wallet Derivation
import { Mnemonic, MnemonicStrength, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';
const mnemonic = Mnemonic.generate();
// Derive wallet at index 0
const wallet0 = mnemonic.derive(0);
// Derive wallet at index 1
const wallet1 = mnemonic.derive(1);
// Each wallet has both classical and quantum keys
console.log('Classical Public Key:', wallet0.publicKey);
console.log('Quantum Public Key:', wallet0.quantumPublicKeyHex);Multiple Wallet Derivation
import { Mnemonic, MnemonicStrength, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';
const mnemonic = Mnemonic.generate();
// Derive first 5 wallets
const wallets = mnemonic.deriveMultiple(5);
wallets.forEach((wallet, index) => {
console.log(`Wallet ${index}:`);
console.log(' P2TR:', wallet.p2tr);
console.log(' ML-DSA Hash:', wallet.address.toHex());
});Custom Derivation Path
import { Mnemonic, MnemonicStrength, MLDSASecurityLevel } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';
const mnemonic = Mnemonic.generate();
// Custom BIP44/BIP84 path
const customWallet = mnemonic.deriveCustomPath(
"m/84'/0'/0'/0/5", // BIP84 path for account 0, index 5
"m/360'/0'/0'/0/5" // BIP360 quantum path (parallel)
);
console.log('Custom wallet address:', customWallet.p2wpkh);Unisat Wallet Compatibility
For compatibility with Unisat and other HD wallets, use deriveOPWallet() which follows standard BIP derivation paths.
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
// Derive P2TR (Taproot) - BIP86
const taprootWallet = mnemonic.deriveOPWallet(AddressTypes.P2TR, 0);
console.log('Taproot:', taprootWallet.p2tr); // bc1p...
// Derive P2WPKH (Native SegWit) - BIP84
const segwitWallet = mnemonic.deriveOPWallet(AddressTypes.P2WPKH, 0);
console.log('Native SegWit:', segwitWallet.p2wpkh); // bc1q...
// Derive P2PKH (Legacy) - BIP44
const legacyWallet = mnemonic.deriveOPWallet(AddressTypes.P2PKH, 0);
console.log('Legacy:', legacyWallet.legacy); // 1...
// Derive P2SH (Nested SegWit) - BIP49
const nestedSegwitWallet = mnemonic.deriveOPWallet(AddressTypes.P2SH_OR_P2SH_P2WPKH, 0);
console.log('Nested SegWit:', nestedSegwitWallet.segwitLegacy); // 3...BIP Standard Mapping
| Address Type | BIP Standard | Path Format | Address Prefix |
|---|---|---|---|
| P2TR | BIP86 | m/86'/0'/account'/change/index | bc1p... (mainnet) |
| P2WPKH | BIP84 | m/84'/0'/account'/change/index | bc1q... (mainnet) |
| P2PKH | BIP44 | m/44'/0'/account'/change/index | 1... (mainnet) |
| P2SH | BIP49 | m/49'/0'/account'/change/index | 3... (mainnet) |
Unisat-compatible paths always use coin type 0 for the purpose field, regardless of network.
Accounts and Change Addresses
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
// Main account (account 0), receiving addresses
const receiving0 = mnemonic.deriveOPWallet(AddressTypes.P2TR, 0, 0, false);
const receiving1 = mnemonic.deriveOPWallet(AddressTypes.P2TR, 1, 0, false);
// Main account (account 0), change addresses
const change0 = mnemonic.deriveOPWallet(AddressTypes.P2TR, 0, 0, true);
const change1 = mnemonic.deriveOPWallet(AddressTypes.P2TR, 1, 0, true);
// Second account (account 1), receiving addresses
const account1_0 = mnemonic.deriveOPWallet(AddressTypes.P2TR, 0, 1, false);
console.log('Receiving 0:', receiving0.p2tr);
console.log('Receiving 1:', receiving1.p2tr);
console.log('Change 0:', change0.p2tr);
console.log('Account 1:', account1_0.p2tr);Bulk Derivation
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
// Derive first 5 Taproot addresses
const taprootWallets = mnemonic.deriveMultipleUnisat(
AddressTypes.P2TR, // Address type
5, // Count
0, // Start index
0, // Account
false // Not change addresses
);
taprootWallets.forEach((wallet, i) => {
console.log(`Address ${i}: ${wallet.p2tr}`);
});
// Derive 10 Native SegWit change addresses starting from index 5
const changeWallets = mnemonic.deriveMultipleUnisat(
AddressTypes.P2WPKH, // Native SegWit
10, // Count
5, // Start at index 5
0, // Account 0
true // Change addresses
);Quantum Keys with Unisat Derivation
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
const wallet = mnemonic.deriveOPWallet(AddressTypes.P2TR, 0);
// Classical Taproot address (BIP86)
console.log('Classical P2TR:', wallet.p2tr);
// Quantum ML-DSA keys (BIP360: m/360'/0'/0'/0/0)
console.log('Quantum Public Key:', wallet.quantumPublicKeyHex);
console.log('Security Level:', wallet.securityLevel);
// Both keys are deterministically derived
console.log('Has quantum keypair:', wallet.mldsaKeypair !== undefined); // trueWallet Properties
Once a wallet is derived from the mnemonic, its properties are accessible through the returned wallet object. This includes classical keys (private key and public key), quantum-resistant keys (ML-DSA key pair), and derived addresses for both classical and quantum formats.
Classical Keys
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
const wallet = mnemonic.derive(0);
// Public keys
console.log('Compressed:', wallet.publicKey); // 33 bytes
console.log('Hex:', wallet.toPublicKeyHex()); // 0x...
console.log('Uncompressed:', wallet.toUncompressedPublicKey()); // 65 bytes
// Private key (handle with care!)
console.log('Private key:', wallet.privateKey); // 32 bytes hex
// Key pair
console.log('EC Keypair:', wallet.keypair); // ECPairInterfaceQuantum Keys
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
const wallet = mnemonic.derive(0);
// ML-DSA keypair
console.log('ML-DSA Keypair:', wallet.mldsaKeypair);
console.log('Security Level:', wallet.securityLevel); // LEVEL2, LEVEL3, or LEVEL5
// Quantum public keys
console.log('Public Key (hex):', wallet.quantumPublicKeyHex);
console.log('Public Key (buffer):', wallet.quantumPublicKey);
console.log('Public Key Size:', wallet.quantumPublicKey.length); // 1312, 1952, or 2592 bytesAddresses
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const mnemonic = Mnemonic.generate();
const wallet = mnemonic.derive(0);
// Classical addresses
console.log('P2TR:', wallet.p2tr); // bc1p...
console.log('P2WPKH:', wallet.p2wpkh); // bc1q...
console.log('Legacy (P2PKH):', wallet.legacy); // 1...
// Quantum address
console.log('Public Key:', wallet.address.toHex());
// Address object
const address = wallet.address;
console.log('ML-DSA Hash:', address.toHex()); // SHA-256 of quantum key
console.log('Classical Key:', address.tweakedToHex()); // Classical public keySecurity Best Practices
Mnemonic Security
Access sensitive information only when needed and in a limited scope!
const phrase = mnemonic.phrase; // Warning: Highly sensitive
const seed = mnemonic.seed; // Warning: Highly sensitiveGood Practices:
- Use hardware wallets.
- Use encrypted storage.
- Use paper backup in secure location.
Bad Practices:
- Use console.log() to log sensitive information.
- Save to a file unencrypted.
- Transmit over network.
- Store in version control.
Passphrase Protection
Add extra security layer with passphrase.
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
const passphrase = 'my-very-strong-passphrase-12345';
const mnemonic = Mnemonic.generate(
MnemonicStrength.MAXIMUM, // 24 words
passphrase, // Required to recover wallet
networks.bitcoin, // Mainnet
MLDSASecurityLevel.LEVEL3 // Security level
);
// IMPORTANT: You need BOTH mnemonic AND passphrase to recover!
// Losing either means permanent loss of fundsNetwork Awareness
Different network will generate DIFFERENT addresses even with same mnemonic. Always ensure the address format matches the intended network.
import {Mnemonic, MnemonicStrength, MLDSASecurityLevel, AddressTypes } from '@btc-vision/transaction';
import { networks } from '@btc-vision/bitcoin';
// Different networks generate different keys!
const mainnetMnemonic = new Mnemonic(phrase, '', networks.bitcoin);
const testnetMnemonic = new Mnemonic(phrase, '', networks.testnet);
const mainnetWallet = mainnetMnemonic.derive(0);
const testnetWallet = testnetMnemonic.derive(0);
// These will be DIFFERENT addresses even with same mnemonic
console.log('Mainnet:', mainnetWallet.p2tr); // bc1p...
console.log('Testnet:', testnetWallet.p2tr); // tb1p...