$npx -y skills add agiprolabs/claude-trading-skills --skill jito-bundlesJito bundle submission for MEV protection on Solana — bundle building, tip strategies, block engine endpoints, and landing rate optimization
| 1 | # Jito Bundle Submission for Solana |
| 2 | |
| 3 | 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. |
| 4 | |
| 5 | > **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. |
| 6 | |
| 7 | ## When to Use Bundles |
| 8 | |
| 9 | | Scenario | Use Bundle? | Why | |
| 10 | |----------|-------------|-----| |
| 11 | | Swap on illiquid token | Yes | Prevents sandwich attacks | |
| 12 | | Multi-step arbitrage | Yes | Atomic execution prevents partial fills | |
| 13 | | Liquidation | Yes | Competitive — tip determines priority | |
| 14 | | Simple SOL transfer | No | Priority fees are cheaper and sufficient | |
| 15 | | Time-insensitive swap | Maybe | Bundles cost tips; priority fees may suffice | |
| 16 | | NFT mint / competitive action | Yes | Guarantees ordering within the slot | |
| 17 | |
| 18 | ## Core Concepts |
| 19 | |
| 20 | ### Bundle Anatomy |
| 21 | |
| 22 | 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. |
| 23 | |
| 24 | ``` |
| 25 | Bundle = [Tx1, Tx2, ..., TxN] (N <= 5) |
| 26 | |
| 27 | - All transactions must be signed |
| 28 | - Transactions execute in order: Tx1 → Tx2 → ... → TxN |
| 29 | - If ANY transaction fails, the ENTIRE bundle is dropped |
| 30 | - The tip instruction goes in the LAST transaction (last instruction) |
| 31 | - Bundle has ~2 slots (~800ms) to land before expiry |
| 32 | ``` |
| 33 | |
| 34 | ### Tip Mechanism |
| 35 | |
| 36 | Tips are SOL transfers to one of Jito's 8 tip accounts. The tip incentivizes validators to include your bundle. |
| 37 | |
| 38 | ```python |
| 39 | # Tip is a standard SOL transfer instruction |
| 40 | tip_instruction = transfer( |
| 41 | from_pubkey=your_wallet, |
| 42 | to_pubkey=tip_account, # One of 8 Jito tip accounts |
| 43 | lamports=tip_amount # Tip in lamports (1 SOL = 1e9 lamports) |
| 44 | ) |
| 45 | # Add as the LAST instruction of the LAST transaction in the bundle |
| 46 | ``` |
| 47 | |
| 48 | Tip accounts are fetched dynamically via `getTipAccounts`. Rotate through them to distribute load. |
| 49 | |
| 50 | ### Block Engine Endpoints |
| 51 | |
| 52 | Jito operates geographically distributed block engines. Choose the one closest to your infrastructure: |
| 53 | |
| 54 | | Region | Endpoint | |
| 55 | |--------|----------| |
| 56 | | New York | `https://mainnet.block-engine.jito.wtf` | |
| 57 | | Amsterdam | `https://amsterdam.block-engine.jito.wtf` | |
| 58 | | Frankfurt | `https://frankfurt.block-engine.jito.wtf` | |
| 59 | | Tokyo | `https://tokyo.block-engine.jito.wtf` | |
| 60 | |
| 61 | All endpoints accept JSON-RPC over HTTPS on port 443. The `/api/v1/bundles` path handles bundle operations. |
| 62 | |
| 63 | ## API Methods |
| 64 | |
| 65 | ### sendBundle |
| 66 | |
| 67 | Submit a bundle of up to 5 transactions. |
| 68 | |
| 69 | ```python |
| 70 | import httpx |
| 71 | |
| 72 | BLOCK_ENGINE = "https://mainnet.block-engine.jito.wtf" |
| 73 | |
| 74 | payload = { |
| 75 | "jsonrpc": "2.0", |
| 76 | "id": 1, |
| 77 | "method": "sendBundle", |
| 78 | "params": [ |
| 79 | [tx1_base58, tx2_base58], # List of base58-encoded signed txs |
| 80 | ] |
| 81 | } |
| 82 | |
| 83 | resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload) |
| 84 | data = resp.json() |
| 85 | bundle_id = data["result"] # UUID string |
| 86 | ``` |
| 87 | |
| 88 | ### getBundleStatuses |
| 89 | |
| 90 | Check the landing status of submitted bundles (up to 5 bundle IDs per request). |
| 91 | |
| 92 | ```python |
| 93 | payload = { |
| 94 | "jsonrpc": "2.0", |
| 95 | "id": 1, |
| 96 | "method": "getBundleStatuses", |
| 97 | "params": [[bundle_id]] |
| 98 | } |
| 99 | resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload) |
| 100 | statuses = resp.json()["result"]["value"] |
| 101 | # Each status: {bundle_id, status, slot, transactions: [{signature, ...}]} |
| 102 | # status: "Invalid", "Pending", "Failed", "Landed" |
| 103 | ``` |
| 104 | |
| 105 | ### getTipAccounts |
| 106 | |
| 107 | Fetch the current list of Jito tip accounts. |
| 108 | |
| 109 | ```python |
| 110 | payload = { |
| 111 | "jsonrpc": "2.0", |
| 112 | "id": 1, |
| 113 | "method": "getTipAccounts", |
| 114 | "params": [] |
| 115 | } |
| 116 | resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload) |
| 117 | tip_accounts = resp.json()["result"] # List of 8 base58 pubkeys |
| 118 | ``` |
| 119 | |
| 120 | ### getInflightBundleStatuses |
| 121 | |
| 122 | Check status of bundles that haven't landed yet (in-flight). |
| 123 | |
| 124 | ```python |
| 125 | payload = { |
| 126 | "jsonrpc": "2.0", |
| 127 | "id": 1, |
| 128 | "method": "getInflightBundleStatuses", |
| 129 | "params": [[bundle_id]] |
| 130 | } |
| 131 | resp = httpx.post(f"{BLOCK_ENGINE}/api/v1/bundles", json=payload) |
| 132 | # status: "Pending", "Failed", "Landed" |
| 133 | ``` |
| 134 | |
| 135 | ## Bundle Construction Pattern |
| 136 | |
| 137 | A typical bundle for a protected swap: |
| 138 | |
| 139 | ```python |
| 140 | from solders.transaction import VersionedTransaction |
| 141 | from solders.message import MessageV0 |
| 142 | from solders.instruction import Instruction |
| 143 | from solders.system_program import transfer, TransferParams |
| 144 | from solders.pubkey import Pubkey |
| 145 | import random |
| 146 | |
| 147 | def build_protected_swap_bundle( |
| 148 | swap_ix: Instruction, |
| 149 | payer: Pubkey, |
| 150 | tip_lamports: int, |
| 151 | tip_accounts: list[str], |
| 152 | recent_blockhash: str, |
| 153 | ) -> |