Best Practices

Simulate Before Sending

Always simulate transactions before broadcasting. This detects potential reverts without spending BTC.

Contract call simulation:
typescript
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.

BigInt usage:
typescript
// 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.

Error handling using try-catch block:
typescript
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.