Expand description
§jito-bundle
Standalone Rust library for submitting Jito Bundles on Solana.
Submit up to 5 transactions that execute atomically and in order. The library handles tip calculation, bundle construction, simulation, endpoint retry, and on-chain confirmation.
Jito Bundle Explorer: https://explorer.jito.wtf/
§Features
- Atomic bundle construction from fixed-size
BundleInstructionSlotsinput. - Automatic tipping via
TipStrategy. - Endpoint retry across Jito mainnet regions.
- Optional Helius
simulateBundlebefore sending. - Optional
jitodontfrontaccount injection. - Typed error handling via
JitoError.
§Requirements
- Rust 1.85+ (edition 2024)
- Solana keypair with SOL for tips
§Usage
§Via JitoBundler facade (recommended)
use jito_bundle::bundler::types::BundleInstructionSlots;
use jito_bundle::client::jito_bundler::{BuildBundleOptions, JitoBundler};
use jito_bundle::config::jito::JitoConfig;
use solana_sdk::signature::Keypair;
async fn run() -> Result<(), Box<dyn std::error::Error>> {
let config = JitoConfig::new("https://api.mainnet-beta.solana.com")
.with_helius_rpc_url("https://mainnet.helius-rpc.com/?api-key=...")
.with_uuid("your-jito-uuid");
let bundler = JitoBundler::new(config)?;
let payer = Keypair::new();
let slots: BundleInstructionSlots = [None, None, None, None, None];
let bundle = bundler
.build_bundle(BuildBundleOptions {
payer: &payer,
transactions_instructions: slots,
lookup_tables: &[],
})
.await?;
let result = bundler.send_and_confirm(&bundle).await?;
println!("bundle landed: {:?}", result.bundle_id);
Ok(())
}§Direct construction via BundleBuilder
use jito_bundle::bundler::builder::types::{BundleBuilder, BundleBuilderInputs};
use jito_bundle::bundler::types::BundleInstructionSlots;
use jito_bundle::constants::DEFAULT_COMPUTE_UNIT_LIMIT;
use solana_sdk::hash::Hash;
use solana_sdk::signature::Keypair;
fn run() -> Result<(), Box<dyn std::error::Error>> {
let payer = Keypair::new();
let slots: BundleInstructionSlots = [None, None, None, None, None];
let bundle = BundleBuilder::build(BundleBuilderInputs {
payer: &payer,
transactions_instructions: slots,
lookup_tables: &[],
recent_blockhash: Hash::default(),
tip_lamports: 100_000,
jitodontfront_pubkey: None,
compute_unit_limit: DEFAULT_COMPUTE_UNIT_LIMIT,
})?;
println!("built {} transactions", bundle.transactions.len());
Ok(())
}§Public Types
BundleInstructionSlots:type BundleInstructionSlots = [Option<Vec<Instruction>>; 5]BuiltBundle:transactions: Vec<VersionedTransaction>tip_account: Pubkeytip_lamports: u64tip_mode: TipMode
§Configuration
JitoConfig uses a builder pattern:
| Method | Description |
|---|---|
new(rpc_url) | Required Solana RPC URL |
.with_network(Network) | Mainnet (default) or Custom { block_engine_url, tip_floor_url } |
.with_helius_rpc_url(url) | Enable Helius simulation before send |
.with_uuid(uuid) | Jito authentication UUID |
.with_tip_strategy(TipStrategy) | Fixed, FetchFloor, or FetchFloorWithCap |
.with_confirm_policy(ConfirmPolicy) | Confirmation polling config |
.with_jitodontfront(pubkey) | Optional frontrun protection account |
.with_compute_unit_limit(u32) | Per-transaction compute budget |
§Bundle Rules
- Max 5 transactions per bundle (hard Jito bundle limit).
- Slots are compacted before build (gaps removed, order preserved).
jitodontfrontis enforced only in the first transaction; existingjitodontfront*accounts are removed by prefix match because the suffix can vary.- Tip instruction is always the final instruction of the final transaction.
- If bundle has fewer than 5 transactions, tip is added as a separate transaction (uses remaining capacity).
- If bundle already has 5 transactions, tip is appended inline to the last transaction (cannot add a 6th transaction).
- If the chosen tip account is present in a lookup table for inline mode, Jito bundle execution fails, so build rejects it.
- Compute budget instruction is prepended to every transaction.
§Error Handling
All operations return Result<T, JitoError>.
use jito_bundle::JitoError;
fn handle(result: Result<(), JitoError>) {
match result {
Err(JitoError::ConfirmationTimeout { attempts }) => {
println!("timed out after {attempts}");
}
Err(JitoError::SimulationFailed { details }) => {
println!("simulation failed: {details}");
}
Err(e) => {
println!("other error: {e}");
}
Ok(()) => {}
}
}§Testing
# Unit tests
cargo test
# Integration tests (requires .env with live credentials)
cargo test -- --ignored§License
MIT
Re-exports§
pub use error::JitoError;