Skip to main content
Halaman ini diterjemahkan secara otomatis oleh AI. Versi bahasa Inggris adalah acuan resmi.Lihat versi bahasa Inggris →
CPI (“cross-program invocation”) adalah mekanisme yang memungkinkan satu program Solana memanggil program lain. Sebagian besar program Raydium dilengkapi dengan crate wrapper CPI Anchor yang membuat call site terlihat seperti pemanggilan fungsi yang diketik, dengan struct akun yang memiliki nama field yang divalidasi dan helper cpi::<ix>(). Halaman ini mendokumentasikan pola umum sekali, kemudian perbedaan per-program. Untuk TypeScript yang dapat dijalankan, lihat halaman code-demos di setiap bab produk.

Pola mana yang berlaku untuk program mana

Jika Anda mengintegrasikan CPMM, CLMM, atau LaunchLab, baca pola umum terlebih dahulu, kemudian lompat ke bagian program Anda untuk daftar akun dan perbedaan apa pun. Farm v6 dan AMM v4 cukup berbeda sehingga layak membaca bagian mereka secara mandiri.

Dependensi Cargo

Kunci dependensi harus cocok dengan [package] name repo target dengan tepat, termasuk tanda hubung. Cargo tidak menganggap raydium_cp_swap setara dengan raydium-cp-swap saat menyelesaikan dependensi git.
branch = "master" melacak sumber terbaru yang dipublikasikan; tetapkan ke rev = "<commit>" tertentu jika Anda memerlukan build yang dapat direproduksi. Ini direkomendasikan setelah Anda melampaui prototyping, karena perubahan tata letak akun upstream di master akan memecahkan build Anda tanpa peringatan sebelumnya. Flag fitur cpi membuat crate dikompilasi ke hanya permukaan CPI (struct akun + invoker) daripada program lengkap, sehingga binary Anda tetap kecil. anchor-lang / anchor-spl harus cocok dengan apa yang ditetapkan crate target:
Ambil kedua crate dari baris Anchor yang sama. Kedua branch master menetapkan =1.0.2, jadi satu program dapat CPI ke CPMM dan CLMM dari satu crate. Mencampur baris memecahkan build: misalnya, raydium-cp-swap di master dengan raydium-clmm ditetapkan ke rev dari sebelum upgrade Anchor 1.0-nya. Cargo harus menautkan dua salinan trait Anchor yang tidak kompatibel ke dalam satu binary. Jika Anda terjebak pada pasangan campuran, pisahkan program menjadi dua, atau lepaskan crate CPI yang diketik untuk satu sisi dan encode manual instruksi itu (pola yang ditunjukkan untuk AMM v4 bekerja untuk program apa pun).
Anchor 1.0 mengubah dua hal yang setiap call site CPI sentuh. Jika Anda memindahkan integrasi yang berfungsi dari 0.3x:
  • CpiContext::new mengambil Pubkey, bukan AccountInfo. CpiContext::new(ctx.accounts.cpmm_program.to_account_info(), accts) menjadi CpiContext::new(*ctx.accounts.cpmm_program.key, accts). Sama untuk new_with_signer. Field struct sekarang program_id: Pubkey.
  • Context memiliki satu lifetime, bukan empat. Context<'_, '_, 'info, 'info, MyProxySwap<'info>> menjadi Context<'info, MyProxySwap<'info>>.
Di sisi klien, RequestBuilder::instructions() milik anchor-client sekarang mengembalikan Vec<Instruction> daripada Result<Vec<Instruction>> (lepaskan ?), dan CommitmentConfig pindah dari solana-sdk — ambil dari anchor_client sebagai gantinya. spl-associated-token-account 8.0 me-re-export helper-nya dari crate spl-associated-token-account-interface yang baru. get_associated_token_address dan ID masih dapat dijangkau di root crate (spl_associated_token_account::{get_associated_token_address, ID}), tetapi helper alamat sudah usang di sana — lebih suka bergantung pada spl-associated-token-account-interface secara langsung dan mengimpor spl_associated_token_account_interface::address::get_associated_token_address dan spl_associated_token_account_interface::program::ID. Perhatikan ::address dan ::program adalah modul dari crate interface; spl_associated_token_account::address::… tidak terselesaikan.
Untuk contoh CPI yang berfungsi yang menghubungkan struct akun end-to-end, lihat raydium-io/raydium-cpi-example (mencakup AMM v4, CPMM, dan CLMM). Branch terbarunya adalah anchor-0.31.0 — belum ada branch Anchor 1.x, jadi perlakukan repo itu sebagai referensi untuk wiring struct akun, bukan untuk pin versi yang halaman ini wajibkan.

Pola CPI Anchor umum

Bagian ini menjelaskan CPMM dari awal hingga akhir sebagai contoh kerja: struct Accounts, CpiContext, cpi::<ix>(). CLMM mengikuti bentuk yang identik, dengan daftar akun berbeda dan persyaratan remaining-accounts. LaunchLab mengikuti mekanika yang sama tetapi daftar akunnya membawa beberapa akun tanpa padanan CPMM/CLMM (global_config, platform_config, event_authority, program), jadi perlakukan sebagai pola yang sama, bukan bentuk yang sama. Lihat bagian masing-masing program daripada mengasumsikan daftar akun walkthrough ini berlaku langsung.

Konstruksi daftar akun

Setiap CPI Raydium memerlukan struct Accounts dalam program pemanggil. Bidangnya adalah akun apa pun yang Anda butuhkan untuk instruksi Anda, dengan validator tingkat bidang; urutan deklarasi mereka tidak harus cocok dengan urutan akun instruksi Raydium sendiri, karena klien yang dihasilkan IDL Anda menanganinya berdasarkan nama, bukan posisi:
Sebagian besar akun sisi Raydium adalah UncheckedAccount karena penerima (Raydium) memiliki validasi. Program pemanggil Anda hanya benar-benar memvalidasi akun yang Anda miliki, seperti ATA pengguna dan PDA Anda sendiri. Komentar doc /// CHECK: menekan peringatan Anchor tentang pemeriksaan yang hilang. Satu-satunya pengecualian sisi Raydium adalah cpmm_program itu sendiri: ini adalah program yang dipanggil daripada akun data yang divalidasi Raydium secara internal, jadi diketik Program<T> dan mendapat pemeriksaan alamat otomatis Anchor daripada /// CHECK: manual. Bentuk ini—sebagian besar UncheckedAccount, di mana Raydium memvalidasi akunnya sendiri—sama untuk CLMM dan LaunchLab. Contoh ini mengasumsikan kedua mint adalah Token SPL klasik; jika salah satu sisi dapat berupa mint Token-2022, tambahkan bidang token_program_2022: Program<'info, anchor_spl::token_2022::Token2022> dan teruskan sebagai input_token_program/output_token_program sisi itu dalam panggilan CPI di bawah daripada token_program.

Membangun panggilan CPI

Anchor menghasilkan satu helper per instruksi, bersama dengan struct akun CPI (cpi::accounts::Swap, dialiaskan CpmmSwap di bawah). Tidak seperti struct MyProxySwap Anda di atas, nama dan urutan bidang ini ditetapkan oleh IDL raydium-cp-swap sendiri dan harus cocok persis:
cpi::swap_base_input dihasilkan dari IDL; daftar argumennya mencerminkan daftar argumen instruksi Anchor. Setiap program Raydium berbasis Anchor yang dikonfirmasi (CPMM, CLMM, LaunchLab) menghasilkan helper cpi::<ix>() dengan cara yang sama, dengan nama fungsi cocok dengan nama instruksi dalam snake_case. Apakah ini berlaku untuk Farm v6 belum dikonfirmasi; lihat bagiannya.

Signer seeds (CPI yang ditandatangani PDA)

Ketika program Anda menandatangani CPI atas nama PDA (umum untuk vault, escrow, dll.), gunakan CpiContext::new_with_signer:
Signer seeds harus cocok dengan derivasi PDA. Untuk akun apa pun yang dilewatkan sebagai authority (atau peran signer serupa), runtime Solana memeriksa bahwa PDA menandatangani melalui seed ini.

Remaining accounts

Beberapa instruksi Raydium mengambil remaining accounts, daftar panjang variabel yang ditambahkan setelah akun tetap. Helper CPI Anchor tidak melakukan type-check remaining accounts; teruskan melalui .with_remaining_accounts(...):
Urutan selalu penting, karena program penerima mengulangi remaining accounts dalam urutan yang Anda teruskan. Dua urutan yang dikonfirmasi:
  • CLMM SwapV2: tick arrays, diurutkan secara direktif.
  • Farm v6: pasangan (reward_vault, user_reward_ata), tetapi hanya dari aliran reward kedua ke depan; lihat Farm v6 untuk apa yang ditunjukkan dekoding transaksi nyata.

Menerapkan pola: CLMM

SwapV2 mengikuti pola umum di atas dengan daftar akun berbeda dan persyaratan remaining-accounts untuk tick arrays. Modul #[program] crate bernama raydium_clmm, yang juga merupakan jalur use Rust-nya.
Struct akun CPI bernama SwapSingleV2, bukan SwapV2. SwapV2 adalah nama instruksi on-chain.
Hitung daftar tick-array dengan cara yang sama seperti SDK, melalui quote terhadap state pool saat ini, daripada menebak jumlah tetap; swap yang melampaui array yang Anda teruskan akan kembali dengan TickArrayNotFound (lihat products/clmm/instructions untuk tabel akun lengkap dan daftar error). Teruskan dalam arah price walk: array pertama dalam arah swap terlebih dahulu.

Menerapkan pola: LaunchLab

LaunchLab berbasis Anchor dan menerbitkan IDL: raydium_launchpad/raydium_launchpad.json di repo publik raydium-idl. Pengenal metadata internal IDL tersebut adalah raydium_launchpad, nama teknis untuk program yang mendasarinya, bukan nama alternatif untuk produk. Tidak seperti CPMM dan CLMM, kode sumber program itu sendiri tidak tersedia untuk publik (lihat reference/program-addresses). Tidak ada dependensi git = "..." untuk menunjuk Cargo, dan tidak ada sumber untuk mengonfirmasi apa yang sebenarnya menjadi path use Rust dalam crate. Hasilkan binding dari IDL yang dipublikasikan menggunakan macro declare_program! milik Anchor. Simpan JSON IDL sebagai idls/raydium_launchpad.json di crate Anda (Cargo mencari direktori idls/ relatif terhadap CARGO_MANIFEST_DIR), kemudian declare_program!(raydium_launchpad); menghasilkan struct raydium_launchpad::cpi::accounts::<Ix> dan fungsi cpi::<ix>() langsung dari IDL, tanpa memerlukan sumber program. Nama struct accounts yang dihasilkan selalu nama instruksi dalam PascalCase (buy_exact_in → BuyExactIn), dan nama field cocok dengan nama account di IDL secara persis, daftar account yang sama yang sudah digunakan di MyProxyBuy di bawah. Bentuk CPI mengikuti pola umum. Daftar account dan argumen di bawah berasal dari instruksi buy_exact_in IDL on-chain, bukan dari products/launchlab/instructions.mdx:
Setelah lulus, program target adalah CPMM atau AMM v4 tergantung pada pool_state.migrate_type, yang menurut products/launchlab/accounts.mdx diatur pada waktu Initialize. Daftar account CPI Anda harus disiapkan untuk keduanya, atau Anda perlu membaca migrate_type dari PoolState terlebih dahulu dan membuat cabang.

Propagasi error

Setiap program Raydium berbasis Anchor mengembalikan enum error-nya sendiri; Anchor membungkusnya, sehingga program pemanggil Anda melihatnya sebagai Err(ProgramError::Custom(code)). Untuk menangani error spesifik:
Tukarkan dengan tipe error yang relevan untuk program yang Anda panggil (raydium_clmm::error::ErrorCode untuk CLMM, dan seterusnya). Nomor kode error stabil sesuai kebijakan IDL (sdk-api/anchor-idl), sehingga Anda dapat menguji kode spesifik dengan membandingkan nilai numerik. Tabel error lengkap: CPMM, CLMM, AMM v4, Farm v6, dan LaunchLab.

Compute budget dalam CPI yang disusun

Setiap frame CPI memiliki overhead, dan konsumsi CU callee sendiri bertumpuk di atas milik Anda, jadi transaksi yang memanggil Raydium dari dalam program Anda memerlukan compute budget eksplisit daripada mengandalkan default 200k CU.
Diukur, bukan diperkirakan. CPMM swap_base_input di mainnet mengonsumsi ~23.000 CU dalam program CPMM itu sendiri — sampel 2026-09-09 di delapan swap langsung pada pool volume tinggi (22.721–23.052), dibaca dari baris log Program CPMMoo8… consumed N of M compute units. Untuk perbandingan: AMM v4 swap ~26.000; CLMM swap ~41.000; CLMM swap_v2 ~48.000 (43.838–52.887), meningkat dengan setiap tick crossing.Revisi sebelumnya dari halaman ini melaporkan ~47.700 CU untuk proxy-swap CPI. Angka tersebut adalah seluruh transaksi (computeUnitsConsumed), yang mencakup program pemanggil sendiri, frame CPI dan setup ATA apa pun — bukan biaya callee. Keduanya berguna, tetapi mereka bukan angka yang sama, jadi bandingkan yang sejenis. Ukur transaksi Anda sendiri daripada memperkirakan dari salah satu.
CLMM dan LaunchLab CPI lebih mahal (CLMM khususnya berjalan melalui tick array tambahan via remaining_accounts, menambah CU per array), tetapi hanya angka CPMM di atas yang merupakan nilai terukur. Selalu atur instruksi ComputeBudgetProgram::set_compute_unit_limit(...) eksplisit yang diukur dari pengukuran Anda sendiri, bukan angka yang disalin dari dokumentasi, karena batas default 200k CU akan diam-diam habis dan biaya per-instruksi bergeser saat program diupgrade.

AMM v4: konstruksi Instruction manual

AMM v4 mendahului Anchor dan tidak memiliki crate CPI, menjadikannya satu-satunya program dalam dokumen ini yang tidak mengikuti pola umum di atas. Bangun Instruction secara manual:
Lihat products/amm-v4/code-demos untuk daftar account lengkap.

Farm v6

Gunakan TS SDK jika itu pilihan untuk integrasi Anda. raydium.farm.deposit(...) (lihat products/farm-staking/code-demos) dilatih oleh demo nyata dan tidak bergantung pada apakah crate Anchor ada untuk program ini.
Farm v6 tidak menawarkan path CPI Anchor. Tidak ada crate raydium_farm_v6 di crates.io, tidak ada repository sumber publik, dan tidak ada IDL on-chain — program tidak memiliki akun anchor:idl legacy maupun entri dalam Program Metadata program (lihat sdk-api/anchor-idl). Perlakukan sebagai program non-Anchor dan bangun instruksinya secara manual, seperti di bawah.
Jika Anda tetap memerlukan Rust CPI, misalnya menyusun dari program on-chain lain, bangun Instruction secara manual, dengan cara yang sama seperti AMM v4: turunkan daftar account nyata dan discriminator instruksi secara independen, misalnya dengan mendekode layout TypeScript SDK (raydium-sdk-V2’s farm module), mendekode transaksi nyata secara langsung (lihat di bawah), atau dump dan disassemble program yang di-deploy. Untuk bentuk instruksi zero-argument yang konsisten dengan harvest atau claim call, urutan account nyata adalah prefix tetap (token_program, akun state farm, PDA vault-authority, vault reward pertama PDA tersebut, PDA kedua, pemanggil, dan ATA pemanggil untuk mint reward pertama), diikuti oleh pasangan (reward_vault_i, user_reward_ata_i) di remaining_accounts untuk setiap reward stream setelah yang pertama. Konvensi pairing itu nyata, tetapi hanya dimulai pada reward stream kedua: vault dan ATA stream pertama adalah account tetap, bukan berdekatan satu sama lain, dan bukan bagian dari remaining_accounts sama sekali.

Menguji alur CPI

Pengembangan lokal memerlukan program Raydium tersedia di validator pengujian Anda. Tiga pilihan:
  1. anchor test dengan program clone. Menarik bytecode mainnet yang sudah di-deploy ke validator lokal Anda; lihat Cloning programs into a local validator di bawah untuk konfigurasi Anchor.toml dan dua hal yang sering menyebabkan masalah pada tes pembuatan pool.
  2. Devnet. Raydium men-deploy sebagian besar program ke devnet, tetapi dengan program ID yang berbeda dari mainnet untuk setiap program (CPMM, CLMM, AMM v4, Stable AMM, dan LaunchLab masing-masing memiliki alamat devnet yang berbeda; lihat tabel Devnet di reference/program-addresses). Farm v3/v5/v6 tidak secara konsisten dipublikasikan di devnet; API langsung (https://api-v3-devnet.raydium.io/main/info) menunjukkan gambaran terkini. Jika Anda menggunakan konstanta DEVNET_PROGRAM_ID bawaan raydium_clmm (atau yang setara untuk crate lain), jangan asumsikan ID mainnet juga berfungsi di devnet. Jalankan anchor test --provider.cluster devnet untuk menjalankan kode langsung setelah Anda memiliki alamat yang benar.
  3. Local deploy. Clone repo Raydium (CPMM, CLMM; sumber LaunchLab tidak tersedia untuk opsi ini) dan anchor deploy ke validator lokal. Menambah overhead siklus pengujian tetapi memungkinkan Anda memodifikasi callee untuk debugging.
Jalankan dengan anchor test, atau anchor build terlebih dahulu dan anchor test --skip-build setelahnya jika Anda melakukan iterasi pada file pengujian tanpa mengubah program.

Cloning programs into a local validator

Ini berfungsi berdasarkan program ID terlepas dari apakah sumber program bersifat publik, jadi LaunchLab melakukan clone dengan cara yang sama seperti CPMM dan CLMM meskipun sumbernya tidak tersedia. reference/program-addresses adalah sumber kebenaran untuk setiap alamat di sini.
Melakukan clone program tidak cukup jika tes Anda juga membuat pool (bukan hanya melakukan swap terhadap pool yang sudah ada). Instruksi initialize CPMM memvalidasi akun amm_config dan create_pool_fee terhadap data on-chain yang sebenarnya, jadi Anda perlu melakukan clone untuk keduanya juga, atau initialize akan gagal total. Untuk CPMM khususnya: clone AmmConfig tier biaya yang Anda inginkan (ambil alamatnya dari GET https://api-v3.raydium.io/main/cpmm-config, indeks 0 adalah tier 0,25%) dan akun token penerima biaya, divalidasi berdasarkan alamat yang tepat, bukan dibuat dengan cepat, jadi harus sudah ada.
Pool yang baru saja dibuat tes Anda tidak dapat ditukar dalam sekejap. initialize CPMM secara diam-diam menimpa open_time yang diminta yang tidak ketat di masa depan (if open_time <= block_timestamp { open_time = block_timestamp + 1 }), jadi bahkan startTime: 0 (“buka segera,” menurut SDK) meninggalkan celah nyata ≥1 detik sebelum pool menerima swap. Tes yang membuat pool dan melakukan swap terhadapnya tanpa penundaan akan mengalami NotApproved. Penundaan singkat await (1–2 detik) antara pembuatan pool dan swap pertama sudah cukup. Ini khusus untuk pengujian; manusia yang menjalankan dua perintah manual terpisah biasanya tidak akan memperhatikan, karena pengetikan dan startup proses sudah memakan lebih dari satu detik.

Penunjuk

Sumber: