No history yet

Архитектура и подключение

Архитектурные различия

При создании децентрализованного приложения (dApp) выбор правильной JavaScript-библиотеки для взаимодействия с блокчейном Ethereum имеет решающее значение. Две основные библиотеки, web3.js и ethers.js, решают эту задачу по-разному, что напрямую влияет на структуру вашего кода.

Исторически web3.js использовала монолитный подход. Вы создавали один всемогущий объект web3, который совмещал в себе все: и подключение к сети для чтения данных, и возможность подписывать транзакции с помощью кошелька. Это было удобно для быстрого старта, но могло приводить к путанице в коде, где не всегда было очевидно, какая операция требует только чтения, а какая — подписи пользователя.

В то время как web3.js предоставляет единый инстанцированный объект web3 с методами для взаимодействия с блокчейном, ethers.js разделяет API на две отдельные роли.

Ethers.js, напротив, с самого начала строилась на принципах модульности и разделения ответственности. В ее архитектуре есть два четко разграниченных понятия: Provider и Signer.

  • Provider — это ваше окно в мир блокчейна. Он предоставляет доступ только для чтения к данным: получение баланса, чтение информации из смарт-контрактов, просмотр истории транзакций. Провайдер не имеет доступа к приватным ключам и не может создавать транзакции.
  • Signer — это абстракция над аккаунтом пользователя. Он наследует все методы Provider, но дополнительно может подписывать транзакции и сообщения. Signer — это то, что позволяет вашему dApp инициировать операции, изменяющие состояние блокчейна (например, отправку токенов или вызов платной функции контракта).

Такое разделение делает код более предсказуемым и безопасным. Вы всегда точно знаете, какая часть вашего приложения имеет право тратить средства пользователя, а какая — только запрашивать публичную информацию.

Подключение к блокчейну

Первый шаг в любом dApp — установить соединение с узлом Ethereum. Это можно сделать с помощью публичных RPC-сервисов, таких как Infura или Alchemy. Это соединение позволяет вашему приложению читать данные из блокчейна.

В ethers.js для этого используется JsonRpcProvider. Вы просто передаете ему URL вашего RPC-сервиса.

// ethers.js
import { ethers } from "ethers";

// Подключение к основной сети Ethereum через Alchemy
const provider = new ethers.JsonRpcProvider("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY");

const blockNumber = await provider.getBlockNumber();
console.log("Текущий номер блока:", blockNumber);

В web3.js процесс выглядит похоже. Вы создаете новый экземпляр класса Web3 и передаете ему URL провайдера.

// web3.js
import Web3 from "web3";

// Подключение к основной сети Ethereum через Alchemy
const web3 = new Web3("https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY");

const blockNumber = await web3.eth.getBlockNumber();
console.log("Текущий номер блока:", blockNumber);

Оба этих способа создают соединение только для чтения. Чтобы подписывать транзакции, нужно подключить кошелек.

Интеграция с кошельками

Чтобы dApp мог отправлять транзакции от имени пользователя, ему нужен доступ к кошельку, например, MetaMask. Браузерные кошельки "внедряют" в веб-страницу специальный объект — window.ethereum. Этот объект служит мостом между вашим сайтом и кошельком пользователя.

В ethers.js версии v6 для работы с браузерным кошельком используется BrowserProvider.

// ethers.js
import { ethers } from "ethers";

// 1. Создаем провайдер из объекта, внедренного кошельком
const provider = new ethers.BrowserProvider(window.ethereum);

// 2. Запрашиваем у пользователя разрешение на подключение 
// и получаем Signer для подписи транзакций
const signer = await provider.getSigner();

// 3. Теперь можно отправлять транзакции
const tx = await signer.sendTransaction({
  to: "0x...", // Адрес получателя
  value: ethers.parseEther("0.01") // Сумма в ETH
});

console.log("Транзакция отправлена:", tx.hash);

Обратите внимание на логику: сначала мы создаем Provider для связи с кошельком, а затем получаем из него Signer. Этот Signer и есть объект, представляющий аккаунт пользователя, который может одобрять операции.

В web3.js 4.x процесс немного проще, так как нет явного разделения на провайдера и подписанта. Вы просто передаете window.ethereum в конструктор, и полученный объект web3 может как читать данные, так и запрашивать подпись транзакций.

// web3.js
import Web3 from "web3";

// 1. Создаем экземпляр web3 из объекта кошелька
const web3 = new Web3(window.ethereum);

// 2. Запрашиваем аккаунты
const accounts = await web3.eth.requestAccounts();
const fromAddress = accounts[0];

// 3. Отправляем транзакцию
const txHash = await web3.eth.sendTransaction({
  from: fromAddress,
  to: "0x...",
  value: web3.utils.toWei("0.01", "ether")
});

console.log("Транзакция отправлена:", txHash);

Хотя подход web3.js может показаться более простым, явное разделение на Provider и Signer в ethers.js помогает писать более структурированный и безопасный код, четко разграничивая операции чтения и записи в блокчейн.

Теперь, когда вы знаете, как установить соединение, можно переходить к взаимодействию со смарт-контрактами.