китаев.tech

JsonRpcProvider и WebSocketProvider

Чем отличаются HTTP и WebSocket provider в ethers.js v6: как читать данные через JsonRpcProvider и подписываться на новые блоки через WebSocketProvider.

Два способа подключиться к RPC

JsonRpcProvider отправляет обычные HTTP-запросы к Ethereum RPC-ноду.

WebSocketProvider держит постоянное WebSocket-соединение. Его используют, когда приложению нужны живые обновления: новые блоки, события контрактов или входящие транзакции.


Читаем блок и ждём следующий

typescript
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 в одном сценарии.


Что дальше

Материалы китаev.tech публикуются в образовательных целях и не являются инвестиционной рекомендацией. Примеры кода и описания протоколов — для обучения; использование в продакшне на ваш собственный риск. Дисклеймер и политика конфиденциальности.