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 on-chain que solo tu programa puede realizar. Casos comunes:- Programas de depósito en garantía / orden limitada — el usuario deposita un token 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 otros DEX, con todos los saltos bajo una única verificación de slippage de propiedad de tu programa.
- Bóvedas con auto-composición — deposita tokens LP o stake de granja en tu bóveda, la bóveda cosecha recompensas según un cronograma, resurtidores de 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ía 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 (por ejemplo, pares de tokens 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 es propietario de un PDA que mantiene el token de entrada del usuario. Al activarse, el PDA firma un CPI a Raydium para intercambiar su propio saldo.CpiContext::new_with_signer. Ver Semillas firmantes de PDA.
Patrón 3: Multi-salto compuesto
Tu programa emite múltiples CPI en una instrucción, imponiendo una única cota de slippage en todas ellas. Las instrucciones de intercambio de Raydium tienen cada una su propiaminimum_amount_out, pero estableces esas en 0 (o un piso muy flexible) y aplicas un mínimo estricto final después del último salto.
Patrón 4: Bóveda / estrategia
Tu programa mantiene tokens LP o stake de 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 las ganancias nuevamente en el LP (otro CPI).
- Participa en el nuevo LP (otro CPI).
Construcción de la 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 por sí mismo. Solo agregas restricciones en las cuentas que posees:
UncheckedAccount en las de Raydium — no es pereza. El receptor valida las suyas propias; validar doblemente en la llamada solo quema CU y corre el riesgo de desincronización cuando Raydium envía un nuevo campo de diseño de estructura.
La llamada CPI en sí misma
Semillas firmantes de PDA
El CPI tiene éxito solo si el PDA pasado comoauthority coincide con la derivación que el llamante afirma. Los dos deben estar de acuerdo en:
- La secuencia de bytes de semilla (aquí
[b"escrow", user.key().as_ref()]). - El bump.
- La 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 del 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 agregadas después de las fijas — cuentas restantes.- CLMM
SwapV2: 1–8 cuentasTickArrayStatepara los arrays de ticks que el intercambio puede recorrer, 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 de Token-2022: el programa del gancho de transferencia más cualquier cuenta que el gancho necesite.
Presupuesto de computadora para llamadas compuestas
Un CPI cuesta ~1.500 CU por el marco de llamada en sí; el uso propio de CU del llamado se apila encima. Presupuesto aproximado por CPI de Raydium:| Llamada | CU (SPL Token) | CU (Token-2022) |
|---|---|---|
| CPMM swap_base_input | ~150.000 | ~200.000 |
| CLMM swap_v2 (single tick array) | ~180.000 | ~230.000 |
| CLMM swap_v2 (crosses 2 ticks) | ~220.000 | ~270.000 |
| Farm v6 deposit | ~120.000 | ~150.000 |
| Farm v6 harvest (per reward slot) | +30.000 | +40.000 |
| AMM v4 swap_base_in | ~140.000 | n/a |
harvest → swap A → swap B → deposit LP → stake LP fácilmente llega a 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)). Propágalos por defecto:
sdk-api/anchor-idl); los nuevos códigos se añaden al final, los códigos existentes nunca cambian de significado.
Ejemplo completo funcional: escrow de orden limitada
Flujo:open_order— el usuario depositaamount_indeinput_minten el PDA del depósito en garantía; registramin_amount_outobjetivo y vencimiento.execute_order— cualquiera (guardián) llama con las cuentas de pool actuales. El programa comprueba la cotización actual ≥min_amount_out, luego CPI el intercambio de Raydium y mantiene la salida en el depósito en garantía.claim— el usuario retira el token de salida del depósito en garantía.
Pruebas
Tirar programas de Raydium en un validador local para pruebas de integración (desdeAnchor.toml):
anchor test las obtiene de mainnet al iniciar. Ver sdk-api/rust-cpi.
Trampas específicas de la composición
Reentrancia
Solana no tiene verdadera reentrancia — un CPI no puede volver a llamar al programa originario en la misma invocación. Pero todavía puedes construirte a ti mismo en 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 CPI no tocan tu estado, por lo que esto es menos una preocupación que, por ejemplo, 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 espera que sea 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 del 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 campos separadosinput_token_program y output_token_program 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+ CPI de Raydium más una creación de ATA rara vez cabe en una transacción heredada (v0 sin LUT). Usa V0 con tablas de búsqueda de direcciones; obtén los LUT 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 del presupuesto de computadora.products/cpmm/code-demos,products/clmm/code-demos,products/farm-staking/code-demos— fragmentos CPI por producto.

