📝0.2.x Bot configurations
This applies to version 0.2.22
Different configuration can greatly impact your profitability using the bot. Tweak it based on your own setup. Join our discord to learn more.
You can also refer the config examples as a starting point to tweak for your own config.
.env
If a config does not exist in your .env file, just add a new line with the config name, =, config value. For example, you can add the following line to your .env:
SKIP_PREFLIGHT=false
To change SKIP_PREFLIGHT flag to false
Jup V6 related configurations
All the config here goes into .env
file
When running the bot with JUPITER_URL=http://0.0.0.0:18080
, the bot will first pull the latest popular token mints from Birdeye, based on last 24h volume. Then spin up a JupV6 API with FILTER_MARKETS_WITH_MINTS
set to the token mints pulled from Birdeye. INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE
configures how many tokens to use from Birdeye. The higher you set for INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE
, the more oppotunity you may see as there are more potential routes from different token pairs. Though higher number also means longer time to get a quote from JupV6 API, and it will also uses more resources from your machine. If YELLOWSTONE_URL
is not set, it is not recommended to set INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE
higher than 100, because hosting JupV6 API without yellowstone is very resource intence. It will eat all your RPC credits and likely get you rate limited very quickly.
If YELLOWSTONE_URL
is set, it will be used to start JupV6 API with it, otherwise the JupV6 API will run in pull mode, which is heavy for your read RPC and it is not recommended when INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE
is set to a high number(>100).
If JUPITER_URL
is set to a different value, none of the params in the following form will apply. This can be used when you have a JupV6 API provider, or running it yourself separately.
If you want to include additional mints to the JupV6 API, you can add them in intermedium-mints.json
, which will always be included as part of the FILTER_MARKETS_WITH_MINTS
More info about self-hosted JupV6 can be found here: https://station.jup.ag/docs/apis/self-hosted
DISABLE_LOCAL_JUPITER
Default: false
When set to true, it will not start the Jupiter API locally. This is useful when you want to run multiple bots on the same machine
EXCLUDED_DEXES
default: 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P,MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG
The full list is here. You can choose which Dex to exclude from your jup api when starting it. Using the address of the Dex not the name, separate by comma. Default exclude Moonshot and Pump.fun
INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE
Default: 50
This param configs how many top tokens to use as intermedium mint. Tokens pulled from Birdeye.
JUPITER_RPC_URL
The RPC that is used to read data. When using default JUPITER_URL value, this RPC will also be used to spin up JupV6 API. If this is not set, the value of RPC_URL will be used.
JUPITER_URL
Default: http://0.0.0.0:18080
Endpoint for JupV6 API. When using default value, it will spin up a JupV6 using top popular mints from Birdeye. When set a value other than default, the rest of the parameters in this form will not be applied.
USE_LOCAL_MARKET_CACHE
Default: false
When this is set to true, it will load the market cache from the local file mainnet.json
. This is useful when you run jup and it's very slow to start, or even fail with error reading a body from connection
. You can update the local file with wget https://cache.jup.ag/markets?v=4 -O mainnet.json
YELLOWSTONE_URL
If present, JupV6 API will use it, otherwise JupV6 will be running in pull mode, which is very heavy on the read RPC.
YELLOWSTONE_XTOKEN
If your yellowstone provider also provides you an x token set it here.
LOCAL_JUPITER_PORT
Default: 18080
The port jupiter api uses. Note if you change this, you should also change your JUPITER_URL with the same port.
MARKET_MODE
Default: remote
Supported value: europa
, remote
The default behavior here will stream new markets for your mint list to Jupiter, but it can be very heavy for some RPC to handle. You can change it to remote
to disable this behavior, which will not update the markets in real time, but has less load to your RPC.
Bot configurations
All the config here goes into .env
file
The Bot tries to find profitable route by getting a quote from BASE_MINT to an INTERMEDIUM_MINT for a given trade size, then get another quote from INTERMEDIUM_MINT to BASE_MINT, and combine them together for a potential profitable route. Basically a route from A -> B -> A.
When USE_DIRECT_ROUTE_ONLY
is set to true, the bot will only return route in the form of A -> B -> A like above. For potentially more oppotunity, you can set it to false, which can lead to routes like A -> B -> C -> A. The downside of setting this to false is it will slow down the time to get a quote, end up sending out the transaction a bit slower.
You can set as many tokens as possible as the INTERMEDIUM_MINT, though the more you have, the heavier your RPC load is, so you may want to adjust this accordingly.
There are two ways for you to select which INTERMEDIUM_MINT to use.
The easiest way is to set
INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE
, it will automatically pull the most popular tokens based on 24h volume from Birdeye. The default number is 50.Add mints to
intermedium-mints.json
. You can add as many token mints there as needed. All will be used as a potential INTERMEDIUM_MINT while the bot is running.
AUTO_RESTART
Default: 60
Unit in minutes. By default, the bot will auto restart every 60min. This will also restart JupV6 if hosted together, to allow fetching the lasted high volume tokens from birdeye. If set to 0, the bot will not auto restart.
BASE_MINT_FILE
Default: base-mint.json
The name for the base mint file. This is convenient when you have multiple different settings and want to switch between them quickly. This can be absolute ore relative path.
BIRDEYE_API_KEY
The API key used to pull top mints from Birdeye. By default a shared key is used for all users, but that can run out of credit very soon. If you restart a lot and fetch a lot of tokens from birdeye, you should set your own here. Follow this instruction to do it: https://docs.birdeye.so/docs/birdeye-data-services-bds
ENABLE_LANDING_LOG
Default: false
When this is enabled, it will output an additional WIN
log when a transaction is landed. Though if you turn this on while having ENABLE_SIMULATION=false, it may consume a lot of your RPC credits.
ENABLE_SIMULATION
Default: true
Whether to run simulateTransaction before sending the transaction. This can help to reduce the number of failed transactions landed on chain if spam mode is enabled.
ENABLE_JITO_RPC
Default: false
DO NOT SET THIS TO TRUE if you don't know what is a Jito RPC. You have to use a Jito RPC when you enable this. When this is enabled, the bot will use simulateBundle
to run simulation, which can give you the actual profit with the simulation. This value is more accurate than then one calculated from Jupiter quote. This is especially useful when you set spamFeeBps
in your base-mint.json
Note: Most providers don't provide Jito RPC. Right now the only options to get one is to either host a RPC node yourself, or rent a dedicated RPC node from a provider like Helius/Triton.
FIXED_COMPUTE_UNIT_LIMIT
Default: 0
You can use a fixed COMPUTE_UNIT_LIMIT to avoid the additional computation needed. When this is set to 0, the bot will call jup to get an estimation of the COMPUTE_UNIT_LIMIT and use that instead. Which is more accurate but a bit slower, and will make 2 additional rpc calls getRecentPrioritizationFees and simulateTransaction for each quote.
A suggested value is 250000 for USE_DIRECT_ROUTE_ONLY=true
and 350000 for USE_DIRECT_ROUTE_ONLY=false
The suggested value should work for 90% of the cases.
Note: when using flashloan, the bot will add 100000 to the value to account for the additional instructions needed.
You should not set this to be less than 200000, it may result in not landing anything successfully.
Read more about what is compute unit limit here.
HELIUS_API_KEY
This is used for fetching lated priority fee. You can get one for free by register an account on https://www.helius.dev/.
HIDE_ERROR
Default: false
If you don't want to see the error messages, you can turn this to true which will hide them.
INTERMEDIUM_MINTS_FILE
Default: intermedium-mints.json
The name for the intermedium mints file. This is convenientwhen you have multiple different settings and want to switch between them quickly
JUP_MAX_ACCOUNTS
Default: 24
the maxAccounts param that is used to call quote from JupV6. Recommended not setting this higher than 32. The higher this number is, the more routes you can find, though as there's a limit on the total accounts, a higher number here will also cause a higher chance to find an invalid route with too many accounts, and it also takes longer to search.
MAX_COMPUTE_TIME
Default: 400
The maximum compute time to send tx for an opportunity. If you are trying to catch an opportunity right after it appears, you usually don't want to send anything when it takes too long to calculate in the first place. If the time took to compute is greater than MAX_COMPUTE_TIME
, the bot won't send any tx for it.
MEMO
Default:
Text that will be added as the last instruction in the transaction. You can use this to distinguish which server you are running the bot from by setting a different value for each server. Note: This will not be added for transaction that uses flashloan to minimize the transaction size.
When not set a MEMO will NOT be added to your tx.
Memo is not added for trades where flashloan is used, to help reduce the total length of the transcation.
MIN_SOL_BALANCE
Default: 0
Units in lamports. Does nothing by default. When set to a none 0 value, the bot will periodically check the wallet's SOL balance, and when it drops below the value, it will unwrap all the WSOL and wrap only the amount needed back, to rebalance the SOL account to avoid running out of SOL. e.g. set this to 1000000000 will auto balance your wsol/sol accounts when your sol drops below 1.
PRIVATE_KEY
Private key for your wallet. All formats are supported, you can export from Phantom/Solflare or just use a json file path. The wallet needs to hold enough SOL/WSOL/USDC for your configuration.
PROCESS_DELAY
Default: 1000
Unit in ms. The default value means the bot will wait for 1000ms then try again for the same token-trade size pair. Reducing this number will increase the chance to catch price change right away, but increase the read RPC load.
PULL_BLOCKHASH_WITH_YELLOWSTONE
Default: false
when enabled, will use your Yellowstone to pull blockhash instead of RPC. This can save you a lot of RPC credits. You must also set YELLOWSTONE_URL
to use this.
RPC_URL
The RPC that is used to read data. When using default JUPITER_URL value, this RPC will also be used to spin up JupV6 API.
SKIP_SAME_OPPORTUNITY
Default: false
When enabled and you are using fixed trade size(either using tradeSize or tradeRange with linear strategy), the bot will check if it's the same as last time and not generate a new opportunity for it if it's the same.
USE_DIRECT_ROUTE_ONLY
Default: true
When set to true, the bot will only look for 2hop(A -> B -> A) trade. Setting to true will lead to shorter quote time to Jup, with faster landing. Setting to false will lead to more opportunity, but taking more time to quote.
INTERMEDIUM_MINT_COUNT_FROM_NEW_TOKENS
Default: 0
Fetch new pools opened through geckoterminal and extract the mints used in the pool. This config is still in development. If you want to set this you can try to set it up to 200. One way to use this is with only SOL base mint with no birdeye intermedium tokens, or use exclude-mints.json
to exclude USDC/USDT for better performance. Default to 0, which means this is not enabled.
FILTER_GECKO_POOLS_FROM_RAYDIUM
Default: true
This config is specifically used together with INTERMEDIUM_MINT_COUNT_FROM_NEW_TOKENS
, when set to false, it will extract all tokens that has a new pool opened, but a lot of them may only have one amm on raydium, which means there's no arb opportunities for them. When set to true you would probably see around 10-20 new tokens fetched at most.
Jito config
Jito provides a way to send transactions through bundles. Bundles will only land when it succeeds, which is perfect for making arbitrage trade!
You can enable jito by setting ENABLE_JITO=true
in your .env
file. The bot will then send all transactions to all jito regions defined in BLOCK_ENGINES
through Jito's http endpoint.
Following is the Jito related configs you can set in your .env
file
BLOCK_ENGINES
Default: ny,amsterdam,frankfurt,tokyo,slc
You should not change this value unless you really know what you are doing. Config which block engines to send to for jito transactions.
ENABLE_JITO
Default: true
Whether to use Jito bundle to send transaction. The good part about Jito is, it will never land if the transaction fails. So everything lands is profit. Thought you will need to pay a tip from your profit. See the JITO_TIP_BP param.
JITO_TIP_BP
Default: 5000
Jito tip as part of your profit. 5000 means 50% of your profit will be used as Jito tip. The higher this number, the better chance you may land your transaction, but in return, less profit earned.
JITO_UUID
By default, jito has a 5/s/ip rate limit. You can ask for a rate limit raise from jito, and they will give you an uuid that you can set with the bot.
NOTE: Currently the key has a bug and the rate limit for the key is universal not per ip.
SHOW_JITO_LOGS
Default: false
When this is enabled, response for sending jito bundles will be added to the output log. This is helpful if you are trying to figure out how often you are hitting jito's rate limit, or testing your UUID to see if it works.
USE_DIFFERENT_TX_FOR_BLOCK_ENGINES
Default: true
When this is enabled, bot will send a different tx for each block engine. When disabled, the same tx will be sent to all block engines.
USE_SEPARATE_TIP_ACCOUNT
Default: false
When this is enabled, a new solana address will be used to send tip in its own tx instead of sending to Jito directly for every Jito transaction. Jito currently is rate limiting bundles based on the accounts in the tx that does the tip, this feature can get around this rate limit by wallet issue to allow you using the same wallet in all locations. This is useful when you have machines in multiple locations but still trying to use the same wallet to run the bot. Example transaction: https://solscan.io/tx/41CBfg3cg1eKvxgJHJ7TqhmrGJ73BxikDVALV7SQYM4FmMqt22Cfpc18f5bErATSUoTDccKtFSVpGQe1WvMr1b9f
Spam configs
Spam strategy means you will send many transactions and hope some of them get landed and landed successful. This is a more advanced strategy as you may lose money on gas fee if you didn't config it carefully.
You can enable spam by setting ENABLE_SPAM=true
in you .env
file. The bot will then use all the rpcs you defined for SEND_RPC_URLS
to send potential profitable transactions.
Jito and spam can be enabled together, the bot will just send 2 different transactions, one through jito and one through rpc.
BLOXROUTE_REGION
Default: ny
Only relevant when you have ENABLE_BLOXROUTE=true
. Valid values are ny
and uk
. Should only set it to be the closest one to your server.
COMPUTE_UNIT_PRICE
Default: 10001
The COMPUTE_UNIT_PRICE aka gas fee set for the transaction. Note: this is not SOL lamport. Generally the higher this is, the better chance your tx can actually land on chain. Learn more about what this is here: https://solana.com/docs/core/fees#prioritization-fee This only applies to spam, jito transactions set its own value as it's not needed.
ENABLE_SPAM
Default: false
Whether to send a normal transaction for every potential arbitrage oppotunity. Note most of the transactions will not even land on chain, for the ones that does, 90% of them will fail. Set ENABLE_SIMULATION=true can help reduce the number of failed transactions.
ENABLE_BLOXROUTE
Default: false
Make sure you set the right value for BLOXROUTE_REGION
when enabling this.
We have a collaboration with BloXroute, when this is set to true, your spam transaction will be sent through BloXroute's Trader API v2, in addition to all your SEND_RPC_URLS.
Note when a tx landed successfully with BloXroute, it charges an additional 0.0005 SOL as fee to use BloXroute's api and send through its staked connection. The bot already takes this into consideration and will fail the tx if your profit is not enough to pay for this fee + the bot fee. But do take this into consideration when you enable it.
This API has a 20tx/s rate limit. So it's highly recommended to enable simulation when using this.
MAX_RETRIES
Default: 0
This is a config for sendTransaction RPC method, Maximum number of times for the RPC node to retry sending the transaction to the leader. The higher this number, the more chance your tx can land, but also lead to high chance of failure, as retried tx is likely too late for the opportunity.
PRIORITY_FEE_UPDATE_INTERVAL
Default: 60
Unit in seconds. This controls how often the priority fee is updated. This only works when you set priorityFeePercentile in your base-mint.json
SEND_RPC_URLS
The RPCs used to send transactions. This can be the same as RPC_URL
You can also set multiple RPCs here, split by comma. Setting multiple ones can increase the rate of tx landing and success.
Example:
http://rpc1.com,http://rpc2.com
This is an example instruction when setting USE_DIFFERENT_TX_FOR_SENDERS=true
This image shows that the second RPC in the SEND_RPC_URLS
list sent this tx(first RPC is RPC 0).
SKIP_PREFLIGHT
Default: true
This is a similar config to ENABLE_SIMULATION. The difference is ENABLE_SIMULATION will run the simulation with your RPC_URL before sending it, when you have SKIP_PREFLIGHT=false, the RPC received your transaction will run the simulation before it forward to the validator. This will also make landing slower as it's an additional call, but also it can reduce the failed transactions you land with ENABLE_SPAM.
You should only have at most one of SKIP_PREFLIGHT=false
and ENABLE_SIMULATION=true
. Setting both is not worth it.
SPAM_RESTRICT_LEVEL
Default: 0
Valid values are 0,1,2,3,4,5.
This config will try to limit how long a tx land compares to when you send it when using spam. 0 is no restriction, the same behavior as before. 5 is maximum restriction and will only allow the tx to land within ~1-2 slots. Note the exact restriction time for each level can be affected by your RPC's latency and performance. You may not land anything when you set this value to 4-5 if your RPC is not fast enough.
This config allows you to use a very high fee for spam strategy and also not losing too much money on failed ones.
USE_DIFFERENT_TX_FOR_SENDERS
Default: false
When setting multiple SEND_RPC_URLS
, this config will send a different tx for each of the RPCs. When this config is set to false, the same tx will be send to all RPCs.
You can also see which RPC send the tx in the last instruction of the tx. Index start from 0. See later section for example*.
Flashloan related params
All the config here goes into .env
file
Currently you need to have at least 0.5 SOL in your wallet to enable Flashloan.
Flashloan is a power tool when you have limited budget. You can set a higher trade size than what you have in your wallet, and get arbitrage opportunities that you usually won't be able to get.
Flashloan may not success 100% of the time. When the vault you are borrowing from does not have enough tokens, your transaction will fail due to insufficient fund. Though this should rarely happen.
When flashloan is enabled with the bot, and you are using SOL as one of your base mint, you should also set WRAP_SOL_AMOUNT
which is the amount of sol you want to wrap into WSOL. The bot will only use flashloan when the amount is larger than WRAP_SOL_AMOUNT
, for trade with less amount it will just use the amount in the wallet, to maximize the potential profit.
ENABLE_FLASHLOAN
Default: false
Whether to enable flashloan. Note you need to have at least 0.5 SOL in the wallet to enable flashloan.
FLASHLOAN_PROVIDER
Default: solend
Currently supported values are solend
.
solend
Soland flashloan charges a 0.04% fee based on the amount you borrow. So a trade that borrows 1000 USDC as shown above will need to find an opportunity that gives you at least 1000.4 USDC back for you to make a profit, compares to at least 1000 USDC when you are not using flashloan. This will results in more failed transactions if you send using spam, or less overall landing if use with Jito. The upside is you can get opportunities that is only possible with big amount. You can also use flash loan as a kick start option to minimize your risk of putting too much amount in your wallet.
Solend only adds 2 more instructions instead of 4. So you will run into less Generated transaction is too large
error compares to marginfi, but paying an additional fee as a trade off.
WRAP_SOL_AMOUNT
Default: 100000000
Default value is 0.1 SOL. Only relevant when SOL is used as one of the base mint. The amount of SOL to wrap into WSOL, and for all the trade with trade size less than this number, the bot will use the balance in the wallet, for larger ones the bot will use flashloan.
base-mint.json
This file is used to control what base mint you want to use for your trades and what trade size you want to use. Base mint means the token you are going to trade and profit with, currently only SOL/USDC/USDT is supported.
The file takes in a dictionary of mint and it's values. The following setup means the bot will run with SOL and USDC. Note the unit is lamports here. So 1 SOL = 1,000,000,000 lamports. 1 USDC = 1,000,000 lamports. 1 USDT = 1,000,000 lamports.
Using 1 SOL/2.5 SOL/5 SOL as trade size for SOL, and will only try to send the transaction when the opportunity provides at least 0.0005 SOL in profit.
Using 100 USDC/250 USDC/500 USDC as trade size for USDC, and will only try to send the transaction when the opportunity provides at least 0.5 USDC in profit.
Using 100 USDT/250 USDT/500 USDT as trade size for USDT, and will only try to send the transaction when the opportunity provides at least 0.5 USDT in profit.
You can use the same mints for different tradeSize/minProfit pair to customize your strategy.
minProfit
minProfit is the threshold for when to send a transaction for the potential profit, it does not guarantee that the actual profit land on chain will be that. The actual profit landed on chain can vary, and the bot will fail all transactions that ends up with a negative profit, and land all the ones with a profit, even if the profit is smaller than minProfit.
jitoMinProfit
Default: 15000 for SOL and 2000 for USDC/USDT
This configs the minimum profit(before tip/fee) you want when using jito. This is helpful to prevent losing money with jito strategy.
Example:
Trade range
If you don't want to manually define every trade size, you can utilize the trade range parameters. To utilize this you need to define 3 params: tradeRange
, tradeRangeCount
, tradeRangeStrategy
tradeRange: This defines the lower bound and higher bound for the range(inclusive). Bot will generate trade sizes only within this range. So make sure you have enough balance of the token for the upper bound.
tradeRangeCount: This defines how many different trade size will be generated within the range.
tradeRangeStrategy: Two values are supported right now: linear
and random
. Linear will generate trade sizes evenly within the range, and random will generate a trade size randomly each time.
The above example defines two trade range for SOL, the first one is equal to use a tradeSize of [50000000,100000000, 150000000, 200000000, 250000000]. The second one will generate a random trade size each time it runs.
Note: quote using random is slightly slower than quote using linear or fixed trade size. As for random two quotes are sent out one by one while for fixed size two quotes are sent out together.
priorityFeePercentile
Value from 0 to 100(you can set higher than 100 but not recommended). Automatically set COMPUTE_UNIT_PRICE based on current priority fee level. You need to set HELIUS_API_KEY
in order to use this. The bot utilize helius's priority fee api, to fetch the latest priority fee levels. The response is something like the following from the api, value map to the response, aka 0 means min, 25 means low, 50 means medium, 75 means high, 100 means veryHigh. If the current response looks like below, and you set 30 as the value for priorityFeePercentile
, the auto generated COMPUTE_UNIT_PRICE would be 10000 + (60082 - 10000) * ((30 - 25) / 25) = 20016. Note the value for each level will change all the time as market moves.
When this is set, it will override the COMPUTE_UNIT_PRICE
value in .env file.
This should be set together with maxPriorityFee
. The max COMPUTE_UNIT_PRICE you are willing to set. This is helpful to prevent setting a huge priority fee as market moves.
Example usage of the config:
spamFeeBps
This allows you to set your gas fee to be a fixed percentage of the projected gain. Note you can only set one of priorityFeePercentile
and spamFeeBps
, not both.
This will override the COMPUTE_UNIT_PRICE
you set in .env
Example usage of the config:
This config will use 5% of projected profit as the fee. Note this is not 5% of the final profit, it's 5% of the projected profit that bot calculated based on Jup API. If you set ENABLE_JITO_RPC
, this will be based on the simulated profit, which is more accurate than the projected one.
intermedium-mints.json
intermedium-mints.json file is optional, you can run the bot without it.
This provides a way to add additional intermedium mints for the bots to use.
Intermedium mints means the middle token the bot will use to find profitable routes. In the following example boden is the intermedium mint.
This is in addition to the Birdeye mints. If you want to only use the mints in intermedium-mints.json
, you can set INTERMEDIUM_MINT_COUNT_FROM_BIRDEYE=0
The following example is to always use SOL/USDC/SLERF as the intermedium mints.
exclude-mints.json
exclude-mints.json file is optional, you can run the bot without it.
This provides a way to exclude certain mints for jupiter api and intermedium mints.
This is useful when you want to exclude certain mints from the birdeye tokens. Especially if you only want to do SOL arbs and don't want to include USDC/USDT in the route, as they are a lot of them and can be heavy for your RPC to load all.
The following example is to exclude USDC/USDT from your jupiter api.
You may see this error if you exclude USDC, it can be safely ignored: price_tracker.update_prices failed with: missing decimals for USDC
You cannot exclude the mints you use as base mint. Those are always needed in the calculated route.
Last updated