Cette page est traduite automatiquement par IA. La version anglaise fait foi.Voir la version anglaise →
sdk-api/rust-cpi couvre la mécanique bas niveau de l’invocation de chaque programme Raydium. Cette page est la contrepartie haut niveau : pourquoi vous composeriez Raydium dans votre propre programme, quel modèle convient à votre cas d’usage, et tout le code de liaison dont vous avez besoin de bout en bout.
Quand CPI est le bon outil
Un programme personnalisé a du sens quand l’échange doit se produire de manière atomique avec d’autres changements d’état on-chain que seul votre programme peut effectuer. Cas courants :- Programmes de séquestre / ordres limités — l’utilisateur dépose un mint dans votre séquestre, votre programme surveille une condition de prix, et quand elle se déclenche, votre programme échange atomiquement via Raydium et crédite le compte de l’utilisateur.
- Proxies agrégateurs — une seule instruction qui achemine un swap via Raydium + un ou plusieurs autres DEX, avec tous les sauts sous une seule vérification de slippage détenue par votre programme.
- Coffres auto-composés — déposez des tokens LP ou des enjeux de ferme dans votre coffre, le coffre récolte les récompenses selon un calendrier, réapprovisionne la liquidité, émet des tokens de part.
- Coffres de stratégie — positions LP à effet de levier qui se rééquilibrent en swappant via CLMM ; liquidateurs qui ferment les positions et swappent les garanties en une seule transaction.
- Plateformes de lancement de tokens avec acquisition personnalisée — votre programme détient les tokens d’acquisition et les libère dans un pool Raydium selon un calendrier.
Modèles de composition
Modèle 1 : Proxy mince
Votre programme expose une seule instruction qui valide une certaine politique (par exemple, paires de mints autorisées, réduction de frais pour les utilisateurs vérifiés) puis transfère à Raydium.Modèle 2 : Séquestre
Votre programme possède un PDA qui détient le mint d’entrée de l’utilisateur. Au déclenchement, le PDA signe un CPI vers Raydium pour swapper son propre solde.CpiContext::new_with_signer. Voir Graines de signataire.
Modèle 3 : Multi-hop composé
Votre programme émet plusieurs CPI en une seule instruction, en appliquant une seule limite de slippage sur tous. Les instructions de swap Raydium ont chacune leur propreminimum_amount_out, mais vous les définissez à 0 (ou un plancher très lâche) et appliquez un minimum strict final vous-même après le dernier hop.
Modèle 4 : Coffre / stratégie
Votre programme détient des tokens LP ou des enjeux de ferme dans un PDA. Un gardien (ou l’utilisateur) appellecompound(), qui :
- Récolte les récompenses de la ferme.
- Échange les récompenses pour les tokens du pool (CPI dans CPMM ou CLMM).
- Redépose les produits dans le LP (un autre CPI).
- Enjeu du nouveau LP (un autre CPI).
Construction de la liste des comptes
La structAccounts du programme appelant reflète l’ordre des comptes du programme Raydium, mais la plupart des comptes côté Raydium sont UncheckedAccount car Raydium les valide lui-même. Vous n’ajoutez des contraintes que sur les comptes que vous possédez :
UncheckedAccount sur ceux de Raydium — n’est pas de la paresse. Le destinataire valide les siens ; double-valider à l’appelant brûle juste du CU et risque de se désynchroniser quand Raydium expédie un nouveau champ de disposition de struct.
L’appel CPI lui-même
Graines de signataire PDA
Le CPI ne réussit que si le PDA passé commeauthority correspond à la dérivation que l’appelant prétend. Les deux doivent s’accorder sur :
- La séquence d’octets de graine (ici
[b"escrow", user.key().as_ref()]). - Le bump.
- L’ID du programme appelant (votre programme, pas celui de Raydium).
authority de CPMM est son propre PDA de coffre — un compte fixe à l’échelle du programme qu’il dérive et signe avec lui-même, et que votre programme ne contrôle ni ne substitue. Le compte avec lequel vos graines PDA doivent s’aligner est payer : la vérification se produit à l’intérieur du helper transfer_from_user_to_pool_vault de CPMM lui-même, qui exige que le compte passé comme payer soit le propriétaire de input_token_account.
Bug courant : passer user comme payer tandis que escrow_input_ata est détenue par le PDA du séquestre. Le programme SPL Token rejette avec owner mismatch. Faites toujours de payer le propriétaire de l’ATA — et signez-le avec new_with_signer quand ce propriétaire est un PDA.
Comptes restants
Plusieurs instructions Raydium prennent une liste de longueur variable de comptes ajoutés après les comptes fixes — comptes restants.- CLMM
SwapV2: 1–8 comptesTickArrayStatepour les tableaux de ticks que le swap peut traverser, dans la direction du swap. - Farm v6
Deposit/Harvest/Withdraw: paires(reward_vault, user_reward_ata), une paire par emplacement de récompense actif. - Mints de crochet de transfert Token-2022 : le programme de crochet de transfert plus tous les comptes dont le crochet a besoin.
Budget de calcul pour les appels composés
Un CPI coûte ~1 500 CU pour le cadre d’appel lui-même ; l’utilisation propre du CU de l’appelé s’empile par-dessus. Les chiffres de l’appelé ci-dessous sont mesurés à partir de transactions mainnet en direct sur des pools à haut volume le 2026-09-09, lus à partir de la ligne de journalProgram <id> consumed N of M compute units pour la propre invocation du programme Raydium (ils incluent donc ses CPI de programme de token internes) :
Ajoutez ~1 500 pour chaque cadre CPI et la surcharge de votre propre programme par-dessus. Le coût du swap CLMM s’échelonne avec les traversées de ticks, donc traitez son chiffre comme un plancher. Les mints Token-2022 ajoutent le coût de gestion des extensions du transfert lui-même ; mesurez-le pour vos propres mints plutôt que d’appliquer un multiplicateur plat.
Définissez toujours une limite explicite
ComputeBudgetProgram::set_compute_unit_limit :
Propagation des erreurs
Les programmes Raydium retournent des erreurs Anchor avec des codes d’erreur stables. Votre programme appelant les voit commeErr(ProgramError::Custom(code)). Propagez par défaut :
ERROR_CODE_OFFSET : les variantes #[error_code] sont émises à partir de 6000, donc comparer contre le discriminant d’énumération nu ne correspond jamais. (Il n’y a pas de helper is_err dans anchor-lang ou dans raydium_cp_swap — les révisions antérieures de cette page en utilisaient un qui n’existe pas.)
Le mappage code d’erreur-à-signification est stable selon la politique IDL (sdk-api/anchor-idl) ; les nouveaux codes s’ajoutent à la fin, les codes existants ne changent jamais de signification.
Exemple complet travaillé : séquestre d’ordre limité
Flux :open_order— l’utilisateur déposeamount_indeinput_mintdans le PDA du séquestre ; enregistre lemin_amount_outcible et l’expiration.execute_order— n’importe qui (gardien) appelle avec les comptes du pool actuels. Le programme vérifie que le devis actuel ≥min_amount_out, puis CPI le swap Raydium et garde la sortie en séquestre.claim— l’utilisateur retire le mint de sortie du séquestre.
order signe le CPI comme payer, car il possède l’ATA d’entrée du séquestre ; ExecuteOrder a donc aussi besoin d’un champ pool_authority: UncheckedAccount<'info> pour le propre PDA de coffre de CPMM. La vérification de slippage côté Raydium et la vérification de delta du séquestre appliquent le plancher — ceinture et bretelles.
Test
Tirer les programmes Raydium dans un validateur local pour les tests d’intégration (depuisAnchor.toml) :
anchor test les récupère depuis mainnet au démarrage. Voir sdk-api/rust-cpi.
Pièges spécifiques à la composition
Réentrance
Solana n’a pas de vraie réentrance — un CPI ne peut pas rappeler le programme d’origine dans la même invocation. Mais vous pouvez toujours vous construire dans une réentrance logique : un CPI qui lit votre état, puis votre code le relit en supposant que le CPI ne l’a pas changé. Pour Raydium, les CPI ne touchent pas votre état, donc c’est moins une préoccupation que par exemple les contextes de prêt flash. Mais si vous composez Raydium avec un protocole de prêt, soyez conscient.Dérive de mutabilité des comptes
Si votre programme passe un compte commemut mais que Raydium s’attend à ce qu’il soit en lecture seule (ou vice versa), le runtime rejette l’invocation avec InvalidAccountData. Vérifiez toujours la mutabilité attendue de l’instruction de Raydium dans l’IDL ; raydium_cp_swap::cpi::accounts::Swap définit la mutabilité de chaque compte pour vous, à partir des marqueurs #[account(mut)] sur la propre struct Swap de CPMM — les champs dérivés sont tous des AccountInfo<'info> simples, donc c’est l’impl ToAccountMetas dérivé, pas les types de champs, qui porte les drapeaux.
Champ du programme Token-2022
Les mints d’entrée et de sortie peuvent être sous différents programmes de token — un SPL Token, un Token-2022. Le CPI a des champsinput_token_program et output_token_program séparés pour cette raison. Vérifiez toujours le champ owner de chaque mint et routez le programme correct dans chaque emplacement.
Transactions versionnées
Une tx composée qui fait 2+ CPI Raydium plus une création d’ATA rentre rarement dans une transaction héritée (v0-sans-LUT). Utilisez V0 avec des tables de recherche d’adresses ; tirez les LUT publiques de Raydium viaraydium.getRaydiumLutAddresses().
Pointeurs
sdk-api/rust-cpi— mécanique CPI bas niveau.integration-guides/priority-fee-tuning— dimensionnement du budget de calcul.products/cpmm/code-demos,products/clmm/code-demos,products/farm-staking/code-demos— extraits CPI par produit.

