本页内容由 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 固定的版本匹配:
有关端到端连接账户结构的工作 CPI 示例,请参见
raydium-io/raydium-cpi-example(涵盖 AMM v4、CPMM 和 CLMM)。其最新分支是 anchor-0.31.0——还没有 Anchor 1.x 分支,所以将该仓库视为账户结构连接的参考,而不是本页规定的版本固定。
通用 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 时(对于 vault、escrow 等很常见),使用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_launchpad/raydium_launchpad.json,位于公开的 raydium-idl 仓库中。该 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 账户列表必须为两者都做好准备,或者你需要先从 PoolState 读取 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
swap_base_input 在 CPMM 程序本身消耗约 23,000 CU——2026-09-09 在高交易量池上采样了八次实时交易(22,721–23,052),从 Program CPMMoo8… consumed N of M compute units 日志行读取。作为对比:AMM v4 交换约 26,000;CLMM swap 约 41,000;CLMM swap_v2 约 48,000(43,838–52,887),随着每次 tick 穿越而增加。本页的早期版本报告了代理交换 CPI 约 47,700 CU。该数字是整个交易(computeUnitsConsumed),包括调用方自身的程序、CPI 帧和任何 ATA 设置——而非被调用方的成本。两者都有用,但它们不是同一个数字,所以要进行类似的比较。根据你自己的测量来衡量你的交易,而不是根据文档中复制的数字进行预算,因为默认的 200k CU 限制会无声地耗尽,而且随着程序升级,每条指令的成本会变化。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 的状态账户、vault 权限 PDA、该 PDA 的第一个奖励 vault、第二个 PDA、调用方和调用方的该第一个奖励 mint 的 ATA),然后是 remaining_accounts 中的 (reward_vault_i, user_reward_ata_i) 对,用于第一个之后的每个奖励流。配对约定是真实的,但它仅从第二个奖励流开始:第一个流的 vault 和 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 仓库(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 文档

