Регистрация событий Ethereum с помощью NodeJS

Хотите верьте, хотите нет, но Web3 и распределенные приложения останутся! Эти технологии способствуют созданию более децентрализованного Интернета, где данные не принадлежат отдельным учреждениям, а приложения не обязательно работают на серверах, управляемых крупными компаниями. Мы говорим об утопическом будущем, в котором данные и приложения не будут привязаны к какому-либо конкретному месту, они просто будут существовать в сетях.

До этого утопического момента традиционные облачные приложения будут сосуществовать с распределенными приложениями, а в некоторых случаях им придется взаимодействовать между собой. Облачным приложениям может понадобиться прочитать транзакции по определенному адресу, проверить, что смарт-контракт выполняет определенное событие, или просто отправить транзакцию или данные по определенному адресу, а также другие виды взаимодействия.
Мы рассмотрим необходимые части для того, чтобы приложение nodeJS могло взаимодействовать с сетью Ethereum на нескольких простых примерах.

Посредник

Первым действующим лицом в этой интеграции между традиционным приложением nodeJS и сетью Ethereum является механизм, который позволит нам слушать блокчейн и отправлять данные в блокчейн.

Чтобы иметь такой механизм связи, у нас есть два варианта: создать узел Ethereum или воспользоваться услугами стороннего провайдера. Основное различие между этими двумя вариантами — уверенность.

Если мы управляем своим узлом, мы знаем, что информацией не управляет третья сторона, и можем доверять данным, которые мы читаем. Напротив, недостатком управления своим узлом является то, что обычно это сложнее, чем использование третьей стороны для подключения к сети блокчейн.

Для монтирования узла Ethereum рекомендуется использовать Geth. Geth — это одна из трех оригинальных реализаций протокола Ethereum, реализованная на языке Go, и это одна из наиболее используемых реализаций для создания узла Ethereum. Вам потребуется машина с МНОГО места на жестком диске, а также загрузка, настройка и запуск Geth.

Другая альтернатива монтированию узла — использование облачного провайдера, такого как AWS или Azure. В облачных провайдерах вы можете смонтировать Geth на обычном облачном экземпляре или использовать специальные сервисы, такие как Amazon Managed Blockchain или узел Ethereum из Azure Marketplace.

Если вы не хотите возиться с настройкой узла Ethereum, вы можете воспользоваться услугами сторонних провайдеров, которые могут предоставить вам доступ к сети через них. Одними из наиболее известных провайдеров являются Infura, Alchemy и QuickNode. В нашем примере мы будем использовать Infura.

Наконец, не рассмотренный здесь, еще одним вариантом взаимодействия с блокчейном может быть использование Etherscan API для чтения информации о счетах, транзакциях, блоках и т.д… с помощью REST API.

Интерфейс Javascript

На предыдущем этапе, используя собственный узел или узел, предоставленный третьей стороной, мы собираемся получить URL-адрес к JSON gRPC API.

Для взаимодействия с узлом Ethereum мы будем использовать JSON gRPC API, но, к счастью, нам не придется взаимодействовать с ним напрямую. Несколько библиотек работают как обертка вокруг API узла, облегчая нам жизнь. Web3js и Ethers — две наиболее часто используемые. В наших примерах мы будем использовать Web3js.

На данный момент у нас есть все необходимое, чтобы начать связывать nodeJS с Ethereum и начать получать события и адреса мониторинга. Следующая диаграмма обобщает все сказанное.

Считывание информации

Когда в нашем приложении NodeJS все готово, мы можем начать получать информацию из сети Ethereum. Web3js предоставляет нам несколько удобных методов получения информации в зависимости от того, что мы хотим отслеживать. Если мы хотим отслеживать происходящее вокруг смарт-контракта, мы будем использовать метод subscribe. Этот метод позволяет нам получать каждое событие, испускаемое смарт-контрактом.
Важным моментом здесь является то, что в случае с испускаемыми событиями мы говорим о событиях, регистрируемых Solidity. Если ваш контракт не испускает никаких событий, вы не увидите никаких данных, используя метод subscribe. Вот выдержка из кода, использующего метод subscribe:

const options = {address: '0xcontract_address'};
var subscription = web3.eth.subscribe('logs', options, function(error, result){
 if (!error) console.log('got result');
 else console.log(error);
}).on("data", function(log){
 const decodedLogs = abiDecoder.decodeLogs([log]);
 console.log(decodedLogs)
}).on("changed", function(log){
 console.log('changed');
});
Вход в полноэкранный режим Выход из полноэкранного режима

В этом фрагменте кода мы просто подписываем наше приложение на журналы Ethereum определенного адреса контракта, указанного в объекте options. Кроме того, мы декодируем событие с помощью библиотеки abiDecoder. Чтобы использовать эту библиотеку, мы предоставляем в конфигурации файл Contract.json, включающий ABI (Application Binary Interface) контракта.

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

Внутри массива событий мы получаем дополнительную информацию об испущенном событии:

Получить дополнительную информацию из сети

На данном этапе мы можем отслеживать смарт-контракт, но мы можем попытаться пойти дальше и попытаться отслеживать то, что происходит вокруг конкретного адреса. Благодаря Web3js мы также можем подписаться на каждый блок, добавленный в блокчейн, и изучить содержимое этого блока.

let blockSubscription = web3.eth.subscribe('newBlockHeaders')

blockSubscription.subscribe((error, result) => {
 if (error) {
   console.log("Error subscribing to event", error)
   process.exit()
 }
}).on('data', async blockHeader => {
 if (!blockHeader || !blockHeader.number)
   return
 const block = await web3.eth.getBlock(blockHeader.number)
 console.log(block)

})
Вход в полноэкранный режим Выход из полноэкранного режима

В данном случае мы просто подписываем наше приложение на newBlockHeader и печатаем результат:

В информации заголовка блока есть много информации о последнем добытом блоке, но есть очень важный для нас раздел transactions.

Этот массив содержит все хэши транзакций, включенных в этот блок, и, опять же благодаря Web3js, у нас есть метод получения информации о конкретной транзакции. Как видите, если мы хотим отслеживать только подмножество адресов, то здесь начинается интенсивная обработка XD.

const block = await web3.eth.getBlock(blockHeader.number)
 block.transactions.foreach( transactionHash => {
   transaction = await web3.eth.getTransaction(transactionHash)
   console.log(transaction)
})
Вход в полноэкранный режим Выход из полноэкранного режима

В результате мы можем получить всю информацию, связанную с транзакцией:

Мы можем получить адреса from и to, любую дополнительную информацию, включенную в транзакцию в поле input или сумму транзакции в Wei в поле value.

DISCLAIMER: Как вы уже догадались, мы выполняем множество запросов к сети, для каждого полученного блока мы запрашиваем информацию о блоке, а затем информацию обо всех транзакциях, включенных в этот блок. Из-за этого мы можем достичь предела использования стороннего узла, такого как Infura. Для данного конкретного случая использования рекомендуется использовать самоуправляемый узел.

Для получения дополнительной информации о конфигурации и проверки ее работы весь представленный код можно найти в этом репозитории. Репозиторий включает простой смарт-контракт, разработанный с помощью Hardhat, и весь необходимый код для мониторинга контракта и некоторых адресов Ethereum с помощью NodeJS.

Cover Photo by Shubham Dhage on Unsplash

Оцените статью
Procodings.ru
Добавить комментарий