How to Create a Solana Trading Bot

In the fast-paced world of crypto trading, having the right tools like the Jupiter Swap API can make all the difference in securing the best token swap routes.

Trading requires a lot of monitoring and analysis because there are different prices on different exchanges. It becomes even more challenging in crypto because the markets in the crypto or blockchain space move so fast. That's where APIs like Jupiter Swap API come to the rescue, as they help you get the best possible code or best possible route for your token swaps while comparing different prices and quotations from various decentralized exchanges and automated market makers.

In this video, we will create a trading bot using QuickNode's Jupiter Swap API to get the best possible routes for our token swaps and execute those swaps. By no means is this financial advice; this video is just for educational purposes and to demonstrate a use case for the Jupiter Swap API. So, without any ado, let's jump into it.

This is QuickNode's Jupiter V6 Swap API, known as Mattis, which is a hosted Jupiter Swap API. Since it's hosted on QuickNode's infrastructure, you don't have to worry about latency; it will be very low. This API also supports the Jupiter Price API, but that's still in beta. To install this add-on, you just have to go to your QuickNode dashboard, find your Solana mainnet endpoint, go to add-ons, and then locate the Mattis Jupiter V6 Swap API to install it from there. I already have it installed, and once you have it installed, it will look something like this. You can access your add-on from the dashboard by clicking on these three buttons and then going to the dashboard. This will SSO and take you to the Jupiter Swap API dashboard, where you will find your desk API URL.

Now, let's start making our bot. For that, we will do npm init in our desired repository or directory and then install a bunch of dependencies. Here, we are installing the Jupiter client or the Jupiter Library, which is JAG API, then Solana Web 3.js, and the Solana SPL Token Library. Once it's installed, let's open the directory in a code editor and create a few new files. The first one will be bot.ts, then index.ts. All of our code for the bot will go into bot.ts, and index.ts will initialize the bot and use all the code we write in bot.ts.

In the environment file, we will need these environment variables. The first one will be the secret key, which will be your Solana wallet secret key. The second will be your Solana endpoint or Solana mainnet endpoint, which will be our QuickNode Solana mainnet endpoint. The third will be your Mattis endpoint or Mattis REST endpoint, which you get from here. Never share your secret key with anyone, and make sure to remove the secret key while uploading your code to GitHub or any public code-sharing platforms.

Now, let me fill in all of these details, like my secret key, my Solana mainnet URL from QuickNode, and my Mattis URL from QuickNode as well. Next, let's start adding stuff to our bot.ts file. First, we will do a bunch of imports where we are importing the file system path and several components from Solana Web 3.js, along with various elements from the Jupiter Library. We will also import getAssociatedTokenAddressSync from the Solana SPL Token Library.

Then, let's create some interfaces. The bot config will be used to create a configuration for our bot, which will include the Solana endpoint, Mattis endpoint, secret key (used to generate our wallet and sign transactions), first trade price (the price of the token we want to buy), target gain percentage (the gain percentage of the next token we want to buy), check intervals (the intervals at which we want to check for token price changes), initial input token (the token we want to use to buy another token), and initial input amount (the amount of the token we want to give to the bot to buy other tokens).

Finally, we will create an interface for the next trade so that we can execute more trades once a transaction is completed.

=> 00:05:46

Automate your crypto trades with precision: set your target gains, monitor prices, and let the bot do the heavy lifting.

To set up our trading bot, we will have a Solana endpoint and a secret key, which will be used to generate our wallet and to sign transactions. The First Trade price will be the price of the token we want to buy. The Target gain percentage will represent the gain percentage of the next token we wish to purchase. The check intervals will determine the intervals at which we want to check for token price changes. The initial input token will be the token we use to buy another token, and the initial input amount will be the amount of the token we want to allocate to the bot for purchasing other tokens.

Next, we will create an interface for the next trade so that we can execute more trades once a trade is completed. The swap tokens will define the tokens we can swap, and for this implementation, we have added Sol and USDC. Additionally, we will have an interface to log swap arguments, which we will use to log data into a JSON file after a successful swap. We will log data such as the input token, input amount, output token, output amount, transaction ID, and timestamp.

Now, let's create a class called rbot class, which will contain all the logic for our trading bot. In this class, we will define a few variables that will help us track the state of our bot. For example, these variables will be used to get the Solana connection, the Jupiter swap API, our wallet, the USDC installments, the USDC public key or the token account, and the Sol and USDC balances for our wallet. We will also track the check interval, last check, and the price watch interval ID. The Target gain percentage, next trade, and waiting confirmation will also be included, with the waiting confirmation set to false by default.

The constructor of our class will initialize a new Solana connection, a new Jupiter swap connection, and our wallet from the secret key. We will then retrieve the associated USDC token accounts from our wallet and check if the target gain percentage and check intervals are provided. If not, we will use the default values we have set for them. We will prepare for the next trade, where if the initial token was Sol, then USDC will be the next input token, and if the output token was USDC, then the next output token will be Sol. We will also get the amount of tokens used in the previous trade and the price of tokens in that trade.

In the init function, we will log two messages. After the first message, we will refresh balances and log the balance of Sol and USDC to the command line. We will then call the initialize price watch function.

The refresh balances function will utilize Promise.allSettled to get the balances of Sol and USDC simultaneously. We will use get balance and get token account balance methods with our Solana connection to retrieve the balances for these tokens. If successful, we will set the balances for Sol and USDC. If not successful, it will throw an error message. If the Sol balance is less than 0.01 Sol, we will terminate the bot.

The initial price watch function will check if the last check time is greater than the check interval. If it is, we will check if there is a transaction waiting for confirmation. If not, we will call the get code function and evaluate the code swap function.

In the get code function, we will retrieve the code from the Jupiter API using the code get method. If no code is found, we will log an error. In the evaluate code and swap function, we will calculate the difference between the code out amount and the next trade threshold. If this difference is positive, we will execute the swap, indicating that the amount of tokens we are receiving from the swap should be greater than the threshold.

=> 00:10:12

Efficiency in trading comes from smart automation—let your bot handle the swaps while you focus on strategy.

In this process, we first check if there is a transaction waiting for confirmation. If there is no transaction pending, we will call the get code function and evaluate the code swap function. Let's delve into what happens in those functions.

In the get code function, we are essentially retrieving the code from the Jupyter API using the code get method. If no code is found, we will log down an error. Moving on to the evaluate code and swap function, we are determining the difference between the code out amount and the next trade threshold. If this difference is positive, we will execute the swap. This essentially means that the amount of tokens we receive from the swap should be greater than the amount of tokens needed as the initial token for the next swap.

Next, in the execute swap function, we perform several tasks. First, we obtain the swap instructions from the Jupyter API. Then, we use the received instruction data to convert them into transaction instructions, utilizing the instruction data to transaction data function that we defined earlier. Essentially, we are flattening the instructions and removing any that may be null or undefined to enhance the efficiency of our transaction.

After that, we retrieve balances using the address lookup tables and create a Solana transaction. In this transaction, we pass the public key, the recent block hash, the instructions, the wallet, and the address lookup accounts. We then sign the transaction using our wallet and send the raw transaction through our Solana endpoint. If there is an error during transaction processing, we log that error and subsequently call the post transaction processing function.

In the post transaction processing function, we call the update next trade function and the refresh balances function to refresh the bot's balances. Additionally, we log the swap using the interface log swap function, which records all relevant information about the current swap in a JSON file. Regarding the update next trade function, we are essentially switching the tokens; for instance, if the input token was Sol in the previous trade, it will now be USDC in the next trade. We also set up the next trade threshold. For example, if we used 10 USDC to buy 0.1 Sol in the previous trade and the gain threshold was 15%, our next trade's input token will be 0.1 Sol, and the target threshold will be 11.5 USDC. This means that the bot will not execute the trade until we receive a quotation for 11.5 USDC.

Now, let’s examine our index.ts file. In this file, we import various components from Solana web3.js, along with our bot and swap token interfaces from our bot.ts file. We also import environment variables from the .env file and set some default configurations. If the APIs in our environment variable face any issues, we can utilize these default values.

In our main function, we begin by checking if there is no secret key in the environment variable. If it is missing, we log an error; if it exists, we save it in decoded secret key by first converting it into JSON format. We then create a new instance of the bot, processing the Solana endpoint, the Jupiter swap API endpoint, and the secret key from the decoded secret key.

For our first trade price, we set the amount we want to buy using our bot and establish the target gain percentage, which is the percentage we aim to gain for the next token. Here, we set it to 1.5%, meaning that our next trade will only execute if we gain 1.5% from the previous trade. Additionally, we set the initial input token to USDC and specify the amount of the initial input token we are providing to the bot, which is one USDC. It is also crucial to consider the decimals of the token. Finally, we run the bot and call the main function.

Now, let’s run the bot for demonstration purposes using the command DS node index. This is how the bot appears, and it is now listening for prices and finding paths.

In conclusion, this is how you can utilize the QuickNode Jupyter swap API to get codes and swap tokens. This example represents just one use case; you can apply this API in various scenarios, such as creating your own decentralized exchange or finding efficient routes for your swaps. You will find all relevant links along with the code used in this video in the description below.

Make sure to like the video, subscribe to the QuickNode YouTube channel, and I will see you in the next one. Bye-bye!