Bitcoin Cash Integration
This guide covers Bitcoin Cash integration with SwapKit, including wallet connections, UTXO management, CashAddr format, and cross-chain swaps.
Overview
Section titled “Overview”Bitcoin Cash is a peer-to-peer electronic cash system that focuses on fast, low-cost transactions. SwapKit provides comprehensive Bitcoin Cash support through:
- Bitcoin Cash Toolbox: UTXO management with BCH-specific features
- CashAddr Support: Modern Bitcoin Cash address format
- Cross-Chain Swaps: Seamless swaps with other cryptocurrencies via THORChain
- Low Transaction Fees: Optimized for micro-transactions and payments
- Multi-Wallet Support: Compatible with hardware and software wallets
Getting Started
Section titled “Getting Started”Installation
Section titled “Installation”# Full SDK (recommended)bun add @swapkit/sdk
# Individual packages for smaller bundlesbun add @swapkit/toolboxes @swapkit/pluginsBasic Setup
Section titled “Basic Setup”// @noErrorValidationimport { createSwapKit, Chain } from '@swapkit/sdk';
const swapKit = createSwapKit();
const bchWallet = await swapKit.getWallet(Chain.BitcoinCash);// @noErrorValidationimport { getBitcoinCashToolbox } from '@swapkit/toolboxes/utxo';
const bchToolbox = await getBitcoinCashToolbox({ phrase: "your twelve word mnemonic phrase here",
derivationPath: [44, 145, 0, 0, 0]});
const bchToolbox = await getBitcoinCashToolbox({ signer: customBitcoinCashSigner, network: "mainnet"});Bitcoin Cash Toolbox
Section titled “Bitcoin Cash Toolbox”Wallet Connection
Section titled “Wallet Connection”Connect to Bitcoin Cash using various wallet types:
// @noErrorValidationimport { Chain, FeeOption } from "@swapkit/sdk";
await swapKit.connectKeystore([Chain.BitcoinCash], "your mnemonic phrase");
await swapKit.connectLedger([Chain.BitcoinCash]);
await swapKit.connectTrezor([Chain.BitcoinCash]);Address Formats
Section titled “Address Formats”Bitcoin Cash supports multiple address formats:
// @noErrorValidation
const addresses = { cashaddr: swapKit.getAddress(Chain.BitcoinCash),
legacy: await bchToolbox.getAddress(0, false, "legacy"),
bitpay: await bchToolbox.getAddress(0, false, "bitpay"),};
console.log("Bitcoin Cash addresses:", addresses);
import { convertBCHAddress } from "@swapkit/toolboxes/utxo";
const cashAddr = "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy";const legacy = convertBCHAddress(cashAddr, "legacy");console.log("Legacy format:", legacy);Bitcoin Cash Transfers
Section titled “Bitcoin Cash Transfers”// @noErrorValidationimport { AssetValue } from "@swapkit/sdk";
const txHash = await swapKit.transfer({ recipient: "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: "0.01", }), feeOptionKey: FeeOption.Fast,});
console.log(`Bitcoin Cash transaction hash: ${txHash}`);
const microPayment = await bchToolbox.transfer({ recipient: "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: "0.0001" }), feeRate: 1,});
const batchPayments = async () => { const recipients = [ { address: "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", amount: "0.001", }, { address: "bitcoincash:qzgpa8j0krfnh9t6qefqp6nq8zqz5zh8tqp7qvqv77", amount: "0.002", }, { address: "bitcoincash:qrmm7edwuj4jf7tn6rqrgf5qdt8hn4qh4qz7wl4wdt", amount: "0.0015", }, ];
for (const { address, amount } of recipients) { const tx = await bchToolbox.transfer({ recipient: address, assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: amount }), feeRate: 1, }); console.log(`Payment to ${address}: ${tx}`); }};UTXO Management
Section titled “UTXO Management”Bitcoin Cash uses the same UTXO model as Bitcoin:
// @noErrorValidation
const utxos = await bchToolbox.getUTXOs( "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy");
console.log("Available UTXOs:");utxos.forEach((utxo, index) => { console.log( `UTXO ${index}: ${utxo.value} sats (${utxo.txHash}:${utxo.index})` );});
const txParams = await bchToolbox.buildTransaction({ recipient: "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: "0.005" }), feeRate: 2, utxos: utxos.slice(0, 3),});
console.log(`Transaction size: ${txParams.size} bytes`);console.log( `Transaction fee: ${txParams.fee} sats (~$${( txParams.fee * 0.0000001 * 120 ).toFixed(4)})`);Fee Management
Section titled “Fee Management”Bitcoin Cash has consistently low fees:
// @noErrorValidation
const feeRates = await bchToolbox.getFeeRates();console.log({ slow: feeRates.average, standard: feeRates.fast, fast: feeRates.fastest,});
const estimateFees = async () => { const amounts = ["0.001", "0.01", "0.1", "1.0"];
for (const amount of amounts) { const fee = await bchToolbox.estimateTransactionFee({ recipient: "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: amount }), feeOptionKey: FeeOption.Fast, });
const feeUsd = fee.toNumber() * 0.0000001 * 120; console.log( `${amount} BCH -> Fee: ${fee.toNumber()} sats (~$${feeUsd.toFixed(4)})` ); }};Transaction History
Section titled “Transaction History”// @noErrorValidation
const transactions = await bchToolbox.getTransactionHistory( "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", 0, 20);
console.log("Recent BCH transactions:");transactions.forEach((tx) => { console.log(`${tx.hash}: ${tx.amount} BCH (${tx.type})`); console.log(` Block: ${tx.blockHeight}, Fee: ${tx.fee} sats`); console.log(` Date: ${new Date(tx.date)}`);});
const analyzeTxHistory = (transactions: any[]) => { const totalVolume = transactions.reduce( (sum, tx) => sum + Math.abs(tx.amount), 0 ); const totalFees = transactions.reduce((sum, tx) => sum + (tx.fee || 0), 0); const avgFee = totalFees / transactions.length;
console.log("Transaction Analysis:"); console.log(`- Total Volume: ${totalVolume.toFixed(4)} BCH`); console.log(`- Total Fees: ${totalFees} sats`); console.log(`- Average Fee: ${avgFee.toFixed(2)} sats per tx`); console.log( `- Fee as % of volume: ${( ((totalFees * 0.00000001) / totalVolume) * 100 ).toFixed(4)}%` );};Cross-Chain Swaps
Section titled “Cross-Chain Swaps”Bitcoin Cash is supported in THORChain cross-chain swaps:
// @noErrorValidation
const bchToBtcQuote = await swapKit.getQuote({ sellAsset: "BCH.BCH", sellAmount: "1", buyAsset: "BTC.BTC", senderAddress: swapKit.getAddress(Chain.BitcoinCash), recipientAddress: swapKit.getAddress(Chain.Bitcoin),});
console.log("BCH -> BTC quote:", { expectedOutput: bchToBtcQuote.expectedOutput, fees: bchToBtcQuote.fees, priceImpact: bchToBtcQuote.priceImpact,});
const swapTx = await swapKit.swap({ route: bchToBtcQuote.routes[0], feeOptionKey: FeeOption.Fast,});
const bchToUsdtQuote = await swapKit.getQuote({ sellAsset: "BCH.BCH", sellAmount: "0.5", buyAsset: "ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7", senderAddress: swapKit.getAddress(Chain.BitcoinCash), recipientAddress: swapKit.getAddress(Chain.Ethereum),});
const bchToRuneQuote = await swapKit.getQuote({ sellAsset: "BCH.BCH", sellAmount: "0.1", buyAsset: "THOR.RUNE", senderAddress: swapKit.getAddress(Chain.BitcoinCash), recipientAddress: swapKit.getAddress(Chain.THORChain),});Bitcoin Cash Specific Features
Section titled “Bitcoin Cash Specific Features”CashAddr Operations
Section titled “CashAddr Operations”// @noErrorValidationimport { convertBCHAddress, validateCashAddr, decodeCashAddr,} from "@swapkit/toolboxes/utxo";
const cashAddr = "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy";const legacy = "1KXrWXciRDrSAvuajXN8u4vBKbLQ9xhNSa";
const formats = { legacy: convertBCHAddress(cashAddr, "legacy"), bitpay: convertBCHAddress(cashAddr, "bitpay"), cashaddr: convertBCHAddress(legacy, "cashaddr"),};
console.log("Address formats:", formats);
const isValidCashAddr = validateCashAddr(cashAddr);console.log(`${cashAddr} is valid: ${isValidCashAddr}`);
const decoded = decodeCashAddr(cashAddr);console.log("Decoded CashAddr:", { prefix: decoded.prefix, type: decoded.type, hash: decoded.hash,});Payment Protocol Support
Section titled “Payment Protocol Support”// @noErrorValidation
const createPaymentRequest = async (amount: string, memo?: string) => { const paymentRequest = { network: "bitcoincash", currency: "BCH", requiredFeeRate: 1, outputs: [ { address: swapKit.getAddress(Chain.BitcoinCash), amount: parseFloat(amount) * 100000000, message: memo, }, ], time: Date.now(), expires: Date.now() + 900000, };
return paymentRequest;};
const paymentReq = await createPaymentRequest("0.001", "Coffee payment");console.log("Payment request:", paymentReq);SLP Token Support (Future)
Section titled “SLP Token Support (Future)”// @noErrorValidation
const slpTokenTransfer = async () => { const slpTx = await bchToolbox.buildTransaction({ recipient: "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: "0.000546", }), feeRate: 1,
opReturn: "SLP_TOKEN_TRANSFER_DATA", });
return slpTx;};Network Configuration
Section titled “Network Configuration”Custom Node Setup
Section titled “Custom Node Setup”// @noErrorValidationimport { SKConfig } from '@swapkit/sdk';
SKConfig.setRpcUrl(Chain.BitcoinCash, [ "https: "https: "https:]);
const customBchRpc = "https:SKConfig.setRpcUrl(Chain.BitcoinCash, customBchRpc);
const bchToolbox = await getBitcoinCashToolbox({ phrase: "your mnemonic", network: "mainnet", apiUrl: "https:});Working with BCH Testnet
Section titled “Working with BCH Testnet”// @noErrorValidation
SKConfig.setRpcUrl(Chain.BitcoinCash, "https:SKConfig.setEnv('isMainnet', false);
const testnetToolbox = await getBitcoinCashToolbox({ phrase: "your mnemonic", network: "testnet", derivationPath: [44, 1, 0, 0, 0]});
const testnetAddress = testnetToolbox.getAddress();console.log("BCH Testnet address:", testnetAddress);Error Handling
Section titled “Error Handling”Handle Bitcoin Cash specific errors:
// @noErrorValidationimport { SwapKitError } from "@swapkit/sdk";
try { await swapKit.transfer({ /* ... */ });} catch (error) { if (error instanceof SwapKitError) { switch (error.code) { case "toolbox_bch_insufficient_funds": console.error("Insufficient Bitcoin Cash balance"); break; case "toolbox_bch_invalid_cashaddr": console.error("Invalid CashAddr format"); break; case "toolbox_bch_address_format_mismatch": console.error("Address format not supported by recipient"); break; case "toolbox_bch_dust_limit": console.error("Transaction output below dust limit (546 sats)"); break; case "toolbox_bch_network_error": console.error("Bitcoin Cash network error:", error.cause); break; default: console.error("Unknown Bitcoin Cash error:", error); } }}Performance Optimization
Section titled “Performance Optimization”Fee Optimization
Section titled “Fee Optimization”// @noErrorValidation
const optimizeForSpeed = async () => { const feeRates = await bchToolbox.getFeeRates();
const recommendedFee = Math.max(feeRates.fast, 2);
return recommendedFee;};
const optimizeForMicrotx = async (amount: string) => { const amountSats = parseFloat(amount) * 100000000;
if (amountSats < 100000) { return 1; }
return 2;};UTXO Management
Section titled “UTXO Management”// @noErrorValidation
const manageUTXOs = async () => { const address = swapKit.getAddress(Chain.BitcoinCash); const utxos = await bchToolbox.getUTXOs(address);
const smallUTXOs = utxos.filter((utxo) => utxo.value < 10000);
if (smallUTXOs.length > 5) { console.log(`Consolidating ${smallUTXOs.length} small UTXOs`);
const consolidationTx = await bchToolbox.transfer({ recipient: address, assetValue: AssetValue.from({ chain: Chain.BitcoinCash, value: ( smallUTXOs.reduce((sum, utxo) => sum + utxo.value, 0) / 100000000 ).toString(), }), feeRate: 1, utxos: smallUTXOs, });
console.log("Consolidation tx:", consolidationTx); }};Best Practices
Section titled “Best Practices”-
Use CashAddr Format:
const cashAddr = "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy";const legacy = "1KXrWXciRDrSAvuajXN8u4vBKbLQ9xhNSa"; -
Leverage Low Fees:
const microPayments = async () => {await bchToolbox.transfer({recipient: "bitcoincash:qp...",assetValue: AssetValue.from({chain: Chain.BitcoinCash,value: "0.0001",}),feeRate: 1,});}; -
Validate Address Formats:
import { validateCashAddr } from "@swapkit/toolboxes/utxo";const recipient = "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy";if (!validateCashAddr(recipient)) {throw new Error("Invalid Bitcoin Cash CashAddr format");} -
Handle Fast Confirmations:
const handleConfirmations = (feeRate: number) => {if (feeRate >= 2) return "~10 minutes (next block)";return "~20 minutes (1-2 blocks)";};console.log("Expected confirmation:", handleConfirmations(2));
Address Validation
Section titled “Address Validation”// @noErrorValidationimport { validateCashAddr, convertBCHAddress } from "@swapkit/toolboxes/utxo";
const validateBCHAddress = (address: string): boolean => { if (validateCashAddr(address)) { return true; }
try { const converted = convertBCHAddress(address, "cashaddr"); return validateCashAddr(converted); } catch { return false; }};
const testAddresses = [ "bitcoincash:qp3wjpa3tjlj042z2wv7hahsldgwhwy0rq9sywjpyy", "1KXrWXciRDrSAvuajXN8u4vBKbLQ9xhNSa", "CHfKUMnrNy8bqM5L1b44WpN9VdB9zD3rUu", "invalid_address",];
testAddresses.forEach((address) => { const isValid = validateBCHAddress(address); console.log(`${address}: ${isValid ? "Valid" : "Invalid"}`);});Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”-
Address format confusion:
const ensureCompatibility = (address: string, service: string) => {if (service === "exchange" && !address.includes("bitcoincash:")) {return convertBCHAddress(address, "legacy");}return address;}; -
Dust limit issues:
const dustLimit = 546;const checkDustLimit = (amount: string) => {const sats = parseFloat(amount) * 100000000;if (sats < dustLimit) {console.error(`Amount ${sats} sats below dust limit of ${dustLimit} sats`);return false;}return true;}; -
Network selection:
const networkConfig = {mainnet: {prefix: "bitcoincash",rpc: "https:},testnet: {prefix: "bchtest",rpc: "https:}};
API Reference Summary
Section titled “API Reference Summary”Core Methods
Section titled “Core Methods”getBalance()- Get Bitcoin Cash balance in BCHtransfer()- Send BCH with automatic UTXO selectionbuildTransaction()- Construct transaction with custom parametersgetUTXOs()- Fetch unspent transaction outputsgetTransactionHistory()- Get transaction history
Address Methods
Section titled “Address Methods”getAddress()- Generate CashAddr format addressconvertBCHAddress()- Convert between address formatsvalidateCashAddr()- Validate CashAddr formatdecodeCashAddr()- Decode CashAddr components
Fee Management
Section titled “Fee Management”getFeeRates()- Get current network fee rates (typically very low)estimateTransactionFee()- Estimate fee for transactionestimateTransactionSize()- Estimate transaction size in bytes
Transaction Methods
Section titled “Transaction Methods”getTransaction()- Get transaction details by hashbroadcastTransaction()- Broadcast signed transactionsignTransaction()- Sign transaction with private key
Next Steps
Section titled “Next Steps”- Learn about other Bitcoin family chains like Litecoin and Dogecoin
- Explore Cross-Chain Swaps using Bitcoin Cash
- Check out Bitcoin Integration for comparison
- Read about Production Best Practices