Skip to main content
Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.Englische Version ansehen →
sdk-api/rust-cpi behandelt die Low-Level-Mechanik des Aufrufs jedes Raydium-Programms. Diese Seite ist der höherwertige Begleiter: warum Sie Raydium in Ihr eigenes Programm integrieren würden, welches Muster zu Ihrem Anwendungsfall passt, und die vollständige Verbindung, die Sie end-to-end benötigen.

Wann CPI das richtige Werkzeug ist

Ein benutzerdefiniertes Programm macht Sinn, wenn der Trade atomar mit anderen On-Chain-Zustandsänderungen erfolgen muss, die nur Ihr Programm vornehmen kann. Häufige Fälle:
  • Escrow- / Limit-Order-Programme — der Benutzer hinterlegt einen Token in Ihrem Escrow, Ihr Programm überwacht eine Preisbedingung, und wenn diese ausgelöst wird, tauscht Ihr Programm atomar über Raydium und schreibt das Ergebnis auf das Benutzerkonto.
  • Aggregator-Proxies — eine einzelne Anweisung, die einen Swap über Raydium + ein oder mehrere andere DEXes leitet, wobei alle Hops unter einer einzigen Slippage-Prüfung stehen, die Ihr Programm besitzt.
  • Auto-Compounding-Vaults — hinterlegen Sie LP oder Farm-Stake in Ihrem Vault, der Vault erntet Rewards nach einem Zeitplan, versorgt die Liquidität erneut und gibt Share-Token aus.
  • Strategy-Vaults — gehebelte LP-Positionen, die sich durch Swaps über CLMM neu ausbalancieren; Liquidatoren, die Positionen schließen und Sicherheiten in einer Transaktion tauschen.
  • Token-Launch-Plattformen mit benutzerdefiniertem Vesting — Ihr Programm hält Vesting-Token und gibt sie nach einem Zeitplan in einen Raydium-Pool frei.
Wenn Sie nur einen Swap von Off-Chain-Code aus senden möchten, ist CPI Overkill — verwenden Sie das SDK. CPI rechtfertigt seine Komplexität nur, wenn Atomarität mit Ihrem eigenen Zustand erforderlich ist.

Kompositionsmuster

Muster 1: Dünner Proxy

Ihr Programm stellt eine einzelne Anweisung bereit, die eine Richtlinie validiert (z. B. Whitelist-Tokenpaare, Gebührenrabatt für verifizierte Benutzer) und leitet dann an Raydium weiter.
Der Zustand lebt in den ATAs des Benutzers. Ihr Programm besitzt keine Token. Minimaler Vertrauens-Fußabdruck.

Muster 2: Escrow

Ihr Programm besitzt einen PDA, der den Input-Token des Benutzers hält. Bei Auslösung signiert der PDA einen CPI zu Raydium, um seinen eigenen Saldo zu tauschen.
Kritisches Detail: Der PDA signiert über CpiContext::new_with_signer. Siehe Signer-Seeds.

Muster 3: Zusammengesetzter Multi-Hop

Ihr Programm gibt mehrere CPIs in einer Anweisung aus und erzwingt eine einzige Slippage-Grenze über alle hinweg. Die Raydium-Swap-Anweisungen haben jeweils ihre eigene minimum_amount_out, aber Sie setzen diese auf 0 (oder eine sehr lockere Untergrenze) und erzwingen nach dem letzten Hop selbst ein striktes Minimum.
Dies gibt Ihnen ein einzelnes Rückgabe-Gate für die gesamte Route. Verwenden Sie dieses Muster nur, wenn Sie jedem Hop vertrauen, dass er slippage-sicher ist; andernfalls lassen Sie jeden Hop sein eigenes Minimum durchsetzen.

Muster 4: Vault / Strategy

Ihr Programm hält LP-Token oder Farm-Stake in einem PDA. Ein Keeper (oder der Benutzer) ruft compound() auf, was:
  1. Rewards aus der Farm erntet.
  2. Rewards für Pool-Token tauscht (CPI in CPMM oder CLMM).
  3. Die Erlöse zurück in die LP einzahlt (ein weiterer CPI).
  4. Die neue LP einsetzt (ein weiterer CPI).
Alles in einer Transaktion, damit sich der NAV des Vaults atomar bewegt. Das Compute-Budget liegt typischerweise bei 600k–1M CU; Address-Lookup-Tabellen sind obligatorisch.

Kontolisten-Konstruktion

Die Accounts-Struktur des aufrufenden Programms spiegelt die Kontoordnung des Raydium-Programms wider, aber die meisten Raydium-seitigen Konten sind UncheckedAccount, da Raydium sie selbst validiert. Sie fügen nur Einschränkungen auf Konten hinzu, die Sie besitzen:
Die Asymmetrie — strikte Validierung auf Ihren Konten, UncheckedAccount auf Raydiums — ist keine Faulheit. Der Empfänger validiert seine eigenen; Doppelvalidierung beim Aufrufer verbrennt nur CU und riskiert, aus der Synchronisation zu geraten, wenn Raydium ein neues Struct-Layout-Feld ausliefert.

Der CPI-Aufruf selbst

PDA-Signer-Seeds

Der CPI ist erfolgreich, nur wenn der als authority übergebene PDA mit der Ableitung übereinstimmt, die der Aufrufer beansprucht. Die beiden müssen sich einigen auf:
  1. Die Seed-Byte-Sequenz (hier [b"escrow", user.key().as_ref()]).
  2. Der Bump.
  3. Die aufrufende Programm-ID (Ihr Programm, nicht Raydiums).
Beachten Sie, womit der PDA übereinstimmen muss. Der authority-Slot von CPMM ist sein eigener Vault-PDA — ein festes, programmweites Konto, das es ableitet und mit sich selbst signiert, und das Ihr Programm weder kontrolliert noch ersetzt. Das Konto, mit dem Ihre PDA-Seeds übereinstimmen müssen, ist payer: Die Prüfung erfolgt innerhalb von CPMMs eigenem transfer_from_user_to_pool_vault-Helfer, der erfordert, dass das als payer übergebene Konto der Besitzer von input_token_account ist. Häufiger Fehler: user als payer übergeben, während escrow_input_ata dem Escrow-PDA gehört. Das SPL-Token-Programm lehnt mit owner mismatch ab. Machen Sie payer immer zum Besitzer der ATA — und signieren Sie dafür mit new_with_signer, wenn dieser Besitzer ein PDA ist.

Verbleibende Konten

Mehrere Raydium-Anweisungen nehmen eine variable Länge einer Liste von Konten, die nach den festen angehängt werden — verbleibende Konten.
  • CLMM SwapV2: 1–8 TickArrayState-Konten für die Tick-Arrays, die der Swap durchqueren kann, in Swap-Richtung.
  • Farm v6 Deposit / Harvest / Withdraw: (reward_vault, user_reward_ata)-Paare, ein Paar pro aktivem Reward-Slot.
  • Token-2022 Transfer-Hook-Mints: das Transfer-Hook-Programm plus alle Konten, die der Hook benötigt.
Die Anchor-CPI-Helfer führen keine Typprüfung für verbleibende Konten durch. Geben Sie sie durch:
Die Reihenfolge ist wichtig. Für CLMM:
Für Farm v6 Harvest:
Ihr aufrufendes Programm muss die verbleibenden Konten, die es vom Client erhält, unverändert durchgeben. Versuchen Sie nicht, sie zu filtern oder neu zu ordnen.

Compute-Budget für zusammengesetzte Aufrufe

Ein CPI kostet ~1.500 CU für den Call-Frame selbst; die eigene CU-Nutzung des Callees stapelt sich oben drauf. Die Callee-Zahlen unten wurden aus Live-Mainnet-Transaktionen auf hochvolumigen Pools am 2026-09-09 gemessen, gelesen aus der Program <id> consumed N of M compute units-Protokollzeile für die eigene Invokation des Raydium-Programms (daher enthalten sie seine inneren Token-Programm-CPIs): Addieren Sie ~1.500 für jeden CPI-Frame und den Overhead Ihres eigenen Programms oben drauf. Die CLMM-Swap-Kosten skalieren mit Tick-Überquerungen, daher behandeln Sie die Zahl als Untergrenze. Token-2022-Mints addieren die Erweiterungs-Handhabungskosten der Übertragung selbst; messen Sie sie für Ihre eigenen Mints, anstatt einen pauschalen Multiplikator anzuwenden.
Frühere Überarbeitungen dieser Seite trugen Schätzungen 5–7× höher (ein ~150.000 CU CPMM-Swap, ~180.000 für CLMM). Diese wurden nie gemessen. Budget aus Ihrer eigenen computeUnitsConsumed-Ablesung, nicht aus einer dokumentierten Zahl — und beachten Sie, dass eine vollständige Transaktion mehr kostet als die Raydium- Anweisung allein, sobald ATA-Erstellung, wSOL-Wrapping und Compute-Budget-Anweisungen gezählt werden.
Setzen Sie immer ein explizites ComputeBudgetProgram::set_compute_unit_limit:
Die Standard-200k-CU-Obergrenze wird stillschweigend erschöpft sein, lange bevor ein zusammengesetzter Aufruf abgeschlossen ist.

Fehlerausbreitung

Raydium-Programme geben Anchor-Fehler mit stabilen Fehlercodes zurück. Ihr aufrufendes Programm sieht sie als Err(ProgramError::Custom(code)). Standardmäßig durchblubbern:
Oder abfangen für spezifische Codes:
Beachten Sie den ERROR_CODE_OFFSET-Term: #[error_code]-Varianten werden ab 6000 ausgegeben, daher stimmt der Vergleich gegen die bloße Enum-Diskriminante nie überein. (Es gibt keinen is_err-Helfer in anchor-lang oder in raydium_cp_swap — frühere Überarbeitungen dieser Seite verwendeten einen, der nicht existiert.) Die Fehlercode-zu-Bedeutung-Zuordnung ist stabil pro IDL-Richtlinie (sdk-api/anchor-idl); neue Codes werden am Ende angehängt, bestehende Codes ändern nie ihre Bedeutung.

Vollständiges Arbeitsbeispiel: Limit-Order-Escrow

Ablauf:
  1. open_order — Benutzer hinterlegt amount_in von input_mint in Escrow-PDA; zeichnet Ziel min_amount_out und Ablauf auf.
  2. execute_order — Jeder (Keeper) ruft mit den aktuellen Pool-Konten auf. Programm prüft das aktuelle Angebot ≥ min_amount_out, dann CPI Raydium-Swap und behält die Ausgabe im Escrow.
  3. claim — Benutzer zieht den Output-Token aus dem Escrow.
Der Keeper zahlt die Transaktionsgebühr (sie erhalten anderswo eine Keeper-Gebühr — nicht gezeigt). Der order-PDA signiert den CPI als payer, da er die Escrow-Input-ATA besitzt; ExecuteOrder benötigt daher auch ein pool_authority: UncheckedAccount<'info>-Feld für CPMMs eigenen Vault-PDA. Sowohl die Raydium-seitige Slippage-Prüfung als auch die eigene Delta-Prüfung des Escrows erzwingen die Untergrenze — Sicherheit und Hosenträger.

Testen

Raydium-Programme in einen lokalen Validator für Integrationstests ziehen (aus Anchor.toml):
Klonen Sie auch die Pool-State-Konten, damit Ihre Tests tatsächlich Swaps ausführen können; anchor test ruft sie beim Start von Mainnet ab. Siehe sdk-api/rust-cpi.

Fallstricke spezifisch für Komposition

Reentrancy

Solana hat keine echte Reentrancy — ein CPI kann nicht in derselben Invokation zurück in das ursprüngliche Programm aufrufen. Aber Sie können sich selbst in eine logische Reentrancy bauen: ein CPI, der Ihren Zustand liest, dann liest Ihr Code ihn erneut an, annehmend, dass der CPI ihn nicht geändert hat. Für Raydium berühren die CPIs Ihren Zustand nicht, daher ist dies weniger ein Problem als z. B. in Flash-Loan-Kontexten. Aber wenn Sie Raydium mit einem Lending-Protokoll zusammensetzen, seien Sie sich bewusst.

Account-Mutabilität-Drift

Wenn Ihr Programm ein Konto als mut übergibt, aber Raydium erwartet es schreibgeschützt (oder umgekehrt), lehnt die Runtime die Invokation mit InvalidAccountData ab. Überprüfen Sie immer die erwartete Mutabilität der Raydium-Anweisung in der IDL; raydium_cp_swap::cpi::accounts::Swap setzt die Mutabilität jedes Kontos für Sie, aus den #[account(mut)]-Markierungen auf CPMMs eigenem Swap-Struct — die generierten Felder sind alle einfache AccountInfo<'info>, daher ist es die abgeleitete ToAccountMetas-Impl, nicht die Feldtypen, die die Flags trägt.

Token-2022-Programmfeld

Input- und Output-Mints können unter verschiedenen Token-Programmen stehen — eines SPL Token, eines Token-2022. Der CPI hat separate input_token_program- und output_token_program-Felder aus diesem Grund. Überprüfen Sie immer das owner-Feld jedes Mints und leiten Sie das richtige Programm in jeden Slot.

Versionierte Transaktionen

Eine zusammengesetzte Tx, die 2+ Raydium-CPIs plus eine ATA-Erstellung macht, passt selten in eine Legacy-Transaktion (v0-ohne-LUT). Verwenden Sie V0 mit Address-Lookup-Tabellen; ziehen Sie Raydiums öffentliche LUTs über raydium.getRaydiumLutAddresses().

Zeiger

Quellen: