跳轉到主要內容

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 交易是以原子方式執行的指令列表。了解交易結構——指令、帳戶、簽署者、計算預算——是使用 Raydium 進行任何開發、除錯或最佳化的前提條件。本頁涵蓋了交易結構、限制條件,以及兩個手續費類別(Solana 網路手續費、Raydium 協議手續費)如何在實際交換中堆疊。

交易解剖

Solana 交易有三個核心元件:
  • 訊息:指令的有序列表、它們參考的帳戶,以及最近的區塊雜湊。
  • 簽名:每個簽署者一個,認證交易獲得授權。
  • 最近的區塊雜湊:證明交易是最近的;具有陳舊區塊雜湊(>150 個槽位舊)的交易會被拒絕。

指令

一個指令指定:
  • program_id — 要呼叫的程式。
  • accounts — 程式可能觸及的帳戶(及其可寫入/簽署者旗標)。
  • data — 程式解釋的不透明位元組。
單一交易可包含多個指令。它們按順序執行;如果任何指令失敗,所有先前的指令都會被回滾(原子性)。 典型的 Raydium 交換交易包括:
  1. ComputeBudget::SetComputeUnitLimit — 提高預設 CU 限額。
  2. ComputeBudget::SetComputeUnitPrice — 設定優先費用。
  3. 可選的 CreateAssociatedTokenAccount — 如果使用者沒有輸出 ATA,建立它。
  4. Raydium::SwapBaseInput — 執行交換。
  5. 可選的 CloseAccount — 關閉 wrapped SOL ATA。
SDK 透過 raydium.trade.swap() 自動打包這些指令。

交易中的帳戶

交易中任何指令觸及的每個帳戶都必須列在交易的帳戶鑰匙中。每個帳戶都有旗標:
  • 簽署者 / 非簽署者:帳戶的擁有者必須簽署交易嗎?
  • 可寫入 / 唯讀:交易可以修改帳戶嗎?
執行時強制執行這些旗標:程式嘗試寫入不可寫入帳戶會失敗,執行時會拒絕缺少必需簽署者的交易。 對於 CPMM 交換,帳戶列表有約 13 個條目(參閱 solana-fundamentals/account-model)。具有多個刻度陣列交叉的 CLMM 交換可能有 20+。

交易大小限制

Solana 將交易上限設為 1232 位元組,包括簽名、訊息和標頭。這是複雜交易最常見的障礙——Raydium 的 CLMM 與多路由路由經常推著這個限制。 典型 ~1000 位元組 Raydium 交換的分解:
元件大小
簽名64 B
簽名計數1 B
訊息標頭3 B
區塊雜湊32 B
帳戶鑰匙 (13 × 32 B)416 B
指令 (4 × ~100-150 B)400–600 B
總計~900–1100 B

位址查閱表 (ALT)

ALT 讓交易透過已發佈表中的 1 位元組索引參考帳戶,而不是完整的 32 位元組公鑰。這大幅壓縮交易:
  • 直接參考 20 個帳戶的交易:~640 B 的公鑰。
  • 同一筆交易使用 ALT:~20 B 的索引 + ALT 參考。
Raydium 在主網上為 CPMM/CLMM 交換路徑維護 ALT。SDK 自動使用它們。構建多路由的聚合商大量依賴它們。
import { VersionedTransaction } from "@solana/web3.js";

// SDK builds a v0 (versioned) tx with ALT references
const { transaction } = await raydium.trade.swap({ /* ... */ });
// transaction is a VersionedTransaction, not a legacy Transaction.

計算預算

每筆交易都有一個計算單位 (CU) 預算。超過預算會終止執行並使交易失敗。
  • 預設值:每筆交易 200,000 CU。
  • 最大值:每筆交易 1,400,000 CU(透過 ComputeBudget::SetComputeUnitLimit 提高)。
  • 每區塊上限:每區塊 48M CU(協議層級)。
典型 Raydium CU 消耗(完整表格參閱 integration-guides/priority-fee-tuning):
指令CU
CPMM 交換~140,000
CLMM 交換(無刻度交叉)~170,000
CLMM 交換(4 次刻度交叉)~320,000
Farm v6 質押~130,000
CPMM 池建立~250,000
總是透過 ComputeBudget 設定明確的 CU 限額;否則你會得到 200k 預設值,對大多數 Raydium 指令來說太低了。
import { ComputeBudgetProgram } from "@solana/web3.js";

tx.add(
  ComputeBudgetProgram.setComputeUnitLimit({ units: 300_000 }),
);
如果你設定的 CU 限額太低,交易在達到上限時會失敗;設定過高你會冒著在壅塞下被降級優先度的風險(根據定價模式,你可能為從未使用的計算付費)。

優先費用

除了基礎交易費用(每個簽名 5000 lamports),驗證者越來越多地優先處理支付優先費用的交易:每 CU 的微 lamport 小費。
priority_fee = compute_unit_price (micro-lamports) × compute_unit_limit
例子:10,000 µL/CU × 300,000 CU = 3,000,000 µL = 0.003 SOL。 優先費用是本地的——它們只影響區塊內的排序;它們不會改善你被納入而非不被納入的機會。在壅塞期間設定合理的優先費用至關重要。
tx.add(
  ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 10_000 }),
);
參閱 integration-guides/priority-fee-tuning 了解如何動態調整這一點。

指令計數與帳戶計數限制

除了 1232 位元組的總限制之外:
  • 每筆交易的最大帳戶數:128。
  • 每個指令的最大帳戶數 (CPI):64。
  • 每筆交易的最大指令數:無硬性限制,僅受大小限制限制。
  • 最大 CPI 深度:4(一個程式可以呼叫另一個程式,它可以呼叫另一個程式,4 層深)。
交叉多個刻度陣列的 Raydium CLMM 交換可能會嚴重推著帳戶限制——單次交換觸及池、輸入/輸出金庫、輸入/輸出 ATA、多個刻度陣列、可能是傳輸鉤子程式的額外帳戶,加上強制計算預算 / 系統 / token 程式參考。透過 CPI 組成 Raydium 的設計(例如自動複合器)需要考慮到這一點。

Raydium 交換中的手續費類別

使用者交換交易在兩個類別中支付手續費:

Solana 網路手續費

支付給驗證者的 SOL。
  • 基礎簽名費:每個簽名 5000 lamports。幾乎總是 1 個簽名 = 0.000005 SOL。
  • 優先費用:CU 價格 × CU 限額(以微 lamport 計)。隨壅塞變化;參閱 integration-guides/priority-fee-tuning
這些費用進入驗證者,與 Raydium 無關,甚至對失敗的交易也會收取(除了某些優先費用邊界情況)。

Raydium 協議手續費

從交換金額中扣除。
  • 交換費:輸入的百分比(CPMM 典型 0.25%,CLMM 0.01%–1% 每層)。分割給流動性提供者和協議目標地址。參閱 ray/protocol-fees
這些費用是 Raydium 帳務內部的——使用者看到的是比零費用池產生的輸出量更小的金額。

範例:$1000 USDC → SOL 透過 CPMM 0.25% 層

手續費類別金額流向
基礎簽名費0.000005 SOL (~$0.0007)驗證者
優先費用 (10k µL × 300k CU)0.003 SOL (~$0.45)驗證者
CPMM 交換費 (0.25%)$2.50LP + 協議
使用者總成本~$2.95
滑點(價格影響 + 市場波動)不是手續費,但會影響相同的最終結果。

版本化交易

Solana 有兩種交易格式:
  • 遺留:原始格式,不支援 ALT。
  • v0 (版本化):支援 ALT,可擴展至未來版本。
所有現代 Solana 工具都使用 v0。Raydium SDK 預設發出 v0 交易。
// Building a v0 tx directly
import { VersionedTransaction, TransactionMessage } from "@solana/web3.js";

const msg = new TransactionMessage({
  payerKey:        owner.publicKey,
  recentBlockhash: blockhash,
  instructions:    [ /* ... */ ],
}).compileToV0Message([lookupTableAccount]);

const tx = new VersionedTransaction(msg);
tx.sign([owner]);

區塊雜湊新鮮度

交易必須包含來自最後約 150 個槽位(約 60 秒)內的區塊雜湊。超出該視窗,驗證者會拒絕它。 對於重試迴圈,在每次重試時取得新的區塊雜湊:
async function sendWithRetry(tx, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
    tx.message.recentBlockhash = blockhash;
    tx.sign([owner]);
    try {
      return await connection.sendRawTransaction(tx.serialize());
    } catch (e) {
      if (i === maxRetries - 1) throw e;
    }
  }
}
參閱 integration-guides/priority-fee-tuning 了解完整的逐步升級費用重試模式。

平行執行

Solana 在多核驗證者上平行執行不衝突的交易。兩筆交易衝突當且僅當它們都寫同一個帳戶。 對 Raydium 的影響:
  • 同一池上的兩筆交換無法平行執行——兩者都寫池狀態。
  • 池 A 上的交換和池 B 上的交換在帳戶列表不重疊時平行執行。
  • 唯讀交易從不阻止同一帳戶的寫入者(唯讀與自己併發,但與寫入不併發)。
這就是為什麼 Solana 儘管有單池序列化,仍能維持高 DEX 吞吐量。

交易確認層級

提交交易時,你選擇一個確認層級:
層級等待最終性
processed~400 ms未最終確認;可能回滾
confirmed~1 s超級多數投票
finalized~13 s超級多數根源化
對於交換 UX,confirmed 是標準。對於處理大價值的操作(池建立、獎勵補充),finalized 更安全。
await connection.sendAndConfirmTransaction(tx, [owner], {
  commitment: "confirmed",
});

模擬

Solana 支援在提交前模擬交易:
const sim = await connection.simulateTransaction(tx);
console.log(sim.value.logs);
console.log(sim.value.unitsConsumed);
Raydium SDK 在計算 getBestSwapInfo 時內部使用模擬來驗證選定的路由確實成功。模擬並非免費的——它消耗 RPC 容量——但它在支付前捕捉錯誤。

指標

來源: