Source: Full executable TypeScript in contract/src/examples/05-error-handling/. This page summarizes the flow — read the source for complete per-step code.
The Story
Kai is a frontend developer at ArtFund, responsible for building the campaign management interface. Before any transaction is sent to the blockchain, Kai wants to:- Preview the outcome — simulate the transaction against the current chain state to see if it would succeed
- Show clear error messages — if the transaction would fail, explain why in plain language and suggest what to do
- Estimate the cost — display the gas estimate so users know what they will pay before confirming
Steps
Step 1: Simulate Before Sending
Simulation calls the contract against the current chain state without broadcasting a transaction. If the simulation succeeds, the real transaction is safe to send. The simulation result includes the predicted return value and gas estimate.Step 2: Prepare Transaction for External Signing
For account-abstraction wallets, Safe multisig, or custom signing flows, usetoPreparedTransaction to extract raw transaction parameters (to, data, value, gas) from a simulation result.
Step 3: Catch Typed Errors
When a transaction reverts, the SDK decodes the raw revert data into a typed error class with a human-readable recovery hint. Three patterns:Step 4: Handle Read-Only Client
When using a read-only client (no private key), write methods throw immediately with"No signer configured" without making an RPC call. Build your UI to handle this gracefully and prompt the user to connect their wallet.
Step 5: Safe Transaction Pattern
A reusable pattern that simulates a transaction, shows the user what will happen, and only sends after simulation passes. Reverts are caught and displayed as user-friendly error messages.Step 6: Simulate With Error Decode
simulateWithErrorDecode wraps simulation and error parsing into a single convenience call. If simulation succeeds it returns the SimulationResult; if it reverts it throws a typed error with a recoveryHint property — no manual getRevertData / parseContractError needed.