Como criar bot/robô sniper para Uniswap V3 em Node.js - Parte 2

Cripto

Como criar bot/robô sniper para Uniswap V3 em Node.js - Parte 2

Luiz Duarte
Escrito por Luiz Duarte em 18/01/2024
Junte-se a mais de 34 mil devs

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

Recentemente escrevi um tutorial onde ensinei a primeira parte da construção de um bot sniper para a dex (exchange decentralizada) Uniswap. Na primeira parte eu ensinei como preparar o ambiente de desenvolvimento, como estruturar o projeto e a fazer o monitoramento dos novos pools criados na plataforma.

Nesta segunda parte a minha missão é lhe ajudar a implementar a compra o mais rápido possível após a criação do pool, que é quando a moeda está mais barata e consequentemente te trará a melhor lucratividade.

Então vamos lá!

#1 – Aprovando a Compra

O primeiro passo é fornecer autorização para que a Uniswap consiga realizar a negociação pra gente, caso contrário, quando o pool for criado e o bot for tentar comprar a moeda, vai dar erro por falta de permissão. Isso porque a função transferFrom, conforme especificação ERC-20, permite que um contrato faça transferência de fundos de uma conta para outra, no entanto isso requer uma aprovação prévia (allowance) do dono da carteira que terá seus fundos transferidos delegando essa permissão para o contrato que fará a transferência, a DEX neste caso.

Resumindo: a DEX não pode sair transferindo seus tokens sem a sua aprovação prévia. Além disso, essa etapa é importante que aconteça ANTES do pool ser criado, para que não atrase o processo de compra que deve ser o mais rápido possível.

Antes de codificar a função de aprovação abaixo, recomendo que revise se fez os passos de criar os arquivos JSON para guardar os ABIs. Mais especificamente vamos precisar do ABI de contrato ERC20 pois a função approve pertence a esse padrão. Para dar esta permissão vamos criar mais uma função em nosso index.js, que vou chamar de approve, já que este é o nome presente na especificação. Se olharmos olharmos o ABI veremos que a função approve do smart contract deve ter a seguinte assinatura (em Solidity).

O primeiro parâmetro é o endereço do contrato que vamos dar a permissão e o segundo parâmetro é a quantidade que vamos autorizar deste token. Esta função approve está presente em todos os contratos de tokens ERC20, e devemos chamá-la sempre antes de um swap onde vamos gastar/enviar tokens daquele contrato em questão.

Assim, uma versão da função approve no index.js pode ser vista abaixo.

Recebemos por parâmetro o objeto do contrato do token e usamos ele para chamar a função approve, passando como primeiro parâmetro quem poderá gastar nosso token (o router da dex) e qual a quantia, aguardando até o final antes de avançar.

Com esta função pronta, agora voltamos à função start e vamos inserir a lógica de approve bem no início da execução.

Aqui eu verifico com a variável isApproved se já aprovei antes e, se ainda não tiver feito, eu configuro um objeto de interação com o contrato do token que vou gastar no swap (eu estou usando o endereço do WETH na constante TOKEN), o ABI do ERC20 e o signer/carteira conectada que configuramos na parte 1 deste tutorial.

Essa aprovação também deve ser feita para preparar o token que compramos para venda. Sendo assim, adicione a chamada da função de aprovação também no nosso listener de novos pools, como abaixo.

Aproveitei e já adicionei também a lógica de verificar se ainda não fiz a compra e se o token1 do pool é o token que eu tenho para gastar (TOKEN, que está apontado para WETH no meu caso). Se entrar no if eu imprimo uma mensagem no console, sinalizo na variável de controle que abri minha posição (isOpened) e por enquanto imprimo que fiz o swap, mesmo sem fazê-lo, apenas para avançarmos.

Depois vem o código de aprovação em si, que é feito configurando um objeto de interação com o contrato do token0 (o que acabamos de comprar, do novo pool) e emitimos a aprovação para poder vendê-lo na quantidade amountOut, que teremos após o swap e compra (logo mais). Se o rodar esse código agora, ele vai funcionar do ponto de vista de aprovações, apenas não vai fazer swap nenhum mesmo, que é a nossa próxima missão.

#2 – Swap do Novo Pool

Agora que já sabemos como monitorar a criação de pools e como aprovar nossos swaps é hora de fazer os swaps em si. É importante salientar que todas transações na blockchain exigem o pagamento da taxa de gás, que deve ser paga sempre em ETH. Ou seja, apesar de não estar negociando ETHs neste bot, você deve ter ETH na carteira a fim de pagar as taxas (saiba mais aqui), ok?

Agora é hora de fazermos o código para swap. Para isso, vamos criar uma nova função, no mesmo arquivo.

A função swap é possivelmente a mais complexa até aqui. Nela, começamos definindo os parâmetros do swap, a saber:

  • tokenIn: endereço do token ERC-20 que você vai gastar/dar no swap;
  • tokenOut: endereço do token ERC-20 que você quer receber no swap;
  • fee: a taxa a ser paga (da Uniswap, definida na criação do pool);
  • recipient: quem vai receber os tokens;
  • deadline: prazo para conclusão do swap (use prazos mais longos nos testes pois a liquidez dos pools de teste é baixa);
  • amountIn: quantidade de tokens que você vai dar no swap (tokenIn, use valores baixos em teste, pois a liquidez dos pools de teste é baixa);
  • amountOutMinimum: o mínimo de tokenOut que você aceita receber (zero quer dizer qualquer quantia);
  • sqrtPriceLimitX96: um parâmetro mais avançado para limitar o preço a ser pago pela moeda (zero quer dizer qualquer preço);

A maioria desses parâmetros é autoexplicativo, mas você encontra a referência técnica completa no site da Uniswap mesmo. Com estes parâmetros, podemos chamar a função do objeto router (que está configurado para o contrato de swap routing) de nome exactInputSingle, que serve para fazer um swap simples/direto. Além dos parâmetros precisamos passar as configurações da transação com quem vai fazê-la (WALLET), qual o preço do gás a ser pago (10 gwei) e qual o limite de gás que estamos dispostos a pagar. Essas configurações adicionais são necessárias porque a lib Ethers não consegue calcular o custo de gás sozinha nos contratos da Uniswap, possivelmente por causa da arquitetura complexa do projeto, explicada aqui.

Com a transação enviada, a gente aguarda a sua conclusão (tx.wait) e depois pega nos logs do recibo a quantidade de tokens da nova moeda recebidos no swap, para que possamos usar essa informação depois na venda.

A nossa função de swap está pronta para uso. Volte à função start, mais especificamente no listener de pools.

Com essa lógica acima, assim que o pool for criado, nós vamos pegar as informações dele e se ele for um par usando TOKEN (WETH no meu exemplo), vamos comprar uma quantidade x dele (recomendo testar com 0.01), já sinalizando que a posição ficou aberta (isOpened true). Por outro lado, se a posição já estiver aberta (isOpened true) e o preço de venda foi superado, então a gente finge que vende, reiniciando a variável de controle para que seja possível o robô entrar em outro ciclo de compra.

Opcionalmente você pode criar alguma lógica de venda, seja baseada em tempo ou monitorando o preço da moeda até que ele fique interessante para venda, mas isso fica a seu critério. De minha parte, conclui aqui este tutorial onde você viu como fazer um bot sniper que compra uma moeda na Uniswap assim que ela é lançada.

Até a próxima!

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 *