Bigmi
TypeScript library and reactive primitives for Bitcoin apps.

Bigmi (short for Bitcoin Is Gonna Make It) is a TypeScript library that provides reactive primitives for building Bitcoin applications. Bigmi simplifies Bitcoin app development by offering:
- Abstractions over the Bitcoin JSON-RPC API
- First-class APIs for interacting with the Bitcoin network, including sending transactions and tracking with Replace-By-Fee (RBF) support
- Connectors for popular Bitcoin wallet extensions
- TypeScript support
Whether you're building a Node.js application or a client-side app, Bigmi provides the tools you need to interact with the Bitcoin.
Packages
Bigmi is modularized into several packages, each suited to different use cases:
- @bigmi/core - Actions, transports, utilities, and other core primitives for Node.js or client-side applications.
- @bigmi/react - Hooks, providers, and other useful primitives for React applications.
- @bigmi/client - Wallet connectors and other tools to connect wallet extensions with Bitcoin applications.
Installation
pnpm add @bigmi/react
pnpm add @bigmi/core
pnpm add @bigmi/client
Getting Started
Node.js
How to setup Bigmi on the backend with Node.js:
import {
createClient,
bitcoin,
blockchair,
sendUTXOTransaction,
waitForTransaction,
getBalance,
} from '@bigmi/core'
const publicClient = createClient({
chain: bitcoin,
rpcSchema: rpcSchema<UTXOSchema>(),
transport: fallback([
blockchair(),
ankr({apiKey: 'YOUR_ANKR_API_KEY'}),
blockcypher(),
mempool(),
]),
})
const address = 'BITCOIN_ADDRESS';
const balance = await getBalance(publicClient, { address });
console.log(`Balance for ${address}:`, balance);
const blockCount = await getBlockCount(publicClient);
console.log('Current block count:', blockCount);
const txHex = 'TRANSACTION_HEX';
const txId = await sendUTXOTransaction(publicClient, { hex: txHex });
console.log('Transaction sent with ID:', txId);
const transaction = await waitForTransaction(publicClient, {
txId,
txHex,
senderAddress: address,
onReplaced: (response) => {
console.log('Transaction replaced due to:', response.reason);
},
});
console.log('Transaction confirmed:', transaction);
React
Simple bigmi setup with a react app:
import { bitcoin, http, createClient } from '@bigmi/core'
import { BigmiProvider, createConfig } from '@bigmi/react'
import { binance, xverse, phantom } from '@bigmi/client'
const config = createConfig({
chains: [bitcoin],
connectors: [binance(), xverse(), phantom()],
client: ({ chain }) => createClient({ chain, transport: http() }),
ssr: true
})
function App() {
return (
<BigmiProvider config={config}>
<YourApp />
</BigmiProvider>
)
}
import { useAccount, useBalance, useConnect } from '@bigmi/react'
const { address, isConnected } = useAccount()
const { balance } = useBalance()
const { connect } = useConnect()
function YourApp() {
return (
<div>
{isConnected ? (
<p>Connected: {address}: {balance}BTC</p>
) : (
<button onClick={connect}>Connect Wallet</button>
)}
</div>
)
}
Creating Bitcoin Transactions
While Bigmi excels at blockchain data retrieval and transaction broadcasting, it doesn't include transaction creation functions. For generating valid transaction hex, we recommend using bitcoinjs-lib (which Bigmi already depends on).
Basic Transaction Creation
Here's how to create a Bitcoin transaction using bitcoinjs-lib with Bigmi:
import * as bitcoin from 'bitcoinjs-lib';
import {
createClient,
getUTXOs,
sendUTXOTransaction,
waitForTransaction,
getBlockStats,
getBlockCount
} from '@bigmi/core';
async function createAndSendTransaction(
client: Client,
fromAddress: string,
toAddress: string,
amount: number,
privateKey: Buffer
) {
const utxos = await getUTXOs(client, { address: fromAddress });
const psbt = new bitcoin.Psbt();
let inputValue = 0;
const estimatedFee = 1000;
for (const utxo of utxos) {
psbt.addInput({
hash: utxo.txId,
index: utxo.vout,
witnessUtxo: {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
},
});
inputValue += utxo.value;
if (inputValue >= amount + estimatedFee) break;
}
psbt.addOutput({
address: toAddress,
value: amount,
});
const change = inputValue - amount - estimatedFee;
if (change > 546) {
psbt.addOutput({
address: fromAddress,
value: change,
});
}
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
psbt.signAllInputs(keyPair);
psbt.finalizeAllInputs();
const rawTx = psbt.extractTransaction().toHex();
const txId = await sendUTXOTransaction(client, { hex: rawTx });
const confirmedTx = await waitForTransaction(client, {
txId,
txHex: rawTx,
senderAddress: fromAddress,
confirmations: 1,
});
return confirmedTx;
}
Fee Estimation
Proper fee estimation is crucial for transaction confirmation:
async function estimateFee(
client: Client,
numInputs: number,
numOutputs: number
): Promise<number> {
const blockHeight = await getBlockCount(client);
const blockStats = await getBlockStats(client, {
blockNumber: blockHeight,
stats: ['avgfeerate']
});
const estimatedSize = (numInputs * 68) + (numOutputs * 31) + 10;
const feeRate = blockStats.avgfeerate || 1;
return Math.ceil(feeRate * estimatedSize);
}
Complete Example with Error Handling
import * as bitcoin from 'bitcoinjs-lib';
import { createClient, getBalance, getUTXOs, sendUTXOTransaction, waitForTransaction } from '@bigmi/core';
async function safeSendBitcoin(
client: Client,
fromAddress: string,
toAddress: string,
amount: number,
privateKey: Buffer
) {
try {
const balance = await getBalance(client, { address: fromAddress });
if (balance < amount + 1000) {
throw new Error('Insufficient balance');
}
const utxos = await getUTXOs(client, {
address: fromAddress,
minValue: amount + 1000,
});
if (utxos.length === 0) {
throw new Error('No UTXOs available');
}
const psbt = new bitcoin.Psbt();
let totalInput = 0;
for (const utxo of utxos) {
psbt.addInput({
hash: utxo.txId,
index: utxo.vout,
witnessUtxo: {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
},
});
totalInput += utxo.value;
}
psbt.addOutput({
address: toAddress,
value: amount,
});
const fee = await estimateFee(client, utxos.length, 2);
const change = totalInput - amount - fee;
if (change < 0) {
throw new Error('Insufficient funds for fee');
}
if (change > 546) {
psbt.addOutput({
address: fromAddress,
value: change,
});
}
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
psbt.signAllInputs(keyPair);
psbt.finalizeAllInputs();
const txHex = psbt.extractTransaction().toHex();
const txId = await sendUTXOTransaction(client, { hex: txHex });
const confirmed = await waitForTransaction(client, {
txId,
txHex,
senderAddress: fromAddress,
confirmations: 1,
});
return {
txId,
fee,
confirmed,
};
} catch (error) {
console.error('Transaction failed:', error);
throw error;
}
}
Working with Different Address Types
import { getAddressInfo } from '@bigmi/core';
function createInputForUTXO(utxo: UTXO, addressInfo: AddressInfo) {
const input: any = {
hash: utxo.txId,
index: utxo.vout,
};
switch (addressInfo.type) {
case 'p2wpkh':
case 'p2wsh':
input.witnessUtxo = {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
};
break;
case 'p2pkh':
case 'p2sh':
input.nonWitnessUtxo = Buffer.from(fullTransactionHex, 'hex');
break;
}
return input;
}
RBF (Replace-By-Fee) Support
Create transactions with RBF enabled for fee bumping:
const psbt = new bitcoin.Psbt();
for (const utxo of utxos) {
psbt.addInput({
hash: utxo.txId,
index: utxo.vout,
sequence: 0xfffffffd,
witnessUtxo: {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
},
});
}
Alternative Libraries
While we recommend bitcoinjs-lib, you can also use:
- @scure/btc-signer - Modern, audited Bitcoin transaction library
- bitcore-lib - Alternative to bitcoinjs-lib
- bcoin - Full Bitcoin implementation
Security Best Practices
- Never expose private keys in client-side code
- Use hardware wallets for production applications
- Validate all inputs before creating transactions
- Test on testnet before mainnet deployment
- Implement proper error handling for all edge cases
Examples
You can explore the LI.FI Widget and LI.FI SDK for detailed production examples.
Documentation
Support
If you encounter any issues or have questions, please open an issue.
Contributing
We welcome contributions from the community!
Changelog
The changelog is regularly updated to reflect what's changed in each new release.
License
This project is licensed under the terms of the MIT License.
Acknowledgments
Bigmi is inspired by the wevm stack. We appreciate the open-source community's contributions to advancing blockchain development.