Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

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 →
Cada transacción en Solana establece (implícita o explícitamente) dos parámetros: un límite de unidades de computación (CUs máximas que la transacción puede consumir; por defecto 200.000 × número de instrucciones hasta un límite por transacción) y una tarifa de prioridad en micro-lamports por CU. Subestimar cualquiera de los dos mata la transacción: límites de CU demasiado bajos causan ProgramFailedToComplete; tarifas de prioridad demasiado bajas hacen que la transacción permanezca sin confirmar hasta expirar.

Los dos parámetros

import { ComputeBudgetProgram } from "@solana/web3.js";

const tx = new Transaction()
  .add(ComputeBudgetProgram.setComputeUnitLimit({ units: 250_000 }))
  .add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50_000 }))
  .add(yourRaydiumSwapIx);
  • setComputeUnitLimit(units) — limita la computación; la transacción paga como máximo units CUs.
  • setComputeUnitPrice(microLamports) — oferta de tarifa de prioridad, en micro-lamports por CU. Tarifa de prioridad total = units × microLamports × 1e-6 lamports.
Cálculo de costo: un límite de 250k CU a 50k micro-lamports/CU ofrece 250_000 × 50_000 / 1e6 = 12.500 lamports ≈ 0,0000125 SOL ≈ $0,003 a $200 SOL. Las tarifas de prioridad en esta escala son insignificantes para la mayoría de swaps de usuarios, pero relevantes para bots que realizan 1000 transacciones/día.

Puntos de referencia de CU por instrucción

Puntos de referencia de registros de ejecución en mainnet, promediados en ejecuciones recientes. Los números son aproximados (±15%); remide para tus flujos específicos.
InstrucciónSPL TokenToken-2022 (simple)Token-2022 (tarifa de transferencia)
CPMM initialize_pool180.000200.000
CPMM swap_base_input140.000180.000200.000
CPMM swap_base_output150.000185.000205.000
CPMM deposit130.000160.000180.000
CPMM withdraw120.000150.000170.000
CLMM create_pool70.00085.000
CLMM open_position_v2120.000140.000160.000
CLMM increase_liquidity_v2150.000175.000195.000
CLMM decrease_liquidity_v2140.000165.000185.000
CLMM swap_v2 (0 cruces de tick)170.000205.000225.000
CLMM swap_v2 (1 cruce de tick)220.000255.000275.000
CLMM swap_v2 (3 cruces de tick)320.000355.000375.000
CLMM collect_fee80.00095.000105.000
AMM v4 swap_base_in140.000
AMM v4 deposit120.000
AMM v4 withdraw110.000
Farm v6 create_farm70.00085.000
Farm v6 deposit (1 ranura de recompensa)130.000155.000175.000
Farm v6 deposit (3 ranuras de recompensa)220.000255.000275.000
Farm v6 withdrawcoincide con deposit
Farm v6 harvestcoincide con deposit
Farm v3/v5 deposit100.000
LaunchLab initialize100.000
LaunchLab buy_exact_in140.000
LaunchLab graduate250.000
La fila de “cruces de tick” para CLMM es la variable de CU más importante. Si no sabes cuántos ticks cruzará el swap, presupuesta para el peor caso: 8 cruces es el límite duro (el programa carga como máximo 8 arrays de tick).

Transacciones compuestas

Suma los presupuestos individuales y agrega:
  • +1.500 CU por marco de CPI — sobrecarga fija del tiempo de ejecución para cada llamada entre programas.
  • +20.000 CU por creación de ATAcreate_associated_token_account no es gratis.
  • +5.000 CU por setComputeUnitLimit / setComputeUnitPrice cada uno.
Ejemplo: un swap de usuario que crea el ATA de salida y envuelve SOL nativo:
wrap_sol (create_ata + system transfer + sync_native)   ≈ 30.000
CPMM swap_base_input (SPL)                              ≈ 140.000
close_account (unwrap)                                  ≈ 5.000
ComputeBudget instructions                              ≈ 10.000
────────────────────────────────────────────────────────
Total                                                   ≈ 185.000 → presupuesta 250.000
Relleno: establece el límite de CU aproximadamente un 25% por encima del uso esperado. Subestimar cuesta toda la transacción; sobrestimar simplemente eleva el costo de la tarifa de prioridad proporcionalmente (la tarifa de prioridad es units × microLamports, así que aproximadamente un 25% por encima del presupuesto cuesta 25% extra en tarifa de prioridad).

Estimación de tarifa de prioridad

El mercado de tarifas local de Solana significa que las tarifas de prioridad son por cuenta escribible. Una transacción que escribe en una cuenta caliente (estado de pool popular) paga más que una que escribe en una cuenta fría. El nivel de tarifa global no es la métrica correcta para swaps de Raydium; quieres tarifas en los pools específicos que estás tocando.

Estrategia 1: Estimador del proveedor RPC

Cada proveedor RPC importante publica un estimador de tarifa de prioridad que consulta tarifas recientes en cuentas específicas:
// Helius
const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${apiKey}`, {
  method: "POST",
  body: JSON.stringify({
    jsonrpc: "2.0",
    id:      "fee-estimate",
    method:  "getPriorityFeeEstimate",
    params: [{
      accountKeys: [poolStatePubkey.toBase58()],
      options:     { priorityLevel: "High" },
    }],
  }),
});
const { result } = await response.json();
const microLamports = result.priorityFeeEstimate;
Niveles de prioridad en la mayoría de proveedores: Min / Low / Medium / High / VeryHigh / UnsafeMax. Mapéalos a percentiles:
NivelPercentilCaso de uso
Min25ºTráfico de bot en segundo plano, no urgente
Low50ºSwaps normales de usuario
Medium60ºValor por defecto para UIs de billetera
High75ºArbitraje sensible al tiempo
VeryHigh95ºLiquidaciones, salidas de última oportunidad
Proveedores: Helius (getPriorityFeeEstimate), Triton (getRecentPrioritizationFees con lista de cuentas), QuickNode (similar).

Estrategia 2: Consulta RPC directa

Usa el RPC estándar getRecentPrioritizationFees:
const fees = await connection.getRecentPrioritizationFees({
  lockedWritableAccounts: [poolStatePubkey],
});

// fees: Array<{ slot, prioritizationFee }>
// Slots recientes N; por defecto ~150 slots.

const median = percentile(fees.map(f => f.prioritizationFee), 0.5);
Este es el método RPC vanilla de Solana; funciona con cualquier proveedor. Desventaja: la muestra es pequeña (150 slots ≈ 60 segundos) y ruidosa. Para estimaciones más suaves, usa la agregación de un proveedor.

Estrategia 3: Auto-ajuste histórico

Para bots con flujo constante, rastrea tus propias tasas aterrizadas vs. expiradas:
objetivo por pool: tasa de aterrizaje del 80% en <30s
si current_land_rate < 80%: priorityFee += 10%
si current_land_rate > 95%: priorityFee -= 5%
Esto se auto-corrige más rápido que los estimadores públicos y captura la estructura por pool que los estimadores públicos no siempre ven.

Manejo de fallos por agotamiento de CU

Síntoma: la transacción falla con exceeded maximum number of instructions allowed (200000) o ProgramFailedToComplete. Diagnóstico:
solana confirm <tx-sig> -v
# Busca "consumed N of M compute units" e identifica qué instrucción se agotó.
Soluciones:
  1. Aumenta el límite de CU. Si tu transacción usaba 195k de un presupuesto de 200k, aumenta a 300k.
  2. Divide la transacción. Si golpeas el límite de 1,4M por transacción, divide en dos transacciones. Farm harvest then stake es un clásico para dividir cuando hay muchas recompensas.
  3. Recorta cuentas. Cada cuenta adicional escribible agrega ~2.000 CU. Recortar cuentas no utilizadas ayuda en casos marginales.
  4. Usa tablas de búsqueda. Las búsquedas de LUT son ~50 CU por dirección resuelta, ahorrando los 5.000 CU de una referencia de cuenta completa por entrada.

Manejo de transacciones atascadas

Síntoma: transacción enviada, nunca confirma, eventualmente expira con BlockhashNotFound. Diagnóstico:
  • getSignatureStatuses([sig]) retorna null → el líder nunca la vio.
  • Retorna { confirmationStatus: null } → el líder la vio pero no la incluyó.
Soluciones:
  1. Aumenta la tarifa de prioridad. Reenvía con 2× la tarifa actual.
  2. Reconstruye con blockhash fresco. La vida útil del blockhash es ~60 segundos; después de eso la transacción es inválida independientemente de las tarifas.
  3. Transmisión RPC múltiple. Algunos RPCs tienen mejor conectividad de líder que otros. Envía a 3–5 en paralelo.
  4. Cambia a bundles de Jito. Ver integration-guides/routing-and-mev. Los bundles evitan las colas de paquetes públicas.
Esqueleto de lógica de reintentos:
async function submitWithRetry(buildTx, maxAttempts = 5) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const tx = await buildTx({
      priorityFee: basePriorityFee * Math.pow(1.5, attempt),
      blockhash:   (await connection.getLatestBlockhash()).blockhash,
    });

    try {
      const sig = await connection.sendRawTransaction(tx.serialize(), {
        skipPreflight: attempt > 0,  // omite después del primer intento para ahorrar latencia
      });

      const result = await connection.confirmTransaction(sig, "confirmed");
      if (result.value.err) {
        // Error de lógica; no reintentar.
        throw result.value.err;
      }
      return sig;

    } catch (e) {
      if (isExpiredError(e)) continue;  // reintentar
      if (isRevertError(e)) throw e;    // no reintentar; fallo determinista
      throw e;
    }
  }
  throw new Error("submit: exhausted retries");
}

Bajo congestión

Cuando la red está congestionada (los dashboards de Jupiter / Jito bundle muestran acumulación, la latencia de RPC aumenta, las tasas de expiración de transacciones suben), ajusta:
ParámetroCondiciones normalesCondiciones congestionadas
Límite de CU+25% por encima de la estimación+25% por encima de la estimación (sin cambios)
Percentil de tarifa de prioridad50º75º–95º
Cantidad de reintentos35–7
Retroceso de reintento500ms1000ms
Usar bundles de JitoOpcionalAltamente recomendado
Actualización de blockhash en reintentoSí, obligatorio
Observar señales de congestión:
  • Percentil 75º de tarifa de prioridad > 500k micro-lamports: congestión.
  • Propina de 50º percentil de Jito > 0,001 SOL: congestión.
  • RPC response p99 > 2s: problema específico de RPC o congestión.

Presupuesto de tarifas para bots

Un bot de trading que ejecuta ~1000 transacciones/día necesita un presupuesto de tarifa de prioridad. Estimación rápida:
CU promedio por transacción:          ~250.000
Tarifa del 50º percentil:        ~20.000 micro-lamports/CU
Costo por transacción:                250_000 × 20_000 × 1e-6 = 5_000 lamports = 5e-6 SOL
Costo diario (1000 tx):       5e-3 SOL ≈ $1 @ $200 SOL
Costo mensual:               ~$30
Ese es el mínimo. Durante la congestión, multiplica por 5–10×. Planifica aproximadamente $150–300/mes en tarifas de prioridad para un bot de flujo constante. Los bots que deben aterrizar en slots específicos (liquidaciones, arb) pagan el percentil 95º continuamente y gastan ~10× más. Las propinas de bundles de Jito dominan en esa escala — a menudo $1000+/mes — pero la alternativa (ser desbordado o expirar) es peor.

Trampas

1. Olvidar el límite de CU

El valor por defecto es 200k CUs × (instrucciones en transacción). Un swap de una sola instrucción por defecto es 200k; eso es suficiente para CPMM en SPL Token pero no para CLMM con cruces de tick o cualquier cosa Token-2022. Siempre establécelo explícitamente.

2. Tarifa de prioridad en la cuenta equivocada

Si estimas la tarifa de prioridad contra el mint del token pero la cuenta caliente es el estado del pool, tu estimación es demasiado baja. El estado del pool es la cuenta escribible correcta para apuntar en Raydium.

3. Las tarifas escalan con el límite de CU

total_priority_fee = units × microLamports. Aumentar units de 200k a 1M a 50k micro-lamports/CU multiplica la tarifa de prioridad 5×. No sobre-presupuestes CU solo por si acaso; mide.

4. Versión de transacción por defecto

Las transacciones heredadas tienen límites de cuenta más bajos; las transacciones V0 con tablas de búsqueda de direcciones desbloquean rutas más grandes. El SDK usa V0 por defecto en txVersion: TxVersion.V0. No cambies a heredado a menos que necesites compatibilidad con billetera.

5. skipPreflight oculta errores de CU

skipPreflight: true envía la transacción sin simulación local. Ahorras ~100ms pero pierdes la retroalimentación temprana sobre agotamiento de CU. Úsalo solo en reintentos, no en el primer intento.

Referencias

Fuentes: