wagmi: хуки useAccount и useReadContract

wagmi превращает работу с блокчейном в привычные React-хуки: useAccount, useReadContract, useWriteContract.

wagmi — набор React-хуков поверх viem для dApp: подключение кошелька, чтение и запись контрактов, кэширование и реактивность «как в обычном React».

Ручной ethers в React утомителен: useEffect, useState под каждый вызов, ручное кэширование, обработка загрузки и ошибок. wagmi прячет это за хуками, очень похожими на React Query. Для React-dApp это де-факто стандарт.

Настройка провайдера

Сначала приложение оборачивают в WagmiProvider с конфигом сетей и транспортов (и обычно в QueryClientProvider, т.к. wagmi использует TanStack Query):

import { WagmiProvider, createConfig, http } from "wagmi";
import { mainnet, polygon } from "wagmi/chains";

const config = createConfig({
  chains: [mainnet, polygon],
  transports: {
    [mainnet.id]: http(),
    [polygon.id]: http(),
  },
});

function App() {
  return (
    <WagmiProvider config={config}>
      <Dapp />
    </WagmiProvider>
  );
}

useAccount: кто подключён

import { useAccount } from "wagmi";

function Header() {
  const { address, isConnected } = useAccount();
  if (!isConnected) return <p>Кошелёк не подключён</p>;
  return <p>Вы: {address}</p>;
}

Хук реактивен: сменил пользователь аккаунт в MetaMask — компонент перерисуется сам. Не нужно вручную слушать accountsChanged — wagmi делает это за вас.

useReadContract: чтение

import { useReadContract } from "wagmi";

function Balance({ user }: { user: `0x${string}` }) {
  const { data, isLoading, error } = useReadContract({
    address: tokenAddress,
    abi,
    functionName: "balanceOf",
    args: [user],
  });
  if (isLoading) return <p>Загрузка…</p>;
  if (error) return <p>Ошибка чтения</p>;
  return <p>Баланс: {data?.toString()}</p>;
}

Хук сам управляет состояниями isLoading/error/data, кэширует результат и умеет обновлять его. Это снимает гору шаблонного кода.

Как работает под капотом

wagmi использует viem для самих вызовов и TanStack Query для кэша и реактивности. useReadContract — это, по сути, useQuery с ключом из адреса/функции/аргументов: одинаковые чтения дедуплицируются, результат кэшируется, при необходимости перезапрашивается. useAccount подписан на события кошелька через viem-коннектор и обновляет состояние при смене аккаунта/сети. Поэтому компоненты «сами» остаются в согласии с реальным состоянием кошелька.

Частые ошибки

  • Забыть обернуть приложение в WagmiProvider/QueryClientProvider. Хуки тогда бросят ошибку контекста.
  • Вручную дублировать слушатели accountsChanged. wagmi уже это делает; ручная подписка вызовет конфликты.
  • Игнорировать isLoading/error. Сетевые вызовы падают и тормозят; состояния надо отрисовывать.

Итоги

  • wagmi даёт React-хуки поверх viem: меньше шаблона, больше реактивности.
  • useAccount — подключение; useReadContract — чтение с кэшем и состояниями.
  • Нужны обёртки WagmiProvider и QueryClientProvider.
Проверьте себя
1. На чём построен wagmi под капотом?
AНа ethers v5
BНа viem и TanStack Query
CНа REST API
DНа Web3.js
2. Что даёт useAccount по сравнению с ручным window.ethereum?
AХранит приватный ключ
BРеактивно обновляет адрес при смене аккаунта без ручных слушателей
CДеплоит контракт
DЗаменяет ABI
3. Какие состояния возвращает useReadContract?
AТолько data
Bdata, isLoading, error
CТолько error
Dhash и receipt