La red de Binance Smart Chain es un ecosistema bastante nuevo, por lo que es difícil encontrar herramientas automatizadas para poder operar en ella. Pero por suerte sabemos que BSC es muy similar a la red Ethereum, por lo que podemos basarnos en la información ya existente en una, para operar en la otra.

Nuestro objetivo en este tutorial será crear un bot capaz de operar en plataformas descentralizadas como PancakeSwap, con el objetivo de poder comprar y vender tokens de forma automatizada, aplicando opciones como “Stop loss”, “trailing stop”, etc.

Para lograr esto hemos elegido C# como lenguaje de programación, si eres conocedor del tema sabrás que este tipo de herramientas en dicho lenguaje es casi inexistente, la información es bastante escasa, y la que hay solo habla de la red Ethereum, pero como mencionamos anteriormente, por suerte BSC es muy similar a Ethereum, por lo que usaremos una librería ya existente llamada “Nethereum”, que nos servirá para lograr nuestro objetivo.

La decisión de usar C# en vez de otros lenguajes más documentados como Python, es debido a que en C# contamos con el maravilloso IDE Visual Studio, que nos permite crear una GUI fácilmente sin necesidad de código, y esto nos permitirá enfocarnos de lleno en la funcionabilidad de nuestro bot, sin tener que molestarnos en lograr un entorno grafico funcional.

Creando nuestro proyecto e instalando los paquetes necesarios

El primer paso para crear nuestro bot, es crear un nuevo proyecto en Visual Studio, este paso es muy simple y no indagaremos mucho en ello, solo debes crear un proyecto, colocarle el nombre que desees, y seleccionar WinForm como aplicación.

Ahora debemos instalar la librería con la que trabajaremos (Nethereum), para ello nos vamos a “Proyecto”, luego a “administrar paquetes NuGet”, y en la pestaña de “Examinar”, colocaremos “Nethereum”.

Vamos a instalar “Nethereum.Web3”, y aceptar todas las dependencias que nos solicite instalar. Ahora nos iremos al código fuente de nuestro Form, e importaremos todas las librerías que necesitaremos:

using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.Contracts;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Util;
using Nethereum.Web3;
using Nethereum.Web3.Accounts;
using Nethereum.Signer;
using Nethereum.Hex.HexTypes;
using Nethereum.Hex.HexConvertors.Extensions;
using System.Globalization;
using System.Threading.Tasks;
using Nethereum.ABI;

Si alguna de estas librerías te causa un error, puede que no se haya instalado su paquete NuGet, para solucionarlo ve nuevamente al administrador de paquetes NuGet, busca la librería que te de error, e instálala.

Ahora el siguiente paso es crear la primera función de nuestro Bot, el código a continuación nos mostrará el saldo en BNB de nuestra Wallet, y además nos mostrará el saldo de un token en específico, en este caso será de $CAKE, el token oficial de PancakeSwap.

public async System.Threading.Tasks.Task testAsync() {
            var web3 = new Web3("https://bsc-dataseed.binance.org");
            var balance = await web3.Eth.GetBalance.SendRequestAsync("AddressDeLaWalletAConsultar");
            Console.WriteLine($"Balance en Wei: {balance.Value}");//Nos muestra el balance de BNB en WEI
            var etherAmount = Web3.Convert.FromWei(balance.Value);
            Console.WriteLine($"Balance en BNB: {etherAmount}");//Nos muestra el Balance de BNB en formato simple con decimales


            var contractABI = @"[{""inputs"":[],""payable"":false,""stateMutability"":""nonpayable"",""type"":""constructor""},{""anonymous"":false,""inputs"":[{""indexed"":true,""internalType"":""address"",""name"":""owner"",""type"":""address""},{""indexed"":true,""internalType"":""address"",""name"":""spender"",""type"":""address""},{""indexed"":false,""internalType"":""uint256"",""name"":""value"",""type"":""uint256""}],""name"":""Approval"",""type"":""event""},{""anonymous"":false,""inputs"":[{""indexed"":true,""internalType"":""address"",""name"":""sender"",""type"":""address""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount0"",""type"":""uint256""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount1"",""type"":""uint256""},{""indexed"":true,""internalType"":""address"",""name"":""to"",""type"":""address""}],""name"":""Burn"",""type"":""event""},{""anonymous"":false,""inputs"":[{""indexed"":true,""internalType"":""address"",""name"":""sender"",""type"":""address""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount0"",""type"":""uint256""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount1"",""type"":""uint256""}],""name"":""Mint"",""type"":""event""},{""anonymous"":false,""inputs"":[{""indexed"":true,""internalType"":""address"",""name"":""sender"",""type"":""address""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount0In"",""type"":""uint256""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount1In"",""type"":""uint256""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount0Out"",""type"":""uint256""},{""indexed"":false,""internalType"":""uint256"",""name"":""amount1Out"",""type"":""uint256""},{""indexed"":true,""internalType"":""address"",""name"":""to"",""type"":""address""}],""name"":""Swap"",""type"":""event""},{""anonymous"":false,""inputs"":[{""indexed"":false,""internalType"":""uint112"",""name"":""reserve0"",""type"":""uint112""},{""indexed"":false,""internalType"":""uint112"",""name"":""reserve1"",""type"":""uint112""}],""name"":""Sync"",""type"":""event""},{""anonymous"":false,""inputs"":[{""indexed"":true,""internalType"":""address"",""name"":""from"",""type"":""address""},{""indexed"":true,""internalType"":""address"",""name"":""to"",""type"":""address""},{""indexed"":false,""internalType"":""uint256"",""name"":""value"",""type"":""uint256""}],""name"":""Transfer"",""type"":""event""},{""constant"":true,""inputs"":[],""name"":""DOMAIN_SEPARATOR"",""outputs"":[{""internalType"":""bytes32"",""name"":"""",""type"":""bytes32""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""MINIMUM_LIQUIDITY"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""PERMIT_TYPEHASH"",""outputs"":[{""internalType"":""bytes32"",""name"":"""",""type"":""bytes32""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""},{""internalType"":""address"",""name"":"""",""type"":""address""}],""name"":""allowance"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""spender"",""type"":""address""},{""internalType"":""uint256"",""name"":""value"",""type"":""uint256""}],""name"":""approve"",""outputs"":[{""internalType"":""bool"",""name"":"""",""type"":""bool""}],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""name"":""balanceOf"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""to"",""type"":""address""}],""name"":""burn"",""outputs"":[{""internalType"":""uint256"",""name"":""amount0"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amount1"",""type"":""uint256""}],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""decimals"",""outputs"":[{""internalType"":""uint8"",""name"":"""",""type"":""uint8""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""factory"",""outputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""getReserves"",""outputs"":[{""internalType"":""uint112"",""name"":""_reserve0"",""type"":""uint112""},{""internalType"":""uint112"",""name"":""_reserve1"",""type"":""uint112""},{""internalType"":""uint32"",""name"":""_blockTimestampLast"",""type"":""uint32""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""_token0"",""type"":""address""},{""internalType"":""address"",""name"":""_token1"",""type"":""address""}],""name"":""initialize"",""outputs"":[],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""kLast"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""to"",""type"":""address""}],""name"":""mint"",""outputs"":[{""internalType"":""uint256"",""name"":""liquidity"",""type"":""uint256""}],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""name"",""outputs"":[{""internalType"":""string"",""name"":"""",""type"":""string""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""name"":""nonces"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""owner"",""type"":""address""},{""internalType"":""address"",""name"":""spender"",""type"":""address""},{""internalType"":""uint256"",""name"":""value"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""deadline"",""type"":""uint256""},{""internalType"":""uint8"",""name"":""v"",""type"":""uint8""},{""internalType"":""bytes32"",""name"":""r"",""type"":""bytes32""},{""internalType"":""bytes32"",""name"":""s"",""type"":""bytes32""}],""name"":""permit"",""outputs"":[],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""price0CumulativeLast"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""price1CumulativeLast"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""to"",""type"":""address""}],""name"":""skim"",""outputs"":[],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""uint256"",""name"":""amount0Out"",""type"":""uint256""},{""internalType"":""uint256"",""name"":""amount1Out"",""type"":""uint256""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""bytes"",""name"":""data"",""type"":""bytes""}],""name"":""swap"",""outputs"":[],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""symbol"",""outputs"":[{""internalType"":""string"",""name"":"""",""type"":""string""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[],""name"":""sync"",""outputs"":[],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""token0"",""outputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""token1"",""outputs"":[{""internalType"":""address"",""name"":"""",""type"":""address""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":true,""inputs"":[],""name"":""totalSupply"",""outputs"":[{""internalType"":""uint256"",""name"":"""",""type"":""uint256""}],""payable"":false,""stateMutability"":""view"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""value"",""type"":""uint256""}],""name"":""transfer"",""outputs"":[{""internalType"":""bool"",""name"":"""",""type"":""bool""}],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""},{""constant"":false,""inputs"":[{""internalType"":""address"",""name"":""from"",""type"":""address""},{""internalType"":""address"",""name"":""to"",""type"":""address""},{""internalType"":""uint256"",""name"":""value"",""type"":""uint256""}],""name"":""transferFrom"",""outputs"":[{""internalType"":""bool"",""name"":"""",""type"":""bool""}],""payable"":false,""stateMutability"":""nonpayable"",""type"":""function""}]";

            var contractAddress = "0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82"; //Contrato del token $CAKE

            try {

                var contract4 = web3.Eth.GetContract(contractABI, contractAddress);
                var balanceFunction = contract4.GetFunction("balanceOf");
                var nameFunction = await contract4.GetFunction("name").CallAsync<string>();
                var balance4 = await balanceFunction.CallAsync<BigInteger>("AddressDeLaWalletAConsultar");
                Console.WriteLine(nameFunction + ": " + Web3.Convert.FromWei(balance4));//Nos muestra el balance del token $Cake en la Wallet consultada
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception Message: " + ex.Message);
            }
        }

El código es fácil de interpretar, primeramente colocamos la red de BSC, luego la dirección de la Wallet que queremos consultar, y esto nos mostrará el saldo BNB que hay en dicha cartera.

Luego definimos el ContractABI de PancakeSwap, y el contrato de su token $CAKE, y colocamos nuevamente la Wallet que queremos consultar, y esto nos arrojará el saldo de dicho token en dicha cartera:

Y así de simple ya podremos consultar el saldo del token que deseemos en nuestra wallet, solo debemos tener el contrato de dicho token para poder obtener su saldo. Recuerda llamar a la función que hemos creado desde un botón o desde el public Form para que se ejecute y nos muestre la consulta. Tambien puedes crear diferentes Labels o TextBox para mostrar tus resultados en el entorno grafico y no solo en consola.

En la siguiente entrada de nuestro tutorial, veremos cómo transferir un token o BNB de una wallet a otra, y además veremos cómo realizar la compra de un Token en PancakeSwap desde nuestro bot.

Parte 2 publicada, puedes ingresar desde aqui.

Bot completo y funcional, lo puedes descargar desde aqui.