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 →
products/clmm/accounts (qué son las cuentas) y products/clmm/math (qué es la matemática). Es autorizada para argumentos y orden de cuentas; los diseños de bytes específicos provienen del IDL.
Inventario de instrucciones
No existe una instrucción de inicialización de matriz de tick, y no se necesita ninguna. Una
matriz de tick se crea dentro de
OpenPosition* / IncreaseLiquidity* mediante
TickArrayState::get_or_create_tick_array, pagada por payer. Pasa el PDA de la matriz de tick
(posiblemente aún sin inicializar y propiedad del sistema) como tick_array_lower /
tick_array_upper y el programa la asigna si falta. OpenLimitOrder hace lo mismo con su única
tick_array.CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) están controladas por la clave admin codificada del programa. CreatePermissionPda / ClosePermissionPda aceptan la clave admin o una clave dedicada permission_pda_admin; CreateSupportMintAssociated / CloseSupportMintAssociated aceptan la clave admin o una clave dedicada de propietario de mints soportados. Las instrucciones de administrador de flujo de recompensas (TransferRewardOwner, CollectRemainingRewards) están controladas por el financiador de recompensas, no por el administrador del programa.
El sufijo V2 significa “soporta Token-2022 en bóvedas/NFT, requiere ranura de extensión de mapa de bits”. El SDK elige V2 por defecto para nuevos pools.
CreatePool
Argumentos
Precondiciones
token_mint_0 < token_mint_1por orden de bytes.amm_config.disable_create_pool == false.- Los mints no son rechazados por la lista blanca de extensión Token-2022.
pool_state.sqrt_price_x64 = sqrt_price_x64,tick_current = floor(log_{1.0001}(price)).pool_state.liquidity = 0(sin posiciones aún).pool_state.fee_on = FromInput(predeterminado heredado).pool_state.dynamic_fee_infoestá en cero (comisión dinámica deshabilitada).
CreateCustomizablePool
Recomendado para nuevos pools. Mismo efecto que CreatePool más modo de recopilación de comisiones por pool y una opción de comisión dinámica opcional.
Argumentos
CreatePool. dynamic_fee_config no es una cuenta declarada.
Precondiciones — igual que CreatePool. Si enable_dynamic_fee = false, no se requiere ningún remaining_account y los que se pasen solo se analizan buscando registros de mints soportados.
Postcondiciones
pool_state.fee_onestablecido a la varianteCollectFeeOnelegida.- Si la comisión dinámica fue habilitada:
pool_state.dynamic_fee_infose inicializa desde elDynamicFeeConfigsuministrado (cinco parámetros de calibración copiados; campos de estado en cero). - De lo contrario:
pool_state.dynamic_fee_infoestá en cero (= comisión dinámica inactiva para siempre en este pool).
fee_on y el bit de habilitación de comisión dinámica se establecen solo en la creación del pool. No hay actualización in situ — los pools creados a través del CreatePool heredado no pueden obtener retroactivamente comisión dinámica o comisión de un lado. Las nuevas implementaciones deben usar esta instrucción por defecto.
CreatePermissionedPool
Tanto CreatePool como CreateCustomizablePool derivan el PDA del pool de ["pool", amm_config, token_mint_0, token_mint_1], por lo que hay exactamente un dirección de pool canónica por triple (config, mint0, mint1) — un segundo init en las mismas semillas falla. CreatePermissionedPool levanta esa restricción plegando un seed_index: u16 suministrado por el cliente en las semillas del PDA del pool, permitiendo múltiples pools para el mismo par y nivel de comisión — cada uno en su propia dirección. Debido a que una dirección de pool arbitraria es una capacidad privilegiada, el pagador debe tener un PDA Permission que lo autorice.
Todo lo demás sobre el pool es idéntico a CreateCustomizablePool: toma los mismos CreateCustomizableParams y soporta comisión de un lado y la opción de comisión dinámica.
Argumentos
CreateCustomizablePool más, al frente:
El PDA
pool_state se deriva de ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()].
Precondiciones
seed_index != 0. Unseed_indexde0está reservado para pools heredados y se rechaza aquí; el componente de semilla[0, 0]es lo que hace que una dirección de pool heredada se colapse a la forma clásica de cuatro semillas.- El PDA
permissionparapayerexiste (creado por un administrador a través deCreatePermissionPda). - Mismas reglas de mint/lista blanca que
CreatePool.
- Un nuevo
pool_stateexiste en la dirección derivada deseed_index, conpool_state.seed_index = seed_index. - Todo otro estado posterior coincide con
CreateCustomizablePool(modo de comisión, comisión dinámica opcional).
Esta instrucción no amplía el acceso general a la creación de pools — la creación sin permisos continúa a través de
CreatePool / CreateCustomizablePool, que permanecen como un pool por par. CreatePermissionedPool existe para el caso específico donde un operador en la lista blanca necesita varios pools para el mismo par (p. ej. precios iniciales diferentes o cohortes de lanzamiento) y tiene un PDA Permission otorgado por el administrador.OpenPositionV2 / OpenPositionWithToken22Nft
Crea una nueva posición dentro de un pool existente.
Argumentos
OpenPositionV2 declara 22; OpenPositionWithToken22Nft declara 20.
OpenPositionV2, en orden:
OpenPositionWithToken22Nft es la misma lista con metadata_account (5) y metadata_program (19) eliminadas — escribe los metadatos de la posición mediante la extensión de metadatos de Token-2022 en el mint del NFT — lo que da 20 cuentas. Su position_nft_mint es un Signer simple y position_nft_account una UncheckedAccount.
Matemática — ver products/clmm/math. Dado base_flag, el programa resuelve liquidity o (amount_0_max, amount_1_max) en la L real y los montos de token reales consumidos.
Precondiciones
tick_lower < tick_upper, ambos múltiplos depool.tick_spacing, dentro de[MIN_TICK, MAX_TICK].- Se pasan los dos PDAs de matriz de tick. No necesitan existir ya —
get_or_create_tick_arrayasigna la que falte a expensas depayerdentro de esta instrucción. No hay una instrucción separada de inicialización de matriz de tick. - El usuario tiene al menos
amount_0_maxyamount_1_maxen las ATAs de fuente.
personal_positionexiste,liquidityestablecida,fee_growth_inside_lastcapturada.- Entradas de matriz de tick en
tick_lowerytick_upperactualizadas (liquidity_gross += L,liquidity_net ± L, instantáneas de crecimiento de comisión mantenidas). pool_state.liquidity += Lsi la posición está en rango (tick_lower ≤ tick_current < tick_upper).- El mint del NFT de posición registra
pool_statecomo autoridad de congelación. La autoridad de acuñación se elimina después de que se acuña el único NFT. Registrar la autoridad de congelación no cambia el estado de la cuenta de token del NFT. - La cuenta de token del NFT permanece descongelada a menos que la instrucción sea
OpenPositionV2uOpenPositionWithToken22Nfty la autoridad de congelación de cualquier mint de bóveda coincida con la lista de emisores restringidos de CLMM. Solo esa ruta V2 coincidente congela la cuenta.OpenPositionV1 no congela.
TickInvalidOrder (tick_lower >= tick_upper), TickAndSpacingNotMatch (un extremo no es múltiplo de tick_spacing), InvalidTickIndex (fuera de [MIN_TICK, MAX_TICK]), MissingTickArrayBitmapExtensionAccount (rango fuera del bitmap en línea y la extensión no fue añadida), NotApproved (pool_state.status bloquea la apertura), ZeroAmountSpecified.
La congelación de posición no añade cuentas de instrucción declaradas o argumentos. Los clientes pueden abrir estas posiciones con los diseños V2 existentes. El comportamiento se selecciona en cadena desde
vault_0_mint y vault_1_mint.IncreaseLiquidityV2
Añade liquidez a una posición ya abierta.
Argumentos
OpenPosition: no hay rent, ni system_program, ni associated_token_program ni cuenta de metadatos.
Añade al principio el PDA
TickArrayBitmapExtension como remaining_accounts[0] cuando el rango de la posición esté fuera del bitmap en línea.
Efecto
- Transfiere
amount_0_actual/amount_1_actualdel usuario → bóvedas. - Incrementa
personal_position.liquidityypool_state.liquidity(si está en rango), y elliquidity_gross/liquidity_netdel tick de punto final en consecuencia. - Recopila comisiones y recompensas adeudadas desde el último toque y las acredita a
token_fees_owed_{0,1}/reward_amount_owed. Esos se pagan solo enDecreaseLiquidity/DecreaseLiquidityV2, no en el aumento — no existe una instrucción de cobro independiente.
DecreaseLiquidityV2
Elimina liquidez de una posición.
Argumentos
IncreaseLiquidityV2: personal_position y pool_state están intercambiadas, las bóvedas van antes de las matrices de tick, las cuentas del lado del usuario se llaman recipient_token_account_*, y hay un memo_program extra.
Cuentas restantes — tres por cada recompensa activa que se esté cobrando, en el orden
reward_token_vault(W), recipient_token_account(W), reward_vault_mint. Añade al principio el PDA TickArrayBitmapExtension cuando el rango de la posición esté fuera del bitmap en línea.
Esta es también la única manera de cobrar comisiones y recompensas. Para cobrar sin cambiar
la posición, llámala con
liquidity = 0, amount_0_min = 0, amount_1_min = 0.- Calcula
(amount_0, amount_1)para laLeliminada dado elsqrt_price_x64actual. - Liquida comisiones/recompensas acumuladas desde el último toque, igual que
IncreaseLiquidity. - Transfiere
amount_0 + fees_owed_0yamount_1 + fees_owed_1fuera de las bóvedas al usuario. - Decrementa contadores de liquidez; si el nuevo
personal_position.liquidity == 0, la posición es elegible paraClosePosition.
amount_0_min y amount_1_min son los mínimos que el usuario acepta netos de comisiones de transferencia Token-2022 en el lado de salida.
ClosePosition
Quema el NFT de posición y cierra PersonalPositionState.
Cuentas declaradas
Cuentas restantes
- NFT descongelado: ninguno requerido; una cuenta de pool adicional es inofensiva porque el controlador no la lee.
- NFT congelado: añade
personal_position.pool_idcomo la primera cuenta restante. El programa la carga comoPoolStatey usa sus semillas de PDA para firmar el descongelamiento.
personal_position.liquidity == 0.tokens_fees_owed_{0,1} == 0.- Todos los contadores de recompensas
reward_amount_owed == 0.
- Si la cuenta de token del NFT está congelada, verifica que la primera cuenta restante sea igual a
personal_position.pool_id, luego la descongela con el PDA del pool. - Quema el NFT.
- Cierra la cuenta de token del NFT y
personal_position, reembolsando alquiler anft_owner. Si el NFT de posición usa Token-2022, también cierra el mint del NFT; los mints de Token SPL clásico no pueden cerrarse y permanecen con suministro cero.
AccountLack al cerrar una posición congelada. Pasar el pool para cada cierre es la estrategia compatible más simple.
SwapV2
Camina por la curva de liquidez; entrada exacta o salida exacta dependiendo de is_base_input.
Argumentos
Los llamadores pasan una lista clasificada de matrices de tick que cubren el recorrido de swap esperado; el programa usa tantas como necesita. El SDK calcula esta lista a través de
PoolUtils.computeAmountOutFormat o el punto final de cotización de la API.
Precondiciones
pool_state.statuspermite swap.now >= open_time.sqrt_price_limit_x64está en el lado correcto desqrt_price_x64para la dirección.
TooLittleOutputReceived (slippage de entrada exacta), TooMuchInputPaid (slippage de salida exacta), SqrtPriceLimitOverflow, NotEnoughTickArrayAccount, InvalidFirstTickArrayAccount, MissingTickArrayBitmapExtensionAccount, LiquidityInsufficient, NotApproved (bit de swap activado en pool_state.status). CLMM no tiene ninguna variante ExceededSlippage — ese nombre es de CPMM — ni TickArrayNotFound.
Lo que SwapV2 hace internamente que los llamadores deben saber (lanzamiento posterior a 2025):
- Recargo de comisión dinámica — si
pool.dynamic_fee_infoes distinto de cero, el programa actualiza el acumulador de volatilidad usando la distancia de tick recorrida desde el último swap (con las reglas de filtro/decaimiento deproducts/clmm/fees) y añade undynamic_fee_componentencima deAmmConfig.trade_fee_rate. La comisión total está limitada al 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000). - Coincidencia de órdenes limitadas — cuando el recorrido de precio cruza un tick que contiene órdenes limitadas abiertas, el programa primero completa la liquidez de orden limitada disponible en ese tick (FIFO por
order_phase), luego procede a lo largo de la curva de liquidez de LP. Los montos completados actualizantick.unfilled_ratio_x64ytick.part_filled_orders_remainingpara liquidación posterior; las órdenes en sí permanecen sin gastar hasta que su propietario llama aSettleLimitOrder. - Enrutamiento de comisión de un lado — cuando
pool.fee_on = Token0OnlyoToken1Only, el paso de swap aún calcula el mismo comercio entrada-salida; la comisión se enruta entonces al lado configurado. Para direcciones donde el lado de comisión configurado es la salida, la comisión se deduce de la salida del swap (el usuario recibeout − fee); para direcciones donde es la entrada, el comportamiento coincide conFromInput. Veris_fee_on_input(zero_for_one)eis_fee_on_token0(zero_for_one)enPoolState.
Swap (V1) implementa la misma comisión dinámica, enrutamiento de comisión de un lado y coincidencia de órdenes limitadas que SwapV2; la única característica que le falta es soporte Token-2022 — ambas bóvedas deben ser Token SPL clásico. Los pools con cualquier mint Token-2022 deben ser intercambiados a través de SwapV2. El agregador y el SDK ya prefieren V2 para cada rama CLMM, por lo que los llamadores no tienen que ramificarse en el tipo de mint.
OpenLimitOrder
Coloca una orden de venta en un tick específico. La orden se sienta en una cohorte FIFO por tick y se completa cuando el precio cruza.
Argumentos
Cuentas restantes —
[0] tick_array_bitmap_extension, requerida solo al inicializar una matriz de tick cuyo índice de inicio cae fuera del bitmap en línea del pool. No pases nada en caso contrario.
Cambio de lista de cuentas (lanzamiento 2026-07).
OpenLimitOrder ahora también toma las cuentas del lado de salida — output_token_account, output_vault y output_vault_mint — además del lado de entrada. Se usan solo para validación: el programa rechaza la orden si la cuenta de token de entrada o salida del propietario está congelada. Esto garantiza que un relleno pueda liquidarse realmente a la ATA de salida del propietario, lo que importa para mints Token-2022 de lista blanca/congelados por defecto (p. ej. tokens permisionados) donde una cuenta puede no estar aún descongelada. Los clientes construidos contra la lista de cuentas de un solo lado anterior deben añadir las tres cuentas de salida.- Ni
input_token_accountnioutput_token_accountestán congeladas (de lo contrarioNotApproved). pool_state.statuspermite tanto la operación de swap (bit 4) como la de orden limitada (bit 5) (de lo contrarioNotApproved).tick_index % pool.tick_spacing == 0y dentro de[MIN_TICK, MAX_TICK].tick_indexestá en el lado correcto depool.tick_currentpara la dirección elegida (vender token0 → tick debe estar arriba del actual, y viceversa). Vender en un tick ya cruzado sería coincidido inmediatamente y se rechaza.
limit_orderexiste, capturandotick.order_phaseytick.unfilled_ratio_x64en el momento de apertura.tick.orders_amount += amount(en la cohorte actual).limit_order_nonce.order_nonce += 1.OpenLimitOrderEventemitido.
NotApproved (cuenta de token de entrada o salida congelada, o el pool tiene swap/orden limitada deshabilitada), ZeroAmountSpecified (amount == 0 después de la comisión de transferencia del lado de entrada), InvalidLimitOrderAmount (la cantidad produciría una salida por debajo de 1 unidad base en ese tick, o desbordaría u64), InvalidTickIndex (fuera de [MIN_TICK, MAX_TICK], o en el lado incorrecto de tick_current para la dirección elegida), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.
IncreaseLimitOrder
Añade a una orden abierta existente. Solo puede ser llamada por el owner de la orden.
Argumentos
system_program.
Precondiciones
limit_order.owner == signer.- La orden aún está en la misma cohorte (
tick.order_phase == limit_order.order_phase). Si la cohorte ya ha comenzado a completarse, la orden está parcialmente liquidada — el llamador debe llamar aDecreaseLimitOrderoSettleLimitOrderprimero para avanzar.
- Transfiere
amountde la ATA del propietario ainput_vault. limit_order.total_amount += amount;tick.orders_amount += amount.
DecreaseLimitOrder
Reduce o cancela completamente una orden abierta. Paga el resto no completado de vuelta al propietario, más cualquier salida ya liquidada por rellenos parciales anteriores.
Argumentos
Efecto
- Recalcula el monto completado de la orden desde el
unfilled_ratio_x64de la cohorte desde la apertura. - Envía salida completada a
output_token_account. - Envía
amountde entrada no completada de vuelta ainput_token_account. - Actualiza
limit_orderen consecuencia. Si el nuevo resto no completado es cero, el programa cierra la cuenta y reembolsa alquiler aowner.
SettleLimitOrder
Empuja tokens de salida completados al propietario sin cambiar el resto no completado de la orden. Útil cuando los guardianes auto_withdraw quieren pagar gradualmente rellenos parciales de larga duración.
Llamador — ya sea el owner de la orden, o el limit_order_admin del programa (una billetera caliente operacional fuera de cadena que ejecuta un bucle de guardián automatizado). El guardián no tiene otra autoridad — no puede mover fondos de usuario fuera de empujar salida completada a la ATA owner.
Cuentas
Efecto
- Calcula la salida acumulada adeudada usando
(limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64). - Transfiere el delta a
output_token_account. - Actualiza
limit_order.settled_output. - No cierra la orden; aún está abierta contra cualquier entrada restante.
CloseLimitOrder
Cierra una cuenta de orden completamente consumida. El alquiler siempre se devuelve a limit_order.owner independientemente de quién firme.
Llamador — ya sea owner o limit_order_admin.
Precondiciones
- La orden tiene cero resto no completado (ya sea
amount == total_amountfue completado y liquidado, o el propietario disminuyó previamente la orden a cero y olvidó cerrar).
- Cierra
limit_order; el alquiler se envía alimit_order.owner.
CreateDynamicFeeConfig (admin)
Crea un conjunto de parámetros reutilizable bajo un índice u16.
Argumentos
Errores comunes —
InvalidDynamicFeeConfigParams si decay_period <= filter_period o cualquier campo con valor 0 está fuera de límites.
UpdateDynamicFeeConfig (admin)
Modifica un DynamicFeeConfig existente. Los pools que ya capturaron la configuración en el momento de creación no se actualizan retroactivamente; solo los pools recién creados que hagan referencia a esta configuración recogerán los nuevos valores.
Argumentos — los mismos cinco campos de calibración que CreateDynamicFeeConfig (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator); index se fija en la creación y no se repasa aquí.
CollectProtocolFee / CollectFundFee
Barre las comisiones de protocolo/fondo acumuladas de las bóvedas del pool hacia un destinatario, poniendo a cero los campos correspondientes PoolState.protocol_fees_* / fund_fees_*. Este no es el diseño de CPMM — CLMM no tiene cuenta authority, y los campos del destinatario se llaman recipient_token_account_{0,1} en lugar de recipient_token_{0,1}_account.
Argumentos — amount_0_requested: u64, amount_1_requested: u64.
InitializeReward
Añade un nuevo flujo de recompensas a un pool. Hasta 3 flujos pueden estar activos a la vez.
Argumentos — un único argumento param, de tipo param: InitializeRewardParam:
param en lugar de tres argumentos posicionales.
Cuentas
Precondiciones
- Menos de 3 flujos actualmente activos en el pool.
- El financiador deposita
total_emission = emissions_per_second × (end_time − open_time)de token de recompensa en la bóveda como parte de esta instrucción. - Mint de recompensa en la lista blanca por
operation_state.
SetRewardParams
Extiende, recarga o cambia la tasa de emisión en un flujo de recompensas existente. Típicamente llamado por un creador de pool o el multisig de Raydium. Las restricciones viven en cadena: generalmente puedes extender end_time o aumentar emisiones, no reducirlas retroactivamente. Verifica la lista de propietarios de operation_state.
UpdateRewardInfos
Pura contabilidad — liquida reward_growth_global_x64 al tiempo actual multiplicando emissions_per_second × Δt / liquidity. Llamado internamente por cada instrucción que toca liquidez. Expuesto como instrucción independiente porque actores externos (UIs, cranks) a veces quieren activarlo.
Collecting rewards
Las recompensas adeudadas a una posición se pagan medianteDecreaseLiquidity / DecreaseLiquidityV2.
Para cobrar sin cambiar la posición, llámala con liquidity = 0, amount_0_min = 0, amount_1_min = 0.
Las bóvedas de recompensas y las cuentas de destinatario van en remaining_accounts en grupos de tres
por cada recompensa activa, en el orden reward_token_vault(W), recipient_token_account(W), reward_vault_mint.
CollectRemainingRewards es algo distinto: permite al financiador de la recompensa, después del
end_time de un flujo, barrer los tokens que nunca se asignaron a ninguna posición.
Matriz de cambio de estado
Dónde ir a continuación
products/clmm/code-demos— muestras de TypeScript ejecutables.products/clmm/fees— detalles sobre acumulación de comisiones y recompensas.reference/error-codes— tabla completa de errores de Anchor de CLMM.
raydium-io/raydium-clmm—programs/amm/src/instructions- Raydium SDK v2 —
@raydium-io/raydium-sdk-v2

