Solana arbitrage bot in Rust that scans DEX prices via Jupiter, detects profitable opportunities, and executes trades automatically with optimized RPC performance.
Solana Arbitrage Bot
Solana arbitrage bot — a Rust bot that discovers and executes profitable DEX arbitrage on Solana via the Jupiter aggregator. RPC-only execution. Supports continuous quote polling and optional Yellowstone gRPC big-trade monitoring.
Search: solana arbitrage bot · Solana arbitrage · Jupiter arbitrage bot · DEX arbitrage Rust · Solana trading bot · Yellowstone gRPC · Jupiter API.
Contact: @hodlwarden
How it works
- Discovery — Polling: sweeps a notional range in a grid across all configured base tokens concurrently, requests Jupiter quotes, keeps opportunities above min profit after fees. Big-trades: optional Yellowstone gRPC subscription triggers quote simulation on large flows.
- Execution — Builds swap instructions via Jupiter API, advances nonce, submits via RPC with requested compute and priority fee.

Profit calculation (execute only when net profit ≥ min profit):

Test Results
$0.006 Profit - $77 -> $0.006 Profit
$0.011 Profit - $77 -> $0.011 Profit
Features
- Dual discovery modes
- 8 liquid intermediates per base token — Each base token is tested against USDC, USDT, WSOL, mSOL, JitoSOL, JUP, ETH (Wormhole), and WBTC to maximize path coverage per round.
- Circuit breaker — Automatically pauses trade submission for 30 seconds after 5 consecutive failures; discovery continues while paused.
- P&L tracker — Tracks cumulative SOL profit, win rate, and trade counts. Stats are logged every 50 poll rounds.
- Rate-limited Jupiter calls — A semaphore caps concurrent Jupiter API requests at 8 to prevent rate-limiting.
- RPC-only submission — Transactions are submitted via your configured
submit_endpointusing standard Solana SDK. No third-party relay dependencies. - Multi-token support — Configure base tokens (e.g. USDC, SOL) with notional ranges, grid steps, and min-profit thresholds.
- Transaction cost awareness — Estimates fee (compute, priority, tip) and SOL price (refreshed every 5 min) to filter only profitable trades.
- Nonce-based submission — Uses a durable nonce account for reliable transaction lifecycle.
Prerequisites
- Rust (stable, e.g. 1.70+): rustup
- Solana RPC — A node or provider (e.g. Helius, QuickNode, Triton) with
submitTransactionsupport. - Wallet — Keypair file for the bot and a funded nonce account.
- Jupiter API — Either the public Jupiter API or a self-hosted proxy; configurable in
Config.toml. - Yellowstone gRPC (optional) — Only if you enable big-trades monitoring; requires endpoint and auth token.
Quick Start
- Clone and build
git clone https://github.com/hodlwarden/solana-arbitrage-bot.git solana-arbitrage-bot && cd solana-arbitrage-bot
cargo build --release
- Create a nonce account (one-time setup)
# Generate a nonce authority keypair (or reuse your bot wallet)
solana-keygen new -o nonce-authority.json
# Create the nonce account (fund it with enough SOL for rent, ~0.002 SOL) solana create-nonce-account nonce-account.json 0.01 --nonce-authority nonce-authority.json
# Get the nonce account public key and paste it into Config.toml solana address -k nonce-account.json
Set nonceaccountpubkey in your config to the address printed above.
- Configure
Config.example.toml to Config.toml (or settings.toml) and fill in your values. Do not commit secrets. The app loads settings.toml first, then falls back to Config.toml. Set at minimum:
- signerkeypairpath, rpcendpoint, submitendpoint - dex_api.endpoint (Jupiter API or proxy) - strategy.nonceaccountpubkey and strategy.instruments - [fees] block
- Run
cargo run --release
# Or after build: ./target/release/jupiterarbitragebot_offchain
Set RUST_LOG=info (or debug) to control log level.
Configuration
Configuration is TOML-based. See Config.example.toml for the full reference.
| Section | Purpose | |---------------|---------| | [connection] | signerkeypairpath, rpcendpoint, submitendpoint; optional geyserendpoint, geyserauth_token for Yellowstone. | | [dexapi] | Jupiter API endpoint and optional authtoken. | | [strategy] | instruments (base tokens with mint, notional range, grid steps, min profit), nonceaccountpubkey, defaultquotemint, pollingenabled / pollintervalms, geyserwatchenabled, executionenabled. | | [fees] | computeunitlimit, priorityfeelamports, relaytipsol; optional thirdpartyfeeprofitpct (e.g. 0.5 = 50% of gross profit in SOL); optional solpriceusd fallback. |
Third-party fee (fixed vs profit-based)
Transaction cost includes a base network fee plus an optional tip. You can set the tip in two ways:
- Fixed — A constant amount in SOL per trade. Use
relaytipsol. - Profit-based — A fraction of the trade's gross profit in SOL. Use
thirdpartyfeeprofitpct(0.0–1.0). When set, the tip is computed as gross profit (in SOL) × this value.
thirdpartyfeeprofitpct = 0.5, the tip is 0.05 SOL. Net profit (after base fee and this tip) is then used to decide if the trade meets min_profit and is submitted.
Config examples:
# Fixed tip: 0.00001 SOL per trade
[fees]
relaytipsol = 0.00001
# Profit-based: 50% of gross profit in SOL as tip
[fees]
relaytipsol = 0.00001 # fallback when profit-based is 0
thirdpartyfeeprofitpct = 0.5
If thirdpartyfeeprofitpct is set and in range (0, 1], it overrides relaytipsol for that trade; otherwise relaytipsol is used.
Project Layout
| Path | Description | |------------|-------------| | src/app/ | Configuration and runtime settings (node, swap API, strategy, fees). | | src/chain/ | Chain data and constants (program maps, token info, fee constants). | | src/engine/ | Arbitrage engine: Jupiter integration, discovery (polling + big-trades), execution, runtime (nonce, blockhash, SOL price, fee cost, circuit breaker, P&L stats). |