跳转到主要内容

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

本页内容由 AI 自动翻译,所有内容以英文版本为准。查看英文版 →
每笔 Solana 交易都会设置(隐式或显式)两个参数:计算单元限额(交易可消耗的最大计算单元,默认为 200,000 × 交易中指令数,但受每笔交易上限)和优先费用,单位为微拉波(micro-lamports)每计算单元。这两个参数设置不足都会导致交易失败——计算单元限额过低会引发 ProgramFailedToComplete;优先费用过低则交易会一直未确认直到过期。

两项设置

import { ComputeBudgetProgram } from "@solana/web3.js";

const tx = new Transaction()
  .add(ComputeBudgetProgram.setComputeUnitLimit({ units: 250_000 }))
  .add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50_000 }))
  .add(yourRaydiumSwapIx);
  • setComputeUnitLimit(units) — 限制计算资源消耗;交易最多支付 units 个计算单元。
  • setComputeUnitPrice(microLamports) — 优先费用竞价,单位为微拉波每计算单元。总优先费用 = units × microLamports × 1e-6 拉波。
费用计算:250k 计算单元限额加上 50k 微拉波/计算单元的价格,优先费用为 250_000 × 50_000 / 1e6 = 12,500 拉波 ≈ 0.0000125 SOL ≈ $0.003(按 $200 SOL 价格)。在这个规模上,优先费用对于大多数用户交换是微不足道的,但对于每天执行 1000 笔交易的机器人来说则是显著成本。

每条指令的计算单元基准

基准数据来自主网执行日志,取多次运行的平均值。数字均为近似值(±15%);建议针对特定流程重新测量。
指令SPL TokenToken-2022(简单)Token-2022(转账费用)
CPMM initialize_pool180,000200,000
CPMM swap_base_input140,000180,000200,000
CPMM swap_base_output150,000185,000205,000
CPMM deposit130,000160,000180,000
CPMM withdraw120,000150,000170,000
CLMM create_pool70,00085,000
CLMM open_position_v2120,000140,000160,000
CLMM increase_liquidity_v2150,000175,000195,000
CLMM decrease_liquidity_v2140,000165,000185,000
CLMM swap_v2(0 个 tick 跨越)170,000205,000225,000
CLMM swap_v2(1 个 tick 跨越)220,000255,000275,000
CLMM swap_v2(3 个 tick 跨越)320,000355,000375,000
CLMM collect_fee80,00095,000105,000
AMM v4 swap_base_in140,000
AMM v4 deposit120,000
AMM v4 withdraw110,000
Farm v6 create_farm70,00085,000
Farm v6 deposit(1 个奖励槽)130,000155,000175,000
Farm v6 deposit(3 个奖励槽)220,000255,000275,000
Farm v6 withdraw与 deposit 相同
Farm v6 harvest与 deposit 相同
Farm v3/v5 deposit100,000
LaunchLab initialize100,000
LaunchLab buy_exact_in140,000
LaunchLab graduate250,000
CLMM 中”tick 跨越”行数是最大的计算单元变量。如果你不知道交换会跨越多少个 tick,应按最坏情况预算——8 个跨越是硬上限(程序最多加载 8 个 tick 数组)。

组合交易

将各个指令的预算相加,再加上:
  • 每个 CPI 帧 +1,500 计算单元 — 运行时对每次跨程序调用的固定开销。
  • 每次创建 ATA +20,000 计算单元create_associated_token_account 并非免费。
  • setComputeUnitLimit / setComputeUnitPrice 各 +5,000 计算单元
示例:一笔创建输出 ATA 并包裹原生 SOL 的用户交换:
wrap_sol(create_ata + system transfer + sync_native)   ≈ 30,000
CPMM swap_base_input(SPL)                              ≈ 140,000
close_account(unwrap)                                  ≈ 5,000
ComputeBudget 指令                                       ≈ 10,000
────────────────────────────────────────────────────────
总计                                                    ≈ 185,000 → 预算 250,000
缓冲:将计算单元限额设置在预期用量的约 25% 以上。低估成本会导致整个交易失败;高估则只会按比例增加优先费用成本(优先费用 = units × microLamports,所以高出 25% 的预算就多花费 25% 的优先费用)。

优先费用估算

Solana 的本地费用市场意味着优先费用是按可写账户计算的。写入热账户(热门池状态)的交易费用高于写入冷账户的交易。全局费用水平不是 Raydium 交换的正确指标;你需要的是涉及的特定池的费用。

策略 1:RPC 提供商估算器

每个主要 RPC 提供商都发布优先费用估算器,可查询特定账户的最近费用:
// Helius
const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${apiKey}`, {
  method: "POST",
  body: JSON.stringify({
    jsonrpc: "2.0",
    id:      "fee-estimate",
    method:  "getPriorityFeeEstimate",
    params: [{
      accountKeys: [poolStatePubkey.toBase58()],
      options:     { priorityLevel: "High" },
    }],
  }),
});
const { result } = await response.json();
const microLamports = result.priorityFeeEstimate;
大多数提供商的优先级划分:Min / Low / Medium / High / VeryHigh / UnsafeMax,映射到百分位数:
级别百分位数使用场景
Min第 25 百分位后台、非紧急的机器人流量
Low第 50 百分位普通用户交换
Medium第 60 百分位钱包界面的默认值
High第 75 百分位时间敏感的套利
VeryHigh第 95 百分位清算、最后时刻的退出
提供商:Helius(getPriorityFeeEstimate)、Triton(getRecentPrioritizationFees + 账户列表)、QuickNode(类似)。

策略 2:直接 RPC 查询

使用标准 getRecentPrioritizationFees RPC:
const fees = await connection.getRecentPrioritizationFees({
  lockedWritableAccounts: [poolStatePubkey],
});

// fees: Array<{ slot, prioritizationFee }>
// 最近 N 个 slot;默认约 150 个 slot。

const median = percentile(fees.map(f => f.prioritizationFee), 0.5);
这是原生 Solana RPC 方法,适用于任何提供商。缺点:样本量小(150 个 slot ≈ 60 秒)且噪声大。为获得更平滑的估算,使用提供商的聚合服务。

策略 3:历史自调优

对于保持恒定流量的机器人,跟踪自身的成功率与过期率:
每个池的目标:在 <30 秒内 80% 的成功率
如果 current_land_rate < 80%:priorityFee += 10%
如果 current_land_rate > 95%:priorityFee -= 5%
这种方式比公共估算器调整得更快,并捕捉公共估算器不一定能看到的按池结构。

处理计算单元耗尽失败

症状:交易失败,错误信息为 exceeded maximum number of instructions allowed (200000)ProgramFailedToComplete 诊断:
solana confirm <tx-sig> -v
# 查找"consumed N of M compute units"以及哪条指令耗尽了资源。
修复:
  1. 提升计算单元限额。 如果交易在 200k 预算中使用了 195k,提高到 300k。
  2. 分拆交易。 如果达到了 1.4M 的每笔交易上限,分成两笔交易。Farm 的「harvest 然后 stake」是经典的需要分拆的场景(当奖励较多时)。
  3. 精简账户。 每增加一个可写账户会增加约 2,000 计算单元。删除未使用的账户在边界情况下会有帮助。
  4. 使用查找表。 LUT 查找约 50 计算单元每解析地址,相比完整账户引用的 5,000 计算单元可节省成本。

处理卡住的交易

症状:交易已提交但从未确认,最终以 BlockhashNotFound 过期。 诊断:
  • getSignatureStatuses([sig]) 返回 null → 领导者从未看到。
  • 返回 { confirmationStatus: null } → 领导者看到但未纳入。
修复:
  1. 提升优先费用。 用 2 倍的当前费用重新提交。
  2. 用新的最近区块哈希重建。 区块哈希生命周期约 60 秒;超过这个时间交易不论费用多少都无效。
  3. 多 RPC 广播。 某些 RPC 与领导者的连接更好。并行提交到 3–5 个 RPC。
  4. 切换到 Jito 束。/zh/integration-guides/routing-and-mev。束绕过公共数据包队列。
重试逻辑框架:
async function submitWithRetry(buildTx, maxAttempts = 5) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const tx = await buildTx({
      priorityFee: basePriorityFee * Math.pow(1.5, attempt),
      blockhash:   (await connection.getLatestBlockhash()).blockhash,
    });

    try {
      const sig = await connection.sendRawTransaction(tx.serialize(), {
        skipPreflight: attempt > 0,  // 首次尝试后跳过以节省延迟
      });

      const result = await connection.confirmTransaction(sig, "confirmed");
      if (result.value.err) {
        // 逻辑错误;不要重试。
        throw result.value.err;
      }
      return sig;

    } catch (e) {
      if (isExpiredError(e)) continue;  // 重试
      if (isRevertError(e)) throw e;    // 不要重试;确定性失败
      throw e;
    }
  }
  throw new Error("submit: exhausted retries");
}

在网络拥堵下

当网络拥堵时(Jupiter / Jito 束仪表板显示积压、RPC 延迟飙升、交易过期率攀升),调整:
参数正常情况拥堵情况
计算单元限额预计用量的 +25%预计用量的 +25%(不变)
优先费用百分位数第 50 百分位第 75–95 百分位
重试次数35–7
重试退避500ms1000ms
使用 Jito 束可选强烈推荐
重试时刷新区块哈希是,必须
监视拥堵信号:
  • 优先费用第 75 百分位 > 500k 微拉波:拥堵。
  • Jito 第 50 百分位小费 > 0.001 SOL:拥堵。
  • RPC 响应 p99 > 2 秒:RPC 特定问题或拥堵。

机器人费用预算

每天运行约 1000 笔交易的交易机器人需要优先费用预算。粗略估计:
每笔交易平均计算单元:      ~250,000
第 50 百分位费用:          ~20,000 微拉波/计算单元
每笔交易成本:              250_000 × 20_000 × 1e-6 = 5_000 拉波 = 5e-6 SOL
日费用(1000 笔交易):      5e-3 SOL ≈ $1(按 \$200 SOL)
月费用:                    ~$30
这是最低限度。在拥堵期间,乘以 5–10 倍。对于稳定流量的机器人,计划约 $150–300/月 的优先费用成本。 必须在特定 slot 中落地的机器人(清算、套利)持续支付第 95 百分位费用,花费约 10 倍。在这个规模下,Jito 束小费占主导——通常 $1000+/月——但替代方案(被抢先或过期)更糟。

陷阱

1. 忘记设置计算单元限额

默认是 200k 计算单元 × (交易中的指令数)。单条指令交换默认 200k;这足以满足 SPL Token 的 CPMM,但不足以满足有 tick 跨越的 CLMM 或任何 Token-2022。务必显式设置。

2. 优先费用针对错误的账户

如果根据代币铸币厂估算优先费用,但热账户是池状态,估算就太低了。对于 Raydium,池状态是正确的可写账户目标。

3. 费用随计算单元限额缩放

total_priority_fee = units × microLamports。将 units 从 200k 提升到 1M(50k 微拉波/计算单元)会将优先费用乘以 5 倍。不要为了以防万一而过度预算计算单元;要测量。

4. 默认交易版本

Legacy 交易的账户限制较低;V0 交易配合地址查找表解锁更大的路由。SDK 默认在 txVersion: TxVersion.V0 中使用 V0。除非需要钱包兼容性,否则不要降低到 legacy。

5. skipPreflight 隐藏计算单元错误

skipPreflight: true 发送交易时不进行本地模拟。节省约 100 毫秒但失去了计算单元耗尽的早期反馈。仅在重试时使用,不要在首次尝试时使用。

参考资源

来源: