As exchanges decentralizadas ou DEX, como são popularmente chamadas, são uma alternativa às exchanges tradicionais, ou centralizadas, como Binance e Coinbase. Enquanto que nas exchanges centralizadas você compra e vende moedas com a corretora como mediadora das negociações e sem a custódia das suas próprias moedas (“not your keys, not your money”), nas DEX temos todas as negociações, chamadas de swaps (trocas), sendo feitas através de usuários que se conectam à rede com suas próprias carteiras de criptomoedas (como MetaMask) e a mediação acontecendo através de contratos inteligentes (smart contracts). Ou seja, não é um P2P “cru”, direto, ainda existe um intermediador, mas ele é um software aberto e transparente, publicado na blockchain.
Como Chanpeng Zhao afirma, o próprio fundador da Binance, as DEX são o futuro das corretoras de criptomoedas já que por rodarem nativamente na blockchain eles garantem a segurança, o anonimato e a descentralização a todas as partes envolvidas, diferente das exchanges tradicionais que sofrem cada vez mais ataques dos órgãos reguladores nos países em que operam. No entanto, operar em uma DEX é ligeiramente mais complicado do que operar em exchanges comuns, pela própria natureza das criptomoedas e blockchain em si. Da mesma forma, programar bots para este tipo de corretora é um desafio maior também.
Desta forma, neste tutorial eu espero lhe ajudar a entender como criar um primeiro bot trader de criptomoedas que fará swaps em seu nome em uma DEX, a SushiSwap V3. A SushiSwap não foi escolhida por acaso: ela é um fork da UniSwap (ensino bot pra ela aqui), a maior DEX do mercado, o que garante que ela segue muitos padrões de desenvolvimento para redes “EVM compatible” (compatíveis com Ethereum Virtual Machine). Assim, uma vez que consiga programar um bot para SushiSwap, possivelmente conseguirá criar bots para outras redes “EVM compatible” no futuro.
É importante você entender, antes de começarmos a programar, que operar no mercado cripto é muito arriscado por este ser um mercado muito volátil e auto-regulado. Não posso prometer ou me responsabilizar por qualquer lucro ou prejuízo que você possa ter ao colocar o seu dinheiro em uma SushiSwap ou qualquer outra DEX, independente se usar os códigos que ensino ou não. Além disso, é imprescindível que você já possua conhecimentos básicos de programação para poder fazer este tutorial e também que já tenha feito swaps manualmente na SushiSwap antes, pois são coisas que não ensinarei aqui.
Dito isso, vamos ao tutorial.
#1 – Ambiente
Usaremos neste tutorial a tecnologia Node.js, cujo setup deve ser feito antes do projeto começar de fato. Baixe e instale diretamente do site oficial e caso tenha dificuldade, pode usar o vídeo abaixo. O vídeo também ensina a instalar o Visual Studio Code, que é a ferramenta de desenvolvimento que uso.
Você vai precisar também de uma carteira de criptomoedas e se já é usuário da SushiSwap certamente você já tem uma. Usarei aqui a MetaMask como exemplo pois é uma carteira bem popular e que consigo dar algum suporte. Via de regra, qualquer carteira compatível com rede Ethereum vai servir. Caso ainda não tenha uma MetaMask, no vídeo abaixo eu ensino a criar uma (é grátis) e a configurar ela com as configurações e saldo de teste. Também mostro isso nesse tutorial, caso prefira ler ao invés de assistir. Usarei aqui a rede Sepolia, mas você pode usar qualquer rede onde a SushiSwap possua operação.
Agora com saldo na carteira e ela apontada para a Sepolia, você pode obter USDC de teste no faucet oficial da Circle (mantenedora da moeda) e também obter WETH de teste pelo próprio contrato do WETH, chamando a função deposit. Caso você não tenha ETH para trocar por WETH, pode obter no faucet Sepolia PoW. Se não conseguir fundos de teste agora também não tem muito problema, mais tarde vou ensinar um truque de forkar a blockchain de produção localmente, aí teremos “fundos infinitos” para os testes.
Para fazer chamadas aos smart contracts da SushiSwap você vai precisar ter acesso a um nó da blockchain que desejará monitorar. Você pode obter um nó gratuitamente com a Infura, um dos maiores provedores de Blockchain as a Service do mundo. Crie uma conta gratuita no site deles e depois crie um node da rede que deseja (eu vou usar Sepolia) para você assim que conseguir entrar no painel. Guarde a API Key que vai receber, vamos precisar dela mais tarde.
E para obter a cotação dos pools de liquidez você vai precisar ter uma API Key criada no site The Graph onde está a Graph API da SushiSwap. Para isso, vá nessa página e siga o passo a passo, que consiste em:
- entrar com sua MetaMask;
- assinar uma mensagem para se autenticar na sessão;
- criar uma chave de API com o nome que quiser
Guarde esta chave consigo também, vamos usá-la à seguir.
E com isso nós estamos com tudo preparado para começar a programar.
#2 – Criando o Projeto
Agora vamos criar nosso projeto Node.js, começando pela criação de uma pasta sushiswap-v3 e inicialização de um projeto Node.js nela.
1 2 3 4 5 |
mkdir sushiswap-v3 cd sushiswap-v3 npm init -y |
Depois, vamos instalar as dependências que vamos precisar:
1 2 3 |
npm install dotenv ethers axios |
A saber:
- DotEnv: dependência para carregamento das variáveis de ambiente;
- Ethers: biblioteca para integração com a blockchain;
- Axios: biblioteca para chamadas HTTP;
Agora crie um arquivo .env na raiz do seu projeto e coloque nele as seguintes variáveis:
- NETWORK: o nome da rede que vai operar, em minúsculas. Ex: sepolia
- INFURA_API_KEY: sua Api Key da Infura.
- INTERVAL: a recorrência do monitoramento, recomendo 300000, que é equivalente a 5 minutos;
- TOKEN0_ADDRESS: o endereço do contrato do token que vai negociar via bot. Se estiver na Sepolia, use
0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 para o token WETH, por exemplo;
- TOKEN1_ADDRESS: o endereço do contrato do token que vai usar para pagar/receber. Se estiver na Sepolia, use
0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238 para o token USDC, por exemplo;POOL_ID: o endereço do pool de liquidez que será monitorado. Mesmo durante testes vamos monitorar um pool de produção. Neste exemplo vamos monitorar o pool de WETH/USDC, com endereço 0x87c7056bbe6084f03304196be51c6b90b6d85aa2;
- WALLET: endereço público da carteira que vai usar para o bot (você pega ela na MetaMask);
- PRIVATE_KEY: chave privada da carteira que vai usar para o bot (você pega ela dentro da MetaMask, em Detalhes da Conta);
- GRAPH_API_URL: a URL de acesso às informações na Graph API da SushiSwap, já com a API Key junto, no formato https://gateway-arbitrum.network.thegraph.com/api/{api-key}/subgraphs/id/7okunX6MGm2pdFK7WJSwm9o82okpBLEzfGrqHDDMWYvq
- ROUTER_ADDRESS: o endereço do contrato de swap routing da SushiSwap v3 na rede em questão. No caso da Sepolia, é
0x93c31c9C729A249b2877F7699e178F4720407733;
- PRICE_TO_BUY: o preço que servirá como gatilho para o bot comprar a moeda, na moeda de cotação (USDC no nosso exemplo). Ex: 5;
- AMOUNT_TO_BUY: a quantidade da moeda base que será usada em cada compra (WETH no nosso caso), na escala ‘ether’, com até 18 casas decimais. Ex: 0.1;
- PROFITABILITY: o multiplicador percentual que será usado como gatilho de venda. Ou seja, define a sua lucratividade. Ex: 1.1 (=10%);
Muita atenção aqui à variável INTERVAL, pois cada chamada à API de monitoramento de preço consome créditos e o plano free deles tem limitação de uso (falarei disso mais adiante). Outro ponto de atenção é com os endereços dos tokens 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 USDC do token WETH e estarei comprando e vendendo ele usando USDC, tudo na rede Sepolia.
Crie o arquivo index.js e coloque o código abaixo dentro dele, para carregar o .env e também para testar o carregamento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
require("dotenv").config(); const { ethers } = require("ethers"); const ROUTER_ADDRESS = process.env.ROUTER_ADDRESS; const WALLET = process.env.WALLET; const TOKEN0 = process.env.TOKEN0_ADDRESS; const TOKEN1 = process.env.TOKEN1_ADDRESS; const PRICE_TO_BUY = parseFloat(process.env.PRICE_TO_BUY); const AMOUNT_TO_BUY = ethers.parseUnits(process.env.AMOUNT_TO_BUY, "ether"); const PRICE_TO_SELL = PRICE_TO_BUY * parseFloat(process.env.PROFITABILITY); let isOpened = false, isApproved = false, amountOut = 0; |
Além de carregar o .env para memória, o código acima importa as bibliotecas que vamos usar e guarda as variáveis de ambiente em constantes locais, para facilitar seu uso mais tarde. Também adicionei algumas variáveis auxiliares ao final do código, que vamos precisar e recomendo que coloque algum console.log também, para ver mais facilmente se subiu o projeto com sucesso.
Ainda sobre o código acima, a maioria das constantes e variáveis ainda serão usadas ao longo do código, quando serão melhor explicadas.
Agora ajuste o seu package.json, na seção scripts, para iniciar o index.js, que será o arquivo principal da aplicação.
1 2 3 4 5 |
"scripts": { "start": "node index.js" }, |
Assim, se quiser fazer um teste, use sempre o comando abaixo.
1 2 3 |
npm start |
O resultado deve ser o código que colocou no index.js, se tiver algum console.log.
#3 – Monitorando o Mercado
A primeira coisa que vamos programar em nosso bot é o monitoramento do mercado. Diferente das exchanges centralizadas, que nos fornecem APIs com dados prontos para tudo, nas DEX não temos tanto ferramental para construir bots e espero que isso no futuro mude. No caso da SushiSwap você pode consultar diretamente na blockchain ou então usar a Graph API, que é o que vamos fazer aqui e que na etapa de ambiente passei as instruções para obter a API Key gratuita.
O monitoramento via Graph API é bem simples e consiste em enviar uma consulta POST para o endpoint e ele vai retornar o que deseja. Infelizmente não temos dados coerentes em ambiente testnet, logo vamos consultar diretamente os preços de produção mesmo, ok? Isso certamente vai atrapalhar qualquer estratégia que tente elaborar em seus testes de desenvolvimento, mas não deve impactar quando estiver apontado para produção.
A função de obter as informações de um pool de liquidez específico, incluindo o preço, pode ser vista abaixo e é explicada logo em seguida (coloque no index.js).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
async function getPrice(poolId) { const query = `{ pool(id: "${poolId}"){ id, feeTier, token0Price, token1Price, token0 { symbol, id, decimals } token1 { symbol, id, decimals } } }`; const { data } = await axios.post(process.env.GRAPH_API_URL, { query }); return parseFloat(data.data.token0price); } |
Nesta função nós fazemos uma chamada POST simples à URL da API, informando a consulta que queremos fazer. Esta consulta é representada por um objeto JSON com o filtro (id do pool) e campos que queremos no retorno. Um desses campos é o token0price, que dá o preço do token0 (WETH no meu caso) baseado no token1 (USDC no meu caso). Nós convertemos e retornamos este preço para fora da função.
Agora vamos chamar esta função getPrice no index.js.
1 2 3 4 5 6 7 8 9 10 |
async function executeCycle() { const usdPrice = await getPrice(process.env.POOL_ID); console.log("USD " + usdPrice); } setInterval(executeCycle, process.env.INTERVAL); executeCycle(); |
Assim, a cada x tempo o seu bot monitora o preço chamando a API, o que no futuro nos permitirá usar essa informação como gatilho para os swaps.
A próxima etapa é justamente fazer a compra ou a venda literalmente, mas este é um assunto para a parte dois deste tutorial, confira aqui!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.
O melhor do agoiros, possível.
Desculpe, não entendi.