What you’ll build
- A Next.js app that connects wallets and handles connection state
- Contract reads and writes against a deployed counter on Base Sepolia
- Batch transaction support for smart wallets via EIP-5792
- A graceful fallback for wallets that do not support batching
Steps
Configure Wagmi for Base
Create the Wagmi config with Base Sepolia, then wrap your app in the required providers.Wrap your root layout with
config/wagmi.ts
ssr: true combined with cookieStorage prevents Next.js hydration mismatches. The baseAccount connector connects users via the Base Account SDK smart wallet — you will detect its capabilities in step 7. The injected connector handles browser extension wallets like MetaMask.app/providers.tsx
<Providers>.Connect wallets
Create a component that handles all four wallet connection states.
components/ConnectWallet.tsx
useAccount exposes four states: isConnecting, isReconnecting, isConnected, and isDisconnected. Checking only isConnected causes UI flashes on page load — handle all four.Deploy a contract with Foundry
Install Foundry and initialize a contracts directory inside your project.Configure Base Sepolia in your environment file.Load the variable and import your deployer key securely.Deploy the contract.Verify the deployment by reading the initial counter value.You need testnet ETH to pay for deployment. Get free Base Sepolia ETH from one of the network faucets.
Terminal
The
--no-git flag prevents Foundry from initialising a nested git repository inside your project.contracts/.env
If
https://sepolia.base.org is unreachable, use an alternative public endpoint such as https://base-sepolia-rpc.publicnode.com. For production apps, use a dedicated RPC provider.Terminal
cast wallet import --interactive requires a TTY (interactive terminal). In scripted or CI environments, pass the key directly instead:Terminal
Terminal
Terminal
Read contract data
Define your contract address and ABI, then read the current counter value.
config/counter.ts
as const is required. Without it, wagmi cannot infer function names, argument types, or return types from the ABI.components/CounterDisplay.tsx
isError can be true while data still holds a valid cached value from a previous successful fetch. Always gate error renders on data === undefined so stale data is preferred over an error message.Write to a contract
Send a transaction and surface all three confirmation states to the user.Surface three states to the user: waiting for wallet signature, waiting for on-chain confirmation, and success.
components/IncrementButton.tsx
useReadContract caches its result and does not automatically refetch after a write. Use queryClient.invalidateQueries with the read’s query key to trigger a single refetch when a transaction confirms.Detect wallet capabilities
Smart wallets support batch transactions via EIP-5792. EOAs do not. Detect support before attempting to batch.See Batch Transactions with Wagmi for a deeper look at EIP-5792 capability detection.
hooks/useWalletCapabilities.ts
useChainId() returns the wallet’s current chain, not your deployment chain. A MetaMask user on Ethereum mainnet would get incorrect capability results. Always check capabilities against the chain where your contract is deployed.Batch transactions with fallback
Use
useSendCalls for smart wallets and useWriteContract for EOAs. The component detects which path to take at render time.components/BatchIncrement.tsx
Next steps
- Go to mainnet — add
baseto yourchainsarray and transports inconfig/wagmi.ts, redeploy your contract to Base mainnet, and updateCOUNTER_ADDRESS. - Sponsor gas — use the
paymasterServicecapability withuseSendCallsto cover your users’ transaction fees. See Sponsor Gas. - Send notifications — use the Notifications guide to fetch opted-in wallet addresses and send in-app notifications.
- Batch read calls — reduce RPC round trips by batching reads via viem’s
multicall. - Optimistic updates — update the UI before confirmation using TanStack Query’s
onMutatecallback. - Wagmi setup reference — review the full Wagmi setup guide for additional configuration options.