B++ Logo

Libraries & SDKs Reference

This guide compares major Bitcoin libraries across languages and provides practical examples for common development tasks.

Library Versions Code examples in this documentation are tested with the following library versions:

  • bitcoinjs-lib: v6.x (uses factory pattern for bip32/ecpair)
  • bip32: v4.x (requires tiny-secp256k1 via BIP32Factory)
  • rust-bitcoin: v0.31.x
  • BDK: v0.29.x
  • python-bitcoinlib: v0.12.x
  • bip32utils: v0.3.x (use BIP32Key.fromSeed() for seed-based derivation)

When using different versions, consult each library's migration guides for API changes.

Library Overview

By Language

LanguageLibraryBest ForMaintenance
JavaScriptbitcoinjs-libWeb apps, general useActive
Rustrust-bitcoinCore developmentActive
RustBDKWallet developmentActive
Pythonpython-bitcoinlibScripts, learningModerate
Gobtcd/btcutilInfrastructureActive
C++libbitcoinPerformance-criticalActive

Feature Comparison

Featurebitcoinjs-librust-bitcoinBDKpython-bitcoinlib
Transaction Building
PSBT SupportPartial
TaprootLimited
HD WalletsVia bip32/bip39Via bip32Via bip32utils
Coin SelectionManualManualManual
Blockchain SyncNoNoNo

JavaScript/TypeScript

bitcoinjs-lib

The most popular JavaScript Bitcoin library.

Installation:

npm install bitcoinjs-lib
npm install ecpair tiny-secp256k1  # For signing
npm install bip32 bip39            # For HD wallets

Basic Usage:

import * as bitcoin from 'bitcoinjs-lib';
import ECPairFactory from 'ecpair';
import * as ecc from 'tiny-secp256k1';
import { BIP32Factory } from 'bip32';
import * as bip39 from 'bip39';

const ECPair = ECPairFactory(ecc);
const bip32 = BIP32Factory(ecc);

// Generate mnemonic and derive keys
const mnemonic = bip39.generateMnemonic(256);
const seed = await bip39.mnemonicToSeed(mnemonic);
const root = bip32.fromSeed(seed);

// BIP84 derivation (Native SegWit)
const child = root.derivePath("m/84'/0'/0'/0/0");

// Create address
const { address } = bitcoin.payments.p2wpkh({
  pubkey: child.publicKey,
  network: bitcoin.networks.bitcoin,
});
console.log('Address:', address);

Transaction Building:

const psbt = new bitcoin.Psbt({ network: bitcoin.networks.bitcoin });

// Add input
psbt.addInput({
  hash: 'txid_hex',
  index: 0,
  witnessUtxo: {
    script: Buffer.from('0014...', 'hex'),
    value: 100000,
  },
});

// Add output
psbt.addOutput({
  address: 'bc1q...',
  value: 50000,
});

// Sign
psbt.signInput(0, ECPair.fromPrivateKey(child.privateKey!));
psbt.finalizeAllInputs();

// Get raw transaction
const tx = psbt.extractTransaction();
console.log('Raw TX:', tx.toHex());

noble-secp256k1

Lightweight cryptographic library for schnorr/ECDSA.

import * as secp from '@noble/secp256k1';

// Generate key pair
const privateKey = secp.utils.randomPrivateKey();
const publicKey = secp.getPublicKey(privateKey);

// Sign message (Schnorr for Taproot)
const message = new Uint8Array(32); // Your message hash
const signature = await secp.schnorr.sign(message, privateKey);

// Verify
const isValid = await secp.schnorr.verify(signature, message, publicKey);

Rust

rust-bitcoin

Low-level Bitcoin library for Rust.

Cargo.toml:

[dependencies]
bitcoin = "0.31"
secp256k1 = { version = "0.28", features = ["global-context"] }

Basic Usage:

use bitcoin::{
    Address, Network, PrivateKey, PublicKey,
    secp256k1::{Secp256k1, SecretKey},
};

fn main() {
    let secp = Secp256k1::new();
    
    // Generate key pair
    let secret_key = SecretKey::new(&mut rand::thread_rng());
    let private_key = PrivateKey::new(secret_key, Network::Bitcoin);
    let public_key = PublicKey::from_private_key(&secp, &private_key);
    
    // Create addresses
    let p2wpkh = Address::p2wpkh(&public_key, Network::Bitcoin).unwrap();
    println!("P2WPKH: {}", p2wpkh);
}

Transaction Building:

use bitcoin::{
    Transaction, TxIn, TxOut, OutPoint, Sequence,
    absolute::LockTime, Amount, ScriptBuf,
    sighash::{SighashCache, EcdsaSighashType},
};

fn create_transaction(
    prev_txid: Txid,
    prev_vout: u32,
    recipient: Address,
    amount: Amount,
) -> Transaction {
    let tx = Transaction {
        version: 2,
        lock_time: LockTime::ZERO,
        input: vec![TxIn {
            previous_output: OutPoint::new(prev_txid, prev_vout),
            script_sig: ScriptBuf::new(),
            sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
            witness: bitcoin::Witness::default(),
        }],
        output: vec![TxOut {
            value: amount,
            script_pubkey: recipient.script_pubkey(),
        }],
    };
    
    tx
}

BDK (Bitcoin Dev Kit)

High-level wallet library built on rust-bitcoin.

Cargo.toml:

[dependencies]
bdk = "0.29"

Wallet Creation:

use bdk::{
    Wallet, SignOptions,
    database::MemoryDatabase,
    bitcoin::Network,
    keys::{DerivableKey, GeneratableKey, bip39::{Mnemonic, Language}},
    template::Bip84,
};

fn create_wallet() -> Result<Wallet<MemoryDatabase>, Box<dyn std::error::Error>> {
    // Generate mnemonic
    let mnemonic = Mnemonic::generate((bdk::keys::bip39::WordCount::Words24, Language::English))?;
    
    // Create wallet with BIP84 descriptors
    let wallet = Wallet::new(
        Bip84(mnemonic.clone(), None),
        Some(Bip84(mnemonic, None)),
        Network::Bitcoin,
        MemoryDatabase::default(),
    )?;
    
    Ok(wallet)
}

Transaction Building with BDK:

use bdk::{FeeRate, wallet::AddressIndex};

fn send_transaction(
    wallet: &Wallet<MemoryDatabase>,
    recipient: &str,
    amount: u64,
) -> Result<Transaction, Box<dyn std::error::Error>> {
    let recipient = Address::from_str(recipient)?;
    
    // Build transaction
    let mut builder = wallet.build_tx();
    builder
        .add_recipient(recipient.script_pubkey(), amount)
        .fee_rate(FeeRate::from_sat_per_vb(5.0))
        .enable_rbf();
    
    let (mut psbt, _details) = builder.finish()?;
    
    // Sign
    wallet.sign(&mut psbt, SignOptions::default())?;
    
    // Extract final transaction
    let tx = psbt.extract_tx();
    Ok(tx)
}

LDK (Lightning Dev Kit)

Embed Lightning in your Rust application.

use lightning::chain::keysinterface::KeysManager;
use lightning::ln::channelmanager::ChannelManager;

// LDK requires more setup - see lightning.dev for full examples
// Key components:
// - ChannelManager: Manages channels
// - PeerManager: Handles peer connections  
// - ChainMonitor: Monitors on-chain events

Python

python-bitcoinlib

pip install python-bitcoinlib

Basic Usage:

from bitcoin import SelectParams
from bitcoin.core import CTransaction, CTxIn, CTxOut, COutPoint, COIN
from bitcoin.core.script import CScript, OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG
from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret

# Select network
SelectParams('mainnet')  # or 'testnet', 'regtest'

# Create address from private key
secret = CBitcoinSecret.from_secret_bytes(bytes(32))  # Use real entropy!
address = CBitcoinAddress.from_pubkey(secret.pub)
print(f"Address: {address}")

Transaction Building:

from bitcoin.core import CTransaction, CTxIn, CTxOut, COutPoint
from bitcoin.core.script import SignatureHash, SIGHASH_ALL

def create_transaction(prev_txid, prev_vout, recipient, amount, private_key):
    # Create input
    outpoint = COutPoint(bytes.fromhex(prev_txid)[::-1], prev_vout)
    txin = CTxIn(outpoint)
    
    # Create output
    recipient_addr = CBitcoinAddress(recipient)
    txout = CTxOut(amount, recipient_addr.to_scriptPubKey())
    
    # Create unsigned transaction
    tx = CTransaction([txin], [txout])
    
    # Sign
    sighash = SignatureHash(
        recipient_addr.to_scriptPubKey(),
        tx, 0, SIGHASH_ALL
    )
    sig = private_key.sign(sighash) + bytes([SIGHASH_ALL])
    
    # Add signature to input
    txin.scriptSig = CScript([sig, private_key.pub])
    
    return CTransaction([txin], [txout])

bip32utils

For HD wallet derivation in Python.

from bip32utils import BIP32Key
from mnemonic import Mnemonic

# Generate mnemonic
mnemo = Mnemonic("english")
words = mnemo.generate(256)
seed = mnemo.to_seed(words)

# Create master key
master = BIP32Key.fromEntropy(seed)

# Derive BIP84 path
account = master.ChildKey(84 + 0x80000000)  # purpose (hardened)
account = account.ChildKey(0 + 0x80000000)   # coin_type (hardened)
account = account.ChildKey(0 + 0x80000000)   # account (hardened)
external = account.ChildKey(0)                # change
address_key = external.ChildKey(0)            # address_index

print(f"Address: {address_key.Address()}")

Go

btcd/btcutil

import (
    "github.com/btcsuite/btcd/btcec/v2"
    "github.com/btcsuite/btcd/btcutil"
    "github.com/btcsuite/btcd/chaincfg"
)

func generateAddress() {
    // Generate private key
    privateKey, _ := btcec.NewPrivateKey()
    
    // Get public key
    publicKey := privateKey.PubKey()
    
    // Create P2WPKH address
    pubKeyHash := btcutil.Hash160(publicKey.SerializeCompressed())
    addr, _ := btcutil.NewAddressWitnessPubKeyHash(
        pubKeyHash,
        &chaincfg.MainNetParams,
    )
    
    fmt.Println("Address:", addr.String())
}

lnd/lnrpc

For Lightning Network in Go.

import (
    "github.com/lightningnetwork/lnd/lnrpc"
    "google.golang.org/grpc"
)

func connectToLND() {
    // Connect to LND
    conn, _ := grpc.Dial("localhost:10009", grpc.WithInsecure())
    client := lnrpc.NewLightningClient(conn)
    
    // Get node info
    info, _ := client.GetInfo(context.Background(), &lnrpc.GetInfoRequest{})
    fmt.Println("Node pubkey:", info.IdentityPubkey)
    
    // Create invoice
    invoice, _ := client.AddInvoice(context.Background(), &lnrpc.Invoice{
        Value: 1000,
        Memo:  "Test payment",
    })
    fmt.Println("Payment request:", invoice.PaymentRequest)
}

Common Tasks

Generate Address (All Languages)

// JavaScript
const { address } = bitcoin.payments.p2wpkh({ pubkey: publicKey });
// Rust
let address = Address::p2wpkh(&public_key, Network::Bitcoin)?;
# Python
address = CBitcoinAddress.from_pubkey(public_key)
// Go
addr, _ := btcutil.NewAddressWitnessPubKeyHash(pubKeyHash, &chaincfg.MainNetParams)

Parse Transaction

// JavaScript
const tx = bitcoin.Transaction.fromHex(rawTxHex);
console.log('TXID:', tx.getId());
console.log('Inputs:', tx.ins.length);
console.log('Outputs:', tx.outs.length);
// Rust
let tx: Transaction = deserialize(&hex::decode(raw_tx_hex)?)?;
println!("TXID: {}", tx.txid());
# Python
tx = CTransaction.deserialize(bytes.fromhex(raw_tx_hex))
print(f"TXID: {tx.GetTxid().hex()}")

Validate Address

// JavaScript
function isValidAddress(address: string): boolean {
  try {
    bitcoin.address.toOutputScript(address, bitcoin.networks.bitcoin);
    return true;
  } catch {
    return false;
  }
}
// Rust
fn is_valid_address(addr_str: &str) -> bool {
    Address::from_str(addr_str)
        .map(|a| a.is_valid_for_network(Network::Bitcoin))
        .unwrap_or(false)
}
# Python
def is_valid_address(address):
    try:
        CBitcoinAddress(address)
        return True
    except:
        return False

Choosing a Library

Decision Matrix

Use CaseRecommended
Web walletbitcoinjs-lib
Mobile app (React Native)bitcoinjs-lib
Backend servicerust-bitcoin or btcd
Wallet applicationBDK
Lightning integrationLDK (Rust) or lnd (Go)
Scripting/automationpython-bitcoinlib
Learning/educationpython-bitcoinlib
High-performancerust-bitcoin or libbitcoin

Considerations

bitcoinjs-lib:

  • Pros: Wide adoption, good docs, browser support
  • Cons: JavaScript ecosystem complexity

rust-bitcoin:

  • Pros: Type safety, performance, active development
  • Cons: Steeper learning curve

BDK:

  • Pros: Full wallet features, handles complexity
  • Cons: Rust knowledge required

python-bitcoinlib:

  • Pros: Easy to learn, great for scripts
  • Cons: Slower, less complete Taproot support

Summary

Each library has its strengths:

  • bitcoinjs-lib: Best for web and cross-platform
  • rust-bitcoin/BDK: Best for production applications
  • python-bitcoinlib: Best for learning and scripting
  • btcd: Best for Go infrastructure

Choose based on your language preference, use case, and required features. For production wallets, consider BDK for its completeness; for web apps, bitcoinjs-lib remains the standard choice.