mcpField
J
jito-bundles

jito-bundles

github.com/agiprolabs开发456439 次安装8 周前更新
代码仓库

关于 jito-bundles

jito-bundles 是面向 Solana 开发者的技能,介绍如何将最多 5 笔交易组成原子执行的 Jito bundle。内容涵盖提交、状态检查、小费策略、落块优化和资金安全检查。

主要功能

  1. 01构建并提交原子交易 bundle
  2. 02查询 bundle 与进行中状态
  3. 03获取 Jito 小费账户并设置小费
  4. 04通过多区域提交和重试优化落块
  5. 05使用演示模式和模拟检查流程

适用场景

  1. 01保护低流动性代币交换免受夹击
  2. 02原子执行多步套利交易
  3. 03提交竞争性清算或 NFT 铸造交易
  4. 04在使用真实资金前模拟 bundle

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agiprolabs/claude-trading-skills --skill jito-bundles

安装后在 Claude Code 中输入/jito-bundles确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
best_practices.md
bundle_api.md
tip_strategies.md
scripts/
build_bundle.py
check_bundle_status.py

详细介绍

Solana 的 Jito Bundle 提交

Jito bundle 允许你提交最多 5 笔 Solana 交易,并以原子方式执行——要么全部在同一个 slot 中落链,要么都不落链。这是 Solana 上防护 MEV 和实现竞争性交易执行的主要机制。Solana 验证者中约有 85% 以上运行 Jito 修改版客户端,因此 bundle 已成为可靠、抗抢跑执行的标准方式。

执行技能 — 安全警告:提交 bundle 会消耗真实 SOL 作为小费。务必先使用 --demo 模式进行测试。未经明确确认,切勿使用真实资金提交 bundle。所有脚本和示例默认使用模拟/干运行模式。

何时使用 Bundle

场景使用 Bundle?原因
交易流动性不足的代币是可防止三明治攻击
多步骤套利是原子执行可防止部分成交
清算是竞争激烈——小费决定优先级
简单的 SOL 转账否优先费更便宜,也足以满足需求
对时效性要求不高的交易可能Bundle 需要支付小费;优先费可能就足够
NFT 铸造/竞争性操作是保证在 slot 内的排序

核心概念

Bundle 结构

Jito bundle 是一条 JSON-RPC 请求,包含 1-5 笔以 base58 编码的已签名交易。这些交易会在单个 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 的 8 个小费账户之一的 SOL 转账。小费可激励验证者纳入你的 bundle。

# Tip is a standard SOL transfer instruction
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)
)
# Add as the LAST instruction of the LAST transaction in the bundle

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

Block Engine 端点

Jito 运营着分布在不同地理区域的 block engine。请选择距离你的基础设施最近的端点:

区域端点
纽约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 方法

sendBundle

提交最多包含 5 笔交易的 bundle。

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
getBundleStatuses

检查已提交 bundle 的落链状态(每次请求最多可查询 5 个 bundle ID)。

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, ...}]}
# status: "Invalid", "Pending", "Failed", "Landed"
getTipAccounts

获取当前的 Jito 小费账户列表。

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
getInflightBundleStatuses

检查尚未落链的 bundle 状态(正在处理中)。

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"

Bundle 构建模式

受保护交易的典型 bundle:

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]

小费金额指南

场景小费范围(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+

根据近期小费水平动态计算小费:

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)

常见错误及修复方法

错误原因修复方法
Bundle dropped (slot expired)Bundle 未能在 2 个 slot 内落链使用新的 blockhash 重试;考虑提高小费
Transaction simulation failedBundle 中的一笔交易在链上会失败分别模拟每笔交易,以找出失败的交易
Bundle already processedBundle ID 重复重试时出现此情况属于预期;改为检查状态
Rate limited向 block engine 发送的请求过多暂缓请求;在不同的 block engine 端点之间轮换
Invalid transaction交易格式错误或未签名确认所有交易均已签名并以 base58 编码
Blockhash not foundblockhash 已过期使用 finalized 确认级别调用 getLatestBlockhash

落块率优化

最大限度提高 Bundle 落块概率的策略:

  1. 多区域提交:同时将同一个 Bundle 发送到多个区块引擎。最先到达当前领导者的 Bundle 将胜出。

  2. 使用最新区块哈希:在构建前立即使用 getLatestBlockhash,并设置 confirmed 确认级别。过期的区块哈希是导致 Bundle 丢弃的首要原因。

  3. 退避重试:如果 Bundle 在 2-3 秒内没有落块,请使用最新的区块哈希重新构建并提交。切勿使用同一个区块哈希重新提交。

  4. 提供足够的小费:小费不足的 Bundle 会被降低优先级。监控网络的小费分布,并根据紧急程度提供不低于第 50 百分位数的小费。

  5. 尽量缩小 Bundle:交易越少 = 模拟时间越短 = 落块率越高。尽可能使用单笔交易的 Bundle。

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 前:

  • 已通过 simulateTransaction 单独模拟所有交易
  • 已确认小费金额合理(没有误用 SOL 而非 lamports)
  • 已确认区块哈希是最新的(创建时间不到 60 秒)
  • 已确认所有交易均已正确签名
  • 已检查钱包余额足以支付所有交易费用和小费
  • 已先在 devnet 或 --demo 模式下测试
  • 已设置小费上限,以防止意外多付

文件

参考资料
  • references/bundle_api.md — 完整的 JSON-RPC API 参考,包含请求/响应架构和错误代码
  • references/tip_strategies.md — 小费计算策略、动态小费和成本优化
  • references/best_practices.md — Bundle 构建模式、落块率优化和常见问题
脚本
  • scripts/build_bundle.py — 构建带小费指令的 Bundle;--demo 模式仅构建,不会提交
  • scripts/check_bundle_status.py — 检查 Bundle 状态并获取小费账户;--demo 模式使用模拟响应

评论

支持 Markdown