
Research
/Security News
Weaponizing Discord for Command and Control Across npm, PyPI, and RubyGems.org
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
@bigmi/core
Advanced tools
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:
Whether you're building a Node.js application or a client-side app, Bigmi provides the tools you need to interact with the Bitcoin.
Bigmi is modularized into several packages, each suited to different use cases:
pnpm add @bigmi/react
pnpm add @bigmi/core
pnpm add @bigmi/client
How to setup Bigmi on the backend with Node.js:
// main.ts
import {
createClient,
bitcoin,
blockchair,
sendUTXOTransaction,
waitForTransaction,
getBalance,
} from '@bigmi/core'
// Create a client for Bitcoin mainnet
const publicClient = createClient({
chain: bitcoin,
rpcSchema: rpcSchema<UTXOSchema>(),
transport: fallback([
blockchair(),
ankr({apiKey: 'YOUR_ANKR_API_KEY'}),
blockcypher(),
mempool(),
]),
})
// Define the Bitcoin address you're working with
const address = 'BITCOIN_ADDRESS';
// Fetch the balance of the address
const balance = await getBalance(publicClient, { address });
console.log(`Balance for ${address}:`, balance);
// Fetch the current block count (height)
const blockCount = await getBlockCount(publicClient);
console.log('Current block count:', blockCount);
// Prepare the transaction hex (as a string)
const txHex = 'TRANSACTION_HEX';
// Send the transaction to the network
const txId = await sendUTXOTransaction(publicClient, { hex: txHex });
console.log('Transaction sent with ID:', txId);
// Wait for the transaction to be confirmed
const transaction = await waitForTransaction(publicClient, {
txId,
txHex,
senderAddress: address,
onReplaced: (response) => {
console.log('Transaction replaced due to:', response.reason);
},
});
console.log('Transaction confirmed:', transaction);
Simple bigmi setup with a react app:
// App.tsx
import { bitcoin, http, createClient } from '@bigmi/core'
import { BigmiProvider, createConfig } from '@bigmi/react'
import { binance, xverse, phantom } from '@bigmi/client'
const chainId = bitcoin.id
// Create bigmi config object
const config = createConfig({
chains: [bitcoin],
connectors: [binance({chainId}), xverse({chainId}), phantom({chainId})],
client: ({ chain }) => createClient({ chain, transport: http() }),
ssr: true // If using Next.js or SSR
})
function App() {
return (
// Wrap your application with the necessary providers:
<BigmiProvider config={config}>
<YourApp />
</BigmiProvider>
)
}
// YourApp.tsx
// Import the hooks from bigmi/react library
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>
)
}
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).
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, // in satoshis
privateKey: Buffer
) {
// 1. Get UTXOs for the address using Bigmi
const utxos = await getUTXOs(client, { address: fromAddress });
// 2. Create a new transaction using bitcoinjs-lib
const psbt = new bitcoin.Psbt();
// 3. Add inputs from UTXOs
let inputValue = 0;
const estimatedFee = 1000; // You should calculate this properly
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;
}
// 4. Add recipient output
psbt.addOutput({
address: toAddress,
value: amount,
});
// 5. Add change output if needed
const change = inputValue - amount - estimatedFee;
if (change > 546) { // Dust threshold
psbt.addOutput({
address: fromAddress,
value: change,
});
}
// 6. Sign the transaction
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
psbt.signAllInputs(keyPair);
psbt.finalizeAllInputs();
// 7. Get the raw transaction hex
const rawTx = psbt.extractTransaction().toHex();
// 8. Broadcast using Bigmi
const txId = await sendUTXOTransaction(client, { hex: rawTx });
// 9. Wait for confirmation using Bigmi
const confirmedTx = await waitForTransaction(client, {
txId,
txHex: rawTx,
senderAddress: fromAddress,
confirmations: 1,
});
return confirmedTx;
}
Proper fee estimation is crucial for transaction confirmation:
async function estimateFee(
client: Client,
numInputs: number,
numOutputs: number
): Promise<number> {
// Get recent block stats for fee estimation
const blockHeight = await getBlockCount(client);
const blockStats = await getBlockStats(client, {
blockNumber: blockHeight,
stats: ['avgfeerate']
});
// Estimate transaction size
// P2WPKH: ~68 bytes per input, ~31 bytes per output, ~10 bytes overhead
const estimatedSize = (numInputs * 68) + (numOutputs * 31) + 10;
// Calculate fee (satoshis per byte * size)
const feeRate = blockStats.avgfeerate || 1; // fallback to 1 sat/byte
return Math.ceil(feeRate * estimatedSize);
}
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 {
// Check balance
const balance = await getBalance(client, { address: fromAddress });
if (balance < amount + 1000) {
throw new Error('Insufficient balance');
}
// Get UTXOs
const utxos = await getUTXOs(client, {
address: fromAddress,
minValue: amount + 1000,
});
if (utxos.length === 0) {
throw new Error('No UTXOs available');
}
// Create transaction
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;
}
// Add outputs
psbt.addOutput({
address: toAddress,
value: amount,
});
// Calculate fee and change
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) { // Dust threshold
psbt.addOutput({
address: fromAddress,
value: change,
});
}
// Sign and finalize
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
psbt.signAllInputs(keyPair);
psbt.finalizeAllInputs();
// Get transaction hex
const txHex = psbt.extractTransaction().toHex();
// Broadcast with Bigmi
const txId = await sendUTXOTransaction(client, { hex: txHex });
// Wait for confirmation
const confirmed = await waitForTransaction(client, {
txId,
txHex,
senderAddress: fromAddress,
confirmations: 1,
});
return {
txId,
fee,
confirmed,
};
} catch (error) {
console.error('Transaction failed:', error);
throw error;
}
}
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':
// Witness UTXOs for SegWit
input.witnessUtxo = {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
};
break;
case 'p2pkh':
case 'p2sh':
// Need full transaction for legacy
input.nonWitnessUtxo = Buffer.from(fullTransactionHex, 'hex');
break;
}
return input;
}
Create transactions with RBF enabled for fee bumping:
const psbt = new bitcoin.Psbt();
// Add inputs with RBF sequence
for (const utxo of utxos) {
psbt.addInput({
hash: utxo.txId,
index: utxo.vout,
sequence: 0xfffffffd, // RBF enabled
witnessUtxo: {
script: Buffer.from(utxo.scriptHex, 'hex'),
value: utxo.value,
},
});
}
While we recommend bitcoinjs-lib, you can also use:
You can explore the LI.FI Widget and LI.FI SDK for detailed production examples.
If you encounter any issues or have questions, please open an issue.
We welcome contributions from the community!
The changelog is regularly updated to reflect what's changed in each new release.
This project is licensed under the terms of the MIT License.
Bigmi is inspired by the wevm stack. We appreciate the open-source community's contributions to advancing blockchain development.
FAQs
TypeScript library for Bitcoin apps.
We found that @bigmi/core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
Security News
Socket now integrates with Bun 1.3’s Security Scanner API to block risky packages at install time and enforce your organization’s policies in local dev and CI.
Research
The Socket Threat Research Team is tracking weekly intrusions into the npm registry that follow a repeatable adversarial playbook used by North Korean state-sponsored actors.