本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
CPI(「跨程式呼叫」)是一個 Solana 程式呼叫另一個程式的機制。Raydium 的大多數程式都附帶 Anchor CPI 包裝 crate,使呼叫位置看起來像一個型別化的函式呼叫,具有經過驗證的欄位名稱的帳戶結構和
cpi::<ix>() 輔助程式。本頁面記錄了一般模式一次,然後是各程式的差異。如需可執行的 TypeScript,請參閱每個產品章節的 code-demos 頁面。哪個模式適用於哪個程式
如果你正在整合 CPMM、CLMM 或 LaunchLab,請先閱讀一般模式,然後跳到你的程式章節以了解帳戶列表和任何差異。Farm v6 和 AMM v4 的差異足夠大,值得獨立閱讀它們的章節。
Cargo 依賴項
branch = "master" 追蹤最新發佈的源代碼;如果你需要可重現的構建,請固定到特定的 rev = "<commit>"。一旦你超過原型設計階段,這是推薦的做法,因為上游在 master 上的帳戶佈局變更將在沒有警告的情況下破壞你的構建。
cpi 功能標誌使 crate 編譯為僅 CPI 表面(帳戶結構 + 呼叫程式),而不是完整程式,因此你的二進位檔案保持較小。
anchor-lang / anchor-spl 必須與目標 crate 固定的版本相符,截至 2026-09,兩個公開 Raydium crate 不一致:
如需連接帳戶結構端到端的可執行 CPI 範例,請參閱
raydium-io/raydium-cpi-example(涵蓋 AMM v4、CPMM 和 CLMM)。
一般 Anchor CPI 模式
本章節以 CPMM 作為實作範例端到端進行:Accounts 結構、CpiContext、cpi::<ix>()。CLMM 遵循相同的形狀,具有不同的帳戶列表和剩餘帳戶要求。LaunchLab 遵循相同的機制,但其帳戶列表包含 CPMM/CLMM 沒有的幾個帳戶(global_config、platform_config、event_authority、program),因此將其視為相同的模式,而不是相同的形狀。參見每個程式自己的章節,而不是假設本演練的帳戶列表直接轉移。
帳戶列表構建
每個 Raydium CPI 都需要在呼叫程式中有一個Accounts 結構。其欄位是你的指令需要的任何帳戶,具有欄位級驗證器;它們的聲明順序不必與 Raydium 自己的指令帳戶順序相符,因為你自己的 IDL 生成的客戶端按名稱而不是位置尋址它們:
UncheckedAccount,因為被呼叫方(Raydium)擁有驗證。你的呼叫程式只嚴格驗證你擁有的帳戶,例如使用者 ATA 和你自己的 PDA。/// CHECK: 文件註解會抑制 Anchor 關於缺少檢查的警告。一個 Raydium 端例外是 cpmm_program 本身:它是被呼叫的程式,而不是 Raydium 內部驗證的資料帳戶,因此它被型別化為 Program<T> 並獲得 Anchor 的自動地址檢查,而不是手動 /// CHECK:。這種大多是 UncheckedAccount 的形狀,其中 Raydium 驗證自己的帳戶,對 CLMM 和 LaunchLab 也是相同的。此範例假設兩個 mint 都是經典 SPL Token;如果任一方可以是 Token-2022 mint,請新增 token_program_2022: Program<'info, anchor_spl::token_2022::Token2022> 欄位,並在下面的 CPI 呼叫中將其作為該方的 input_token_program/output_token_program 傳遞,而不是 token_program。
構建 CPI 呼叫
Anchor 為每個指令生成一個輔助程式,以及一個 CPI 帳戶結構(cpi::accounts::Swap,下面別名為 CpmmSwap)。與上面你自己的 MyProxySwap 結構不同,這個的欄位名稱和順序由 raydium-cp-swap 自己的 IDL 固定,必須完全相符:
cpi::swap_base_input 是從 IDL 生成的;其引數列表鏡像 Anchor 指令的引數列表。每個確認的基於 Anchor 的 Raydium 程式(CPMM、CLMM、LaunchLab)以相同的方式生成其 cpi::<ix>() 輔助程式,函式名稱與蛇形大小寫的指令名稱相符。這是否擴展到 Farm v6 未確認;參見其章節。
簽署者種子(PDA 簽署的 CPI)
當你的程式代表 PDA 簽署 CPI 時(對於保管庫、託管等很常見),使用CpiContext::new_with_signer:
authority(或類似簽署者角色)傳遞的任何帳戶,Solana 執行時檢查 PDA 是否透過這些種子簽署。
剩餘帳戶
某些 Raydium 指令採用剩餘帳戶,一個附加在固定帳戶之後的可變長度列表。Anchor 的 CPI 輔助程式不對剩餘帳戶進行型別檢查;透過.with_remaining_accounts(...) 傳遞它們:
- CLMM
SwapV2:tick 陣列,按方向順序。 - Farm v6:
(reward_vault, user_reward_ata)對,但僅從第二個獎勵流開始;參見 Farm v6 以了解解碼真實交易顯示的內容。
應用模式:CLMM
SwapV2 遵循一般模式,具有不同的帳戶列表和 tick 陣列的剩餘帳戶要求。crate 的 #[program] 模組名為 raydium_clmm,這也是其 Rust use 路徑。
TickArrayNotFound 回復(參見 products/clmm/instructions 以了解完整帳戶表和錯誤列表)。按價格遊走方向傳遞它們:交換方向的第一個陣列優先。
應用模式:LaunchLab
LaunchLab 基於 Anchor 且 IDL 已發佈:公開raydium-idl repo 中的 raydium_launchpad/raydium_launchpad.json。該 IDL 的內部元資料識別碼是 raydium_launchpad,是底層程式的技術名稱,而不是產品的替代名稱。不過,與 CPMM 和 CLMM 不同,程式自己的源代碼不公開(參見 reference/program-addresses)。沒有 git = "..." 依賴項可指向 Cargo,也沒有源代碼來確認真實 crate 的 Rust use 路徑會是什麼。
使用 Anchor 的 declare_program! 巨集從已發佈的 IDL 生成綁定。將 IDL JSON 儲存為 crate 中的 idls/raydium_launchpad.json(Cargo 在 CARGO_MANIFEST_DIR 相對位置查找 idls/ 目錄),然後 declare_program!(raydium_launchpad); 直接從 IDL 生成 raydium_launchpad::cpi::accounts::<Ix> 結構和 cpi::<ix>() 函式,無需程式源代碼。生成的帳戶結構名稱始終是 PascalCase 中的指令名稱(buy_exact_in → BuyExactIn),欄位名稱與 IDL 的帳戶名稱完全相符,與下面 MyProxyBuy 中已使用的相同帳戶列表。
CPI 形狀遵循一般模式。下面的帳戶列表和引數來自鏈上 IDL 的 buy_exact_in 指令,而不是 products/launchlab/instructions.mdx:
pool_state.migrate_type,products/launchlab/accounts.mdx 說在 Initialize 時設定。你的 CPI 帳戶列表必須為任一方做好準備,或者你需要先讀取 pool_state 中的 migrate_type 並分支。
錯誤傳播
每個基於 Anchor 的 Raydium 程式都返回自己的錯誤列舉;Anchor 包裝它們,因此你的呼叫程式將它們視為Err(ProgramError::Custom(code))。要處理特定錯誤:
raydium_clmm::error::ErrorCode,等等)。錯誤代碼編號根據 IDL 政策穩定(sdk-api/anchor-idl),因此你可以透過與數值進行比較來測試特定代碼。完整錯誤表:CPMM、CLMM、AMM v4、Farm v6 和 LaunchLab。
組合 CPI 中的計算預算
每個 CPI 框架都有開銷,被呼叫方自己的 CU 消耗堆疊在你的之上,因此從你的程式內部呼叫 Raydium 的交易需要明確的計算預算,而不是依賴 200k CU 預設值。單一測量資料點,不是基準。 CPMM 交換 CPI 的常見經驗法則估計(大約 1,500 CU CPI 開銷 + 150,000 CU 用於交換本身 + 10,000 CU 用於觀察更新,總計約 161,500 CU)高估了實際使用量。真實交換 CPI(
my_proxy_swap 呼叫 swap_base_input、SPL token mint、新建立的雙 token 池)消耗了約 47,700 CU 總計,從 connection.getTransaction(...).meta.computeUnitsConsumed 讀取,大約是該估計的三分之一。將此視為來自一個池形狀和一個 mint 配置的一個資料點,而不是規格。測量你自己的交易,而不是根據任一數字進行預算。remaining_accounts 遊走額外的 tick 陣列,每個陣列增加 CU),但只有上面的 CPMM 數字是測量值。始終設定明確的 ComputeBudgetProgram::set_compute_unit_limit(...) 指令,大小來自你自己的測量,而不是從文件複製的數字,因為預設 200k CU 限制會無聲地耗盡,每指令成本隨著程式升級而變化。
AMM v4:手動指令構建
AMM v4 早於 Anchor,沒有 CPI crate,使其成為本文件中唯一不遵循上面一般模式的程式。手動構建Instruction:
products/amm-v4/code-demos 以了解完整帳戶列表。
Farm v6
如果這是你整合的選項,請使用 TS SDK。raydium.farm.deposit(...) (參見 products/farm-staking/code-demos)由真實演示執行,不依賴於此程式是否存在 Rust Anchor crate。
如果你無論如何都需要 Rust CPI,例如從另一個鏈上程式組合,手動構建 Instruction,與 AMM v4 相同的方式:獨立推導真實帳戶列表和指令判別器,例如透過解碼 SDK 的 TypeScript 佈局(raydium-sdk-V2 的 farm 模組)、直接解碼真實交易(參見下面)或轉儲和反組譯已部署的程式。
對於與收穫或聲稱呼叫一致的零引數指令形狀,真實帳戶順序是固定前綴(token_program、farm 的狀態帳戶、保管庫授權 PDA、該 PDA 的第一個獎勵保管庫、第二個 PDA、呼叫者和呼叫者的該第一個獎勵 mint 的 ATA),然後是 remaining_accounts 中每個第一個之後的獎勵流的 (reward_vault_i, user_reward_ata_i) 對。配對約定是真實的,但它僅從第二個獎勵流開始:第一個流的保管庫和 ATA 是固定帳戶,彼此不相鄰,根本不是 remaining_accounts 的一部分。
測試 CPI 流
本地開發需要 Raydium 程式在你的測試驗證器中可用。三個選項:anchor test與程式複製。 將已部署的主網位元組碼拉入你的本地驗證器;參見下面的將程式複製到本地驗證器以了解Anchor.toml配置和兩件特別會絆倒池建立測試的事情。- Devnet。 Raydium 將大多數程式部署到 devnet,但在不同的程式 ID 上,與主網不同,每個程式(CPMM、CLMM、AMM v4、Stable AMM 和 LaunchLab 各有不同的 devnet 地址;參見
reference/program-addresses中的 Devnet 表)。Farm v3/v5/v6 在 devnet 上不可靠發佈;實時 API(https://api-v3-devnet.raydium.io/main/info)有當前圖景。如果你使用raydium_clmm的捆綁DEVNET_PROGRAM_ID常數(或其他 crate 的等效項),不要假設主網 ID 也適用於 devnet。執行anchor test --provider.cluster devnet以在你有正確地址後命中實時代碼。 - 本地部署。 複製 Raydium repo(CPMM、CLMM;LaunchLab 的源代碼對此選項不可用)並
anchor deploy到本地驗證器。增加測試週期開銷,但讓你修改被呼叫方以進行除錯。
anchor test,或如果你在迭代測試檔案而不改變程式,先 anchor build 然後 anchor test --skip-build。
將程式複製到本地驗證器
reference/program-addresses 是此處每個地址的真實來源。
指標
products/cpmm/code-demos、products/clmm/code-demos、products/amm-v4/code-demos、products/farm-staking/code-demos、products/launchlab/code-demos:產品特定的 CPI 和 TypeScript 範例。sdk-api/anchor-idl:IDL 檢索和客戶端重新生成,包括 LaunchLab 的 IDL 代碼生成路徑。integration-guides/cpi-integration:更高級的整合模式,如託管、保管庫和聚合器組合。
- raydium-cp-swap
- raydium-clmm
- raydium-idl:LaunchLab IDL(程式源代碼本身已關閉)
- Anchor CPI 文件

