Aviso de versión. Todas las demos en TypeScript usan
@raydium-io/raydium-sdk-v2@0.2.64-alpha. Se ejecutaron por última vez con 0.2.42-alpha (2026-04) y sus firmas de llamada se revisaron de nuevo frente al código fuente de 0.2.64-alpha el 2026-09-09, en Solana mainnet-beta. El esqueleto de CPI en Rust que aparece al final apunta a raydium-clmm en master, con Anchor 1.0.2, la misma versión fijada que en la página de CPMM, de modo que ambas pueden convivir en un mismo crate. Los IDs de programa se obtienen del SDK a partir de reference/program-addresses.Configuración
raydium-sdk-V2-demo/src/clmm; el enlace a GitHub aparece junto a cada sección. La inicialización sigue el config.ts.template del repositorio de demos (fuente). Para cualquier integración no trivial, se recomienda disableFeatureCheck: true:
Crear un pool de CLMM
Fuente:src/clmm/createPool.ts
- Ordena
mint1/mint2por orden de bytes antes de la derivación. - Calcula
sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64). - Crea las cuentas
observationytick_array_bitmap_extension. - Paga la comisión de creación del pool definida en
ammConfig.
Abrir una posición en un rango elegido
Fuente:src/clmm/createPosition.ts
OpenPosition* crea por sí mismo el tick array que falte, con cargo al pagador.
Aumentar la liquidez de una posición existente
Fuente:src/clmm/increaseLiquidity.ts
Reducir la liquidez (y recolectar comisiones al mismo tiempo)
Fuente:src/clmm/decreaseLiquidity.ts y src/clmm/closePosition.ts
decreaseLiquidity con liquidity = new BN(0). El efecto secundario de la instrucción es liquidar token_fees_owed_{0,1} y reward_amount_owed y transferirlos fuera del pool. Es la única forma de recolectar cualquiera de los dos.
Para cerrar la posición por completo, una vez que la liquidez y las comisiones estén a cero, pasa ownerInfo: { closePosition: true } en la última llamada a decreaseLiquidity. El SDK añade ClosePosition y quema el NFT.
Para un cliente Anchor directo, mantén sin cambios las cuentas declaradas y añade el pool al final:
poolId en todos los cierres. CLMM solo lo lee cuando positionNftAccount está congelada, lo que permite que una misma ruta de cliente sea compatible con posiciones antiguas y nuevas.
Recolectar recompensas
Fuente:src/clmm/harvestAllRewards.ts
harvestAllRewards recorre todas las posiciones de todos los pools que se le pasan, agrupa las llamadas DecreaseLiquidity de liquidez cero que liquidan comisiones y recompensas (además de cualquier UpdateRewardInfos) y, si hace falta, las reparte en varias transacciones.
Swap
Fuente:src/clmm/swap.ts
Esto replica src/clmm/swap.ts, que simula con swapInternal en lugar de
PoolUtils.computeAmountOutFormat.
amountCalculated) junto con la lista exacta de cuentas que tocará el swap (accounts).
Pase siempre los remainingAccounts que devuelve la simulación: si faltan, el swap revierte a mitad del recorrido con NotEnoughTickArrayAccount; si sobran o están desactualizados, solo desperdician cómputo.
PoolUtils.computeAmountOutFormat sigue existiendo, pero necesita un ComputeClmmPoolInfo (el
computePoolInfo devuelto por getPoolInfoFromRpc, no un objeto de pool de la API) y dos argumentos
obligatorios más: tickarrayBitmapExtension y blockTimestamp. Además, no existe el método
raydium.clmm.fetchTickArrays (fetchTickArrays es una función independiente; los helpers a nivel de
módulo son PoolUtils.fetchMultiplePoolTickArrays y los tickData / tickArrays que devuelve
getPoolInfoFromRpc).Crear un pool CLMM personalizable
createCustomizablePool es el punto de entrada que expone los interruptores de comisión dinámica y de comisión de un solo lado en el momento de crear el pool. Recibe la misma forma que createPool más dos parámetros adicionales:
createPool sigue funcionando para el camino de comisión por defecto, sin comisión dinámica. Use createCustomizablePool cuando necesite cualquiera de estos dos ajustes. Consulte products/clmm/instructions para ver la lista de cuentas on-chain.
Órdenes límite
Una orden límite deposita el importe del usuario en un único tick y se ejecuta por orden FIFO cuando un swap cruza ese tick. Los importes resultantes se envían al ATA del propietario en el momento de la liquidación; el propietario no necesita estar conectado para que se ejecute.Abrir una orden límite
No existe una cuenta de configuración de órdenes límite por pool ni un helpergetClmmLimitOrderConfigs(): las órdenes se identifican por tick.
LimitOrderState a partir de (owner, nonce PDA, order nonce), incrementa el LimitOrderNonce de la wallet e inserta la orden en la cohorte FIFO de ese tick.
Aumentar / reducir una orden abierta
decreaseLimitOrder solo puede retirar importe de la parte no ejecutada de la orden; la parte ejecutada queda bloqueada hasta la liquidación. Ambas instrucciones revierten con InvalidOrderPhase si la orden ya se ha ejecutado por completo.
Liquidar una orden ejecutada
settleLimitOrder lee unfilled_ratio_x64 de la orden frente al rastreador de la cohorte, calcula el importe ejecutado y lo transfiere al ATA del propietario. El propietario puede invocarlo él mismo; limit_order_admin (un keeper operativo off-chain) también puede hacerlo en nombre del propietario, y el importe seguirá yendo al propietario.
Para cerrar órdenes totalmente liquidadas y recuperar la renta, use closeLimitOrder (individual) o closeAllLimitOrder (por lotes). Para liquidar muchas a la vez, settleAllLimitOrder agrupa en una transacción v0 todas las llamadas SettleLimitOrder que quepan.
Listar las órdenes activas de una wallet (off-chain)
totalAmount / filledAmount / pendingSettle distinguen las fases). Para el historial de órdenes cerradas use /limit-order/history/order/list-by-user?wallet=… (por wallet, paginado con nextPageId); para el registro completo de eventos de una orden concreta use /limit-order/history/event/list-by-pda?pda=….
Esqueleto de CPI en Rust
SwapV2:
Errores comunes
- Extremos de tick que no coinciden con el espaciado →
TickAndSpacingNotMatch. Ajuste siempre los valores conTickUtil.getPriceAndTick(TickUtilen singular). - No se proporcionan suficientes tick arrays en
SwapV2→NotEnoughTickArrayAccount. Tome la lista deswapInternal(...).accounts. - Posición de rango completo sin la extensión de bitmap → la PDA de la extensión debe ser escribible. El SDK se encarga de esto automáticamente.
- Confundir
sqrt_price_x64conprice→ una confusión de factor 2 en este punto resulta especialmente costosa. En caso de duda, deje que el SDK calcule el valor a partir de un precio legible. - Recolectar recompensas con demasiada frecuencia → cada recolección es un
DecreaseLiquiditycon liquidez cero y cuesta una transacción. Agrúpelas conharvestAllRewardspara varias posiciones, y recuerde que suexecutenecesita{ sequentially: true }. - Cerrar por su cuenta las cuentas de NFT →
ClosePositionquema el NFT y cierra su ATA. También cierra el mint de un NFT de Token-2022; un mint de SPL Token clásico permanece con supply cero, porque ese programa no puede cerrar mints. No cierre por separado las cuentas admitidas, o la instrucción fallará. - Abrir una orden límite en un tick que no respeta el espaciado →
TickAndSpacingNotMatch. Cuantifique siempre el valor con el helper exportadogetOrderTick. - Llamar a
decreaseLimitOrdersobre una orden totalmente ejecutada →InvalidOrderPhase. UsesettleLimitOrdery despuéscloseLimitOrder. - Esperar un flag
enableDynamicFee→ no existe. Si omitedynamicFeeConfig, simplemente se crea un pool de comisión estática, sin aviso ni error. Si quiere comisiones dinámicas, pase elPublicKeyde la cuenta de configuración, tomado de/main/clmm-dynamic-config.
Próximos pasos
sdk-api/typescript-sdk: referencia completa del SDK.sdk-api/rest-api: endpoints de cotización y de metadatos de pools.user-flows/create-clmm-pool: guía paso a paso sin código.integration-guides/aggregator: cómo enrutar CLMM como parte de una ruta.

