bitroot
v1.0.0
Published
Bitcoin Taproot toolkit for Node.js - create addresses, sign transactions, and manage Taproot UTXOs
Downloads
34
Maintainers
Readme
Bitroot 🌱
A comprehensive Bitcoin Taproot library for Node.js
Bitroot is a modern, easy-to-use library for creating and managing Bitcoin Taproot (P2TR) addresses and transactions. Built on top of bitcoinjs-lib, it provides a clean API for working with Bitcoin's latest address format.
Features
- ✨ BIP86 HD Wallets - Generate hierarchical deterministic wallets using BIP39 mnemonics
- 🔐 Taproot Addresses - Create and manage P2TR addresses (bc1p...)
- ✍️ Schnorr Signatures - Sign transactions and messages with Schnorr signatures
- 💸 Transaction Building - Build, sign, and broadcast Taproot transactions
- 🌐 Network Support - Mainnet, testnet, and regtest
- 📦 TypeScript - Full TypeScript support with type definitions
Installation
npm install bitrootQuick Start
Generate a new wallet
import { TaprootWallet } from 'bitroot';
// Generate new mnemonic
const mnemonic = TaprootWallet.generateMnemonic(); // 12 words
console.log('Mnemonic:', mnemonic);
// Create wallet from mnemonic
const wallet = new TaprootWallet({
network: 'testnet',
mnemonic
});
// Get first address
const address = wallet.getAddress(0, 0);
console.log('Address:', address.address);
console.log('Public Key:', address.publicKey);
console.log('Path:', address.path);Create address from private key
import { TaprootAddress } from 'bitroot';
import * as crypto from 'crypto';
const address = new TaprootAddress('testnet');
// Generate random private key (32 bytes)
const privateKey = crypto.randomBytes(32);
// Create address
const addressInfo = address.fromPrivateKey(privateKey);
console.log('Address:', addressInfo.address);
console.log('Tweaked Public Key:', addressInfo.tweakedPublicKey);Build and sign transaction
import { TaprootTransaction } from 'bitroot';
const tx = new TaprootTransaction('testnet');
// Create transaction
const signedTx = await tx.create({
inputs: [
{
utxo: {
txid: 'your_utxo_txid',
vout: 0,
value: 100000, // satoshis
},
privateKey: yourPrivateKey,
}
],
outputs: [
{
address: 'recipient_address',
value: 90000, // satoshis
}
],
feeRate: 1, // sat/vB
});
console.log('Transaction ID:', signedTx.txid);
console.log('Transaction Hex:', signedTx.hex);
console.log('Fee:', signedTx.fee, 'sats');
console.log('Size:', signedTx.vsize, 'vB');Simple send transaction
import { TaprootTransaction } from 'bitroot';
const tx = new TaprootTransaction('testnet');
// Send bitcoin
const signedTx = await tx.send(
{
utxos: [
{
txid: 'your_utxo_txid',
vout: 0,
value: 100000,
}
],
privateKey: yourPrivateKey,
},
'recipient_address',
50000, // amount in satoshis
{
feeRate: 1,
changeAddress: 'your_change_address', // optional
}
);
console.log('Sent! TXID:', signedTx.txid);Sign and verify messages
import { TaprootSigner } from 'bitroot';
const signer = new TaprootSigner('testnet');
// Sign message
const message = 'Hello, Taproot!';
const signature = signer.signMessage(message, privateKey);
console.log('Signature:', signature.toString('hex'));
// Verify signature
const publicKey = getYourPublicKey();
const isValid = signer.verifyMessage(message, signature, publicKey);
console.log('Valid:', isValid);API Reference
TaprootWallet
HD Wallet implementation following BIP86 (Taproot) standard.
class TaprootWallet {
constructor(options?: WalletOptions)
static generateMnemonic(strength?: 128 | 256): string
static validateMnemonic(mnemonic: string): boolean
fromMnemonic(mnemonic: string): void
fromSeed(seed: Buffer): void
getAddress(accountIndex?: number, addressIndex?: number, isChange?: boolean): AddressInfo
getAddresses(count: number, accountIndex?: number, startIndex?: number, isChange?: boolean): AddressInfo[]
getPrivateKey(accountIndex?: number, addressIndex?: number, isChange?: boolean): Buffer
getPublicKey(accountIndex?: number, addressIndex?: number, isChange?: boolean): Buffer
getKeyPair(accountIndex?: number, addressIndex?: number, isChange?: boolean): TaprootKeyPair
exportXpub(): string
exportXprv(): string
getMasterFingerprint(): string
}TaprootAddress
Taproot address generation and validation.
class TaprootAddress {
constructor(network?: 'mainnet' | 'testnet' | 'regtest')
fromPublicKey(publicKey: Buffer): AddressInfo
fromPrivateKey(privateKey: Buffer): AddressInfo
fromScriptTree(internalPubkey: Buffer, scriptTree: Taptree): AddressInfo
decode(address: string): Buffer
isValid(address: string): boolean
getInfo(address: string): { outputScript: string; type: string }
}TaprootTransaction
Build and sign Taproot transactions.
class TaprootTransaction {
constructor(network?: 'mainnet' | 'testnet' | 'regtest')
create(options: TransactionOptions): Promise<SignedTransaction>
send(from: { utxos: UTXO[], privateKey: Buffer }, to: string, amount: number, options?: { feeRate?: number, changeAddress?: string }): Promise<SignedTransaction>
createPsbt(options: TransactionOptions): Psbt
signPsbt(psbt: Psbt, privateKeys: Buffer[]): Psbt
decode(txHex: string): Transaction
getInfo(tx: Transaction): TransactionInfo
}TaprootSigner
Sign transactions and messages with Schnorr signatures.
class TaprootSigner {
constructor(network?: 'mainnet' | 'testnet' | 'regtest')
tweakPrivateKey(privateKey: Buffer): Buffer
signInput(psbt: Psbt, inputIndex: number, privateKey: Buffer, sighashTypes?: number[]): void
signAllInputs(psbt: Psbt, privateKey: Buffer, sighashTypes?: number[]): void
signMessage(message: string | Buffer, privateKey: Buffer): Buffer
verifyMessage(message: string | Buffer, signature: Buffer, publicKey: Buffer): boolean
createKeyPair(privateKey: Buffer): TaprootKeyPair
}Types
interface AddressInfo {
address: string;
publicKey: string;
tweakedPublicKey: string;
path?: string;
}
interface UTXO {
txid: string;
vout: number;
value: number;
scriptPubKey?: string;
}
interface SignedTransaction {
txid: string;
hex: string;
fee: number;
size: number;
vsize: number;
}
interface TaprootKeyPair {
privateKey: Buffer;
publicKey: Buffer;
tweakedPrivateKey: Buffer;
tweakedPublicKey: Buffer;
}Utilities
// Network helpers
getNetwork(network: 'mainnet' | 'testnet' | 'regtest'): Network
// Address validation
isValidAddress(address: string, network?: string): boolean
isTaprootAddress(address: string, network?: string): boolean
// Conversion utilities
hexToBuffer(hex: string): Buffer
bufferToHex(buffer: Buffer): string
satoshiToBTC(satoshi: number): number
btcToSatoshi(btc: number): number
// Transaction utilities
calculateVSize(transaction: Transaction): number
calculateFee(transaction: Transaction, feeRate: number): numberSecurity Considerations
⚠️ Important Security Notes:
- Never share your private keys or mnemonics - Anyone with access to these can steal your funds
- Store mnemonics securely - Write them down offline and keep in a safe place
- Use testnet for development - Always test on testnet before using mainnet
- Verify addresses - Double-check addresses before sending funds
- Be cautious with fees - Set appropriate fee rates to avoid overpaying
Network Derivation Paths (BIP86)
- Mainnet:
m/86'/0'/0'/0/0 - Testnet:
m/86'/1'/0'/0/0
The derivation path format is: m/86'/<coin_type>'/<account>'/<change>/<address_index>
Examples
Check out the examples directory for more usage examples:
Requirements
- Node.js >= 16.0.0
- Bitcoin Core (optional, for broadcasting transactions)
Dependencies
bitcoinjs-lib- Bitcoin library@bitcoinerlab/secp256k1- Schnorr signaturesbip32- HD key derivationbip39- Mnemonic generationecpair- Key pair utilities
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see the LICENSE file for details
Resources
- BIP86 - Key Derivation for Single Key P2TR Outputs
- BIP340 - Schnorr Signatures
- BIP341 - Taproot
- BIP342 - Tapscript
Support
If you find this library helpful, please give it a ⭐️ on GitHub!
Made with ❤️ for the Bitcoin community
