Інтеграція фронтенда з Wagmi
Wagmi v2 — де-факто стандарт для React + EVM. Перехід з Wagmi v1 на v2 сломав багато API (перехід на Viem замість ethers.js, зміна hooks), тому якщо проект написаний під старо версію — інтеграція включає міграцію. Якщо з нуля — ставимо v2 одразу.
Настройка та конфігурація
// config.ts
import { createConfig, http } from 'wagmi';
import { mainnet, polygon, arbitrum, base } from 'wagmi/chains';
import { injected, coinbaseWallet, walletConnect } from 'wagmi/connectors';
export const config = createConfig({
chains: [mainnet, polygon, arbitrum, base],
transports: {
[mainnet.id]: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'),
[polygon.id]: http('https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY'),
[arbitrum.id]: http('https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY'),
[base.id]: http('https://base-mainnet.g.alchemy.com/v2/YOUR_KEY'),
},
connectors: [
injected(),
coinbaseWallet({ appName: 'AppName' }),
walletConnect({ projectId: process.env.VITE_WC_PROJECT_ID! }),
],
});
WagmiProvider оборачує додаток; QueryClientProvider (TanStack Query) — обов'язковий, Wagmi використовує його для кешування.
Основні паттерни
Читання даних
useReadContract для одного виклику, useReadContracts для батча через Multicall3:
const { data: balance } = useReadContract({
address: TOKEN_ADDRESS,
abi: erc20Abi,
functionName: 'balanceOf',
args: [address],
query: { enabled: !!address },
});
query.enabled — критична опція: без неї хук намагається читати до того, як address визначений. staleTime та gcTime контролюють як часто дані перечитуються — для балансів розумно 30 секунд, для повільно мінливих параметрів контракту — 5 хвилин.
Запис (трансакції)
const { writeContractAsync } = useWriteContract();
const { isLoading: isConfirming } = useWaitForTransactionReceipt({ hash });
const handleStake = async () => {
const hash = await writeContractAsync({
address: STAKING_ADDRESS,
abi: stakingAbi,
functionName: 'stake',
args: [parseEther(amount)],
});
// hash отримані — трансакція відправлена, чекаємо підтвердження
};
Підписи
Для SIWE та permit-підписей — useSignMessage та useSignTypedData:
const { signTypedDataAsync } = useSignTypedData();
// EIP-712 типізовані дані для permit
const signature = await signTypedDataAsync({
domain, types, primaryType: 'Permit', message: permitMessage,
});
Типічні проблеми при інтеграції
SSR/гідрація: Next.js App Router + Wagmi вимагають 'use client' на компонентах з хуками та обережного розділення серверної та клієнтської логіки. useAccount() на сервері завжди повертає disconnected — це нормально.
ABI типізація: Wagmi + Viem генерують типи з ABI через as const. Без as const втрачається type inference для аргументів та повертаних значень.
ENS resolution: useEnsName та useEnsAddress працюють тільки на mainnet. Для інших мереж — явно передавати chainId: mainnet.id.
Stale дані після трансакції: після успішної трансакції потрібно інвалідувати кеш:
const queryClient = useQueryClient();
// після успішного writeContract:
queryClient.invalidateQueries({ queryKey: ['readContract', ...] });
Або використовувати useWaitForTransactionReceipt з onSuccess callback для автоматичної інвалідації.
Орієнтири по строкам
Настройка з нуля (мультичейн, wallet UI, базові read/write хуки): 1 день. Інтеграція існуючого React-додатка з кількома смарт-контрактами та міграція з v1: 2-3 дні.







