Что такое viem и зачем он нужен, если я уже знаю ethers.js
Узнаешь, чем viem отличается от ethers.js, установишь пакет и прочитаешь баланс адреса через createPublicClient.
TypeScript-first SDK для Ethereum
viem — это TypeScript-библиотека для чтения Ethereum и отправки транзакций через JSON-RPC. Она решает те же задачи, что ethers.js, но устроена иначе: вместо классов Provider / Signer / Contract — клиенты и отдельные функции, плюс автовывод типов из ABI.
Учить второй SDK имеет смысл, если ты идёшь в wagmi, RainbowKit или свежие React-dApp: там viem уже стоит под капотом.
Установка и чтение баланса
npm install viemimport { createPublicClient, http, formatEther } from "viem";
import { mainnet } from "viem/chains";
const publicClient = createPublicClient({
chain: mainnet,
transport: http("https://ethereum.publicnode.com"),
});
const vitalikAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
const balance = await publicClient.getBalance({
address: vitalikAddress,
});
console.log(formatEther(balance)); // например "1234.56"Код только читает сеть. Приватный ключ не нужен.
Как это работает
createPublicClient() — создаёт клиент для чтения: баланс, блоки, eth_call. Это аналог JsonRpcProvider в ethers.
chain: mainnet — говорит клиенту, какая сеть ожидается (chainId 1). Неверная сеть на RPC даст ошибку раньше, чем ты отправишь транзакцию не туда.
http(...) — транспорт: как именно ходить в ноду. Здесь обычный HTTP JSON-RPC.
getBalance({ address }) — RPC eth_getBalance. Результат — нативный bigint в wei, не объект BigNumber.
formatEther() — wei → строка в ETH. Имя то же, что в ethers v6.
Если ты знаешь ethers.js
Та же задача на ethers v6:
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("https://ethereum.publicnode.com");
const balance = await provider.getBalance(
"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
);
console.log(ethers.formatEther(balance));| ethers v6 | viem |
|---|---|
new JsonRpcProvider(url) | createPublicClient({ chain, transport: http(url) }) |
provider.getBalance(address) | publicClient.getBalance({ address }) |
ethers.formatEther(balance) | formatEther(balance) |
BigNumber / bigint | всегда bigint |
Главный сдвиг не в синтаксисе getBalance, а в модели: клиент + transport + явная chain вместо одного класса провайдера.
Частые ошибки
«Зачем ещё один SDK, если ethers уже умеет всё» → ethers умеет. viem нужен не потому что ethers сломан, а потому что экосистема React (wagmi v2) и TypeScript-инференс ABI сейчас строятся вокруг него.
Импорт только from "viem" для сетей → mainnet, sepolia и остальные цепи лежат в viem/chains. Без этого импорта клиент не собрать.
Сравнение бандла «на глаз» по одному import → viem модульный: в бандл попадает то, что ты реально вызываешь. Выгода видна на tree-shaking в сборке, а не на размере node_modules.
Что дальше
- Настройка publicClient и walletClient — разобрать замену Provider/Signer на два клиента
- Провайдер vs Сайнер — если ещё путаешь чтение сети и подпись
- ethers.js vs viem: что выбрать — сравнение по критериям и экосистеме