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 dari 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 memperlakukan raydium_cp_swap sebagai setara dengan raydium-cp-swap saat menyelesaikan dependensi git.
branch = "master" melacak sumber terbaru yang dipublikasikan; pin ke rev = "<commit>" spesifik 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 hanya ke permukaan CPI (struct akun + invoker) daripada program lengkap, sehingga binary Anda tetap kecil. anchor-lang / anchor-spl harus cocok dengan apa yang disematkan crate target, dan per 2026-09 dua crate Raydium publik tidak setuju:
Anda tidak dapat bergantung pada kedua crate dari satu program sekarang. Masing-masing menyematkan Anchor dengan =, jadi Cargo harus menautkan dua salinan Anchor yang tidak kompatibel ke satu binary, dan build gagal. Jika program Anda CPI ke dalam CPMM dan CLMM, Anda harus membaginya menjadi dua program, atau menghilangkan crate CPI yang diketik untuk salah satunya dan mengkodekan instruksi itu secara manual (pola yang ditunjukkan untuk AMM v4 berfungsi untuk program apa pun). Periksa kembali kedua file Cargo.toml sebelum memulai — ini diharapkan untuk diselesaikan ketika CLMM pindah ke Anchor 1.x.
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() dari anchor-client sekarang mengembalikan Vec<Instruction> daripada Result<Vec<Instruction>> (hilangkan ?), 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 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 diselesaikan.
Untuk contoh CPI yang berfungsi yang menghubungkan struct akun end-to-end, lihat raydium-io/raydium-cpi-example (mencakup AMM v4, CPMM, dan CLMM). Cabang terbarunya adalah anchor-0.31.0 — belum ada cabang 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 berjalan melalui CPMM end-to-end sebagai contoh yang dikerjakan: struct Accounts, CpiContext, cpi::<ix>(). CLMM mengikuti bentuk yang identik, dengan daftar akun yang 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 ditransfer secara langsung.

Konstruksi daftar akun

Setiap CPI Raydium memerlukan struct Accounts dalam program pemanggil. Field-nya adalah akun apa pun yang instruksi Anda butuhkan, dengan validator tingkat field; urutan deklarasi mereka tidak harus cocok dengan urutan akun instruksi Raydium sendiri, karena klien yang dihasilkan IDL Anda menangani mereka berdasarkan nama, bukan posisi:
Sebagian besar akun sisi Raydium adalah UncheckedAccount karena callee (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 pengecualian sisi Raydium adalah cpmm_program itu sendiri: ini adalah program yang dipanggil daripada akun data yang Raydium validasi secara internal, jadi diketik Program<T> dan mendapat pemeriksaan alamat otomatis Anchor daripada /// CHECK: manual. Bentuk sebagian besar UncheckedAccount ini, 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 field 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, dialias CpmmSwap di bawah). Tidak seperti struct MyProxySwap Anda di atas, nama field dan urutan ini diperbaiki oleh IDL raydium-cp-swap sendiri dan harus cocok dengan tepat:
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 meluas ke Farm v6 tidak 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 penanda 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 memeriksa tipe remaining accounts; teruskan melalui .with_remaining_accounts(...):
Urutan selalu penting, karena program penerima mengulangi remaining accounts dalam urutan Anda teruskan. Dua urutan yang dikonfirmasi:
  • CLMM SwapV2: tick arrays, diurutkan secara directional.
  • Farm v6: pasangan (reward_vault, user_reward_ata), tetapi hanya dari aliran reward kedua ke depan; lihat Farm v6 untuk apa yang ditunjukkan decoding transaksi nyata.

Menerapkan pola: CLMM

SwapV2 mengikuti pola umum di atas dengan daftar akun yang berbeda dan persyaratan remaining-accounts untuk tick arrays. Modul #[program] crate dinamai raydium_clmm, yang juga merupakan path Rust use-nya.
Struct akun CPI dinamai 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 lewatkan 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 IDL-dipublikasikan: raydium_launchpad/raydium_launchpad.json di repo raydium-idl publik. Identifier metadata internal IDL itu adalah raydium_launchpad, nama teknis untuk program yang mendasar, bukan nama alternatif untuk produk. Tidak seperti CPMM dan CLMM, bagaimanapun, sumber program itu sendiri tidak tersedia untuk publik (lihat reference/program-addresses). Tidak ada dependensi git = "..." untuk ditunjuk Cargo, dan tidak ada sumber untuk mengkonfirmasi apa path Rust use crate nyata. Hasilkan binding dari IDL yang dipublikasikan menggunakan makro declare_program! 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, tidak ada sumber program yang diperlukan. Nama struct akun yang dihasilkan selalu nama instruksi dalam PascalCase (buy_exact_in → BuyExactIn), dan nama field cocok dengan nama akun IDL dengan tepat, daftar akun yang sama sudah digunakan di MyProxyBuy di bawah. Bentuk CPI mengikuti pola umum. Daftar akun dan argumen di bawah berasal dari instruksi buy_exact_in IDL on-chain, bukan dari products/launchlab/instructions.mdx:
Pasca-kelulusan, program target adalah CPMM atau AMM v4 tergantung pada pool_state.migrate_type, yang products/launchlab/accounts.mdx katakan diatur pada waktu Initialize. Daftar akun CPI Anda harus disiapkan untuk salah satu, atau Anda perlu membaca migrate_type dari PoolState terlebih dahulu dan cabang.

Propagasi error

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

Compute budget dalam CPI yang dikomposisi

Setiap frame CPI memiliki overhead, dan konsumsi CU callee sendiri menumpuk di atas milik Anda, jadi transaksi yang memanggil Raydium dari dalam program Anda memerlukan compute budget eksplisit daripada mengandalkan default 200k CU.
Diukur, bukan diestimasi. swap_base_input CPMM di mainnet mengkonsumsi ~23.000 CU dalam program CPMM itu sendiri — sampel 2026-09-09 di delapan swap langsung di pool volume tinggi (22.721–23.052), dibaca dari baris log Program CPMMoo8… consumed N of M compute units. Untuk perbandingan: swap AMM v4 ~26.000; swap CLMM ~41.000; swap_v2 CLMM ~48.000 (43.838–52.887), naik dengan setiap tick crossing.Revisi sebelumnya dari halaman ini melaporkan ~47.700 CU untuk proxy-swap CPI. Angka itu adalah seluruh transaksi (computeUnitsConsumed), yang mencakup program pemanggil Anda sendiri, frame CPI dan setup ATA apa pun — bukan biaya callee. Keduanya berguna, tetapi mereka bukan angka yang sama, jadi bandingkan seperti dengan seperti. Ukur transaksi Anda sendiri daripada membudgetkan dari salah satu.
CPI CLMM dan LaunchLab lebih mahal (CLMM khususnya berjalan tick arrays tambahan melalui remaining_accounts, menambah CU per array), tetapi hanya angka CPMM di atas yang merupakan nilai terukur. Selalu atur batas ComputeBudgetProgram::set_compute_unit_limit(...) eksplisit yang diukur dari pengukuran Anda sendiri, bukan angka yang disalin dari dokumentasi, karena batas CU default 200k 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 doc ini yang tidak mengikuti pola umum di atas. Bangun Instruction dengan tangan:
Lihat products/amm-v4/code-demos untuk daftar akun lengkap.

Farm v6

Gunakan TS SDK jika itu pilihan untuk integrasi Anda. raydium.farm.deposit(...) (lihat products/farm-staking/code-demos) dijalankan 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 repo 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 dengan tangan, seperti di bawah.
Jika Anda memerlukan Rust CPI bagaimanapun, misalnya composing dari program on-chain lain, bangun Instruction dengan tangan, dengan cara yang sama seperti AMM v4: turunkan daftar akun nyata dan discriminator instruksi secara independen, misalnya dengan mendecode layout TypeScript SDK (raydium-sdk-V2’s farm module), mendecode 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 akun nyata adalah prefix tetap (token_program, akun state farm, PDA vault-authority, vault reward pertama PDA itu, PDA kedua, caller, dan ATA caller untuk mint reward pertama itu), diikuti oleh pasangan (reward_vault_i, user_reward_ata_i) dalam remaining_accounts untuk setiap aliran reward setelah yang pertama. Konvensi pairing adalah nyata, tetapi hanya dimulai pada aliran reward kedua: vault dan ATA aliran pertama adalah akun tetap, bukan berdekatan satu sama lain, dan bukan bagian dari remaining_accounts sama sekali.

Menguji alur CPI

Dev lokal memerlukan program Raydium tersedia di test validator Anda. Tiga opsi:
  1. anchor test dengan program clone. Menarik bytecode mainnet yang di-deploy ke validator lokal Anda; lihat Cloning programs into a local validator di bawah untuk konfigurasi Anchor.toml dan dua hal yang membuat test pembuatan pool gagal secara khusus.
  2. Devnet. Raydium men-deploy sebagian besar program ke devnet, tetapi di 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 dapat diandalkan dipublikasikan di devnet; API langsung (https://api-v3-devnet.raydium.io/main/info) memiliki gambaran saat ini. Jika Anda menggunakan konstanta DEVNET_PROGRAM_ID bundel raydium_clmm (atau setara untuk crate lain), jangan asumsikan ID mainnet juga berfungsi di devnet. Jalankan anchor test --provider.cluster devnet untuk mengenai kode langsung setelah Anda memiliki alamat yang tepat.
  3. Local deploy. Clone repo Raydium (CPMM, CLMM; sumber LaunchLab tidak tersedia untuk opsi ini) dan anchor deploy ke validator lokal. Menambah overhead siklus test tetapi memungkinkan Anda memodifikasi callee untuk debugging.
Jalankan dengan anchor test, atau anchor build terlebih dahulu dan anchor test --skip-build setelahnya jika Anda mengulangi file test tanpa mengubah program.

Cloning programs into a local validator

Ini berfungsi dengan program ID terlepas dari apakah sumber program publik, jadi LaunchLab clone dengan cara yang sama seperti CPMM dan CLMM meskipun sumbernya tidak tersedia. reference/program-addresses adalah sumber kebenaran untuk setiap alamat di sini.
Clone program tidak cukup jika test Anda juga membuat pool (daripada swap terhadap yang sudah ada). Instruksi initialize CPMM memvalidasi akun amm_config dan create_pool_fee-nya terhadap data on-chain nyata, jadi Anda perlu clone itu juga, atau initialize gagal sama sekali. Untuk CPMM khususnya: clone tier biaya AmmConfig 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 dengan alamat tepat, bukan dibuat on-the-fly, jadi harus sudah ada.
Pool yang baru dibuat test Anda tidak dapat ditukar dalam sekejap. initialize CPMM 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,” per SDK) meninggalkan celah nyata ≥1-detik sebelum pool menerima swap. Test yang membuat pool dan swap terhadapnya dengan penundaan nol akan mengenai NotApproved. await singkat (1–2s) antara pembuatan pool dan swap pertama sudah cukup. Ini spesifik untuk testing; manusia menjalankan dua perintah manual terpisah biasanya tidak akan memperhatikan, karena mengetik dan startup proses sudah makan lebih dari satu detik.

Pointer

Sumber: