What you’ll build
A form that signs a guest book contract on testnet. It moves through four states: waiting for the wallet, sent, confirmed or reverted, and failed. The guest book is deployed at0x7962412A92E5553E66C794c3a352422DEB7BAc27 on testnet. Its sign(string message) function stores your message.
Prerequisites
- A React app with wagmi set up and a wallet connected. See Set up wagmi and Connect a wallet.
- A little testnet BOT for gas. See Get testnet BOT.
Steps
1
Write the component
src/SignGuestBook.tsx
2
Understand the flow
write.mutate(...)asks the wallet to sign and send. While the popup is open,write.isPendingistrue.- When the wallet sends it,
write.datais the transaction hash. That’s the moment to show the BOTScan link. useWaitForTransactionReceiptpolls the RPC until the transaction is in a block. Blocks are fast, so this usually takes a few seconds.- A receipt with
status: "reverted"means the transaction was mined but failed. The user still paid gas. - Passing
chainIdmakes wagmi refuse to send if the wallet is on another network, instead of sending to the wrong chain.
3
Render it
src/App.tsx
Verify it worked
- Click Sign and approve in the wallet.
- You see Sent: view on BOTScan, then Confirmed in block followed by a number.
- Open the BOTScan link. The transaction shows Success and the
signmethod.
Handle errors
The most common errors, and whaterrorMessage shows:
shortMessage is a one-line summary that is safe to show users. Log the full error to the console for debugging.
Troubleshooting
The transaction is stuck as pending
The transaction is stuck as pending
BOT Chain needs a gas price of at least 20 gwei. Most wallets read it from the RPC, but if yours set a lower price by hand, the transaction won’t be picked up. Send it again with the default gas settings.
The receipt never arrives
The receipt never arrives
The public RPC sometimes drops requests. wagmi retries, but if it gives up, open the BOTScan link to check the status, and call
receipt.refetch() to try again.Simulate before sending
Simulate before sending
To catch reverts before the wallet opens, call
useSimulateContract with the same arguments and pass simulation.data.request to write.mutate. The button stays disabled until the simulation succeeds.Next steps
Work without eth_getLogs
Show activity without event queries.
Gasless transactions
Let users act without holding BOT.