Trang này được dịch tự động bằng AI. Phiên bản tiếng Anh là bản chính thức.Xem bản tiếng Anh →
sdk-api/rust-cpi bao gồm các cơ chế cấp thấp để gọi từng chương trình Raydium. Trang này là người bạn đồng hành cấp cao hơn: tại sao bạn sẽ composition Raydium vào chương trình của riêng mình, mẫu nào phù hợp với trường hợp sử dụng của bạn, và toàn bộ glue bạn cần từ đầu đến cuối.Khi nào CPI là công cụ phù hợp
Một chương trình tùy chỉnh có ý nghĩa khi giao dịch cần xảy ra một cách nguyên tử với các thay đổi trạng thái on-chain khác mà chỉ chương trình của bạn mới có thể thực hiện. Các trường hợp phổ biến:- Escrow / limit-order programs — người dùng gửi một mint vào escrow của bạn, chương trình của bạn theo dõi điều kiện giá, và khi nó kích hoạt, chương trình của bạn swap một cách nguyên tử thông qua Raydium và ghi có tài khoản của người dùng.
- Aggregator proxies — một instruction duy nhất định tuyến swap thông qua Raydium + một hoặc nhiều DEX khác, với tất cả các hop dưới một kiểm tra slippage duy nhất do chương trình của bạn sở hữu.
- Auto-compounding vaults — gửi LP hoặc farm stake vào vault của bạn, vault thu hoạch rewards theo lịch trình, cung cấp lại liquidity, phát hành share tokens.
- Strategy vaults — các vị trí LP có đòn bẩy rebalance bằng cách swap thông qua CLMM; liquidators đóng vị trí và swap collateral trong một giao dịch.
- Token-launch platforms with custom vesting — chương trình của bạn giữ vesting tokens và phát hành vào pool Raydium theo lịch trình.
Các mẫu composition
Mẫu 1: Thin proxy
Chương trình của bạn expose một instruction duy nhất xác thực một số chính sách (ví dụ: whitelisted mint pairs, fee discount cho người dùng được xác minh) và sau đó chuyển tiếp đến Raydium.Mẫu 2: Escrow
Chương trình của bạn sở hữu một PDA giữ mint đầu vào của người dùng. Khi kích hoạt, PDA ký một CPI đến Raydium để swap số dư của chính nó.CpiContext::new_with_signer. Xem Signer seeds.
Mẫu 3: Composed multi-hop
Chương trình của bạn phát hành nhiều CPIs trong một instruction, thực thi một giới hạn slippage duy nhất trên tất cả chúng. Các instructions swap Raydium mỗi cái cóminimum_amount_out riêng của chúng, nhưng bạn đặt những cái đó thành 0 (hoặc một sàn rất lỏng lẻo) và thực thi một minimum cuối cùng nghiêm ngặt của riêng bạn sau hop cuối cùng.
Mẫu 4: Vault / strategy
Chương trình của bạn giữ LP tokens hoặc farm stake trong một PDA. Một keeper (hoặc người dùng) gọicompound(), cái mà:
- Thu hoạch rewards từ farm.
- Swap rewards cho pool tokens (CPI vào CPMM hoặc CLMM).
- Gửi lại các khoản tiền vào LP (một CPI khác).
- Stake LP mới (một CPI khác).
Xây dựng danh sách tài khoản
StructAccounts của chương trình gọi phản ánh thứ tự tài khoản của chương trình Raydium, nhưng hầu hết các tài khoản phía Raydium là UncheckedAccount vì Raydium xác thực chúng. Bạn chỉ thêm ràng buộc trên các tài khoản bạn sở hữu:
UncheckedAccount trên các tài khoản của Raydium — không phải là sự lười biếng. Người nhận xác thực của riêng họ; double-validating tại caller chỉ đốt CU và rủi ro đi ra khỏi đồng bộ khi Raydium gửi một trường layout struct mới.
Cuộc gọi CPI chính nó
PDA signer seeds
CPI chỉ thành công nếu PDA được truyền làmauthority khớp với derivation mà caller tuyên bố. Hai cái phải đồng ý về:
- Chuỗi byte seed (ở đây
[b"escrow", user.key().as_ref()]). - Bump.
- ID chương trình gọi (chương trình của bạn, không phải của Raydium).
authority của CPMM là vault PDA của riêng nó — một account cố định, dùng chung toàn chương trình, do CPMM tự dẫn xuất và tự ký, và chương trình của bạn không kiểm soát cũng không thay thế được. Account mà các seed PDA của bạn phải khớp với là payer: phép kiểm tra diễn ra bên trong hàm trợ giúp transfer_from_user_to_pool_vault của chính CPMM, hàm này yêu cầu account được truyền làm payer phải là chủ sở hữu của input_token_account.
Bug phổ biến: truyền user làm payer trong khi escrow_input_ata lại được sở hữu bởi escrow PDA. Chương trình SPL Token từ chối với owner mismatch. Luôn để payer chính là chủ sở hữu của ATA — và hãy ký cho nó bằng new_with_signer khi chủ sở hữu đó là một PDA.
Remaining accounts
Một số instructions Raydium lấy một danh sách tài khoản có độ dài thay đổi được thêm vào sau những cái cố định — remaining accounts.- CLMM
SwapV2: 1–8 tài khoảnTickArrayStatecho các tick arrays mà swap có thể traverse, theo hướng swap. - Farm v6
Deposit/Harvest/Withdraw: các cặp(reward_vault, user_reward_ata), một cặp cho mỗi live reward slot. - Token-2022 transfer-hook mints: chương trình transfer-hook cộng với bất kỳ tài khoản nào mà hook cần.
Compute budget cho composed calls
Một CPI chi phí ~1,500 CU cho call frame chính nó; sử dụng CU của callee xếp chồng lên trên. Các con số callee dưới đây được đo từ các giao dịch mainnet trực tiếp trên các pool có khối lượng lớn vào 2026-09-09, đọc từ dòng logProgram <id> consumed N of M compute units cho chính lần gọi chương trình Raydium (nên chúng đã bao gồm các CPI token-program bên trong):
Thêm ~1,500 cho mỗi CPI frame và overhead của chương trình của riêng bạn lên trên. Chi phí swap CLMM tỷ lệ theo số lần vượt tick, nên hãy coi con số của nó là mức sàn. Các mint Token-2022 làm tăng thêm chi phí xử lý extension của chính lệnh chuyển; hãy tự đo cho các mint của bạn thay vì áp một hệ số nhân cố định.
Luôn đặt một
ComputeBudgetProgram::set_compute_unit_limit rõ ràng:
Error propagation
Các chương trình Raydium trả về Anchor errors với mã lỗi ổn định. Chương trình gọi của bạn thấy chúng làErr(ProgramError::Custom(code)). Bubble through theo mặc định:
ERROR_CODE_OFFSET: các biến thể #[error_code] được phát ra bắt đầu từ 6000, nên việc so sánh với discriminant enum thuần túy sẽ không bao giờ khớp. (Không có trình trợ giúp is_err nào trong anchor-lang hay trong raydium_cp_swap — các bản sửa đổi trước đây của trang này đã dùng một trình trợ giúp không tồn tại.)
Ánh xạ mã lỗi-to-meaning là ổn định theo chính sách IDL (sdk-api/anchor-idl); các mã mới append ở cuối, các mã hiện tại không bao giờ thay đổi ý nghĩa.
Ví dụ đầy đủ được thực hiện: limit-order escrow
Flow:open_order— người dùng gửiamount_incủainput_mintvào escrow PDA; ghi lại targetmin_amount_outvà expiry.execute_order— bất kỳ ai (keeper) gọi với các tài khoản pool hiện tại. Chương trình kiểm tra quote hiện tại ≥min_amount_out, sau đó CPIs Raydium swap và giữ output trong escrow.claim— người dùng rút output mint từ escrow.
order ký CPI với vai trò payer, vì nó sở hữu ATA đầu vào của escrow; do đó ExecuteOrder cũng cần một trường pool_authority: UncheckedAccount<'info> cho vault PDA của riêng CPMM. Cả kiểm tra slippage phía Raydium và kiểm tra delta của escrow đều thực thi mức sàn — belt and braces.
Testing
Kéo các chương trình Raydium vào một local validator cho integration tests (từAnchor.toml):
anchor test tìm nạp chúng từ mainnet khi khởi động. Xem sdk-api/rust-cpi.
Pitfalls cụ thể cho composition
Reentrancy
Solana không có true reentrancy — một CPI không thể gọi lại vào chương trình gốc trong cùng một invocation. Nhưng bạn vẫn có thể xây dựng bản thân vào một logical reentrancy: một CPI đọc trạng thái của bạn, sau đó mã của bạn đọc lại nó giả định CPI không thay đổi nó. Đối với Raydium, các CPIs không chạm vào trạng thái của bạn, vì vậy đây là ít quan tâm hơn ví dụ như flash-loan contexts. Nhưng nếu bạn composition Raydium với một giao thức cho vay, hãy nhận thức được.Account mutability drift
Nếu chương trình của bạn truyền một tài khoản làmut nhưng Raydium mong đợi nó read-only (hoặc ngược lại), runtime từ chối invocation với InvalidAccountData. Luôn kiểm tra mutability mong đợi của instruction Raydium trong IDL; raydium_cp_swap::cpi::accounts::Swap đặt mutability cho từng account thay bạn, dựa trên các dấu #[account(mut)] trên struct Swap của chính CPMM — các trường được sinh ra đều là AccountInfo<'info> thuần, nên chính impl ToAccountMetas được dẫn xuất mới mang các cờ đó, không phải kiểu của trường.
Token-2022 program field
Input và output mints có thể dưới các chương trình token khác nhau — một SPL Token, một Token-2022. CPI có các trườnginput_token_program và output_token_program riêng biệt vì lý do này. Luôn kiểm tra trường owner của mỗi mint và định tuyến chương trình chính xác vào mỗi slot.
Versioned transactions
Một composed tx làm 2+ Raydium CPIs cộng với một ATA creation hiếm khi vừa trong một legacy (v0-without-LUT) transaction. Sử dụng V0 với address lookup tables; kéo LUTs công khai của Raydium thông quaraydium.getRaydiumLutAddresses().
Pointers
sdk-api/rust-cpi— cơ chế CPI cấp thấp.integration-guides/priority-fee-tuning— sizing compute budget.products/cpmm/code-demos,products/clmm/code-demos,products/farm-staking/code-demos— CPI snippets cho mỗi sản phẩm.

