Реализация взаимодействия с блокчейном через wagmi/viem на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация взаимодействия с блокчейном через wagmi/viem на сайте
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация взаимодействия с блокчейном через wagmi/viem на сайте

wagmi + viem — современный стандарт для Web3-фронтенда на React. wagmi предоставляет хуки (useAccount, useReadContract, useWriteContract), viem — низкоуровневый типизированный клиент. Связка заменяет ethers.js + react-query: меньше boilerplate, встроенный кэш, автоматический refetch по блокам.

Чем отличается от ethers.js

ethers.js — класс-ориентированная библиотека с мутабельным состоянием. new Contract(...) создаёт объект, который держит провайдер внутри себя. В React это проблема: при смене сети или аккаунта объект нужно пересоздавать.

viem строится на функциях и иммутабельных клиентах. wagmi управляет жизненным циклом клиентов автоматически — при смене аккаунта хуки автоматически обновляют данные.

// ethers.js подход
const provider = new BrowserProvider(window.ethereum);
const contract = new Contract(address, abi, provider);
const balance = await contract.balanceOf(walletAddress);

// viem/wagmi подход
const balance = await readContract(publicClient, {
  address,
  abi,
  functionName: 'balanceOf',
  args: [walletAddress],
});

Настройка

// lib/wagmi.ts
import { createConfig, http } from 'wagmi';
import { mainnet, arbitrum, base } from 'wagmi/chains';
import { injected, walletConnect } from 'wagmi/connectors';

export const config = createConfig({
  chains: [mainnet, arbitrum, base],
  connectors: [
    injected(),
    walletConnect({ projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID! }),
  ],
  transports: {
    [mainnet.id]: http(process.env.ETH_RPC_URL!),
    [arbitrum.id]: http(process.env.ARBITRUM_RPC_URL!),
    [base.id]: http(process.env.BASE_RPC_URL!),
  },
});
// app/providers.tsx
'use client';
import { WagmiProvider } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { config } from '@/lib/wagmi';

const queryClient = new QueryClient();

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    </WagmiProvider>
  );
}

Чтение данных из контракта

// hooks/useTokenData.ts
import { useReadContracts } from 'wagmi';
import { erc20Abi, formatUnits } from 'viem';

export function useTokenData(tokenAddress: `0x${string}`, userAddress?: `0x${string}`) {
  const { data, isLoading } = useReadContracts({
    contracts: [
      { address: tokenAddress, abi: erc20Abi, functionName: 'name' },
      { address: tokenAddress, abi: erc20Abi, functionName: 'symbol' },
      { address: tokenAddress, abi: erc20Abi, functionName: 'decimals' },
      { address: tokenAddress, abi: erc20Abi, functionName: 'totalSupply' },
      ...(userAddress ? [{
        address: tokenAddress,
        abi: erc20Abi,
        functionName: 'balanceOf' as const,
        args: [userAddress] as [`0x${string}`],
      }] : []),
    ],
    query: {
      refetchInterval: 30_000,
      staleTime: 10_000,
    },
  });

  const decimals = (data?.[2].result as number) ?? 18;

  return {
    isLoading,
    name: data?.[0].result as string | undefined,
    symbol: data?.[1].result as string | undefined,
    decimals,
    totalSupply: data?.[3].result
      ? formatUnits(data[3].result as bigint, decimals)
      : undefined,
    userBalance: userAddress && data?.[4]?.result
      ? formatUnits(data[4].result as bigint, decimals)
      : undefined,
  };
}

Запись в контракт

// hooks/useTokenTransfer.ts
import { useWriteContract, useWaitForTransactionReceipt, useSimulateContract } from 'wagmi';
import { erc20Abi, parseUnits } from 'viem';
import { useState } from 'react';

export function useTokenTransfer(tokenAddress: `0x${string}`, decimals: number) {
  const [recipient, setRecipient] = useState<`0x${string}` | undefined>();
  const [amount, setAmount] = useState('');

  const amountWei = amount ? parseUnits(amount, decimals) : 0n;

  // Симуляция до подписи — выявляем ошибки без gas
  const { error: simError } = useSimulateContract({
    address: tokenAddress,
    abi: erc20Abi,
    functionName: 'transfer',
    args: [recipient!, amountWei],
    query: { enabled: !!recipient && amountWei > 0n },
  });

  const { writeContract, data: txHash, isPending } = useWriteContract();
  const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash: txHash });

  const transfer = () => {
    if (!recipient || amountWei === 0n) return;
    writeContract({
      address: tokenAddress,
      abi: erc20Abi,
      functionName: 'transfer',
      args: [recipient, amountWei],
    });
  };

  return {
    recipient, setRecipient,
    amount, setAmount,
    simError,
    transfer,
    txHash,
    isPending,
    isConfirming,
    isSuccess,
  };
}

Прямой viem-клиент для серверного использования

wagmi работает только в React-контексте. Для API routes, server components, cron — прямой viem:

// lib/publicClient.ts
import { createPublicClient, http, createWalletClient } from 'viem';
import { mainnet } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';

export const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(process.env.ETH_RPC_URL!),
});

// Серверный wallet-клиент (для автоматических транзакций, relayer)
export const serverWallet = createWalletClient({
  account: privateKeyToAccount(process.env.RELAYER_PRIVATE_KEY as `0x${string}`),
  chain: mainnet,
  transport: http(process.env.ETH_RPC_URL!),
});

Подписка на события через viem

// Polling для HTTP транспорта
import { watchContractEvent } from 'viem/actions';

const unwatch = watchContractEvent(publicClient, {
  address: contractAddress,
  abi: contractAbi,
  eventName: 'Transfer',
  onLogs: (logs) => {
    for (const log of logs) {
      console.log(log.args);
    }
  },
  poll: true,
  pollingInterval: 4_000,
});

// Для WebSocket транспорта — push, не polling
import { webSocket } from 'viem';
const wsClient = createPublicClient({
  chain: mainnet,
  transport: webSocket(process.env.ETH_WS_URL!),
});

Типогенерация из ABI

# Установка wagmi CLI
npm i -D @wagmi/cli

# Автогенерация типизированных хуков
npx wagmi generate

После генерации появляются хуки вида useReadErc20BalanceOf(...) с полной типизацией аргументов — ошибка передачи неверного типа поймается на этапе компиляции.

Сроки: настройка wagmi/viem в проекте, подключение кошелька, чтение и запись в 1–2 контракта — 1–2 дня. Полный слой взаимодействия с типогенерацией, серверными клиентами и event-подпиской — 2–3 дня.