JsonRpcProvider и WebSocketProvider
Чем отличаются HTTP и WebSocket provider в ethers.js v6: как читать данные через JsonRpcProvider и подписываться на новые блоки через WebSocketProvider.
Два способа подключиться к RPC
JsonRpcProvider отправляет обычные HTTP-запросы к Ethereum RPC-ноду.
WebSocketProvider держит постоянное WebSocket-соединение. Его используют, когда приложению нужны живые обновления: новые блоки, события контрактов или входящие транзакции.
Читаем блок и ждём следующий
import { JsonRpcProvider, WebSocketProvider, formatEther } from "ethers";
const httpRpcUrl = "https://ethereum.publicnode.com";
const websocketRpcUrl = "wss://ethereum.publicnode.com";
const httpProvider = new JsonRpcProvider(httpRpcUrl);
const websocketProvider = new WebSocketProvider(websocketRpcUrl);
const vitalikAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
async function main() {
const network = await httpProvider.getNetwork();
const currentBlock = await httpProvider.getBlockNumber();
const balance = await httpProvider.getBalance(vitalikAddress);
console.log(`Сеть: ${network.name} (${network.chainId})`);
console.log(`Текущий блок: ${currentBlock}`);
console.log(`Баланс адреса: ${formatEther(balance)} ETH`);
console.log("Ждём следующий блок через WebSocket...");
await new Promise<void>((resolve) => {
websocketProvider.once("block", (blockNumber) => {
console.log(`Новый блок: ${blockNumber}`);
resolve();
});
});
}
try {
await main();
} finally {
httpProvider.destroy();
websocketProvider.destroy();
}Этот пример ничего не подписывает и не отправляет. Он только читает публичные данные Ethereum и один раз получает live-уведомление о новом блоке.
Как это работает
new JsonRpcProvider(httpRpcUrl) — создаёт provider для HTTP RPC. Такой provider подходит для обычных запросов: баланс, блок, call, чтение контракта.
new WebSocketProvider(websocketRpcUrl) — создаёт provider с постоянным соединением. Нода может сама прислать новое событие без повторных HTTP-запросов.
httpProvider.getBlockNumber() — делает RPC-запрос eth_blockNumber и возвращает номер последнего блока.
httpProvider.getBalance(address) — читает ETH-баланс адреса в текущей сети.
websocketProvider.once("block", callback) — подписывается на следующий новый блок и вызывает callback один раз.
provider.destroy() — закрывает соединения и таймеры provider. Это особенно важно для WebSocket, иначе Node.js-процесс может не завершиться.
Когда какой provider использовать
| Provider | Когда подходит | Что важно помнить |
|---|---|---|
JsonRpcProvider | чтение балансов, блоков, контрактов, отправка транзакций | каждый запрос идёт отдельно |
WebSocketProvider | подписки на блоки и события | соединение нужно закрывать |
Для большинства экранов dApp достаточно JsonRpcProvider или BrowserProvider. WebSocket нужен там, где интерфейс должен обновляться сразу после события в сети.
Частые ошибки
Использовать WebSocket для всего подряд → WebSocket дороже для инфраструктуры и сложнее в поддержке. Для обычного чтения используйте HTTP RPC.
Не закрывать WebSocketProvider → процесс или вкладка могут держать открытое соединение. После одноразовой задачи вызывайте destroy().
Смешивать сети → HTTP и WebSocket URL должны указывать на одну сеть. Не подключайте HTTP к mainnet, а WebSocket к Sepolia в одном сценарии.
Что дальше
- Подключение MetaMask через BrowserProvider — подключить браузерный кошелёк пользователя
- Провайдер vs Сайнер — понять разницу между чтением сети и подписью действий
- Events и Logs — разобраться, какие события можно слушать через WebSocket