Transaction Fees
Understanding Bitcoin transaction fees and how they work in the BSV TypeScript SDK.
What are Transaction Fees?
Transaction fees are payments to miners for including transactions in blocks:
import { Transaction } from '@bsv/sdk'
// Calculate transaction fee
const tx = new Transaction()
const feeRequired = tx.getFee()
// Set custom fee rate
const customFee = tx.getFee(feePerKB)
Fee Calculation
Fees are calculated based on transaction size:
- Fee Rate: Satoshis per kilobyte (sat/kB)
- Transaction Size: Total bytes in serialized transaction
- Total Fee: Size × Fee Rate
SDK Fee Handling
Automatic Fee Calculation
The SDK calculates fees automatically:
// Wallet handles fees automatically
const wallet = new WalletClient()
const action = await wallet.createAction({
outputs: [{
satoshis: 1000,
lockingScript: script
}]
})
// Fee calculated and deducted automatically
Manual Fee Control
For advanced use cases:
// Calculate fee manually
const tx = new Transaction()
tx.addInput(/* input */)
tx.addOutput(/* output */)
const estimatedSize = tx.getSerializedSize()
const feeRequired = estimatedSize * feePerByte
Fee Rates
Network Fee Rates
BSV typically uses low, predictable fees:
- Standard Rate: ~0.5 sat/byte
- Priority Rate: ~1.0 sat/byte
- Economy Rate: ~0.1 sat/byte
Dynamic Fee Estimation
// Get current network fee rates
const feeRates = await chainTracker.getFeeRates()
const recommendedFee = feeRates.standard
Fee Components
Input Costs
Each input adds to transaction size:
- Previous transaction hash (32 bytes)
- Output index (4 bytes)
- Unlocking script (variable)
- Sequence number (4 bytes)
Output Costs
Each output adds to transaction size:
- Value (8 bytes)
- Locking script length (1-9 bytes)
- Locking script (variable)
Base Transaction
Fixed overhead for every transaction:
- Version (4 bytes)
- Input count (1-9 bytes)
- Output count (1-9 bytes)
- Lock time (4 bytes)
Fee Optimization
UTXO Selection
Choose UTXOs efficiently:
// Prefer fewer, larger UTXOs to reduce fees
const utxos = await wallet.getUTXOs()
const selected = selectOptimalUTXOs(utxos, targetAmount)
Output Consolidation
Combine multiple payments:
// Batch multiple outputs in one transaction
const outputs = [
{ satoshis: 1000, lockingScript: script1 },
{ satoshis: 2000, lockingScript: script2 },
{ satoshis: 1500, lockingScript: script3 }
]
Script Efficiency
Use efficient script templates:
// P2PKH is more efficient than complex scripts
const p2pkh = new P2PKH()
const efficientScript = p2pkh.lock(publicKeyHash)
Fee Estimation
Size Estimation
Estimate transaction size before creation:
// Estimate size for fee calculation
const estimatedInputs = 2
const estimatedOutputs = 3
const estimatedSize = estimateTransactionSize(estimatedInputs, estimatedOutputs)
const estimatedFee = estimatedSize * feeRate
Template-Based Estimation
// Use script templates for accurate estimation
const template = new P2PKH()
const scriptSize = template.estimateLength([publicKeyHash])
Error Handling
Common fee-related issues:
- Insufficient funds for fees
- Fee rate too low for network
- Transaction size miscalculation
try {
const action = await wallet.createAction({
outputs: outputs
})
} catch (error) {
if (error.message.includes('Insufficient funds')) {
// Handle insufficient balance for fees
console.log('Not enough funds to cover transaction and fees')
}
}
Best Practices
Fee Management
- Always account for fees in balance calculations
- Use appropriate fee rates for urgency
- Monitor network conditions for fee adjustments
- Implement fee estimation before transaction creation
Cost Optimization
- Batch transactions when possible
- Use efficient script templates
- Optimize UTXO selection
- Consider transaction timing
User Experience
- Display estimated fees to users
- Provide fee rate options (economy, standard, priority)
- Handle insufficient fund errors gracefully
- Show fee breakdown for transparency
Wallet Integration
Most applications rely on wallets for fee handling:
// Wallet manages fees automatically
const wallet = new WalletClient()
// Fees are calculated and deducted automatically
const result = await wallet.createAction({
description: 'Payment with automatic fees',
outputs: [/* outputs */]
})
Advanced Fee Strategies
Replace-by-Fee (RBF)
Increase fees for faster confirmation:
// Create transaction with RBF enabled
const tx = new Transaction()
tx.setRBF(true) // Enable replace-by-fee
Child-Pays-for-Parent (CPFP)
Use dependent transactions to increase effective fee rate:
// Create child transaction with higher fee
const childTx = new Transaction()
childTx.addInput(/* from parent transaction */)
// Higher fee rate pulls parent transaction along
Next Steps
- Understand Transaction Structure for size calculation
- Learn about Wallet Integration for automatic fee handling
- Explore Script Templates for efficient fee optimization