jito-bundles

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Jito Bundle Submission for Solana

Solana上的Jito Bundle提交指南

Jito bundles allow you to submit up to 5 Solana transactions that execute atomically — either all land in the same slot or none do. This is the primary mechanism for MEV protection and competitive transaction execution on Solana. Approximately 85%+ of Solana validators run the Jito-modified client, making bundles the standard for reliable, front-run-resistant execution.
EXECUTION SKILL — SAFETY WARNING: Submitting bundles spends real SOL on tips. Always test with
--demo
mode first. Never submit bundles with real funds without explicit confirmation. Default to simulation/dry-run in all scripts and examples.
Jito Bundle允许你提交最多5笔Solana交易,这些交易将原子化执行——要么全部在同一个slot中落地,要么全部不落地。这是Solana上实现MEV防护和竞争性交易执行的核心机制。约85%以上的Solana验证节点运行Jito修改版客户端,使得Bundle成为可靠、防抢先交易执行的标准方案。
执行技能——安全警告:提交Bundle会消耗真实SOL作为小费。请始终先使用
--demo
模式进行测试。未经明确确认,切勿使用真实资金提交Bundle。所有脚本和示例默认使用模拟/试运行模式。

When to Use Bundles

何时使用Bundle

ScenarioUse Bundle?Why
Swap on illiquid tokenYesPrevents sandwich attacks
Multi-step arbitrageYesAtomic execution prevents partial fills
LiquidationYesCompetitive — tip determines priority
Simple SOL transferNoPriority fees are cheaper and sufficient
Time-insensitive swapMaybeBundles cost tips; priority fees may suffice
NFT mint / competitive actionYesGuarantees ordering within the slot
场景是否使用Bundle?原因
在非流动性代币上进行兑换防止三明治攻击
多步骤套利原子化执行避免部分成交
清算操作具有竞争性——小费决定优先级
简单SOL转账优先费用更便宜且足够
时间不敏感的兑换可能Bundle需要支付小费;优先费用可能已足够
NFT铸造 / 竞争性操作保证slot内的交易顺序

Core Concepts

核心概念

Bundle Anatomy

Bundle结构

A Jito bundle is a JSON-RPC request containing 1-5 base58-encoded signed transactions. The transactions execute sequentially and atomically within a single slot.
Bundle = [Tx1, Tx2, ..., TxN]  (N <= 5)

- All transactions must be signed
- Transactions execute in order: Tx1 → Tx2 → ... → TxN
- If ANY transaction fails, the ENTIRE bundle is dropped
- The tip instruction goes in the LAST transaction (last instruction)
- Bundle has ~2 slots (~800ms) to land before expiry
Jito Bundle是一个JSON-RPC请求,包含1-5个base58编码的已签名交易。这些交易在单个slot内按顺序原子化执行。
Bundle = [Tx1, Tx2, ..., TxN]  (N <= 5)

- 所有交易必须已签名
- 交易按顺序执行:Tx1 → Tx2 → ... → TxN
- 若任何一笔交易失败,整个Bundle会被丢弃
- 小费指令需放在最后一笔交易的最后一个指令中
- Bundle在过期前有约2个slot(约800ms)的时间窗口落地

Tip Mechanism

小费机制

Tips are SOL transfers to one of Jito's 8 tip accounts. The tip incentivizes validators to include your bundle.
python
undefined
小费是向Jito的8个小费账户之一转账SOL。小费用于激励验证节点包含你的Bundle。
python
undefined

Tip is a standard SOL transfer instruction

小费是标准的SOL转账指令

tip_instruction = transfer( from_pubkey=your_wallet, to_pubkey=tip_account, # One of 8 Jito tip accounts lamports=tip_amount # Tip in lamports (1 SOL = 1e9 lamports) )
tip_instruction = transfer( from_pubkey=your_wallet, to_pubkey=tip_account, # Jito的8个小费账户之一 lamports=tip_amount # 小费以lamports为单位(1 SOL = 1e9 lamports) )

Add as the LAST instruction of the LAST transaction in the bundle

添加为Bundle中最后一笔交易的最后一个指令


Tip accounts are fetched dynamically via `getTipAccounts`. Rotate through them to distribute load.

小费账户可通过`getTipAccounts`动态获取。轮换使用账户以分散负载。

Block Engine Endpoints

区块引擎端点

Jito operates geographically distributed block engines. Choose the one closest to your infrastructure:
RegionEndpoint
New York
https://mainnet.block-engine.jito.wtf
Amsterdam
https://amsterdam.block-engine.jito.wtf
Frankfurt
https://frankfurt.block-engine.jito.wtf
Tokyo
https://tokyo.block-engine.jito.wtf
All endpoints accept JSON-RPC over HTTPS on port 443. The
/api/v1/bundles
path handles bundle operations.
Jito运营着地理分布的区块引擎。选择离你的基础设施最近的端点:
地区端点
纽约
https://mainnet.block-engine.jito.wtf
阿姆斯特丹
https://amsterdam.block-engine.jito.wtf
法兰克福
https://frankfurt.block-engine.jito.wtf
东京
https://tokyo.block-engine.jito.wtf
所有端点通过HTTPS端口443接受JSON-RPC请求。
/api/v1/bundles
路径处理Bundle相关操作。

API Methods

API方法

sendBundle

sendBundle

Submit a bundle of up to 5 transactions.
python
import httpx

BLOCK_ENGINE = "https://mainnet.block-engine.jito.wtf"

payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "sendBundle",
    "params": [
        [tx1_base58, tx2_base58],  # List of base58-encoded signed txs
    ]
}

resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
data = resp.json()
bundle_id = data["result"]  # UUID string
提交最多包含5笔交易的Bundle。
python
import httpx

BLOCK_ENGINE = "https://mainnet.block-engine.jito.wtf"

payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "sendBundle",
    "params": [
        [tx1_base58, tx2_base58],  # base58编码的已签名交易列表
    ]
}

resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
data = resp.json()
bundle_id = data["result"]  # UUID字符串

getBundleStatuses

getBundleStatuses

Check the landing status of submitted bundles (up to 5 bundle IDs per request).
python
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getBundleStatuses",
    "params": [[bundle_id]]
}
resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
statuses = resp.json()["result"]["value"]
查询已提交Bundle的落地状态(每次请求最多支持5个Bundle ID)。
python
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getBundleStatuses",
    "params": [[bundle_id]]
}
resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
statuses = resp.json()["result"]["value"]

Each status: {bundle_id, status, slot, transactions: [{signature, ...}]}

每个状态结构:{bundle_id, status, slot, transactions: [{signature, ...}]}

status: "Invalid", "Pending", "Failed", "Landed"

status可选值: "Invalid", "Pending", "Failed", "Landed"

undefined
undefined

getTipAccounts

getTipAccounts

Fetch the current list of Jito tip accounts.
python
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTipAccounts",
    "params": []
}
resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
tip_accounts = resp.json()["result"]  # List of 8 base58 pubkeys
获取当前Jito小费账户列表。
python
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTipAccounts",
    "params": []
}
resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
tip_accounts = resp.json()["result"]  # 8个base58公钥的列表

getInflightBundleStatuses

getInflightBundleStatuses

Check status of bundles that haven't landed yet (in-flight).
python
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getInflightBundleStatuses",
    "params": [[bundle_id]]
}
resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)
查询尚未落地的Bundle(在途)状态。
python
payload = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getInflightBundleStatuses",
    "params": [[bundle_id]]
}
resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload)

status: "Pending", "Failed", "Landed"

status可选值: "Pending", "Failed", "Landed"

undefined
undefined

Bundle Construction Pattern

Bundle构建模式

A typical bundle for a protected swap:
python
from solders.transaction import VersionedTransaction
from solders.message import MessageV0
from solders.instruction import Instruction
from solders.system_program import transfer, TransferParams
from solders.pubkey import Pubkey
import random

def build_protected_swap_bundle(
    swap_ix: Instruction,
    payer: Pubkey,
    tip_lamports: int,
    tip_accounts: list[str],
    recent_blockhash: str,
) -> list[VersionedTransaction]:
    """Build a 1-tx bundle: swap + tip in the same transaction.

    For simple swaps, a single-transaction bundle is sufficient.
    The tip instruction is appended as the last instruction.
    """
    # Pick a random tip account
    tip_account = Pubkey.from_string(random.choice(tip_accounts))

    # Tip instruction
    tip_ix = transfer(TransferParams(
        from_pubkey=payer,
        to_pubkey=tip_account,
        lamports=tip_lamports,
    ))

    # Build transaction with swap + tip
    msg = MessageV0.try_compile(
        payer=payer,
        instructions=[swap_ix, tip_ix],
        address_lookup_table_accounts=[],
        recent_blockhash=recent_blockhash,
    )
    tx = VersionedTransaction(msg, [keypair])
    return [tx]
用于防护型兑换的典型Bundle:
python
from solders.transaction import VersionedTransaction
from solders.message import MessageV0
from solders.instruction import Instruction
from solders.system_program import transfer, TransferParams
from solders.pubkey import Pubkey
import random

def build_protected_swap_bundle(
    swap_ix: Instruction,
    payer: Pubkey,
    tip_lamports: int,
    tip_accounts: list[str],
    recent_blockhash: str,
) -> list[VersionedTransaction]:
    """构建单交易Bundle:兑换 + 小费在同一笔交易中。

    对于简单兑换,单交易Bundle已足够。
    小费指令追加为最后一个指令。
    """
    # 随机选择一个小费账户
    tip_account = Pubkey.from_string(random.choice(tip_accounts))

    # 小费指令
    tip_ix = transfer(TransferParams(
        from_pubkey=payer,
        to_pubkey=tip_account,
        lamports=tip_lamports,
    ))

    # 构建包含兑换+小费的交易
    msg = MessageV0.try_compile(
        payer=payer,
        instructions=[swap_ix, tip_ix],
        address_lookup_table_accounts=[],
        recent_blockhash=recent_blockhash,
    )
    tx = VersionedTransaction(msg, [keypair])
    return [tx]

Tip Sizing Guide

小费规模指南

ScenarioTip Range (lamports)Tip Range (SOL)
Normal swap (low urgency)1,000 - 10,0000.000001 - 0.00001
Normal swap (standard)10,000 - 50,0000.00001 - 0.00005
Competitive action (arb, liquidation)50,000 - 500,0000.00005 - 0.0005
Highly competitive (NFT mint, MEV)500,000 - 5,000,0000.0005 - 0.005
Emergency (must land this slot)5,000,000+0.005+
Dynamic tip calculation based on recent tip levels:
python
def calculate_dynamic_tip(
    base_tip: int = 10_000,
    urgency_multiplier: float = 1.0,
    recent_tip_percentile_50: int = 15_000,
) -> int:
    """Calculate tip based on urgency and recent network tips.

    Args:
        base_tip: Minimum tip in lamports.
        urgency_multiplier: 1.0 = normal, 2.0 = urgent, 5.0 = critical.
        recent_tip_percentile_50: Median tip from recent bundles.

    Returns:
        Tip amount in lamports.
    """
    dynamic_tip = max(base_tip, int(recent_tip_percentile_50 * urgency_multiplier))
    # Cap at 0.01 SOL to prevent accidents
    return min(dynamic_tip, 10_000_000)
场景小费范围(lamports)小费范围(SOL)
普通兑换(低紧急度)1,000 - 10,0000.000001 - 0.00001
普通兑换(标准)10,000 - 50,0000.00001 - 0.00005
竞争性操作(套利、清算)50,000 - 500,0000.00005 - 0.0005
高竞争性操作(NFT铸造、MEV)500,000 - 5,000,0000.0005 - 0.005
紧急操作(必须在当前slot落地)5,000,000+0.005+
基于近期小费水平的动态小费计算:
python
def calculate_dynamic_tip(
    base_tip: int = 10_000,
    urgency_multiplier: float = 1.0,
    recent_tip_percentile_50: int = 15_000,
) -> int:
    """根据紧急度和近期网络小费计算小费金额。

    参数:
        base_tip: 最小小费(lamports)。
        urgency_multiplier: 1.0=正常, 2.0=紧急, 5.0=关键。
        recent_tip_percentile_50: 近期Bundle的中位小费。

    返回:
        小费金额(lamports)。
    """
    dynamic_tip = max(base_tip, int(recent_tip_percentile_50 * urgency_multiplier))
    # 上限为0.01 SOL以防止意外超额支付
    return min(dynamic_tip, 10_000_000)

Common Errors and Fixes

常见错误与修复方案

ErrorCauseFix
Bundle dropped (slot expired)
Bundle didn't land within 2 slotsRetry with fresh blockhash; consider higher tip
Transaction simulation failed
A tx in the bundle would fail on-chainSimulate each tx individually to find the failing one
Bundle already processed
Duplicate bundle IDExpected on retry; check status instead
Rate limited
Too many requests to block engineBack off; rotate between block engine endpoints
Invalid transaction
Malformed or unsigned transactionVerify all txs are signed and base58-encoded
Blockhash not found
Stale blockhashUse
getLatestBlockhash
with
finalized
commitment
错误原因修复
Bundle dropped (slot expired)
Bundle未在2个slot内落地使用新鲜blockhash重试;考虑提高小费
Transaction simulation failed
Bundle中某笔交易在链上会执行失败单独模拟每笔交易以找出失败的交易
Bundle already processed
重复的Bundle ID重试时属于预期情况;请检查状态
Rate limited
向区块引擎发送请求过于频繁退避重试;轮换使用区块引擎端点
Invalid transaction
交易格式错误或未签名验证所有交易已签名且为base58编码
Blockhash not found
Blockhash已过期使用
getLatestBlockhash
并指定
finalized
确认级别

Landing Rate Optimization

落地率优化策略

Strategies to maximize bundle landing probability:
  1. Multi-region submission: Send the same bundle to multiple block engines simultaneously. The first to reach the current leader wins.
  2. Fresh blockhash: Use
    getLatestBlockhash
    with
    confirmed
    commitment immediately before building. Stale blockhashes are the #1 cause of dropped bundles.
  3. Retry with backoff: If a bundle doesn't land within 2-3 seconds, rebuild with a fresh blockhash and resubmit. Do NOT resubmit with the same blockhash.
  4. Adequate tipping: Under-tipped bundles are deprioritized. Monitor the network's tip distribution and tip at or above the 50th percentile for your urgency level.
  5. Minimal bundle size: Fewer transactions = less simulation time = higher landing rate. Use single-transaction bundles when possible.
python
async def submit_with_retry(
    bundle_txs: list[str],
    endpoints: list[str],
    max_retries: int = 3,
) -> str | None:
    """Submit bundle to multiple endpoints with retry logic.

    Returns bundle_id if submitted, None if all retries exhausted.
    """
    for attempt in range(max_retries):
        # Submit to all endpoints in parallel
        async with httpx.AsyncClient() as client:
            tasks = [
                client.post(
                    f"{ep}/api/v1/bundles",
                    json={
                        "jsonrpc": "2.0", "id": 1,
                        "method": "sendBundle",
                        "params": [bundle_txs],
                    },
                    timeout=5.0,
                )
                for ep in endpoints
            ]
            # Process first successful response
            for resp in asyncio.as_completed(tasks):
                result = (await resp).json()
                if "result" in result:
                    return result["result"]

        # Wait before retry with fresh blockhash
        await asyncio.sleep(0.5 * (attempt + 1))
    return None
最大化Bundle落地概率的策略:
  1. 多地区提交:同时向多个区块引擎发送相同的Bundle。最先到达当前领导者的请求会被优先处理。
  2. 新鲜Blockhash:在构建Bundle前立即使用
    getLatestBlockhash
    并指定
    confirmed
    确认级别。过期Blockhash是Bundle被丢弃的首要原因。
  3. 退避重试:如果Bundle在2-3秒内未落地,使用新鲜Blockhash重新构建并重新提交。请勿使用相同的Blockhash重新提交。
  4. 充足小费:小费不足的Bundle会被降级处理。监控网络小费分布,根据你的紧急度水平,小费不低于50分位数。
  5. 最小化Bundle规模:交易越少=模拟时间越短=落地率越高。尽可能使用单交易Bundle。
python
async def submit_with_retry(
    bundle_txs: list[str],
    endpoints: list[str],
    max_retries: int = 3,
) -> str | None:
    """向多个端点提交Bundle并带有重试逻辑。

    提交成功则返回bundle_id,所有重试耗尽则返回None。
    """
    for attempt in range(max_retries):
        # 并行提交到所有端点
        async with httpx.AsyncClient() as client:
            tasks = [
                client.post(
                    f"{ep}/api/v1/bundles",
                    json={
                        "jsonrpc": "2.0", "id": 1,
                        "method": "sendBundle",
                        "params": [bundle_txs],
                    },
                    timeout=5.0,
                )
                for ep in endpoints
            ]
            # 处理第一个成功响应
            for resp in asyncio.as_completed(tasks):
                result = (await resp).json()
                if "result" in result:
                    return result["result"]

        # 重试前等待,使用新鲜Blockhash
        await asyncio.sleep(0.5 * (attempt + 1))
    return None

Safety Checklist (Execution)

执行安全检查清单

Before submitting any bundle with real funds:
  • Simulated all transactions individually via
    simulateTransaction
  • Verified tip amount is reasonable (not accidentally SOL instead of lamports)
  • Confirmed blockhash is fresh (< 60 seconds old)
  • Verified all transactions are properly signed
  • Checked wallet balance covers all transaction costs + tip
  • Tested with devnet or --demo mode first
  • Set maximum tip cap to prevent accidental overpayment
在使用真实资金提交任何Bundle前:
  • 通过
    simulateTransaction
    单独模拟所有交易
  • 验证小费金额合理(未误将SOL当作lamports)
  • 确认Blockhash是新鲜的(生成时间<60秒)
  • 验证所有交易已正确签名
  • 检查钱包余额足以覆盖所有交易成本+小费
  • 先在devnet或--demo模式中测试
  • 设置最大小费上限以防止意外超额支付

Files

文件

References

参考资料

  • references/bundle_api.md
    — Complete JSON-RPC API reference with request/response schemas and error codes
  • references/tip_strategies.md
    — Tip calculation strategies, dynamic tipping, cost optimization
  • references/best_practices.md
    — Bundle construction patterns, landing rate optimization, common pitfalls
  • references/bundle_api.md
    — 完整的JSON-RPC API参考,包含请求/响应 schema和错误码
  • references/tip_strategies.md
    — 小费计算策略、动态小费、成本优化
  • references/best_practices.md
    — Bundle构建模式、落地率优化、常见陷阱

Scripts

脚本

  • scripts/build_bundle.py
    — Bundle construction with tip instruction;
    --demo
    mode builds but does not submit
  • scripts/check_bundle_status.py
    — Bundle status checking and tip account fetching;
    --demo
    mode uses mock responses
  • scripts/build_bundle.py
    — 带有小费指令的Bundle构建;
    --demo
    模式仅构建不提交
  • scripts/check_bundle_status.py
    — Bundle状态查询和小费账户获取;
    --demo
    模式使用模拟响应