useReadContract, then many calls at once with useReadContracts.
What you’ll build
Two components:UsdtBalanceshows the connected wallet’s USDT balance.TokenBalancesshows the symbol and balance of USDT and WBOT in a single RPC request.
Prerequisites
- A React app with wagmi set up. See Set up wagmi.
- The
ConnectWalletcomponent from Connect a wallet.
Steps
1
Read one value with useReadContract
src/UsdtBalance.tsx
erc20Abiships with viem, so you don’t need to paste an ABI for standard tokens.getAddressesreturns the token and DEX addresses for a chain. You can also copy them from Contract addresses.query.enabledstops the read until a wallet is connected.argsstaysundefineduntil then.chainIdpins the read to testnet, even if the wallet is on another network.- USDT uses 6 decimals, so
formatUnits(data, 6). See USDT and decimals.
2
Batch reads with useReadContracts
src/TokenBalances.tsx
eth_call to Multicall3. On testnet that contract is at 0x47FA21f684bBAD707A53a0f9BE59F1422F46C265, not the usual Multicall3 address. See Known limitations.With allowFailure: true, each result has a status. One failed call doesn’t fail the others, so check status === "success" before you use result.3
Render them
src/App.tsx
Verify it worked
Runnpm run dev and connect a wallet. You should see your USDT balance, then a list like this, with your own numbers:
Output
https://rpc.bohr.life.
Keep values fresh
Reads are cached by TanStack Query and don’t refresh on their own. Pick one:- Refetch on an interval:
query: { refetchInterval: 5_000 }. - Refetch after a transaction confirms: call the
refetchfunction returned by the hook.
Troubleshooting
The balance is a huge number
The balance is a huge number
You formatted with 18 decimals, or didn’t format at all. USDT has 6. Read
decimals from the contract, as TokenBalances does, when you don’t know a token.The read returns an error about the contract function returning no data
The read returns an error about the contract function returning no data
The address has no contract on the chain you read from. Check
chainId and the address. Testnet and mainnet addresses differ.Multicall fails on testnet with a custom chain definition
Multicall fails on testnet with a custom chain definition
If you defined the chain yourself with
defineChain, add contracts.multicall3.address with the testnet address above. wagmi batches through the address on the chain object, so it needs this entry.Next steps
Send transactions
Write to a contract and wait for the receipt.
Batch reads with Multicall3
Do the same batching from a script with viem.