SolanaMevBotSolanaMevBot

Bot Configurations

The complete SolanaMevBot 2.0.0 configuration reference

Version 2.0.0 uses [bot], one or both settlement profiles under [auto], and a repeated [[senders]] entry for each sending service. [auto_rebalance] and [log] are optional.

Unknown config fields are rejected. Start from a 2.0.0 example instead of carrying forward a 1.x config.

Bot

[bot]
rpc_url = "https://YOUR_READ_RPC"
encrypted_key_path = "~/keys/ENCRYPTED_PRIVATE_KEY"
flashloan = true
FieldDefaultMeaning
rpc_urlRequiredSolana RPC for account reads and blockhashes. Must support reads, not just transaction submission.
flashloanfalseEnable borrowing from the executor's settlement loan vault. The wallet still pays fees, tips, and account creation.
encrypted_key_pathAutomatic searchPath to an existing bot key file. Supports ~/, absolute paths, and paths relative to the working directory. Without it, the bot searches for ENCRYPTED_PRIVATE_KEY in the working directory and its parents.
private_keyUnsetFirst-run key import: a base58 string or a JSON byte array encoded as a string. The bot writes ENCRYPTED_PRIVATE_KEY and exits. Remove this field before restarting. Do not combine it with an existing key file.

See Getting Started for first-run key setup.

Automatic market selection

Configure [auto.sol], [auto.usdc], or both. Each profile selects routes that start and end in its settlement token. The SOL profile settles in wrapped SOL (WSOL).

[auto.sol]
min_total_profit = 5_000_000
min_tx_count = 2
lookback_secs = 3_600
max_routes = 50
process_delay = 50

[auto.usdc]
min_total_profit = 750_000
min_tx_count = 2
lookback_secs = 3_600
max_routes = 25
process_delay = 50
FieldDefaultMeaning
min_total_profitRequired per profileCombined profit the feed observed through a route during lookback_secs. Integer lamports for SOL; integer millionths of USDC for USDC.
min_tx_count1Minimum observed transaction count. Integer from 1 to 9_007_199_254_740_991.
lookback_secs300Observation window in seconds, from 1 to 3600.
max_routes50Maximum selected routes for this settlement, from 1 to 100.
process_delay0Milliseconds each route waits between send passes. 0 adds no timed delay.

For example, 5_000_000 is 0.005 SOL in [auto.sol], while 750_000 is 0.75 USDC in [auto.usdc]. These are historical selection thresholds, not per-trade profit requirements. The program checks current pool state when a transaction executes.

Each route runs independently. process_delay is not a global requests-per-second limit; use each sender's rate_limit_per_second, or from 2.0.4 each key's, to cap submissions across all routes and both settlements.

Senders

Add at least one enabled sender to submit transactions. Each sender builds transactions using its own prices and tips.

[[senders]]
name = "rpc"
type = "json_rpc"
urls = ["https://YOUR_SENDING_RPC"]
rate_limit_per_second = 20
compute_unit_price = { strategy = "Random", from = 1000, to = 2000, count = 1 }
request_params = { maxRetries = 10 }

Sender types and defaults

typeRequest formatDefault submissions/secondDefault timeoutDefault strategy
json_rpcJSON-RPC sendTransaction201500 msAllAtOnce
jitoJSON-RPC sendBundle, appending /bundles to each URL; from 2.0.4, also gRPC to a key's grpc_urls15000 msOneByOne
send_bundleJSON-RPC sendBundle to the exact URLNo configured cap5000 msAllAtOnce
submit_batchA transactions array of base64 transactionsNo configured cap5000 msAllAtOnce
next_blockA transaction object with base64 contentNo configured cap5000 msAllAtOnce
harmonicHarmonic bundles over gRPC (2.0.2 or later)No configured cap5000 msOneByOne
temporalNozomi sendBundle, posting each transaction's bytes after its length to the URL's /api/sendBundle (2.0.4 or later)55000 msAllAtOnce

type is required. For jito, supply a block-engine URL ending in /api/v1, not /api/v1/bundles; a key's grpc_urls take the block engine without a path, such as https://ny.mainnet.block-engine.jito.wtf (see Jito with several uuids and gRPC). For harmonic, supply a regional URL such as https://fra.be.harmonic.gg; see Harmonic. For temporal, supply a regional host with your key, such as https://fra2.nozomi.temporal.xyz/?c=YOUR_API_KEY. See Temporal Nozomi bundles.

Sender fields

FieldDefaultMeaning
nameRequiredNonempty, unique name used in logs, including for disabled senders.
typeRequiredOne of the types above.
enabledtrueWhether this sender submits transactions.
urlsEmptyEndpoint URLs. Required for an enabled sender unless using keys.
auth_header, auth_valueUnsetHTTP authentication header and value. Set both together. Not accepted by harmonic.
keysEmptyEndpoint groups with separate credentials and, from 2.0.4, their own rate limits; see below. Not accepted by harmonic.
request_paramsUnsetTable merged into JSON-RPC request options. Supported by json_rpc, jito, and send_bundle only.
sending_strategyBy typeAllAtOnce sends to every endpoint. OneByOne rotates the starting endpoint and tries another on connection failures, timeouts, HTTP server errors (5xx), or gRPC errors other than a rejection or rate limit. Acceptance or rejection ends the submission, and a rate-limit response stops it trying further endpoints. From 2.0.4, keys with their own rate limit are separate lanes: AllAtOnce sends through every lane that has room, and OneByOne moves on to another lane with room when every endpoint of its lane is unreachable or the lane is rate limited.
compute_unit_priceUnsetPriority price strategy in micro-lamports per CU. Unset means no added priority fee. Required for harmonic, at least 10000.
tip_amountUnsetTip strategy in lamports. Required for jito and temporal. Not accepted by harmonic, which is paid through compute_unit_price.
tip_accountsEmptyTip destination public keys. Required with a tip for other senders. jito and temporal (2.0.4 or later) use their built-in accounts when omitted.
rate_limit_per_secondBy typeInteger from 1 to 1000. Shared across all routes, settlement profiles, and source IPs for this sender. From 2.0.4, a key can set its own; keys that don't share the sender's.
timeout_msBy typePositive request timeout in milliseconds.
no_failure_modefalseAllow the executor to return without a trade when no profitable route is found. Does not suppress every possible transaction error.
uuidUnsetJito-only uuid query parameter. A key's own uuid (2.0.4 or later) replaces it for that key.
auth_keypairUnsetPath to the keypair file of a public key Harmonic whitelisted. Without it, bundles go to Harmonic's public service. Accepted on the sender by harmonic only; from 2.0.4, a Jito key with grpc_urls can set its own to sign in to Jito.
ip_addressesEmptyLocal source IPs or CIDR ranges. Submissions rotate through them. These addresses must be configured on your machine. HTTP only: not accepted by harmonic, and Jito gRPC keys connect from the default address.
use_separate_tip_accountOn for Jito with ip_addresses; otherwise offJito-only: use a temporary tip account and a second transaction in the bundle to forward the tip. Requires tip_amount.

A rate limit counts submissions, not requests. A submission counts once against each lane it goes through, including a lane it moves on to. With AllAtOnce, a submission goes to every endpoint of its lanes, so the number of HTTP requests can be higher.

JSON-RPC transaction options default to encoding = "base64", skipPreflight = true, preflightCommitment = "confirmed", and maxRetries = 10. Bundle options default to encoding = "base64". request_params overrides matching options. Keep base64 encoding, since that is how the bot serializes transactions.

Multiple credentials

Use [[senders.keys]] when one sender has multiple endpoint groups with different credentials. Each group supports urls, auth_header, auth_value, and request_params. From 2.0.4, a group can also set rate_limit_per_second, and a Jito group can set uuid, or list grpc_urls with an optional auth_keypair instead of urls.

[[senders]]
name = "rpc-keys"
type = "json_rpc"
rate_limit_per_second = 10
sending_strategy = "OneByOne"
request_params = { maxRetries = 0 }

[[senders.keys]]
urls = ["https://YOUR_FIRST_RPC"]
auth_header = "authorization"
auth_value = "YOUR_FIRST_API_KEY"

[[senders.keys]]
urls = ["https://YOUR_SECOND_RPC"]
auth_header = "authorization"
auth_value = "YOUR_SECOND_API_KEY"

When using keys, omit sender-level urls, auth_header, and auth_value. A key's request_params replaces the sender-level table for that key; the chosen table is then merged into the request defaults.

Rate limits per key

Requires bot 2.0.4 or later. A key that sets rate_limit_per_second gets a limit of its own, apart from the sender's and other keys'. Keys that set none share the sender's limit. If every key sets its own, leave the sender's rate_limit_per_second unset; the bot rejects a sender limit that would apply to no key.

Each limit is a lane. OneByOne sends each submission through the next lane that has room, and moves on to another lane that has room when every endpoint of its lane is unreachable or the lane is rate limited. AllAtOnce sends through every lane that has room. A rate-limit reply pauses only its lane, for two seconds. With OneByOne, the sender can send up to the sum of its lanes' limits. Logs name the shared lane by the sender's name, and a key with its own limit by the sender's name and the key's position counting from 0, such as jito keys[1] for the second key of a sender named jito. See Jito with several uuids and gRPC for an example.

Tips and no-failure mode

With no_failure_mode = false, a transaction must profit at least its tip. For jito, send_bundle, and harmonic from 2.0.3, and temporal from 2.0.4, whose bundles do not land when they revert, it must also cover the bundle's fees: the signature fee, the priority fee, and the tip forwarder's transaction if there is one. For other senders the floor does not cover transaction fees. For USDC settlement, the bot converts the floor into USDC with a 20% margin.

With no_failure_mode = true, the bot removes that profit floor. A transaction may succeed without a trade and still pay its tip and network fees. This setting does not make submissions free or guarantee a profit.

Astralane endpoints without a supplied API key use the bot's shared default key and require no_failure_mode = true. Use an api_key header or an api-key/api_key URL query parameter to supply your own key.

See Sending Vendor Examples for service-specific setups.

Price and tip strategies

compute_unit_price and tip_amount use the same strategy structure, except Helius is supported only for compute unit prices. Strategy names are case-sensitive.

StrategyFieldsBehavior
Randomfrom, to, countUniform random integers in the inclusive range. Set from equal to to for a fixed value.
ExponentialRandomfrom, to, countRandom values distributed on a logarithmic scale. Use positive from below to.
Linearfrom, to, countValues spaced with an integer step across the range. One value uses from.
Exponentialfrom, to, countValues spaced geometrically across the range. from must be at least 1.
Filefile_pathRead integer values, one per line. Blank lines and # or // comments are ignored. The file is reread each send pass.
Heliusapi_key; optional fields belowScale the Helius priority fee estimate for the transaction's accounts.

For the four range strategies, provide count of at least 1 and from no greater than to (ExponentialRandom requires a strict increase). An optional min sets a lower bound on generated values for non-Helius strategies. max applies only to Helius.

Each send pass tries the combinations of generated tip amounts and compute unit prices, subject to the sender's rate limits. For example, two tips and three prices produce six candidate submissions per basket.

Helius priority prices

[[senders]]
name = "rpc-helius-prices"
type = "json_rpc"
urls = ["https://YOUR_SENDING_RPC"]
compute_unit_price = { strategy = "Helius", api_key = "YOUR_HELIUS_API_KEY", from = 90, to = 130, count = 3, max = 20000, fetch_interval = 5 }

Here from and to are percentages of the estimate, not micro-lamport amounts. This example generates three prices from 90% to 130% of the estimate, capped at 20,000 micro-lamports per CU.

Helius fieldDefaultMeaning
api_keyRequiredHelius API key used for priority fee estimates.
from100Starting percentage of the estimate.
toSame as fromEnding percentage.
count1Number of generated prices; values below 1 are treated as 1.
maxUnsetUpper bound in micro-lamports per CU.
fetch_interval5Cache interval in seconds, with a minimum of 1.
account_keysEmptyAdditional account addresses to include with the transaction's accounts when requesting an estimate.

Auto-rebalance

This optional section checks the wallet every minute. When native SOL falls below min_sol_balance, the bot unwraps WSOL and wraps min_wsol_balance again. It skips rebalancing if the combined SOL and WSOL balance is below the two configured amounts added together.

[auto_rebalance]
min_sol_balance = 500_000_000
min_wsol_balance = 200_000_000
compute_unit_price = 10_000

All three fields are required when this section is present. Balances are in lamports; compute_unit_price is in micro-lamports per CU. Rebalancing does not sell USDC, and it is not an initial funding mechanism for the WSOL account.

Logging

[log]
enable_sending_log_summary = true
summary_interval_seconds = 60

enable_sending_log_summary defaults to false. When enabled, periodic summaries replace the per-transaction logs of successful sends; failed sends are still logged, except replies that the transaction was already processed. summary_interval_seconds defaults to 60.

Applying config changes

The bot checks the config file every second. Sender settings and filters for the existing settlement profiles can update while it runs. Invalid edits keep the previous config active.

Restart after adding or removing a settlement profile, changing the RPC or wallet, or changing auto-rebalance settings. These changes take effect on the next start.

Removed 1.x settings

Previous setting2.0.0 replacement
[rpc]bot.rpc_url
[wallet]bot.private_key for first import, then bot.encrypted_key_path
[flashloan].enabledbot.flashloan
[spam], [jito], [[sending_venders.sending_vender]][[senders]] with an explicit type
request_format, enable_submit_batchSender type = "send_bundle" or "submit_batch"
Manual mint/pool lists and bundle groups[auto.sol] and/or [auto.usdc]
Manual compute limits, transaction-version selection, and lookup table configurationManaged by the bot

Remove old fields rather than leaving them alongside the new ones: unknown fields prevent the config from loading.

On this page