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

Moonbeam in Russian
6 min readMay 3, 2021

--

Вступление

Возможность подписаться на Ethereum-события была добавлена ​​с релизом Moonbase Alpha v2. В этом руководстве мы расскажем о доступных типах подписки и текущих ограничениях.

Проверка предварительных условий

Примеры в этом руководстве работают в среде Ubuntu 18.04. Также Вам понадобится следующее:

Кроме того, нам нужно установить Node.js (мы будем использовать v14.x) и npm. Вы можете сделать это, запустив такую команду в своем терминале:

Мы можем проверить правильность установки, запросив версию каждого из пакетов:

node -vnpm -v

На момент написания этого руководства использовались версии 14.6.0 и 6.14.6 соответственно. Нам также потребуется установить пакет Web3, выполнив:

npm install --save web3

Чтобы проверить установленную версию Web3, Вы можете использовать команду:

npm ls web3

На момент написания этого руководства использовалась версия 1.3.0.

Подписка на Event Logs в Moonbase Alpha

Любой контракт, следующий токен-стандарту ERC-20, генерирует событие, связанное с передачей токенов, то есть event Transfer(address indexed from, address indexed to, uint256 value). В данном примере мы подпишемся на журналы этих событий. Используя web3.js библиотеку, мы выполним следующий фрагмент кода:

const Web3 = require('web3');
const web3 = new Web3('wss://wss.testnet.moonbeam.network');
web3.eth.subscribe('logs', {
address: 'ContractAddress',
topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef']
}, (error, result) => {
if (error)
console.error(error);
})
.on("connected", function (subscriptionId) {
console.log(subscriptionId);
})
.on("data", function (log) {
console.log(log);
});

Обратите внимание, что мы подключаемся к WebSocket эндпоинту Moonbase Alpha. Мы используем метод web3.eth.subscribe(‘logs’, options [, callback])для подписки на журналы, отфильтрованные по заданным параметрам. В нашем случае опциями являются адрес контракта, где совершаются события, и заголовки, используемые для описания события. Более подробную информацию о заголовках можно найти в этом посте на Medium. Если заголовки не включены, Вы подписываетесь на все события, связанные с контрактом. Для того чтобы отфильтровать только событие передачи, нам нужно включить сигнатуру события, рассчитываемую как:

EventSignature = keccak256(Transfer(address,address,uint256))

Результат вычисления показан в предыдущем фрагменте кода. Позже мы вернемся к фильтрации по заголовкам. Остальная часть кода обрабатывает колбэк-функцию. Как только мы выполним этот код, мы получим ID подписки, и терминал будет ожидать любое событие в рамках подписки:

Далее будет совершена Передача токена ERC-20 со следующими параметрами:

  • Адрес отправителя: 0x44236223aB4291b93EEd10E4B511B37a398DEE55
  • Адрес получателя: 0x8841701Dba3639B254D9CEe712E49D188A1e941e
  • Значение (токены): 1000000000000000000, т.е. 1 с 18 нулями

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

Давайте разберем полученный ответ. Наше целевое событие отправляет две части индексированной информации: адреса от и к (в этом порядке), которые обрабатываются как заголовки. Другая часть данных, которые отправляет наше событие, — это количество токенов, которое не индексируется. Таким образом, существует всего три заголовка (максимум четыре), которые соответствуют коду операции LOG3:

Следовательно, вы видите, что адреса “от” и “к” содержатся внутри заголовков, возвращаемых журналами. Адреса Ethereum имеют длину в 40 шестнадцатеричных символов (1 шестнадцатеричный символ равен 4 битам, следовательно, 160 битам или формату H160). Таким образом, дополнительные 24 нуля необходимы, чтобы заполнить пробел для H256, который составляет 64 шестнадцатеричных символа.

Неиндексированные данные возвращаются в поле данных журналов, но они кодируются в bytes32/hex. Чтобы расшифровать его, мы можем использовать, например, этот онлайн-инструмент и проверить, что данные на самом деле равны 1 (плюс 18 нулей).

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

Использование подстановочных знаков и условного форматирования

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

Используя тот же пример, что и в предыдущем разделе, давайте подпишемся на события токен-контракта со следующим кодом:

const Web3 = require('web3');
const web3 = new Web3('wss://wss.testnet.moonbeam.network');
web3.eth
.subscribe(
'logs',
{
address: 'ContractAddress',
topics: [
null,
[
'0x00000000000000000000000044236223aB4291b93EEd10E4B511B37a398DEE55',
'0x0000000000000000000000008841701Dba3639B254D9CEe712E49D188A1e941e',
],
],
},
(error, result) => {
if (error) console.error(error);
}
)
.on('connected', function (subscriptionId) {
console.log(subscriptionId);
})
.on('data', function (log) {
console.log(log);
});

Здесь, используя подстановочный знак null вместо сигнатуры события, мы выставляем фильтр на прослушивание всех событий, производимых контрактом, на который мы подписались. Но в этой конфигурации мы также можем использовать второе поле ввода (topic_1) для задания фильтра по адресу, как упоминалось ранее. В случае нашей подписки мы уведомляем, что хотим получать только те события, где topic_1 является одним из адресов, которые мы предоставляем. Обратите внимание, что адреса должны быть в формате H256. Например, адрес 0x44236223aB4291b93EEd10E4B511B37a398DEE55 должен быть введен как 0x00000000000000000000000044236223aB4291b93EEd10E4B511B37a398DEE55. Как и прежде, выходные данные этой подписки будут содержать сигнатуру события в topic_0, чтобы сообщить нам, какое событие было отдано контрактом.

Как показано, после того, как мы предоставили два адреса с условным форматированием, мы получили два журнала с одним и тем же ID подписки. События, генерируемые транзакциями с других адресов, не будут отдавать журналы в эту подписку.

Этот пример показал, как мы можем подписаться только на журналы событий конкретного контракта, но web3.js библиотека предоставляет другие типы подписок, которые мы рассмотрим в следующих разделах.

Подписка на входящие ожидающие транзакции

Чтобы подписаться на ожидающие транзакции, мы можем использовать метод web3.eth.subscribe(‘pendingTransactions’, [, callback]), реализующий ту же колбэк-функцию для проверки ответа. Это намного проще, чем наш предыдущий пример, и он возвращает транзакционный хэш ожидающих транзакций.

Мы можем убедиться, что этот хэш транзакции совпадает с хэшем, показанным в MetaMask (или Remix).

Подписка на заголовки входящих блоков

Другой тип, доступный в Web3.js библиотеке — подписка на новые заголовки блоков. Для этого мы используем метод web3.eth.subscribe('newBlockHeaders' [, callback]), реализующий ту же колбэк-функцию для проверки ответа. Эта подписка предоставляет входящие заголовки блоков и может использоваться для отслеживания изменений в блокчейне.

Обратите внимание, что на изображении показан только один заголовок блока. Эти сообщения отображаются для каждого созданного блока, поэтому они могут довольно быстро заполнить терминал.

Проверка синхронизизации ноды с сетью

С помощью pub/sub также можно проверить, синхронизирована ли конкретная нода, на которую вы подписаны в данный момент с сетью. Для этого мы можем использовать метод web3.eth.subscribe(‘syncing' [, callback]), реализующий ту же колбек-функцию для проверки ответа. Эта подписка возвращает объект, когда нода синхронизируется с сетью.

Текущие ограничения

Реализация pub/sub в Frontier все еще находится в активном развитии. Данная первая версия позволяет разработчикам DApp (или пользователям в целом) подписываться на определенные типы событий, но все же существуют некоторые ограничения. Возможно, Вы заметили из предыдущих примеров, что некоторые поля не отображают правильную информацию в соответствии с текущей релизной версией. Это связано с тем, что некоторые свойства еще не поддерживаются в Frontier.

Обратная связь

Если у Вас есть фидбек относительно реализации Moonbase Alpha, подписки на события или другие темы, связанные с Moonbeam, не стесняйтесь обращаться к нам через наш официальный сервер в Discord.

Подготовлено при участии Anril#1704, Oksana#9601, Lyn.

--

--

Moonbeam in Russian
Moonbeam in Russian

Written by Moonbeam in Russian

Moonbeam — это совместимая с Ethereum платформа смарт-контрактов на Polkadot

No responses yet