本页内容由 AI 自动翻译,所有内容以英文版本为准。查看英文版 →
CPI(“跨程序调用”)是一个 Solana 程序调用另一个程序的机制。Raydium 的 Anchor 程序提供 CPI 包装 crate,使调用点看起来像一个类型化函数调用 — 带有经过验证的字段名称的账户结构体和
cpi::<ix>() 助手。本页记录了通用模式;特定产品的代码片段请参见各产品章节的代码演示页面。Cargo 依赖
cpi 功能标志使 crate 编译为仅 CPI 表面层(账户结构体 + 调用器),而不是完整程序,因此你的二进制文件保持精小。
如需端到端完整连接账户结构体的工作 CPI 示例,请查看 raydium-io/raydium-cpi-example(涵盖 AMM v4、CPMM 和 CLMM)。
账户列表构造
每个 Raydium CPI 都需要在调用程序中使用Accounts 结构体。字段与程序的指令账户顺序一一对应,包含字段级验证器:
UncheckedAccount,因为被调用方(Raydium)负责验证。你的调用程序只需严格验证你拥有的账户 — 用户 ATA、你自己的 PDA。/// CHECK: 文档注释会抑制 Anchor 关于缺少检查的警告。
构建 CPI 调用
Anchor 为每条指令生成一个助手:cpi::swap_base_input 由 IDL 生成;其参数列表镜像 Anchor 指令的参数列表。
签名者种子(PDA 签名的 CPI)
当你的程序代表 PDA 签署 CPI 时(对于保险库、托管等很常见),使用CpiContext::new_with_signer:
authority(或类似签名者角色)传递的任何账户,Solana 运行时会检查 PDA 是否通过这些种子签署。
剩余账户
某些 Raydium 指令接受剩余账户 — 在固定账户之后附加的可变长度列表。规范示例:- CLMM
SwapV2:附加 1–8 个TickArrayState账户,对应于交换可能遍历的 tick 数组。 - Farm v6
Deposit:对每个活跃奖励流附加(reward_vault, user_reward_ata)对。
.with_remaining_accounts(...) 传递它们:
错误传播
Raydium 的程序返回自己的错误枚举。Anchor 包装它们;你的调用程序将它们视为Err(ProgramError::Custom(code))。要处理特定错误:
sdk-api/anchor-idl)。你可以通过与数值进行比较来测试特定代码。
组合 CPI 中的计算预算
每个 CPI 帧都有开销(~1,500 CU 用于调用本身),被调用者的自身 CU 消耗堆积在你的消耗之上。从你的程序内部调用 CPMM 交换的事务消耗:ComputeBudgetProgram::set_compute_unit_limit(...) 指令 — 默认 200k CU 限制会悄然耗尽。
AMM v4 — 手动指令构造
AMM v4 没有 Anchor crate。手动构建Instruction:
products/amm-v4/code-demos。
Farm v6 — 奖励对剩余账户
Farm v6 的Deposit / Withdraw / Harvest 在剩余账户中使用 (reward_vault_i, user_reward_ata_i) 对模式。确切顺序:
farm_state.reward_infos[i].reward_state 分派。
测试 CPI 流
本地开发需要 Raydium 程序在你的测试验证器中可用。选项:-
anchor testwith program clone — 在Anchor.toml中:这会将已部署的字节码从主网拉入你的本地验证器。 -
Devnet — Raydium 将所有程序部署到 devnet,使用与主网相同的程序 ID。运行
anchor test --provider.cluster devnet以使用实时代码。 -
本地部署 — 克隆 Raydium 仓库并
anchor deploy到本地验证器。增加了测试周期开销,但让你可以修改被调用方以进行调试。
参考资源
products/cpmm/code-demos、products/clmm/code-demos、products/amm-v4/code-demos、products/farm-staking/code-demos— 特定产品的 CPI 示例。sdk-api/anchor-idl— IDL 检索和客户端重新生成。integration-guides/cpi-integration— 更高级的模式:托管、保险库、聚合器组合。

