Visão geral
Olá leitor! Hoje estaremos mergulhando em detalhes sobre como fazer um bot que compra tokens recém-cunhados na DEX PancakeSwap. Hoje pode ser a sua primeira vez criando um bot de negociação ou usando a rede BSC, e tudo bem! Quando você tiver lido e concluído todo este guia, você terá um nó Binance Smart Chain com uma carteira conectada e um bot de negociação para iniciar negociações na DEX PancakeSwap!
Pré-requisitos:
- WBNB para gastar
- BNB para pagar taxas de gás na BSC
- MetaMask instalada no seu navegador de escolha
- NodeJS instalado na sua máquina
- Um editor de texto
- Familiaridade com a linha de comando
O que é a PancakeSwap?
A PancakeSwap é uma Exchange Descentralizada ou DEX. Se você pensasse em termos de finanças tradicionais, a PancakeSwap seria um mercado onde você pode comprar e trocar bens. A PancakeSwap se baseia na blockchain BSC, o que significa que as transações acontecem um pouco mais rápido e as taxas de gás são um pouco menores quando comparadas com uma DEX Ethereum. Outras DEXs com as quais você poderia comparar a PancakeSwap são o SushiSwap ou a UniSwap, embora essas estejam ambas na Ethereum.
Como monitorar tokens recém-criados
Chega de lição de história. Você veio aqui para comprar alguns tokens recém-criados, certo? Em primeiro lugar, gostaria de avisá-lo de que este bot que estamos codificando para comprar novos tokens é funcional apenas como uma prova de conceito. Embora você possa teoricamente ganhar dinheiro com ele, eu recomendo fortemente fazer suas alterações personalizadas nele para atender ao seu apetite de risco. Este tutorial é para lhe dar as ferramentas para construir seu próprio bot mais inteligente.
A essência deste bot depende de escutar eventos específicos emitidos na blockchain. Neste caso, estamos monitorando a criação de novos tokens na PancakeSwap.
Antes de ficar muito animado, precisamos configurar nossas ferramentas para trabalhar com a PancakeSwap. As ferramentas, neste caso, são a nossa carteira e um nó que está conectado à rede BSC. Para o guia de hoje, estou usando uma carteira MetaMask emparelhada com um nó BSC alimentado pelo QuickNode.
Configurando um Nó
Embora este objetivo possa ser alcançado por qualquer conexão de nó na rede BSC, aqui no QuickNode, tornamos rápido e fácil configurar um nó BSC com capacidades WebSocket. Isso será útil mais tarde no tutorial, pois queremos monitorar um fluxo de informações.
Você pode se registrar para o plano que melhor atenda às suas necessidades e, em seguida, certifique-se de lançar seu nó na rede principal da BSC.
Você pode se registrar para uma avaliação gratuita, bem como ver os preços aqui.
Você precisará dos pontos de extremidade HTTPS e WSS para este tutorial. Deve ser algo parecido com isso:
Configurando a MetaMask
Com o nó configurado com sucesso, agora precisamos conectar nossa MetaMask a esta nova rede. Com a extensão aberta, você vai expandir a aba de redes e clicar em “Custom RPC”. Você o preencherá exatamente como esta imagem, exceto que copiará seu ponto de extremidade HTTPS do QuickNode no campo "Novo URL RPC".
Bom trabalho! Agora você pode usar sua carteira na rede BSC. Com tudo configurado corretamente, podemos começar a codificar o bot!
Codificando o Bot
Configuração do projeto
Em primeiro lugar, você precisa configurar um diretório para o código do bot.
mkdir PancakeSwapBot
cd PancakeSwapBot
Feito isso, crie um arquivo bot.js dentro do seu diretório.
Instalando Dependências
Antes de começar a codificar, precisamos adicionar o pacote ethers. Esta biblioteca nos permite interagir com a blockchain usando javascript. Para instalá-lo, execute o comando na raiz do diretório do seu projeto:
npm i ethers
O Código
O Boilerplate
Vá em frente e abra o seu arquivo bot.js com o seu editor de texto de escolha. Em seguida, adicione este pedaço de código no topo:
const ethers = require('ethers');
const addresses = {
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
router: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
factory: "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73",
me: "YOUR_WALLET_ADDRESS"
}
const mnemonic = "orange banana apple bravo charlie delta gamma ........."
const provider = new ethers.providers.WebSocketProvider("PROVEDOR_QUICKNODE_WSS_AQUI")
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
const account = wallet.connect(provider)
Para desmembrar isso, vamos analisar linha por linha.
- Linha 1: importando a biblioteca etehrs que instalamos anteriormente.
- Linha 3-8: listando todos os endereços que precisaremos para completar nosso script.
- WBNB é o endereço do token WBNB. WBNB, também conhecido como Wrapped BNB, é um token BEP20 com um valor de negociação 1-para-1 com o token nativo da BSC, o BNB. Vamos precisar de WBNB para comprar os tokens recém-criados.
- router é o endereço do contrato inteligente do roteador da PancakeSwap. Você pode encontrá-lo aqui.
- factory é o endereço do contrato factory da PancakeSwap. Você pode encontrá-lo aqui.
- me é o endereço da sua carteira!
- Linha 10: mnemonic é o mnemônico da sua carteira. Você pode obtê-lo através da MetaMask. Certifique-se de não compartilhar isso com ninguém ou colocá-lo em um repositório voltado para o público. Qualquer pessoa com este mnemônico pode acessar e controlar sua carteira!
- Linha 12-14: provider, wallet e account são as variáveis que permitem você se conectar do seu programa ao provedor Websocket do QuickNode e, em seguida, conectar sua carteira a todo o resto. Essa seção é a cola do seu projeto.
Os contratos
Com todos os endereços fora do caminho, a próxima coisa que precisamos fazer é definir os dois contratos que vamos usar.
const factory = new ethers.Contract(
addresses.factory,
['event PairCreated(address indexed token0, address indexed token1, address pair, uint)'],
account
);
const router = new ethers.Contract(
addresses.router,
[
'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)',
'function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)',
],
account
);
Aqui inicializamos dois contratos diferentes usando o método Contract do ethers. Para criar um novo contrato, você precisa passar o endereço do contrato inteligente, a parte da ABI que deseja usar na forma de um array e uma carteira. Para saber mais sobre ABI's, você pode ler nosso guia sobre o assunto.
Eu só vou desmembrar o factory, pois o formato é o mesmo para ambos.
- Linha 1: Chamando o método ethers.Contract.
- Linha 2: Passando o endereço do contrato Factory da PancakeSwap.
- Linha 3: Passando a ABI para o evento PairCreated que emite uma sinalização sempre que um novo par é criado na PancakeSwap. Você pode encontrar a ABI inteira do contrato aqui.
- Linha 4: Passando a variável account, que é o que permite o acesso do contrato à nossa carteira.
Se você quiser verificar a ABI do roteador (router), poderá encontrá-la aqui. Esta é uma ótima maneira de se familiarizar com o código do Solidity. Pode até lhe dar ideias que você não teria de outra forma!
Com esses dois contratos inicializados, agora podemos usar a funcionalidade definida na ABI em nosso código JavaScript. Este próximo passo é onde a mágica acontece!
Juntando tudo
Antes de entrarmos no código, vale a pena pensar no que precisamos fazer. Temos o evento que é emitido sempre que um novo token é lançado na PancakeSwap. No nosso caso, queremos comprar um pouco do nosso token. Com isso em mente, nosso plano ficará mais ou menos assim:
- Ouça o evento
- Descubra qual token é qual
- Use nosso WBNB para comprar uma certa quantidade do novo token
- Verifique se a taxa de câmbio está próxima do que foi cotado
- Envie os novos tokens para nossa carteira
Com este roteiro, você poderá acompanhar um pouco mais o que está acontecendo. Hora de entrar no código!
factory.on("PairCreated", async (token0, token1, addressPair) => {
console.log(`
~~~~~~~~~~~~~~~~~~
Novo par detectado
~~~~~~~~~~~~~~~~~~
token0: ${token0}
token1: ${token1}
addressPair: ${addressPair}
`);
// Este bloco garante que pagamos com WBNB
let buyToken, sellToken;
if(token0 === addresses.WBNB) {
buyToken = token0;
sellToken = token1;
}
if (token1 === addresses.WBNB) {
buyToken = token1;
sellToken = token0;
}
//Nenhum dos tokens é WBNB e não podemos comprar
if(typeof buyToken === "undefined") {
return
}
const amountIn = ethers.utils.parseUnits('0.1', 'ether'); //ether é a medida, não a moeda
const amounts = await router.getAmountsOut(amountIn, [buyToken, sellToken]);
const amountOutMin = amounts[1].sub(amounts[1].div(10)); // matemática para grandes números em JS
console.log(`
~~~~~~~~~~~~~~~~~~~~
Comprando um novo token
~~~~~~~~~~~~~~~~~~~~
buyToken: ${amountIn.toString()} ${buyToken} (WBNB)
sellToken: ${amountOutMin.toString()} ${sellToken}
`);
const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[buyToken, sellToken],
addresses.me,
Date.now() + 1000 * 60 * 5 //5 minutos
);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
}
)
Este bloco de código é um pouco grande, então vamos dividi-lo em partes menores, começando de cima.
factory.on("PairCreated", async (token0, token1, addressPair) => {
console.log(`
~~~~~~~~~~~~~~~~~~
Novo par detectado
~~~~~~~~~~~~~~~~~~
token0: ${token0}
token1: ${token1}
addressPair: ${addressPair}
`);
- Linha 1: colocando um ouvinte no método PairCreated do contrato factory que chamará de volta para esta função lambda assíncrona toda vez que for acionado.
- Linha 2-9: Imprimindo token0, token1 e addressPair que mapeiam para os parâmetros dados na ABI do PairCreated do factory.
// Este bloco garante que pagamos com WBNB
let buyToken, sellToken;
if(token0 === addresses.WBNB) {
buyToken = token0;
sellToken = token1;
}
if (token1 === addresses.WBNB) {
buyToken = token1;
sellToken = token0;
}
//Nenhum dos tokens é WBNB e não podemos comprar
if(typeof buyToken === "undefined") {
return
}
const amountIn = ethers.utils.parseUnits('0.1', 'ether'); //ether é a medida, não a moeda
const amounts = await router.getAmountsOut(amountIn, [buyToken, sellToken]);
const amountOutMin = amounts[1].sub(amounts[1].div(10)); // matemática para grandes números em JS
console.log(`
~~~~~~~~~~~~~~~~~~~~
Comprando um novo token
~~~~~~~~~~~~~~~~~~~~
buyToken: ${amountIn.toString()} ${buyToken} (WBNB)
sellToken: ${amountOutMin.toString()} ${sellToken}
`);
- Linha 2-14: Essa série de instruções if garante que as variáveis corretas sejam atribuídas de token0 e token1 que obtemos do evento PairCreated. Precisamos de lógica em torno disso porque o algoritmo da PancakeSwap não garante que WBNB seja token0 e o novo token seja token1. Isso garante que o token que estamos comprando seja WBNB e o token vendido para nós seja o novo token.
- Linha 15: amountIn é onde decidimos quanto gastar. Em nosso caso, estamos gastando 0,1 BNB. Você pode ver o "ether" usado no método parseUnits. Nesse contexto, "ether" não é uma moeda, mas uma medida.
- Linha 16-18: amounts usa o método getAmountsOut da ABI da PancakeSwap que definimos anteriormente. Ele leva a quantidade que você gostaria de comprar em BNB e um array contendo os dois endereços de contrato. Em seguida, retorna um array de números. Usamos amountOutMin para adicionar um pouco de flexibilidade à nossa compra. O número no índice 1 do array amounts é o número de tokens que receberemos em troca do nosso 0,1 WBNB que estamos colocando. A matemática realizada neste número pode parecer um pouco estranha à primeira vista. Isso é porque esses números que são retornados para nós estão em wei, que é 1e-18 dígitos longo. Números deste tamanho não podem ser manipulados matematicamente no JavaScript nativamente. As bibliotecas Ethereum usam outra biblioteca chamada Big Number sob o capô para realizar essas operações em grandes números. A saída de amountOutMin acaba sendo 90% de qualquer que seja o número original. Isso nos dá alguma flexibilidade necessária no nosso código, pois o preço muda tão frequentemente. Se não tivéssemos isso, teríamos dificuldade em encontrar negociações que correspondessem ao nosso algoritmo.
- Linha 19+: esse console.log() imprime os endereços do token que estamos comprando e vendendo. Também imprime quanto estamos comprando e vendendo.
Isso é tudo para esse bloco de código. Vamos para o último!
const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[buyToken, sellToken],
addresses.me,
Date.now() + 1000 * 60 * 5 //5 minutos
);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
}
)
O segundo contrato definido no roteador, swapExactTokensForTokens, é chamado.
Ele aceita 5 argumentos:
- A quantidade de tokens que desejamos vender - amountIn
- A quantidade de tokens que esperamos receber de volta - amountOutMin
- Um array com os endereços dos dois tokens - [buyToken, sellToken]
- O endereço da carteira do comprador - addresses .me
- Uma data de expiração para a transação - Date.now() + 1000 * 60 * 5 // 5 minutos
Observação: isso só funcionará se você tiver WBNB para comprar o token e BNB para pagar as taxas de gás!
Depois de invocar o método, tudo o que resta é imprimir um recibo após a compra bem-sucedida!
Isso é tudo para o nosso bot! Caso você tenha se perdido em algum lugar ao longo do caminho, aqui está uma cópia completa do roteiro:
const ethers = require('ethers');
const addresses = {
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
router: "0x10ED43C718714eb63d5aA57B78B54704E256024E",
factory: "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73",
me: "YOUR_WALLET_ADDRESS"
}
const mnemonic = "orange banana apple bravo charlie delta gamma ........."
const provider = new ethers.providers.WebSocketProvider("PROVEDOR_QUICKNODE_WSS_AQUI")
const wallet = ethers.Wallet.fromMnemonic(mnemonic);
const account = wallet.connect(provider)
const factory = new ethers.Contract(
addresses.factory,
['event PairCreated(address indexed token0, address indexed token1, address pair, uint)'],
account
);
const router = new ethers.Contract(
addresses.router,
[
'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)',
'function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)',
],
account
);
factory.on("PairCreated", async (token0, token1, addressPair) => {
console.log(`
~~~~~~~~~~~~~~~~~~
Novo par detectado
~~~~~~~~~~~~~~~~~~
token0: ${token0}
token1: ${token1}
addressPair: ${addressPair}
`);
// Este bloco garante que pagamos com WBNB
let buyToken, sellToken;
if(token0 === addresses.WBNB) {
buyToken = token0;
sellToken = token1;
}
if (token1 === addresses.WBNB) {
buyToken = token1;
sellToken = token0;
}
//Nenhum dos tokens é WBNB e não podemos comprar
if(typeof buyToken === "undefined") {
return
}
const amountIn = ethers.utils.parseUnits('0.1', 'ether'); //ether é a medida, não a moeda
const amounts = await router.getAmountsOut(amountIn, [buyToken, sellToken]);
const amountOutMin = amounts[1].sub(amounts[1].div(10)); // matemática para grandes números em JS
console.log(`
~~~~~~~~~~~~~~~~~~~~
Comprando um novo token
~~~~~~~~~~~~~~~~~~~~
buyToken: ${amountIn.toString()} ${buyToken} (WBNB)
sellToken: ${amountOutMin.toString()} ${sellToken}
`);
const tx = await router.swapExactTokensForTokens(
amountIn,
amountOutMin,
[buyToken, sellToken],
addresses.me,
Date.now() + 1000 * 60 * 5 //5 minutos
);
const receipt = await tx.wait();
console.log('Transaction receipt');
console.log(receipt);
}
)
Se você fez tudo corretamente, você poderá executar:
node bot.js
E veja o bot começar a comprar novos tokens que surgirem na PancakeSwap! Você pode ver erros como "Liquidez insuficiente" ou "Não é possível estimar o preço do gás". Tenha certeza de que esses são problemas com os novos tokens que estão sendo criados e não do seu lado. Se você deixar o script seguir seu curso, eventualmente será saudado com um recibo em seus logs de uma de suas compras!
Conclusão
Parabéns por fazer uma compra totalmente automatizada em uma DEX! Você está no caminho certo para se tornar um excelente formador de mercado DeFi. Vou reiterar novamente que isso é puramente uma prova de conceito e, embora você possa, em teoria, ganhar dinheiro com uma estratégia como essa, você provavelmente não ganharia. Não posso recomendar colocar muito dinheiro em sua carteira enquanto executa um script como este. Este guia é para educá-lo sobre como esses bots funcionam, não para ganhar dinheiro. Também oferece um excelente lugar para começar sozinho! As maneiras pelas quais você pode modificar ou melhorar o bot são infinitas.
Você poderia:
Em vez de comprar os tokens imediatamente, envie um e-mail ou mensagem de texto ao ouvir o sinal. Isso permitiria que você fizesse sua devida diligência em suas compras, em vez de comprar às cegas.
Tornar o processo de venda automatizado; dessa forma você não está se expondo ao risco por períodos prolongados.
Adicione mais parâmetros ao comprar algo. Em vez de apenas monitorar quando os tokens surgem, você pode garantir que ele atinja um limite arbitrário de sua escolha antes de comprar.
As possibilidades são muitas e limitadas apenas pela sua imaginação e determinação.
Assine nossa newsletter para mais artigos e guias sobre Ethereum. Se você tiver algum comentário, entre em contato conosco via Twitter. Você sempre pode conversar conosco em nosso servidor da comunidade no Discord, apresentando alguns dos desenvolvedores mais fantásticos que você já conheceu 😃.
Artigo original publicado por Quicknode. Traduzido por Paulinho Giovannini.
Oldest comments (0)