Eu costumo dizer que o mundo web3 é um mundo selvagem: ele não é fácil de dominar, mas tem muita oportunidade para os pioneiros que o desbravam. As exchanges descentralizadas (dex) são um bom exemplo disso: corretoras operando diretamente na blockchain sem book de ofertas, sem APIs REST, com interfaces muitas vezes pouco amigáveis aos investidores tradicionais, cheias de novas terminologias…em um primeiro olhar, porque alguém iria querer usar isso?
Mas você sabe que tem muito “ouro” nelas, certo? E uma das maneiras mais inteligentes de extrair esse ouro todo é através de automação: de softwares que costumamos chamar de robôs ou bots e que, uma vez construídos, nos permitem monitorar e fazer os swaps por nós, nos melhores momentos que seriam possíveis.
Neste tutorial de hoje eu vou lhe ensinar a primeira das duas atividades que citei acima: monitoramento. Esse monitoramento vai permitir que um software nosso, escrito em Node.js, fique atento a flutuações de preços de uma moeda em uma exchange descentralizada específica. Em virtude do provedor de blockchain as a service que vamos usar, a Moralis, nosso bot terá suporte essas redes e exchanges. Uma vez com esse monitoramento implementado, você poderá fazer swaps, enviar sinais ou o que quer que sua imaginação lhe permita sonhar.
É importante entender que para conseguir acompanhar este tutorial você deve ter conhecimentos básicos de Node.js e de funcionamento de uma dex (swap ao menos), como usuário. Ajuda um pouco se você conhecer o básico de smart contracts em Solidity também, mas não é algo obrigatório.
Se preferir, você pode assistir ao vídeo abaixo ao invés de ler este tutorial.
Vamos lá!
O desafio do monitoramento
Uma das primeiras barreiras que encontramos quando queremos iniciar um trabalho de monitorar uma dex qualquer, como a Uniswap ou PancakeSwap, por exemplo, é que como elas rodam inteiramente na blockchain (web3 baby!), não há APIs REST para usarmos do modo que faríamos com corretoras centralizadas como Binance, por exemplo. Ao invés disso, precisamos interagir com smart contracts na blockchain usando bibliotecas com Web3.js ou EthersJS, que já mostrei como algumas vezes aqui no blog (clique nos links para conhecer os tutoriais).
No entanto, as dex não costumam fornecer em seus smart contracts funções que exibam os preços dos ativos (ou quase isso) e aí mora nosso primeiro e maior problema. Isso não é possível de maneira tão simples quanto em exchanges centralizadas porque não existe um book de ofertas para se consultar o preço atual em 99% das dex, pois elas operam de maneira diferente, baseadas na Constant Product Formula e outras “matemáticas” derivadas dela. Assim, com base na oferta de um par de moedas em um pool de liquidez vs o tamanho do lote a ser negociado, um “preço” é estipulado para aquela operação, na própria transação do swap em si.
Ou seja, não é algo impossível de ser calculado, apenas um pouco mais complexo do que gostaríamos. Felizmente outras empresas e projetos se encarregaram desse desafio pra gente, e o cenário mais comum é que qualquer automação que você venha a criar use de alguma fonte externa para obter os preços dos ativos, que não o smart contract da dex em si. E é isso que faremos.
Introdução à Moralis
Existem vários provedores de serviços web3/blockchain atualmente no mercado e um dos mais famosos se chama Moralis. A Moralis é uma empresa que construiu todo um conjunto de APIs e streams em cima de full nodes de blockchains famosas como Ethereum e BSC, permitindo que outros desenvolvedores consigam desenvolver aplicações integradas à blockchain sem de fato se integrarem diretamente na dita-cuja.
Claro que isso tira o look-and-feel web3 de tais projetos e cria uma dependência com o fabricante em questão, o que chamamos no mercado de cloud de “vendor lockin”, mas por outro lado aumenta consideravelmente a sua produtividade e consequentemente diminui o seu time to market, o que é algo extremamente desejável principalmente em MVPs. Então se para você, chegar mais rápido no mercado para validar sua hipótese e conseguir seus primeiros clientes é mais importante do que ter uma aplicação 100% descentralizada, então vai adorar trabalhar com as APIs da Moralis.
Inclusive uma das APIs que eles desenvolveram, e que nos interessa neste tutorial em questão, é a Token API. Basicamente eles rastreiam todos os pares de moedas negociados nas principais dex do mercado (as baseadas em Uniswap) através de várias redes blockchain e coletam diversas informações úteis de serem consumidas por outros softwares, fornecendo-as através de endpoints web2. Você encontra a documentação completa aqui, se quiser se adiantar.
Para usar a Token API, e qualquer outra API da Moralis, o primeiro passo é acessar o site oficial e fazer o seu cadastro gratuitamente. Avance por todas etapas do cadastro e ao término do assistente de configuração você deverá ter um projeto criado e com este projeto, uma API Key que você pode acessar na área de Settings. Com esta API Key em mãos, podemos avançar para a criação do nosso projeto.
Configurando o Projeto
Agora vamos criar nosso projeto Node.js, começando pela criação de uma pasta dex-monitor (vou configurar para Uniswap, mas você pode alterar para outras dex) e inicialização de um projeto Node.js nela.
1 2 3 4 5 |
mkdir dex-monitor cd dex-monitor npm init -y |
Depois, vamos instalar as dependências que vamos precisar. Ao invés de chamar a API da Moralis diretamente, utilizarei o SDK para Node.js fornecido pela empresa.
1 2 3 |
npm install dotenv moralis @moralisweb3/common-evm-utils |
Agora crie um arquivo .env na raiz do seu projeto e coloque nele as seguintes variáveis:
- API_KEY: informe sua API Key da Moralis;
- INTERVAL: informe o intervalo em que o bot vai coletar o preço atualizado. Ex: 300000 (5min);
- TOKEN_ADDRESS: informe o endereço do token ERC-20 que o bot vai monitorar. Ex: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 (WETH);
- EXCHANGE: o nome da dex que vamos monitorar, segundo essa lista da Moralis. Ex: uniswapv3
Muita atenção aqui à variável INTERVAL, pois cada chamada à API da Moralis consome créditos e o plano free deles tem limitação de uso. Outro ponto de atenção é com o endereço do token ERC-20 que você vai monitorar, pois eles mudam de rede para rede. Usarei como exemplo aqui o monitoramento a cada 5 minutos do preço em dólar do Wrapped Ether (WETH), que na prática é o mesmo que monitorar o preço do ETHUSD (Ether em dólares).
A rede eu vou deixar diretamente no código, mas seria outra informação candidata a virar variável de ambiente, caso queira deixar o projeto mais flexível.
![Curso Beholder](https://www.luiztools.com.br/wp-content/uploads/2021/05/banner-beholder.jpg)
Programando o Monitoramento
O próximo passo é criar nosso index.js e dentro dele o código de monitoramento, sendo abaixo um exemplo, que logo na sequência eu explico.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
require("dotenv").config(); const Moralis = require("moralis").default; const { EvmChain } = require("@moralisweb3/common-evm-utils"); async function getPrice(){ const price = await Moralis.EvmApi.token.getTokenPrice({ address: process.env.TOKEN_ADDRESS, chain: EvmChain.ETHEREUM, exchange: process.env.EXCHANGE }) console.log("USD " + price.result.usdPrice); } async function start() { await Moralis.start({ apiKey: process.env.API_KEY }); getPrice(); setInterval(getPrice(), process.env.INTERVAL) } start(); |
Começamos carregando as variáveis de ambiente através do pacote DotEnv e na sequência carregamos o pacote do Moralis SDK e um outro pacote da Moralis de utilitários. Depois eu defino uma função de obtenção de preço e outra de inicialização do nosso bot, que será chamada ao final do arquivo para dar o start no mesmo.
Esta função de start, a parte mais importante do nosso bot, começa com a configuração da API Key no Moralis SDK, algo que deve ser feito antes de usá-lo de fato. Na sequência eu pego o preço pela primeira vez (para não ter de esperar pelo timer) e defino um timer JS com setInterval, para que o bot funcione ininterruptamente a cada x tempo repetindo a monitoria. Monitoria essa que é feita com a mesma função getPrice que por sua vez chama a função getTokenPrice, equivalente a esta chamada de API aqui.
Repare que aqui eu setei no código que a rede a ser utilizada é a Ethereum (Mainnet) e que a exchange descentralizada que usarei como base é a Uniswap V3 (conforme citei na explicação do .env). Você pode mudar livremente estes valores conforme o seu interesse de monitoramento. O retorno que você tem nesta chamada (objeto price) é este abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
ResponseAdapter { jsonResponse: { tokenName: 'Wrapped Ether', tokenSymbol: 'WETH', tokenLogo: 'https://cdn.moralis.io/eth/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png', tokenDecimals: '18', nativePrice: { value: '1000000000000000000', decimals: 18, name: 'Ether', symbol: 'ETH', address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' }, usdPrice: 1669.9231459319842, usdPriceFormatted: '1669.9231459319842', exchangeAddress: '0x1f98431c8ad98523631ae4a59f267346ea31f984', exchangeName: 'Uniswap v3', tokenAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' }, getResponse: [Function (anonymous)] } |
Sendo que a única informação que me importa no momento é a usdPrice, que eu pego e imprimo no console como resultado do monitoramento. No entanto, outra informação que pode ser interessante para você em outros cenários é a nativePrice, que é basicamente o preço daquele token ERC-20 na moeda nativa da rede. Como estou na rede Ethereum, repare que o nativePrice é em ETH e que como estou monitorando WETH, que é um wrapped token pareado com ETH, seu valor é o equivalente a 1 ETH (em wei).
Outra forma de fazer esse tipo de monitoramento sem depender da Moralis é consultando diretamente os contratos da dex na blockchain (que é o que a Moralis faz), como nesse tutorial com Uniswap e nesse de PancakeSwap, mas é algo mais avançado ou via Graph API (Uniswap e PancakeSwap), que é um meio termo. E por fim, outra dica é usar desse monitoramento para alimentar um bot trader para Uniswap ou PancakeSwap.
E com isso finalizamos mais este tutorial. Até o próximo!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.