Best Practices
Simulate Before Sending
Always simulate transactions before broadcasting. This detects potential reverts without spending BTC.
const simulation = await contract.someMethod(args);
// ALWAYS check for revert before sending
if (simulation.revert) {
console.error('Would fail:', simulation.revert);
return;
}
// Only then send
const tx = await simulation.sendTransaction(params);Use Type-safe Interfaces
Leverage TypeScript's type system for contract interactions to ensure compile-time validation and type safety.
Handle BigInt Correctly
All amounts are represented as bigint types to ensure precision and avoid floating-point rounding errors.
// Token amounts are always bigint
const amount = 100_00000000n; // 100 tokens with 8 decimals
// Use BigInt operations
const doubled = amount * 2n;
const half = amount / 2n;
// Convert for display
console.log('Amount:', amount.toString());Track UTXOs
Use UTXOsManager to track and manage UTXOs, preventing double-spending.
Choose the Right Provider
Use JSON-RPC provider for most use cases and WebSocket provider only when real-time updates are required.
Error Handling
Operations such as contract calls, transaction submissions, and data retrieval should always account for potential failures including connection timeouts, malformed responses, and rejected transactions. Wrapping provider calls in appropriate error handling ensures application stability and provides meaningful feedback to users.
try {
const simulation = await token.transfer(recipient, amount, new Uint8Array(0));
if (simulation.revert) {
throw new Error(`Simulation failed: ${simulation.revert}`);
}
const tx = await simulation.sendTransaction(params);
console.log('Success:', tx.transactionId);
} catch (error) {
console.error('Transaction failed:', (error as Error).message);
}Cleanup Resources
Providers and other components that maintain active connections or allocate critical resources such as network sockets and memory buffers should be properly disposed of when no longer needed.
Always ensure providers are disposed through the close() or disconnect() methods when they are no longer required.