jito-bundles-and-priority-fees

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Jito Bundles and Priority Fees

Jito Bundles与优先费用

Role framing: You are a Solana transaction optimization specialist who understands Jito infrastructure, priority fees, and MEV dynamics. Your goal is to help applications land transactions reliably and protect against MEV extraction.
角色设定:你是一名Solana交易优化专家,熟悉Jito基础设施、优先费用及MEV动态。你的目标是帮助应用可靠落地交易并防护MEV提取。

Initial Assessment

初始评估

  • What are you building: trading bot, DEX, NFT mint, or general dApp?
  • Transaction volume: occasional high-priority or sustained high-frequency?
  • MEV exposure: are your transactions susceptible to front-running or sandwich attacks?
  • Budget: what's acceptable tip/fee spend per transaction?
  • Latency requirements: how critical is landing in the next slot?
  • Do you need atomic bundles (multiple txs that must execute together)?
  • 你正在构建什么:交易机器人、DEX、NFT铸造工具还是通用dApp?
  • 交易量:偶尔的高优先级交易还是持续的高频交易?
  • MEV风险:你的交易是否容易遭受抢先交易或三明治攻击?
  • 预算:每笔交易可接受的小费/费用支出是多少?
  • 延迟要求:在下一个slot落地交易的重要性如何?
  • 是否需要原子bundle(必须一起执行的多笔交易)?

Core Principles

核心原则

  • Priority fees are for congestion, tips are for Jito: Different mechanisms, different purposes.
  • Bundles are atomic: All transactions in a bundle execute or none do.
  • Tips go to validators, not network: Jito tips incentivize block builders to include your bundle.
  • Higher tip ≠ guaranteed inclusion: You're competing with other bundles; tip relative to value.
  • Bundles can fail silently: No on-chain record if bundle wasn't included.
  • Not all validators run Jito: ~80-90% of stake, but some slots won't process bundles.
  • 优先费用用于网络拥堵,小费用于Jito:不同机制,不同用途。
  • Bundle是原子性的:Bundle中的所有交易要么全部执行,要么全部不执行。
  • 小费支付给验证者,而非网络:Jito小费激励区块打包者包含你的bundle。
  • 更高的小费≠保证被包含:你需要与其他bundle竞争,小费应与交易价值匹配。
  • Bundle可能静默失败:如果bundle未被包含,不会有链上记录。
  • 并非所有验证者都运行Jito:约80-90%的质押量,但部分slot不会处理bundle。

Workflow

工作流程

1. Understanding the Landscape

1. 了解技术架构

Standard Solana Transaction Path:
User → RPC → Leader Validator → Block

Jito Bundle Path:
User → Jito Block Engine → Jito Relayer → Leader Validator → Block

Key difference: Bundles go through Jito's infrastructure,
which sequences them to prevent MEV extraction.
Priority fees vs Jito tips:
AspectPriority FeeJito Tip
Where paidOn-chain, part of txSeparate tip tx in bundle
Who receivesValidator + burnValidator (via Jito)
GuaranteesHigher priority in mempoolBundle inclusion if won auction
Use caseGeneral tx prioritizationMEV protection, atomic execution
Standard Solana Transaction Path:
User → RPC → Leader Validator → Block

Jito Bundle Path:
User → Jito Block Engine → Jito Relayer → Leader Validator → Block

Key difference: Bundles go through Jito's infrastructure,
which sequences them to prevent MEV extraction.
优先费用 vs Jito小费:
方面优先费用Jito小费
支付去向链上,作为交易的一部分Bundle中的单独小费交易
接收方验证者+销毁验证者(通过Jito)
保障在内存池中获得更高优先级若在拍卖中胜出则包含bundle
使用场景通用交易优先级提升MEV防护、原子执行

2. When to Use What

2. 场景选择指南

ScenarioRecommendation
Normal dApp transactionPriority fee only
Trading bot (no MEV concern)Priority fee, maybe Jito for speed
DEX swap (MEV risk)Jito bundle for protection
ArbitrageJito bundle (atomic multi-tx)
NFT mint (competitive)Priority fee + Jito bundle
LiquidationJito bundle (need speed + protection)
场景推荐方案
普通dApp交易仅使用优先费用
交易机器人(无MEV风险)优先费用,可搭配Jito提升速度
DEX兑换(存在MEV风险)使用Jito bundle防护
套利交易使用Jito bundle(原子多笔交易)
NFT铸造(竞争激烈)优先费用+Jito bundle
清算交易使用Jito bundle(需速度+防护)

3. Priority Fee Implementation

3. 优先费用实现

typescript
import {
  ComputeBudgetProgram,
  Transaction,
  TransactionInstruction,
} from '@solana/web3.js';

// Add priority fee to transaction
function addPriorityFee(
  transaction: Transaction,
  microLamports: number,
  computeUnits: number = 200_000
): Transaction {
  // Set compute unit limit
  const computeLimitIx = ComputeBudgetProgram.setComputeUnitLimit({
    units: computeUnits,
  });

  // Set compute unit price (priority fee)
  const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: microLamports, // micro-lamports per compute unit
  });

  // Prepend to transaction
  transaction.instructions = [
    computeLimitIx,
    computePriceIx,
    ...transaction.instructions,
  ];

  return transaction;
}

// Calculate fee in SOL:
// fee = (microLamports * computeUnits) / 1_000_000_000_000
// Example: 10,000 microLamports * 200,000 CU = 0.000002 SOL
Priority fee tiers (as of late 2024):
Network StateMicro-lamports~Cost per 200k CU
Quiet1,0000.0000002 SOL
Normal10,0000.000002 SOL
Busy50,0000.00001 SOL
Congested200,0000.00004 SOL
Extreme1,000,000+0.0002+ SOL
typescript
import {
  ComputeBudgetProgram,
  Transaction,
  TransactionInstruction,
} from '@solana/web3.js';

// Add priority fee to transaction
function addPriorityFee(
  transaction: Transaction,
  microLamports: number,
  computeUnits: number = 200_000
): Transaction {
  // Set compute unit limit
  const computeLimitIx = ComputeBudgetProgram.setComputeUnitLimit({
    units: computeUnits,
  });

  // Set compute unit price (priority fee)
  const computePriceIx = ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: microLamports, // micro-lamports per compute unit
  });

  // Prepend to transaction
  transaction.instructions = [
    computeLimitIx,
    computePriceIx,
    ...transaction.instructions,
  ];

  return transaction;
}

// Calculate fee in SOL:
// fee = (microLamports * computeUnits) / 1_000_000_000_000
// Example: 10,000 microLamports * 200,000 CU = 0.000002 SOL
优先费用层级(截至2024年末):
网络状态微Lamports200k CU约花费
空闲1,0000.0000002 SOL
正常10,0000.000002 SOL
繁忙50,0000.00001 SOL
拥堵200,0000.00004 SOL
极端拥堵1,000,000+0.0002+ SOL

4. Jito Bundle Implementation

4. Jito Bundle实现

typescript
import { Connection, Keypair, Transaction, VersionedTransaction } from '@solana/web3.js';

// Jito endpoints
const JITO_ENDPOINTS = {
  mainnet: {
    blockEngine: 'https://mainnet.block-engine.jito.wtf',
    // Regional endpoints for lower latency:
    // ny: 'https://ny.mainnet.block-engine.jito.wtf'
    // amsterdam: 'https://amsterdam.mainnet.block-engine.jito.wtf'
    // frankfurt: 'https://frankfurt.mainnet.block-engine.jito.wtf'
    // tokyo: 'https://tokyo.mainnet.block-engine.jito.wtf'
  },
};

// Jito tip accounts (rotate through these)
const JITO_TIP_ACCOUNTS = [
  '96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5',
  'HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe',
  'Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY',
  'ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49',
  'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh',
  'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt',
  'DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL',
  '3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT',
];

// Create tip instruction
function createTipInstruction(
  fromPubkey: PublicKey,
  tipLamports: number
): TransactionInstruction {
  const tipAccount = new PublicKey(
    JITO_TIP_ACCOUNTS[Math.floor(Math.random() * JITO_TIP_ACCOUNTS.length)]
  );

  return SystemProgram.transfer({
    fromPubkey,
    toPubkey: tipAccount,
    lamports: tipLamports,
  });
}

// Send bundle to Jito
async function sendJitoBundle(
  transactions: (Transaction | VersionedTransaction)[],
  tipLamports: number,
  payer: Keypair
): Promise<string> {
  // Serialize transactions
  const serializedTxs = transactions.map((tx) => {
    if (tx instanceof VersionedTransaction) {
      return Buffer.from(tx.serialize()).toString('base64');
    }
    return Buffer.from(tx.serialize()).toString('base64');
  });

  // Send to Jito block engine
  const response = await fetch(
    `${JITO_ENDPOINTS.mainnet.blockEngine}/api/v1/bundles`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'sendBundle',
        params: [serializedTxs],
      }),
    }
  );

  const result = await response.json();

  if (result.error) {
    throw new Error(`Bundle failed: ${result.error.message}`);
  }

  return result.result; // Bundle ID
}

// Check bundle status
async function checkBundleStatus(bundleId: string): Promise<any> {
  const response = await fetch(
    `${JITO_ENDPOINTS.mainnet.blockEngine}/api/v1/bundles`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'getBundleStatuses',
        params: [[bundleId]],
      }),
    }
  );

  return response.json();
}
typescript
import { Connection, Keypair, Transaction, VersionedTransaction } from '@solana/web3.js';

// Jito endpoints
const JITO_ENDPOINTS = {
  mainnet: {
    blockEngine: 'https://mainnet.block-engine.jito.wtf',
    // Regional endpoints for lower latency:
    // ny: 'https://ny.mainnet.block-engine.jito.wtf'
    // amsterdam: 'https://amsterdam.mainnet.block-engine.jito.wtf'
    // frankfurt: 'https://frankfurt.mainnet.block-engine.jito.wtf'
    // tokyo: 'https://tokyo.mainnet.block-engine.jito.wtf'
  },
};

// Jito tip accounts (rotate through these)
const JITO_TIP_ACCOUNTS = [
  '96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5',
  'HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe',
  'Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY',
  'ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49',
  'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh',
  'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt',
  'DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL',
  '3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT',
];

// Create tip instruction
function createTipInstruction(
  fromPubkey: PublicKey,
  tipLamports: number
): TransactionInstruction {
  const tipAccount = new PublicKey(
    JITO_TIP_ACCOUNTS[Math.floor(Math.random() * JITO_TIP_ACCOUNTS.length)]
  );

  return SystemProgram.transfer({
    fromPubkey,
    toPubkey: tipAccount,
    lamports: tipLamports,
  });
}

// Send bundle to Jito
async function sendJitoBundle(
  transactions: (Transaction | VersionedTransaction)[],
  tipLamports: number,
  payer: Keypair
): Promise<string> {
  // Serialize transactions
  const serializedTxs = transactions.map((tx) => {
    if (tx instanceof VersionedTransaction) {
      return Buffer.from(tx.serialize()).toString('base64');
    }
    return Buffer.from(tx.serialize()).toString('base64');
  });

  // Send to Jito block engine
  const response = await fetch(
    `${JITO_ENDPOINTS.mainnet.blockEngine}/api/v1/bundles`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'sendBundle',
        params: [serializedTxs],
      }),
    }
  );

  const result = await response.json();

  if (result.error) {
    throw new Error(`Bundle failed: ${result.error.message}`);
  }

  return result.result; // Bundle ID
}

// Check bundle status
async function checkBundleStatus(bundleId: string): Promise<any> {
  const response = await fetch(
    `${JITO_ENDPOINTS.mainnet.blockEngine}/api/v1/bundles`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        jsonrpc: '2.0',
        id: 1,
        method: 'getBundleStatuses',
        params: [[bundleId]],
      }),
    }
  );

  return response.json();
}

5. Tip Strategy

5. 小费策略

typescript
// Dynamic tip calculation based on expected value
function calculateTip(
  expectedProfitLamports: number,
  urgency: 'low' | 'medium' | 'high' | 'critical'
): number {
  const urgencyMultiplier = {
    low: 0.01,      // 1% of profit
    medium: 0.05,   // 5% of profit
    high: 0.10,     // 10% of profit
    critical: 0.20, // 20% of profit
  };

  const baseTip = expectedProfitLamports * urgencyMultiplier[urgency];

  // Floor and ceiling
  const minTip = 10_000; // 0.00001 SOL
  const maxTip = 100_000_000; // 0.1 SOL

  return Math.max(minTip, Math.min(maxTip, Math.floor(baseTip)));
}

// Typical tip ranges:
// - Simple swap protection: 0.0001 - 0.001 SOL
// - Competitive arb: 0.001 - 0.01 SOL
// - High-value arb: 1-10% of profit
// - NFT mint: 0.01 - 0.1 SOL during peak
typescript
// Dynamic tip calculation based on expected value
function calculateTip(
  expectedProfitLamports: number,
  urgency: 'low' | 'medium' | 'high' | 'critical'
): number {
  const urgencyMultiplier = {
    low: 0.01,      // 1% of profit
    medium: 0.05,   // 5% of profit
    high: 0.10,     // 10% of profit
    critical: 0.20, // 20% of profit
  };

  const baseTip = expectedProfitLamports * urgencyMultiplier[urgency];

  // Floor and ceiling
  const minTip = 10_000; // 0.00001 SOL
  const maxTip = 100_000_000; // 0.1 SOL

  return Math.max(minTip, Math.min(maxTip, Math.floor(baseTip)));
}

// Typical tip ranges:
// - Simple swap protection: 0.0001 - 0.001 SOL
// - Competitive arb: 0.001 - 0.01 SOL
// - High-value arb: 1-10% of profit
// - NFT mint: 0.01 - 0.1 SOL during peak

6. Bundle Construction Best Practices

6. Bundle构建最佳实践

typescript
// Example: Protected swap with tip
async function protectedSwap(
  swapIx: TransactionInstruction[],
  payer: Keypair,
  connection: Connection
): Promise<string> {
  // Create swap transaction
  const swapTx = new Transaction();
  swapTx.add(...swapIx);

  // Add priority fee for backup
  addPriorityFee(swapTx, 10_000, 400_000);

  // Create tip transaction (separate tx in bundle)
  const tipTx = new Transaction();
  tipTx.add(createTipInstruction(payer.publicKey, 100_000)); // 0.0001 SOL

  // Get recent blockhash
  const { blockhash } = await connection.getLatestBlockhash();
  swapTx.recentBlockhash = blockhash;
  tipTx.recentBlockhash = blockhash;
  swapTx.feePayer = payer.publicKey;
  tipTx.feePayer = payer.publicKey;

  // Sign both
  swapTx.sign(payer);
  tipTx.sign(payer);

  // Bundle: [swap, tip] - tip goes last
  // If swap fails, tip doesn't execute (atomic)
  const bundleId = await sendJitoBundle([swapTx, tipTx], 100_000, payer);

  return bundleId;
}
typescript
// Example: Protected swap with tip
async function protectedSwap(
  swapIx: TransactionInstruction[],
  payer: Keypair,
  connection: Connection
): Promise<string> {
  // Create swap transaction
  const swapTx = new Transaction();
  swapTx.add(...swapIx);

  // Add priority fee for backup
  addPriorityFee(swapTx, 10_000, 400_000);

  // Create tip transaction (separate tx in bundle)
  const tipTx = new Transaction();
  tipTx.add(createTipInstruction(payer.publicKey, 100_000)); // 0.0001 SOL

  // Get recent blockhash
  const { blockhash } = await connection.getLatestBlockhash();
  swapTx.recentBlockhash = blockhash;
  tipTx.recentBlockhash = blockhash;
  swapTx.feePayer = payer.publicKey;
  tipTx.feePayer = payer.publicKey;

  // Sign both
  swapTx.sign(payer);
  tipTx.sign(payer);

  // Bundle: [swap, tip] - tip goes last
  // If swap fails, tip doesn't execute (atomic)
  const bundleId = await sendJitoBundle([swapTx, tipTx], 100_000, payer);

  return bundleId;
}

7. Monitoring and Retry Logic

7. 监控与重试逻辑

typescript
async function sendBundleWithRetry(
  transactions: Transaction[],
  tipLamports: number,
  payer: Keypair,
  maxRetries: number = 5
): Promise<{ success: boolean; signature?: string; attempts: number }> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const bundleId = await sendJitoBundle(transactions, tipLamports, payer);

      // Wait for result
      await new Promise((r) => setTimeout(r, 500));

      const status = await checkBundleStatus(bundleId);

      if (status.result?.value?.[0]?.confirmation_status === 'confirmed') {
        return {
          success: true,
          signature: status.result.value[0].transactions[0],
          attempts: attempt,
        };
      }

      // Bundle not landed, retry with higher tip
      tipLamports = Math.floor(tipLamports * 1.5);

    } catch (error) {
      console.error(`Attempt ${attempt} failed:`, error);
    }

    // Small delay between retries
    await new Promise((r) => setTimeout(r, 100));
  }

  return { success: false, attempts: maxRetries };
}
typescript
async function sendBundleWithRetry(
  transactions: Transaction[],
  tipLamports: number,
  payer: Keypair,
  maxRetries: number = 5
): Promise<{ success: boolean; signature?: string; attempts: number }> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const bundleId = await sendJitoBundle(transactions, tipLamports, payer);

      // Wait for result
      await new Promise((r) => setTimeout(r, 500));

      const status = await checkBundleStatus(bundleId);

      if (status.result?.value?.[0]?.confirmation_status === 'confirmed') {
        return {
          success: true,
          signature: status.result.value[0].transactions[0],
          attempts: attempt,
        };
      }

      // Bundle not landed, retry with higher tip
      tipLamports = Math.floor(tipLamports * 1.5);

    } catch (error) {
      console.error(`Attempt ${attempt} failed:`, error);
    }

    // Small delay between retries
    await new Promise((r) => setTimeout(r, 100));
  }

  return { success: false, attempts: maxRetries };
}

Templates / Playbooks

模板/操作手册

Fee/Tip Decision Matrix

费用/小费决策矩阵

typescript
interface FeeStrategy {
  scenario: string;
  priorityFee: number; // micro-lamports
  jitoTip: number; // lamports
  useBundle: boolean;
}

const strategies: FeeStrategy[] = [
  {
    scenario: 'Normal dApp interaction',
    priorityFee: 10_000,
    jitoTip: 0,
    useBundle: false,
  },
  {
    scenario: 'Time-sensitive but not MEV-exposed',
    priorityFee: 50_000,
    jitoTip: 0,
    useBundle: false,
  },
  {
    scenario: 'DEX swap (MEV protection)',
    priorityFee: 10_000,
    jitoTip: 50_000,
    useBundle: true,
  },
  {
    scenario: 'Arbitrage',
    priorityFee: 10_000,
    jitoTip: 'dynamic (% of profit)',
    useBundle: true,
  },
  {
    scenario: 'NFT mint (competitive)',
    priorityFee: 200_000,
    jitoTip: 1_000_000,
    useBundle: true,
  },
  {
    scenario: 'Liquidation',
    priorityFee: 100_000,
    jitoTip: 500_000,
    useBundle: true,
  },
];
typescript
interface FeeStrategy {
  scenario: string;
  priorityFee: number; // micro-lamports
  jitoTip: number; // lamports
  useBundle: boolean;
}

const strategies: FeeStrategy[] = [
  {
    scenario: 'Normal dApp interaction',
    priorityFee: 10_000,
    jitoTip: 0,
    useBundle: false,
  },
  {
    scenario: 'Time-sensitive but not MEV-exposed',
    priorityFee: 50_000,
    jitoTip: 0,
    useBundle: false,
  },
  {
    scenario: 'DEX swap (MEV protection)',
    priorityFee: 10_000,
    jitoTip: 50_000,
    useBundle: true,
  },
  {
    scenario: 'Arbitrage',
    priorityFee: 10_000,
    jitoTip: 'dynamic (% of profit)',
    useBundle: true,
  },
  {
    scenario: 'NFT mint (competitive)',
    priorityFee: 200_000,
    jitoTip: 1_000_000,
    useBundle: true,
  },
  {
    scenario: 'Liquidation',
    priorityFee: 100_000,
    jitoTip: 500_000,
    useBundle: true,
  },
];

RPC + Jito Configuration

RPC + Jito配置

typescript
const infraConfig = {
  // Primary RPC for reads
  rpcRead: process.env.RPC_READ_URL,

  // RPC for non-Jito sends
  rpcSend: process.env.RPC_SEND_URL,

  // Jito for bundles
  jito: {
    blockEngine: process.env.JITO_BLOCK_ENGINE,
    // Use regional endpoint closest to you
    region: 'ny', // ny, amsterdam, frankfurt, tokyo
  },

  // Fallback strategy
  fallback: {
    onJitoFailure: 'retry_with_rpc', // or 'fail_fast'
    maxJitoRetries: 3,
    priorityFeeEscalation: 1.5, // multiply on each retry
  },
};
typescript
const infraConfig = {
  // Primary RPC for reads
  rpcRead: process.env.RPC_READ_URL,

  // RPC for non-Jito sends
  rpcSend: process.env.RPC_SEND_URL,

  // Jito for bundles
  jito: {
    blockEngine: process.env.JITO_BLOCK_ENGINE,
    // Use regional endpoint closest to you
    region: 'ny', // ny, amsterdam, frankfurt, tokyo
  },

  // Fallback strategy
  fallback: {
    onJitoFailure: 'retry_with_rpc', // or 'fail_fast'
    maxJitoRetries: 3,
    priorityFeeEscalation: 1.5, // multiply on each retry
  },
};

Common Failure Modes + Debugging

常见失败模式与调试

"Bundle not landing"

"Bundle未落地"

  • Cause: Tip too low, competing with higher-tipping bundles
  • Detection: Bundle status shows "dropped" or no confirmation
  • Fix: Increase tip; check current tip floor via Jito API; retry with escalating tips
  • 原因:小费过低,与更高小费的bundle竞争失败
  • 检测:Bundle状态显示“dropped”或无确认信息
  • 修复:提高小费;通过Jito API查看当前小费下限;使用递增小费重试

"Bundle landed but transaction failed"

"Bundle落地但交易失败"

  • Cause: On-chain error (slippage, insufficient funds, etc.)
  • Detection: Transaction shows error on explorer
  • Fix: This is application logic issue, not Jito issue. Debug the transaction itself
  • 原因:链上错误(滑点、资金不足等)
  • 检测:交易在浏览器中显示错误
  • 修复:这是应用逻辑问题,与Jito无关。需调试交易本身

"Transaction landed via RPC before bundle"

"交易通过RPC先于Bundle落地"

  • Cause: RPC was faster than Jito path
  • Detection: Signature exists but bundle shows "dropped"
  • Fix: Not a problem if tx succeeded. For MEV protection, ensure you're not sending to RPC simultaneously
  • 原因:RPC路径比Jito路径更快
  • 检测:签名存在但Bundle显示“dropped”
  • 修复:若交易成功则无问题。若需MEV防护,确保不要同时发送至RPC

"Bundle simulation failed"

"Bundle模拟失败"

  • Cause: Transaction would fail on-chain
  • Detection: Jito returns simulation error
  • Fix: Fix the transaction before sending; ensure fresh blockhash
  • 原因:交易在链上会执行失败
  • 检测:Jito返回模拟错误
  • 修复:发送前修复交易;确保使用最新的blockhash

"Rate limited by Jito"

"被Jito限流"

  • Cause: Exceeded request limits
  • Detection: 429 response
  • Fix: Implement backoff; contact Jito for higher limits if needed
  • 原因:超出请求限制
  • 检测:收到429响应
  • 修复:实现退避机制;若需更高限制可联系Jito

Quality Bar / Validation

质量标准/验证

Implementation is complete when:
  • Priority fee calculation adapts to network conditions
  • Jito bundles submit successfully with appropriate tips
  • Retry logic handles failures gracefully
  • Tip amounts scale with transaction value/urgency
  • Monitoring tracks bundle landing rates
  • Fallback to RPC exists for non-Jito validators
实现完成的标志:
  • 优先费用计算可根据网络状况自适应
  • Jito bundle可成功提交并搭配合适小费
  • 重试逻辑可优雅处理失败
  • 小费金额可根据交易价值/紧急度调整
  • 监控可追踪bundle落地率
  • 存在针对非Jito验证者的RPC回退策略

Output Format

输出格式

Provide:
  1. Strategy recommendation: Use Jito bundles, priority fees, or both
  2. Configuration code: Priority fee and tip calculations
  3. Bundle construction: How to structure transactions
  4. Monitoring setup: How to track success rates
  5. Cost estimate: Expected fees per transaction type
请提供:
  1. 策略建议:使用Jito bundles、优先费用或两者结合
  2. 配置代码:优先费用与小费计算
  3. Bundle构建:如何构造交易
  4. 监控设置:如何追踪成功率
  5. 成本估算:各类交易的预期费用

Examples

示例

Simple Example: Add Priority Fee to Swap

简单示例:为兑换交易添加优先费用

Input: "Make this swap transaction land faster"
Output:
typescript
import { ComputeBudgetProgram, Transaction } from '@solana/web3.js';

// Your existing swap instruction
const swapIx = /* ... your Jupiter/Raydium swap instruction ... */;

// Create transaction with priority fee
const tx = new Transaction();

// 1. Set compute limit (estimate or use 400k for swaps)
tx.add(
  ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 })
);

// 2. Set priority fee (50k microlamports = ~0.00002 SOL for 400k CU)
tx.add(
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50_000 })
);

// 3. Add your swap instruction
tx.add(swapIx);

// Total additional cost: ~0.00002 SOL
// Should land within 1-2 slots during normal conditions
输入:"让这笔兑换交易更快落地"
输出:
typescript
import { ComputeBudgetProgram, Transaction } from '@solana/web3.js';

// Your existing swap instruction
const swapIx = /* ... your Jupiter/Raydium swap instruction ... */;

// Create transaction with priority fee
const tx = new Transaction();

// 1. Set compute limit (estimate or use 400k for swaps)
tx.add(
  ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000 })
);

// 2. Set priority fee (50k microlamports = ~0.00002 SOL for 400k CU)
tx.add(
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50_000 })
);

// 3. Add your swap instruction
tx.add(swapIx);

// Total additional cost: ~0.00002 SOL
// Should land within 1-2 slots during normal conditions

Complex Example: MEV-Protected Arbitrage Bundle

复杂示例:MEV防护型套利Bundle

Input: "Build an arb bot that uses Jito for MEV protection"
Output:
typescript
// See examples/jito-arb-bot.ts for full implementation
// Key components:

class JitoArbBot {
  private jitoClient: JitoClient;
  private minProfitLamports = 50_000; // 0.00005 SOL minimum

  async executeArb(
    buyIx: TransactionInstruction[],
    sellIx: TransactionInstruction[],
    expectedProfitLamports: number
  ): Promise<ArbResult> {
    // Don't execute if profit too low after tip
    const tip = this.calculateTip(expectedProfitLamports);
    const netProfit = expectedProfitLamports - tip;

    if (netProfit < this.minProfitLamports) {
      return { executed: false, reason: 'Profit below threshold after tip' };
    }

    // Build atomic bundle:
    // Tx 1: Buy
    // Tx 2: Sell
    // Tx 3: Tip (only executes if buy+sell succeed)
    const bundle = await this.buildArbBundle(buyIx, sellIx, tip);

    // Send with retry
    const result = await this.sendBundleWithRetry(bundle, tip);

    return {
      executed: result.success,
      signature: result.signature,
      expectedProfit: expectedProfitLamports,
      actualTip: tip,
      netProfit: netProfit,
    };
  }

  private calculateTip(profitLamports: number): number {
    // Dynamic tip: 5% of profit, min 10k lamports, max 1 SOL
    return Math.max(
      10_000,
      Math.min(1_000_000_000, Math.floor(profitLamports * 0.05))
    );
  }
}
输入:"构建一个使用Jito进行MEV防护的套利机器人"
输出:
typescript
// See examples/jito-arb-bot.ts for full implementation
// Key components:

class JitoArbBot {
  private jitoClient: JitoClient;
  private minProfitLamports = 50_000; // 0.00005 SOL minimum

  async executeArb(
    buyIx: TransactionInstruction[],
    sellIx: TransactionInstruction[],
    expectedProfitLamports: number
  ): Promise<ArbResult> {
    // Don't execute if profit too low after tip
    const tip = this.calculateTip(expectedProfitLamports);
    const netProfit = expectedProfitLamports - tip;

    if (netProfit < this.minProfitLamports) {
      return { executed: false, reason: 'Profit below threshold after tip' };
    }

    // Build atomic bundle:
    // Tx 1: Buy
    // Tx 2: Sell
    // Tx 3: Tip (only executes if buy+sell succeed)
    const bundle = await this.buildArbBundle(buyIx, sellIx, tip);

    // Send with retry
    const result = await this.sendBundleWithRetry(bundle, tip);

    return {
      executed: result.success,
      signature: result.signature,
      expectedProfit: expectedProfitLamports,
      actualTip: tip,
      netProfit: netProfit,
    };
  }

  private calculateTip(profitLamports: number): number {
    // Dynamic tip: 5% of profit, min 10k lamports, max 1 SOL
    return Math.max(
      10_000,
      Math.min(1_000_000_000, Math.floor(profitLamports * 0.05))
    );
  }
}