Реализация взаимодействия с блокчейном через ethers.js/web3.js на сайте

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

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

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

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация взаимодействия с блокчейном через ethers.js/web3.js на сайте
Средняя
~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

Реализация взаимодействия с блокчейном через ethers.js/web3.js на сайте

ethers.js v6 и web3.js v4 — две зрелые библиотеки для работы с EVM-блокчейнами. ethers.js используется чаще: меньший размер бандла, лучшая типизация, более чистый API. web3.js встречается в legacy-проектах и там, где исторически использовался этот стек. Разбираем оба варианта.

ethers.js v6: ключевые концепции

В ethers v6 изменились импорты и появилась поддержка ESM без CJS-fallback:

import {
  BrowserProvider,      // для window.ethereum (кошелёк пользователя)
  JsonRpcProvider,      // для серверного RPC-доступа
  Contract,             // для взаимодействия с контрактами
  formatEther,          // BigInt → строка в ETH
  parseEther,           // строка в ETH → BigInt
  formatUnits,          // с учётом decimals
  parseUnits,
  isAddress,            // валидация адреса
  getAddress,           // нормализация к checksum
} from 'ethers';

Провайдеры

// Серверный провайдер (для SSR, API routes, cron)
const serverProvider = new JsonRpcProvider(process.env.ETH_RPC_URL);

// Клиентский провайдер через кошелёк пользователя
async function getWalletProvider() {
  if (!window.ethereum) throw new Error('Wallet not found');
  const provider = new BrowserProvider(window.ethereum);
  const signer = await provider.getSigner();
  return { provider, signer };
}

// Fallback: пробуем несколько RPC
import { FallbackProvider } from 'ethers';

const fallbackProvider = new FallbackProvider([
  { provider: new JsonRpcProvider('https://rpc1.example.com'), priority: 1, weight: 2 },
  { provider: new JsonRpcProvider('https://rpc2.example.com'), priority: 2, weight: 1 },
]);

Работа с контрактами через ethers.js

const ERC20_ABI = [
  'function balanceOf(address owner) view returns (uint256)',
  'function transfer(address to, uint256 amount) returns (bool)',
  'function approve(address spender, uint256 amount) returns (bool)',
  'function allowance(address owner, address spender) view returns (uint256)',
  'event Transfer(address indexed from, address indexed to, uint256 value)',
];

// Read-only контракт (серверный провайдер)
const tokenRead = new Contract(TOKEN_ADDRESS, ERC20_ABI, serverProvider);

// Контракт с подписью (кошелёк пользователя)
const { signer } = await getWalletProvider();
const tokenWrite = new Contract(TOKEN_ADDRESS, ERC20_ABI, signer);

// Чтение
const balance = await tokenRead.balanceOf(walletAddress);
console.log(formatUnits(balance, 18));

// Запись
const tx = await tokenWrite.transfer(recipientAddress, parseUnits('10', 18));
const receipt = await tx.wait(); // ждём подтверждения
console.log('Confirmed in block', receipt.blockNumber);

Подписка на события

// Слушаем Transfer-события токена в реальном времени
tokenRead.on('Transfer', (from, to, value, event) => {
  console.log(`${from} → ${to}: ${formatUnits(value, 18)} токенов`);
  console.log('Block:', event.log.blockNumber);
});

// Фильтрованные события — только входящие на адрес
const filter = tokenRead.filters.Transfer(null, walletAddress);
tokenRead.on(filter, (from, to, value) => {
  console.log(`Получено ${formatUnits(value, 18)} от ${from}`);
});

// Отписка при unmount
return () => { tokenRead.removeAllListeners(); };

Исторические события

async function getTransferHistory(
  contractAddress: string,
  walletAddress: string,
  fromBlock: number,
) {
  const contract = new Contract(contractAddress, ERC20_ABI, serverProvider);
  const filter = contract.filters.Transfer(null, walletAddress);
  const events = await contract.queryFilter(filter, fromBlock, 'latest');

  return events.map(event => ({
    from: event.args[0],
    to: event.args[1],
    amount: formatUnits(event.args[2], 18),
    blockNumber: event.blockNumber,
    txHash: event.transactionHash,
  }));
}

web3.js v4: основные паттерны

web3.js v4 — полный переписанный API с TypeScript-нативной поддержкой:

import { Web3 } from 'web3';

const web3 = new Web3(window.ethereum);

// Или с HTTP провайдером
const web3Server = new Web3(process.env.ETH_RPC_URL);
// Контракт через web3.js
const erc20Contract = new web3.eth.Contract(ERC20_ABI, TOKEN_ADDRESS);

// Чтение
const balance = await erc20Contract.methods.balanceOf(walletAddress).call();
const formatted = web3.utils.fromWei(balance, 'ether');

// Запись
const accounts = await web3.eth.getAccounts();
const receipt = await erc20Contract.methods
  .transfer(recipient, web3.utils.toWei('10', 'ether'))
  .send({ from: accounts[0] });

Обработка BigInt в UI

ethers v6 возвращает нативный BigInt, web3.js v4 тоже. Проблема — JSON.stringify не сериализует BigInt:

// Безопасная сериализация для state/API
const replacer = (_: string, value: unknown) =>
  typeof value === 'bigint' ? value.toString() : value;

JSON.stringify(data, replacer);

// Или используйте SuperJSON для Prisma/tRPC стека
import superjson from 'superjson';
superjson.stringify(data); // автоматически обрабатывает BigInt

Утилиты, которые нужны в каждом проекте

// Сокращение адреса для отображения
export function shortenAddress(address: string): string {
  return `${address.slice(0, 6)}…${address.slice(-4)}`;
}

// Проверка и нормализация адреса
export function safeGetAddress(input: string): string | null {
  try {
    return getAddress(input); // бросает если невалидный
  } catch {
    return null;
  }
}

// Конвертация timestamp блока в дату
export async function blockToDate(blockNumber: number): Promise<Date> {
  const block = await serverProvider.getBlock(blockNumber);
  return new Date(Number(block!.timestamp) * 1000);
}

Сроки: интеграция чтения данных из контракта и подписки на события через ethers.js — 1–2 дня. Полноценный слой взаимодействия с несколькими контрактами, обработкой ошибок, fallback-провайдерами и историческими событиями — 3–4 дня.