Como monitorar eventos da blockchain com Node.js e Web3.js

Cripto

Como monitorar eventos da blockchain com Node.js e Web3.js

Luiz Duarte
Escrito por Luiz Duarte em 25/04/2023
Junte-se a mais de 34 mil devs

Entre para minha lista e receba conteúdos exclusivos e com prioridade

Muitas vezes em aplicações web nós enviamos uma requisição para um servidor e ela levará um tempo considerável para ser processada. Quando não sabemos quanto é esse tempo e não podemos manter a conexão ativa até receber uma resposta sob risco de timeout temos de pensar em alternativas. A alternativa mais simples e ineficiente é fazer “pulling”, uma técnica que consiste em criar um timer e ficar fazendo requisições ao servidor pedindo por atualizações. A melhor alternativa é buscar ser avisado pelo servidor de algum forma quando o processamento acabar, geralmente envolvendo websockets ou webhooks.

Na programação para blockchain temos este mesmo problema elevado à enésima potência uma vez que o processamento em nós da rede é caro e geralmente lento, ao menos nas redes mais famosas como a Ethereum. Mesmo que esteja usando uma rede mais barata como a BNB Smart Chain (BSC) ou Polygon, ainda enfrentará esse dilema de como saber que um processamento terminou sem ficar consultando várias vezes a blockchain?

Neste universo em específico a solução é monitorar/escutar por eventos específicos nos smart contracts aguardando por novidades e é isso que vamos explorar no tutorial de hoje, usando a biblioteca Web3 e a tecnologia Node.js.

Curso Web3 para Iniciantes

#1 – Eventos em Solidity

O primeiro ponto é entender como os eventos em Solidity funcionam, assumindo aqui que você estará trabalhando com blockchains baseadas em Ethereum/EVM. Quando estamos programando nossos smart contracts nós podemos usar um keyword event para declarar um evento, como abaixo retirado de um contrato de token ERC-20.

Este evento Transfer é declarado no contrato e indica que ele pode ser monitorado/escutado por alguém conectado à blockchain. Agora para que o evento aconteça de fato, seja disparado, o programador do smart contract deve usar a keyword emit em alguma função do contrato, como abaixo, retirado do mesmo contrato ERC-20.

Assim, quando chamamos emit Transfer, nós enviamos um registro de evento para a blockchain que será incluído junto aos logs do bloco minerado e qualquer sistema que esteja monitorando este evento em específico será avisado, como uma carteira de criptomoedas por exemplo.

Um último ponto ainda sobre eventos no Solidity é que você pode querer escutar os eventos de uma carteira específica, ao invés de ficar escutando qualquer transferência que acontecer. Isso é possível através do uso da keyword indexed como mostrado acima, onde tanto o from quanto o to podem ser usados como filtro no monitoramento para receber apenas eventos de um from ou de um to específicos. Importante frisar que o uso da keyword indexed aumenta o custo de gás das transações que emitirem este evento, além do que existe um limite de até 3 variáveis indexed por evento apenas, então use com parcimônia.

Apesar do exemplo acima ser bem comum, envolvendo tokens e transferências, você pode criar o evento que quiser para qualquer finalidade. Por exemplo, se tiver um smart contract de uma dex (exchange descentralizada), você pode querer ter um evento para quando um trade é realizado entre dois traders, como abaixo.

Repare que este evento não tem nada a ver com o anterior, seus campos são completamente diferentes. E aí, na função que faz o trade acontecer de fato, você emite este evento para avisar quem quer que esteja monitorando este evento neste contrato.

Dito isso, agora que você entendeu como os eventos são declarados e emitidos nos contratos é hora de entender como monitoramos eles em nossas aplicações web.

#2 – Monitorando eventos no backend

Existem duas bibliotecas para criar aplicações Web3 no mercado que realmente valem a pena ser citadas: a Web3.js e a EthersJS. Neste tutorial usarei a primeira por ser a mais antiga e mais largamente utilizada.

Para nosso exemplo de aplicação web frontend eu usarei Node.js, que é uma tecnologia muito usada em backend para Web3. Mesmo sem conhecimento algum de Node.js você pode criar um projeto simples usando o comando abaixo na sua máquina, dentro de uma pasta criada para guardar o projeto (a minha chamei de nodejs-evento-web3).

Depois, entre na pasta do projeto e vamos instalar as bibliotecas web3.js e dotenv que vamos usar.

Agora com tudo preparado, vamos criar uma funcionalidade no backend (crie um arquivo index.js) que espera pelo evento de transferência de um token. Para que você consiga simular esse teste é importante que você já tenha publicado um contrato seu na blockchain, a fim de poder interagir com ele de forma a causar o disparo do evento que estará monitorando. Eu estarei usando este contrato de token ERC-20 que publiquei na BSC Testnet.

Para fazer a conexão com seu contrato você vai precisar ter o ABI dele (Application Binary Interface) que você consegue após compilar ele ou após verificá-lo no BSCScan/EtherScan. O meu ABI do contrato ERC-20 está abaixo e ele define toda a especificação pública do contrato.

Com seu ABI em mãos, crie um abi.json na pasta do seu projeto de backend e importe ele no topo do arquivo index.js junto do pacote Web3 e do carregamento do dotenv (que vamos configurar logo mais).

Para receber eventos da blockchain é importante que você tenha uma conexão de websockets com um full node. Felizmente hoje é dia é muito fácil conseguir acesso a um usando provedores de blockchain as a service como Infura, Moralis, Ankr, Quicknode e outros que fornecem um acesso limitado gratuito aos mesmos. No meu caso que tenho o contrato publicado na BSC Testnet  vou usar a Quicknode neste exemplo que é um dos provedores que fornecem nós para BSC. Se vai publicar na Ethereum ou Sepolia, pode usar a Infura por exemplo. Apenas crie uma conta no provedor da sua preferência e use o nó gratuito para obter a URL do servidor de websockets que será necessário mais abaixo.

Essa URL, bem como o endereço do seu contrato na blockchain devem ser colocados por segurança em um arquivo .env na raiz do seu projeto, que não deve ser versionado, como abaixo.

Com as importações realizadas e variáveis de ambiente posicionadas, vamos escrever a função dentro do index.js que fará o monitoramento e tratamento do evento depois de recebido.

Começamos a função carregando um objeto Web3 com a URL do servidor de websockets. Depois inicializamos com este objeto um contrato configurado com o ABI e endereço do contrato que temos publicado na blockchain. Com este contrato podemos configurar a assinatura (eth_subscribe) de eventos da blockchain onde o nome do evento é Transfer em meu exemplo, conforme consta no contrato em Solidity.  Para a função Transfer podemos passar ainda um objeto de opções com as propriedades filter, fromBlock e toBlock. O filter (que eu usei a minha carteira como exemplo) permite usar qualquer propriedade indexed do evento para usar como filtro, enquanto que fromBlock e toBlock definem os números de blocos válidos para receber os eventos.

Uma vez configurada essa conexão ao evento Transfer nós definimos alguns listeners de eventos como o data, que é disparado cada vez que um novo evento é enviado ou o connected que é disparado quando a conexão é estabelecida. Neste exemplo eu configurei todos os eventos possíveis apenas imprimindo no console, para você conseguir testar.

Agora rode a sua aplicação com ‘node index.js’ e conseguirá testar facilmente desde que consiga simular a situação que emitirá o evento, como na imagem abaixo. Com isso finalizamos nosso exemplo de backend.

E com isso finalizamos o nosso tutorial de como monitorar eventos da blockchain com Web3.js, espero que tenha lhe ajudado!

TAGS:

Olá, tudo bem?

O que você achou deste conteúdo? Conte nos comentários.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *