Esta página fue traducida automáticamente por IA. La versión en inglés es la fuente autorizada.Ver versión en inglés →
Cuándo CPI es la herramienta correcta
Un programa personalizado tiene sentido cuando el intercambio debe ocurrir de forma atómica con otros cambios de estado en cadena que solo tu programa puede realizar. Casos comunes:- Programas de depósito en garantía / órdenes limitadas — el usuario deposita un mint en tu depósito en garantía, tu programa vigila una condición de precio, y cuando se activa, tu programa intercambia atómicamente a través de Raydium y acredita la cuenta del usuario.
- Proxies agregadores — una única instrucción que enruta un intercambio a través de Raydium + uno o más DEXes adicionales, con todos los saltos bajo una única verificación de slippage propiedad de tu programa.
- Bóvedas de auto-capitalización — deposita LP o participación en granja en tu bóveda, la bóveda cosecha recompensas según un cronograma, re-suministra liquidez, emite tokens de participación.
- Bóvedas de estrategia — posiciones LP apalancadas que se reequilibran intercambiando a través de CLMM; liquidadores que cierran posiciones e intercambian garantías en una transacción.
- Plataformas de lanzamiento de tokens con vesting personalizado — tu programa mantiene tokens de vesting y los libera en un pool de Raydium según un cronograma.
Patrones de composición
Patrón 1: Proxy delgado
Tu programa expone una única instrucción que valida alguna política (p. ej. pares de mint en lista blanca, descuento de tarifa para usuarios verificados) y luego reenvía a Raydium.Patrón 2: Depósito en garantía
Tu programa posee un PDA que mantiene el mint de entrada del usuario. Al activarse, el PDA firma un CPI a Raydium para intercambiar su propio saldo.CpiContext::new_with_signer. Ver Semillas de firmante PDA.
Patrón 3: Multi-salto compuesto
Tu programa emite múltiples CPIs en una instrucción, aplicando un único límite de slippage en todos ellos. Las instrucciones de intercambio de Raydium tienen cada una su propiominimum_amount_out, pero estableces esos en 0 (o un piso muy flexible) y aplicas un mínimo estricto final tú mismo después del último salto.
Patrón 4: Bóveda / estrategia
Tu programa mantiene tokens LP o participación en granja en un PDA. Un guardián (o el usuario) llama acompound(), que:
- Cosecha recompensas de la granja.
- Intercambia recompensas por tokens de pool (CPI en CPMM o CLMM).
- Deposita los ingresos de vuelta en el LP (otro CPI).
- Participa en el nuevo LP (otro CPI).
Construcción de lista de cuentas
La estructuraAccounts del programa que llama refleja el orden de cuentas del programa de Raydium, pero la mayoría de las cuentas del lado de Raydium son UncheckedAccount porque Raydium las valida a sí mismo. Solo añades restricciones en cuentas que tú posees:
UncheckedAccount en las de Raydium — no es pereza. El receptor valida las suyas; validar dos veces en el llamador solo quema CU y arriesga desincronización cuando Raydium envía un nuevo campo de diseño de struct.
La llamada CPI en sí
Semillas de firmante PDA
El CPI solo tiene éxito si el PDA pasado comoauthority coincide con la derivación que el llamador reclama. Los dos deben estar de acuerdo en:
- La secuencia de bytes de semilla (aquí
[b"escrow", user.key().as_ref()]). - El bump.
- El ID del programa que llama (tu programa, no el de Raydium).
authority cubra la transacción y que el ATA de entrada sea propiedad de esa autoridad. La validación ocurre en anchor_spl::token::transfer: el campo authority del ATA debe ser igual al firmante.
Error común: pasar user como la autoridad (e intercambiar desde escrow_input_ata que es propiedad del PDA de depósito en garantía). El programa SPL Token rechaza con owner mismatch. Siempre haz que el campo authority coincida con el propietario del ATA.
Cuentas restantes
Varias instrucciones de Raydium toman una lista de longitud variable de cuentas añadidas después de las fijas — cuentas restantes.- CLMM
SwapV2: 1–8 cuentasTickArrayStatepara los arrays de tick que el intercambio puede atravesar, en dirección de intercambio. - Farm v6
Deposit/Harvest/Withdraw: pares(reward_vault, user_reward_ata), un par por ranura de recompensa activa. - Mints de gancho de transferencia Token-2022: el programa de gancho de transferencia más cualquier cuenta que el gancho necesite.
Presupuesto de cómputo para llamadas compuestas
Un CPI cuesta ~1.500 CU por el marco de llamada en sí; el uso de CU propio del llamado se apila encima. Presupuesto aproximado por CPI de Raydium:
Añade ~1.500 por cada marco CPI y ~20.000 por la sobrecarga de tu propio programa. Un auto-capitalizador haciendo
harvest → swap A → swap B → deposit LP → stake LP fácilmente alcanza 700k CU.
Siempre establece un ComputeBudgetProgram::set_compute_unit_limit explícito:
Propagación de errores
Los programas de Raydium devuelven errores de Anchor con códigos estables. Tu programa que llama los ve comoErr(ProgramError::Custom(code)). Propaga por defecto:
sdk-api/anchor-idl); nuevos códigos se añaden al final, códigos existentes nunca cambian de significado.
Ejemplo completo trabajado: depósito en garantía de orden limitada
Flujo:open_order— el usuario depositaamount_indeinput_minten el PDA de depósito en garantía; registramin_amount_outobjetivo y vencimiento.execute_order— cualquiera (guardián) llama con las cuentas de pool actuales. El programa verifica que la cotización actual ≥min_amount_out, luego CPI intercambio de Raydium y mantiene la salida en depósito en garantía.claim— el usuario retira el mint de salida del depósito en garantía.
Pruebas
Extrayendo programas de Raydium en un validador local para pruebas de integración (desdeAnchor.toml):
anchor test las obtiene de mainnet al inicio. Ver sdk-api/rust-cpi.
Trampas específicas de composición
Reentrancia
Solana no tiene verdadera reentrancia — un CPI no puede llamar de vuelta al programa originador en la misma invocación. Pero aún puedes construirte una reentrancia lógica: un CPI que lee tu estado, luego tu código lo lee de nuevo asumiendo que el CPI no lo cambió. Para Raydium, los CPIs no tocan tu estado, así que esto es menos una preocupación que p. ej. contextos de préstamo flash. Pero si compones Raydium con un protocolo de préstamo, ten cuidado.Deriva de mutabilidad de cuenta
Si tu programa pasa una cuenta comomut pero Raydium la espera de solo lectura (o viceversa), el tiempo de ejecución rechaza la invocación con InvalidAccountData. Siempre verifica la mutabilidad esperada de la instrucción de Raydium en el IDL; anchor_cp_swap::cpi::accounts::Swap la aplica a través de sus tipos de campo.
Campo de programa Token-2022
Los mints de entrada y salida pueden estar bajo diferentes programas de token — uno SPL Token, uno Token-2022. El CPI tiene camposinput_token_program y output_token_program separados por esta razón. Siempre verifica el campo owner de cada mint y enruta el programa correcto en cada ranura.
Transacciones versionadas
Una tx compuesta que hace 2+ CPIs de Raydium más una creación de ATA raramente cabe en una transacción heredada (v0-sin-LUT). Usa V0 con tablas de búsqueda de direcciones; extrae los LUTs públicos de Raydium a través deraydium.getRaydiumLutAddresses().
Punteros
sdk-api/rust-cpi— mecánica CPI de bajo nivel.integration-guides/priority-fee-tuning— dimensionamiento de presupuesto de cómputo.products/cpmm/code-demos,products/clmm/code-demos,products/farm-staking/code-demos— fragmentos CPI por producto.

