Frontend
The Web3 variant adds blockchain-specific frontend components, hooks, and configuration on top of the base package's React setup.
Configuration
The createWeb3Config() function sets up RainbowKit with the supported chains and WalletConnect project ID. It uses RainbowKit's getDefaultConfig() for a simple setup with standard wallet options.
Chain configuration lives in src/shared/contracts/chain.ts. The WEB3_SUPPORTED_CHAINS environment variable specifies which networks to enable. Supported chains include anvil (local development), mainnet, sepolia, and base. The first chain in the list becomes the primary chain.
Provider Structure
The Web3 variant wraps the base provider stack with WagmiProvider and RainbowKitProvider:
<ThemeProvider>
<WagmiProvider config={web3Config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider theme={rainbowKitTheme}>
<AuthProvider>
<SocketProvider>
<ToastProvider>
{/* App content */}
</ToastProvider>
</SocketProvider>
</AuthProvider>
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
</ThemeProvider>
RainbowKit's theme automatically adapts to the app's light/dark mode via the useTheme() hook.
Wallet Connection
The ConnectWallet component uses RainbowKit's ConnectButton.Custom API to render wallet connection UI. It coordinates with AuthContext to trigger SIWE authentication after wallet connection.
The component shows different states: a connect button when disconnected, a "Wrong network" warning for unsupported chains, and the connected account address when authenticated. The optional showNetwork prop adds a chain selector button.
Token Hooks
Two hooks handle ERC-20 token operations:
useTokens.ts provides read operations:
useMyTokens()— Fetches all tokens where the connected wallet has a balance, using multicall for efficiencyuseTokenInfo(address)— Fetches details for a specific token (name, symbol, decimals, balance)useTokenCount()— Returns the total number of tokens deployed through the factory
useTokenActions.ts provides write operations:
useCreateToken()— Deploys a new ERC-20 token through the factory contractuseTransferToken()— Transfers tokens to another addressuseTransactionStatus(hash)— Tracks transaction confirmation status
These hooks use React Query for caching and automatic refetching. Token queries refresh every 5-30 seconds to keep balances current.
Contract Utilities
The src/shared/contracts/ folder provides utilities for contract interactions:
getFactoryContractInfo()— Returns the factory contract address and ABIgetERC20ContractInfo(address)— Returns ERC-20 ABI for any token addressreadContract()— Reads contract state with proper typingwriteContract()— Sends transactions through the walletfetchTokenWithBalance()— Fetches token metadata and balance in one multicall
Contract ABIs are generated from Solidity files during build. See src/shared/abi/generated.ts for the generated types.
Token Components
Several components handle token display and management:
TokenList— Displays all tokens owned by the connected walletCreateTokenDialog— Modal form for deploying new tokensSendTokenDialog— Modal form for transferring tokensContractValue— Displays values read from contractsNumTokens— Shows the total token count from the factoryIfWalletConnected— Conditionally renders children only when a wallet is connected
Multicall
Token operations use Viem's multicall support to batch multiple contract reads into a single RPC request. The fetchMultipleTokensWithBalances() function demonstrates this — it fetches name, symbol, decimals, and balance for multiple tokens in one call.
For development on Anvil, QuickDapp automatically deploys Multicall3 if it doesn't exist. See Chain Monitoring for details on the deployMulticall3 worker job.
Error Handling
Transaction errors are caught and displayed through the toast system. Common errors include:
- User rejected the transaction
- Insufficient funds for gas
- Contract reverted (with the revert reason if available)
The hooks return error and isError states so components can display appropriate feedback.