Development of dApp React — Reliable Frontend for Decentralized Applications
Web3 frontend development requires a specific approach: there are no traditional HTTP requests, and users interact directly with the blockchain. We use the wagmi v2 and viem ecosystem for reliable work with EVM networks. React hooks from wagmi simplify wallet integration and transaction management. Our experience helps avoid common pitfalls and accelerates product delivery.
| Feature | wagmi + viem | ethers.js v6 |
|---|---|---|
| Bundle size (gzip) | ~60 KB | ~200 KB |
| TypeScript support | Excellent (tree-shakeable) | Good but complex |
| Caching | Built-in (TanStack Query) | None, must be written manually |
| SSR compatibility | Out of the box | Requires wrappers |
More about the stack
We also use TanStack Query for caching and server state, which avoids redundant RPC calls. The built-in multicall via Multicall3 reduces the number of requests by 2-3 times.Why We Use wagmi and viem Instead of ethers.js
Developing a dApp frontend faces non-obvious problems: transactions can hang for hours, users switch networks without warning, and RPC providers fail at the worst moment. Porting the architecture of regular web applications doesn't work here. In a dApp, there are no sessions, server-side authorization, or guaranteed API availability. Our approach is to use the wagmi v2 and viem ecosystem. These are not just libraries but an opinionated layer for React that covers 90% of scenarios: from wallet management to caching on-chain data. Wagmi with viem loads 3x faster than ethers.js, as confirmed by benchmarks.
How to Manage Transaction State
A transaction in EVM is not an HTTP request. It goes through stages: pending in the mempool → included in a block → confirmed (N confirmations). Users should see what's happening at each stage.
import { useWriteContract, useWaitForTransactionReceipt } from "wagmi"; function MintButton() { const { writeContract, data: hash, isPending } = useWriteContract(); const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash, confirmations: 2, }); return ( <button disabled={isPending || isConfirming}> {isPending ? "Signing..." : isConfirming ? "Waiting for block..." : "Mint"} </button> ); } This pattern ensures the user does not send a duplicate transaction while the current one is pending. If a transaction has been stuck for more than 5 minutes, we provide Speed Up (increase gas by 10% with the same nonce) or Cancel (send 0 ETH to self with same nonce) — both via viem's sendTransaction.
How to Read Contract Data Efficiently
For request batching, we use useReadContracts—it combines multiple calls into one RPC request via Multicall3. Wagmi automatically caches data through TanStack Query (default staleTime = 4 seconds). For DeFi panels with rapidly changing data, we lower staleTime to 0 and enable refetchInterval. This reduces RPC load and speeds up the UI.
What Common Errors Arise and How to Solve Them
- User rejected (code 4001) — simply close the modal, do not show a toast.
- Insufficient funds (code -32000) — show a message with the missing amount.
- Revert with reason — parse via
ContractFunctionRevertedErrorfrom viem:
import { ContractFunctionRevertedError } from "viem"; if (error instanceof ContractFunctionRevertedError) { const reason = error.data?.errorName ?? error.shortMessage; // Show the reason } - Stuck transaction — if pending > 5 minutes, provide UI for Speed Up or Cancel.
Another frequent issue is network mismatch. We use a ChainGuard component that checks chainId via useChainId and calls switchChain when needed. This prevents cryptic errors and improves UX.
How to Integrate a Wallet in 5 Steps
- Install wagmi and viem via npm/yarn.
- Set up
WagmiProviderwith the configuration of networks and wallets. - Use
useConnectanduseAccountfor connection. - Implement
useDisconnectfor logout. - Add ChainGuard for automatic network switching.
Development Stages
| Stage | What We Do | Result | Duration |
|---|---|---|---|
| Analysis | Study contract specifications, UX requirements | Technical specification | 2 days |
| Design | Component diagram, state management, routing | Architectural document | 2 days |
| Development | Wallet integration, transactions, events, UI | Working prototype on testnet | 5–10 days |
| Testing | QA on Sepolia, edge cases, network switching errors | Fixed bugs | 2 days |
| Deployment | Production environment setup, monitoring | Production | 1 day |
Cost is calculated individually, timeline from 10 business days. Get a consultation and we'll evaluate your project in 1 day.
What You Get in the End?
- Architecture and setup — wagmi configuration, multi-chain support, SSR wrappers.
- Contract integration — generation of hooks from ABI, multicall, confirmation handling.
- Wallet UX — ChainGuard for network control, disconnect handling, desktop/mobile wallets.
- Documentation — README with stack description, environment variables, commands.
- Team training — 2 code sessions, custom hooks analysis.
- 3 months of support — bug consultations, dependency updates.
Why Choose Us
5+ years of Web3 experience, 10+ implemented dApps, certified Solidity developers. Our solutions work on Ethereum, Arbitrum, Optimism, Polygon — we adapt to your network. Gas savings through call optimization up to 40%. Contact us for a project evaluation.







