- Регистрация
- 23 Август 2023
- Сообщения
- 2 819
- Лучшие ответы
- 0
- Реакции
- 0
- Баллы
- 51
Offline
Создание фронтенда для Web3-приложений - это не только дизайн, кнопки и React. Это мост между пользователем и блокчейном. И ты, как фронтенд-разработчик - тот, кто этот мост строит.
В этой статье ты узнаешь:
Что такое Web3 Frontend и чем он отличается от Web2
Какие инструменты тебе реально нужны
Как начать с нуля
Как использовать wagmi - главный инструмент Web3-интерфейсов
Web3 Frontend — это интерфейс для децентрализованного приложения (dApp), который работает вместо сервера, напрямую общаясь с блокчейном и кошельком пользователя.
Если ты еще не знаешь что такое децентрализация, то обязательно прочитай об этом отдельно. Это целая концепция вокруг которой все web3 и построено.
Ты не отправляешь запросы на backend, как в Web2. Ты взаимодействуешь с сетью (Ethereum, Polygon, Base и т.п.) через смарт-контракты и подключённый кошелёк.
Что тебе нужно для старта?
1. Библиотеки Web3
Библиотека | Назначение |
---|---|
wagmi | Основной инструмент для Web3-интерфейса |
viem | RPC-клиент для вызова контрактов (вместо ethers.js) |
@rainbow-me/rainbowkit | Подключение кошельков с UI |
ethers.js (опц.) | Старый, но популярный Web3-клиент |
2. Базовые понятия Web3 - кратко и по делу
Чтобы комфортно работать с wagmi и любыми Web3-инструментами, нужно понимать, как устроен фундамент. Ниже представлены все ключевые термины, которые ты будешь встречать в dApp’ах снова и снова.
address → адрес кошелька или контракта
Это строка, которая представляет пользователя или контракт в сети. Она всегда начинается с 0x, содержит 40 символов.
Пример:
0x1234567890abcdef1234567890abcdef12345678
Есть два вида:
EOA (Externally Owned Account) — обычный кошелёк (например, MetaMask)
Contract Account — адрес, по которому развёрнут смарт-контракт
Чтобы отображать адрес красиво, используют ENS (например: vitalik.eth)
token → цифровой актив на балансе
ERC-20 — взаимозаменяемые (USDC, DAI):
поддерживают balanceOf, transfer, approve, decimals
Используй useBalance({ token }) в wagmi для получения баланса
ERC-721 — NFT (уникальные ID):
функции ownerOf, tokenURI, transferFrom
Через tokenURI получаешь метаданные с image, name
decimals — количество знаков после запятой:
ETH = 18, USDC = 6
Используй parseUnits / formatUnits из viem для конвертации
approve + allowance — разрешение контракту тратить токены
Обязательно для свапов, стейкинга и NFT-маркетплейсов
chainId → идентификатор сети
Показывает, к какой сети подключён пользователь. Каждый блокчейн имеет уникальный chainId.
Примеры:
Ethereum Mainnet → 1
Goerli Testnet → 5
Polygon → 137
Arbitrum → 42161
Optimism → 10
Ты используешь chainId, чтобы:
определить активную сеть
переключать сеть (через switchNetwork)
отображать правильные токены/цены
Это объект, через который ты читаешь данные из сети: балансы, блоки, события. Он не может подписывать транзакции.
→ В wagmi и viem провайдер создаётся через publicProvider() или RPC-провайдеры вроде Alchemy, Infura и т. д.
→ Примеры возможностей:
Получить текущий блок
Прочитать состояние контракта
Подписаться на события
Это расширение provider с доступом к приватному ключу (который держит MetaMask).
С помощью signer ты можешь:
отправить транзакцию (sendTransaction)
подписать сообщение (signMessage)
вызывать contract.write() (например, mint())
→ В wagmi тебе не нужно напрямую работать с signer, он используется внутри хуков типа useContractWrite.
smart contract, ABI, read/write
Смарт-контракт — это программа на блокчейне.
ABI (Application Binary Interface) — это инструкция для твоего фронтенда: какие функции у контракта, какие параметры, что возвращается.
Пример ABI-функции:
{
"name": "mint",
"type": "function",
"stateMutability": "payable",
"inputs": [],
"outputs": []
}
Есть два типа вызовов:
read → бесплатный, безопасный, не требует подписи (например, totalSupply(), balanceOf())
write → платный (gas), требует подписи (например, mint(), transfer())
→ gas → топливо, которое тратится на выполнение кода
→ gasPrice → цена за одну единицу газа (в Gwei)
→ fee = gas × gasPrice (тебе нужно заплатить в ETH или другой валюте)
→ nonce → счётчик количества транзакций от адреса (чтобы они шли по порядку)
Все write-функции тратят gas, даже если они не срабатывают (например, revert’ятся)
network, chain, L2
→ network = chain = блокчейн-среда, в которой работает dApp
→ L1 → основной уровень (Ethereum Mainnet)
→ L2 → надстройка над L1 для ускорения и удешевления транзакций
Ты должен всегда:
проверять, в какой сети находится пользователь
уметь предлагать переключение сети (например, с mainnet на L2)
работать с несколькими chainId через wagmi-конфигурацию
На блокчейне балансы измеряются в целых числах, без запятой
- ETH имеет 18 знаков после запятой
- USDC — 6
В wagmi ты используешь useBalance({ address }) — и получаешь уже отформатированное значение
Краткая таблица для повторения
Термин | Пояснение |
---|---|
address | Адрес пользователя или контракта (0x...) |
chainId | ID блокчейна |
provider | Канал к блокчейну (чтение) |
signer | Подписант транзакций (MetaMask и т.д.) |
contract | Программа на блокчейне |
ABI | Описание функций контракта |
gas | Стоимость исполнения |
read | Чтение без газа |
write | Транзакции с подписью и оплатой |
nonce | Счётчик транзакций |
signMessage | Подпись строки через кошелёк |
SIWE | Авторизация без пароля через Ethereum |
token | цифровой актив |
wagmi — must-have для Web3 Frontend
Библиотека wagmi — это набор React-хуков, которые позволяют:
Подключать кошелёк
читать/записывать в смарт-контракт
Получать баланс, ENS, chain info
Подписывать сообщения и транзакции
1. Установка:
npm install wagmi viem @rainbow-me/rainbowkit
2. Настройка WagmiConfig
// main.tsx
import { WagmiConfig, createConfig, configureChains } from 'wagmi'
import { publicProvider } from 'wagmi/providers/public'
import { mainnet, polygon, optimism } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const { publicClient, webSocketPublicClient } = configureChains(
[mainnet, polygon, optimism],
[publicProvider()]
)
const config = createConfig({
autoConnect: true,
publicClient,
webSocketPublicClient,
})
const queryClient = new QueryClient()
export function Web3Provider({ children }) {
return (
<WagmiConfig config={config}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiConfig>
)
}
3. Подключение кошелька
// ConnectWallet.tsx
import { useAccount, useConnect, useDisconnect } from 'wagmi'
import { InjectedConnector } from 'wagmi/connectors/injected'
export function ConnectWallet() {
const { connect } = useConnect({
connector: new InjectedConnector(),
})
const { disconnect } = useDisconnect()
const { isConnected, address } = useAccount()
return isConnected ? (
<div>
<p>Вы подключены: {address}</p>
<button onClick={() => disconnect()}>Отключиться</button>
</div>
) : (
<button onClick={() => connect()}>Подключить MetaMask</button>
)
}
4. Чтение баланса
// Balance.tsx
import { useBalance, useAccount } from 'wagmi'
export function Balance() {
const { address } = useAccount()
const { data, isLoading } = useBalance({ address })
if (isLoading) return <p>Загрузка...</p>
return <p>Баланс: {data?.formatted} {data?.symbol}</p>
}
5. Вызов функции смарт-контракта
// MintNFT.tsx
import { usePrepareContractWrite, useContractWrite } from 'wagmi'
import { parseEther } from 'viem'
const contractAddress = '0x123...' // твой контракт
const abi = [
{
name: 'mint',
type: 'function',
stateMutability: 'payable',
inputs: [],
outputs: [],
},
]
export function MintNFT() {
const { config } = usePrepareContractWrite({
address: contractAddress,
abi,
functionName: 'mint',
value: parseEther('0.01'),
})
const { write, isLoading, isSuccess } = useContractWrite(config)
return (
<button disabled={!write || isLoading} onClick={() => write?.()}>
{isLoading ? 'Минтим...' : 'Минт NFT'}
{isSuccess && <p>Успех!</p>}
</button>
)
}
Что по итогу?
Web3 Frontend - это не сложно, если начать с правильных инструментов.
Твоя цель - не перепридумать backend, а создать безопасный, быстрый и дружелюбный интерфейс поверх блокчейна. И в этом тебе максимально помогает wagmi.
В следующих частях мы остановимся более подробно на живых примерах dapp приложений и разберем как это все работает под капотом.