One flow
A write is not done when the wallet opens. It is not even done when the wallet returns a hash.
The safe flow is: call the contract, get a transaction hash, show pending, wait for the receipt, then show success or failure.
Write vs read
A read calls a view or pure function. It does not change chain state and does not ask the user to pay gas.
A write changes blockchain state. The wallet must show the transaction, the user must approve it, and the network must include it in a block.
What your UI tracks
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done
Write button example
This example calls a simple contract function named increment. Replace the address, ABI, and function name with your own project contract.
Keep the button text boring and clear. A recruiter should understand the transaction path in 10 seconds.
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
const counterAbi = [
{
type: 'function',
name: 'increment',
stateMutability: 'nonpayable',
inputs: [],
outputs: [],
},
]
const counterAddress = '0x0000000000000000000000000000000000000000'
export function IncrementButton() {
const {
data: hash,
writeContract,
isPending: isWalletOpen,
error: writeError,
} = useWriteContract()
const {
isLoading: isConfirming,
isSuccess: isConfirmed,
error: receiptError,
} = useWaitForTransactionReceipt({
hash,
})
function sendIncrement() {
writeContract({
address: counterAddress,
abi: counterAbi,
functionName: 'increment',
})
}
return (
<section>
<button onClick={sendIncrement} disabled={isWalletOpen || isConfirming}>
{isWalletOpen ? 'Check wallet' : isConfirming ? 'Waiting for confirmation' : 'Increment counter'}
</button>
{hash && <p>Transaction hash: {hash}</p>}
{isConfirmed && <p>Confirmed on-chain.</p>}
{writeError && <p>Transaction was not sent: {writeError.message}</p>}
{receiptError && <p>Transaction failed after sending: {receiptError.message}</p>}
</section>
)
}Show the hash
Show the transaction hash as soon as you have it. It proves the wallet returned a broadcast transaction.
For a hackathon demo, this also helps judges see that your dapp is not just changing local React state.
Do not fake success
Beginners often show “Done” right after writeContract runs. That is too early.
The transaction may still be waiting, may be replaced, or may revert. Wait for useWaitForTransactionReceipt before showing final success.
What to explain
Near the button, show the contract action in plain English. For example: “This sends one transaction to increment the counter on Sepolia.”
Do not hide gas or chain details behind vague text. Users should know they are signing a real state-changing transaction.
Do this now
Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.
0 of 5 done