Skip to main content
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 →
Esta página se complementa con products/clmm/accounts (qué son las cuentas) y products/clmm/math (qué es la matemática). Es autoritativa para argumentos y orden de cuentas; los diseños de bytes específicos provienen del IDL.La actualización del programa 2026-09 reconstruyó CLMM en Anchor 1.0.2 / Solana 3.1.10, agregó la instrucción de administrador CollectExcessLamports y cambió lo que CreateAmmConfig escribe en owner / fund_owner. Ninguna instrucción orientada al usuario cambió sus cuentas, argumentos o matemática. Consulta la entrada del registro de cambios 2026-09-30.La actualización del programa 2026-10-22 renombra CreatePermissionedPool a CreateCustomizablePoolV2, la hace invocable por cualquiera y elimina la cuenta Permission con sus dos instrucciones de administrador. Consulta la entrada del registro de cambios 2026-10-22.

Inventario de instrucciones

No hay instrucción de inicialización de matriz de ticks, y ninguna es necesaria. Una matriz de ticks se crea dentro de OpenPosition* / IncreaseLiquidity* por TickArrayState::get_or_create_tick_array, pagada por payer. Pasa el PDA de matriz de ticks (posiblemente aún no inicializado, propiedad del sistema) como tick_array_lower / tick_array_upper y el programa lo asigna si falta. OpenLimitOrder hace lo mismo para su único tick_array.
La mayoría de instrucciones solo de administrador (CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) están protegidas por la clave pública admin codificada del programa. CreateSupportMintAssociated / CloseSupportMintAssociated aceptan la clave pública admin o una clave de propietario de mint de soporte dedicada; CollectExcessLamports acepta la clave pública admin o una billetera de recopilación de lamports dedicada. Las instrucciones de administrador de flujo de recompensas (TransferRewardOwner, CollectRemainingRewards) están protegidas 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
Cuentas (abreviadas)
Las ranuras 10 y 11 son por mint, no “Token SPL luego Token-2022”. Cada una está restringida por mint::token_program en el mint correspondiente, por lo que para un pool cuyo token_mint_0 es Token-2022 y token_mint_1 es SPL clásico debes pasar Token-2022 en la ranura 10 y Token SPL en la ranura 11. CreateCustomizablePool y CreateCustomizablePoolV2 usan las mismas dos ranuras.
Precondiciones
  • token_mint_0 < token_mint_1 por orden de bytes.
  • amm_config.disable_create_pool == false.
  • Los mints no son rechazados por la lista de permisos de extensión Token-2022.
Postcondiciones
  • 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_info está en cero (comisión dinámica deshabilitada).

CreateCustomizablePool

Recomendado para nuevos pools. Mismo efecto que CreatePool más modo de recopilación de comisión por pool y una opción de comisión dinámica opcional. Argumentos
Cuentas — exactamente las 13 cuentas declaradas de CreatePool. dynamic_fee_config no es una cuenta declarada.
Cuando enable_dynamic_fee = true, el DynamicFeeConfig a capturar debe suministrarse como la última remaining_account — el manejador lee ctx.remaining_accounts.last(). Cualquier PDA de derivación SupportMintAssociated debe por lo tanto venir antes que ella, o el programa captura la cuenta incorrecta y falla la deserialización. Omitirla mientras la bandera está establecida falla con AccountLack.
Precondiciones — igual que CreatePool. Si enable_dynamic_fee = false, no se requiere remaining_account y cualquiera que se pase solo se escanea para registros de mint de soporte. Postcondiciones
  • pool_state.fee_on establecido en la variante CollectFeeOn elegida.
  • Si la comisión dinámica fue habilitada: pool_state.dynamic_fee_info se inicializa desde el DynamicFeeConfig suministrado (cinco parámetros de calibración copiados; campos de estado en cero).
  • De lo contrario: pool_state.dynamic_fee_info está en cero (= comisión dinámica inactiva para siempre para este pool).
fee_on y la bandera 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.

CreateCustomizablePoolV2

Tanto CreatePool como CreateCustomizablePool derivan el PDA del pool a partir de ["pool", amm_config, token_mint_0, token_mint_1], por lo que existe exactamente una dirección de pool canónica por cada tupla (config, mint0, mint1) — un segundo init con las mismas semillas falla. CreateCustomizablePoolV2 elimina esa restricción al incorporar 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. Cualquiera puede llamarlo. Todo lo demás sobre el pool es idéntico a CreateCustomizablePool: toma los mismos CreateCustomizableParams y admite comisión de un solo lado y la opción de comisión dinámica.
Hasta la actualización del 2026-10-22, esta instrucción se llamaba CreatePermissionedPool y requería que el pagador tuviera un PDA de Permission emitido por un administrador. La actualización la renombró, eliminó la cuenta permission y borró la maquinaria de permisos. El discriminador cambió con el nombre, por lo que los clientes compilados contra CreatePermissionedPool deben reconstruirse.
Argumentos
Cuentas remaining_accounts: los PDAs del registro de mints de soporte cuando un mint de Token-2022 los necesita, y el DynamicFeeConfig al final cuando enable_dynamic_fee = true — como en CreateCustomizablePool. Precondiciones
  • seed_index != 0. Un seed_index de 0 está reservado para pools heredados y se rechaza aquí; el componente de semilla [0, 0] es lo que hace que la dirección de un pool heredado se reduzca a la forma clásica de cuatro semillas.
  • No existe ningún pool en la dirección derivada.
  • Las mismas reglas de mint y lista de permitidos que CreatePool.
Postcondiciones
  • Existe un nuevo pool_state en la dirección derivada de seed_index, con pool_state.seed_index = seed_index.
  • Todo el resto del estado posterior coincide con CreateCustomizablePool (modo de comisión, comisión dinámica opcional).
Dado que pool_creator no se verifica, cualquier pagador puede escribir cualquier dirección en pool_state.owner. Esa dirección puede llamar a InitializeReward en el pool, pero no es prueba de quién creó el pool. Los integradores no deben etiquetar ni clasificar pools V2 por su owner.

OpenPositionV2 / OpenPositionWithToken22Nft

Crea una nueva posición dentro de un pool existente. Argumentos
Cuentas — las dos variantes tienen listas de cuentas diferentes. OpenPositionV2 declara 22; OpenPositionWithToken22Nft declara 20. OpenPositionV2, en orden: OpenPositionWithToken22Nft es la misma lista con metadata_account (5) y metadata_program (19) eliminados — escribe los metadatos de la posición a través de la extensión de metadatos de Token-2022 en el mint del NFT en su lugar — dando 20 cuentas. Su position_nft_mint es un Signer simple y position_nft_account es un UncheckedAccount.
tick_array_bitmap_extension no es una cuenta declarada en ninguna de las dos variantes. Cuando el rango de la posición cae fuera del tick_array_bitmap en línea del pool (±512 arrays de ticks), añade el PDA TickArrayBitmapExtension en las semillas ["pool_tick_array_bitmap_extension", pool_state] como remaining_accounts[0].
Matemáticas — 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 de pool.tick_spacing, dentro de [MIN_TICK, MAX_TICK].
  • Se pasan los dos PDAs de arrays de ticks. No necesitan existir ya — get_or_create_tick_array asigna uno faltante en payer’s expense dentro de esta instrucción. No hay una instrucción separada de inicialización de arrays de ticks.
  • El usuario tiene al menos amount_0_max y amount_1_max en los ATAs de origen.
Postcondiciones
  • personal_position existe, liquidity establecida, fee_growth_inside_last capturada.
  • Las entradas del array de ticks en tick_lower y tick_upper se actualizan (liquidity_gross += L, liquidity_net ± L, snapshots de crecimiento de comisión mantenidos).
  • pool_state.liquidity += L si la posición está en rango (tick_lower ≤ tick_current < tick_upper).
  • El mint del NFT de la posición registra pool_state como 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 OpenPositionV2 u OpenPositionWithToken22Nft y la autoridad de congelación de cualquiera de los mints de bóveda coincida con la lista de emisores restringidos de CLMM. Solo esa ruta V2 coincidente congela la cuenta. OpenPosition V1 no congela.
Errores comunes — 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 posiciones no añade cuentas de instrucción declaradas ni argumentos. Los clientes pueden abrir estas posiciones con los layouts V2 existentes. El comportamiento se selecciona en cadena a partir de vault_0_mint y vault_1_mint.

IncreaseLiquidityV2

Añade liquidez a una posición ya abierta. Argumentos
Cuentas — 15, y no derivables de OpenPosition: no hay rent, no hay system_program, no hay associated_token_program y no hay cuenta de metadatos. Antepone 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_actual de usuario → bóvedas.
  • Incrementa personal_position.liquidity y pool_state.liquidity (si está en rango), y el liquidity_gross / liquidity_net de los ticks de extremo en consecuencia.
  • Recauda comisiones y recompensas adeudadas desde el último toque y las acredita a token_fees_owed_{0,1} / reward_amount_owed. Estos se pagan solo en DecreaseLiquidity / DecreaseLiquidityV2, no en aumento — no hay una instrucción de recaudación independiente.

DecreaseLiquidityV2

Elimina liquidez de una posición. Argumentos
Cuentas — 16, y no la misma forma u orden que IncreaseLiquidityV2: personal_position y pool_state se intercambian, las bóvedas vienen antes de los arrays de ticks, las cuentas del lado del usuario se nombran recipient_token_account_*, y hay un memo_program adicional. Cuentas restantes — tres por cada recompensa activa siendo recaudada, en el orden reward_token_vault(W), recipient_token_account(W), reward_vault_mint. Antepone el PDA TickArrayBitmapExtension cuando el rango de la posición está fuera del bitmap en línea.
Esta es también la única forma de recaudar comisiones y recompensas. Para recaudar sin cambiar la posición, llámala con liquidity = 0, amount_0_min = 0, amount_1_min = 0.
Efecto
  • Calcula (amount_0, amount_1) para la L eliminada dado el sqrt_price_x64 actual.
  • Liquida comisiones/recompensas acumuladas desde el último toque, igual que IncreaseLiquidity.
  • Transfiere amount_0 + fees_owed_0 y amount_1 + fees_owed_1 fuera de las bóvedas al usuario.
  • Decrementa los contadores de liquidez; si el nuevo personal_position.liquidity == 0, la posición es elegible para ClosePosition.
Slippage — amount_0_min y amount_1_min son los mínimos que el usuario acepta netos de comisiones de transferencia de Token-2022 en el lado de salida.

ClosePosition

Quema el NFT de posición y cierra PersonalPositionState. Cuentas declaradas Cuentas restantes
  • NFT no congelado: ninguna requerida; una cuenta de pool adicional es inofensiva porque el manejador no la lee.
  • NFT congelado: añade personal_position.pool_id como la primera cuenta restante. El programa la carga como PoolState y usa sus semillas PDA para firmar el descongelamiento.
Precondiciones
  • personal_position.liquidity == 0.
  • tokens_fees_owed_{0,1} == 0.
  • Todos los contadores de recompensas reward_amount_owed == 0.
(Es decir, recopila todo y disminuye a cero primero.) Efecto
  • 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 la renta a nft_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.
El descongelamiento, quema y cierre son atómicos. El NFT no puede volverse transferible entre esos pasos. Ruptura de cliente condicional — el diseño IDL declarado no cambia, por lo que los clientes heredados continúan cerrando posiciones existentes y no congeladas. Un constructor heredado que omita la cuenta de pool restante falla con AccountLack al cerrar una posición congelada. Pasar el pool para cada cierre es la estrategia compatible más simple.

SwapV2

Recorre la curva de liquidez; entrada exacta o salida exacta según is_base_input. Argumentos
Cuentas (resumidas) Los llamadores pasan una lista clasificada de arrays de ticks que cubren el recorrido de swap esperado; el programa usa tantos como necesita. El SDK calcula esta lista mediante PoolUtils.computeAmountOutFormat o el endpoint de cotización de la API. Precondiciones
  • pool_state.status permite swap.
  • now >= open_time.
  • sqrt_price_limit_x64 está en el lado correcto de sqrt_price_x64 para la dirección.
Errores comunes — TooLittleOutputReceived (slippage entrada exacta), TooMuchInputPaid (slippage salida exacta), SqrtPriceLimitOverflow, NotEnoughTickArrayAccount, InvalidFirstTickArrayAccount, MissingTickArrayBitmapExtensionAccount, LiquidityInsufficient, NotApproved (bit de swap establecido en pool_state.status). CLMM no tiene variante ExceededSlippage — ese nombre es de CPMM — ni TickArrayNotFound. Lo que SwapV2 hace internamente que los llamadores deben saber (lanzamiento posterior a 2025):
  1. Recargo de tarifa dinámica — si pool.dynamic_fee_info es 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 de products/clmm/fees) y añade un dynamic_fee_component además de AmmConfig.trade_fee_rate. La tarifa total está limitada al 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000).
  2. Coincidencia de órdenes limitadas — cuando el recorrido de precio cruza un tick que contiene órdenes limitadas abiertas, el programa primero llena la liquidez de órdenes limitadas disponible en ese tick (FIFO por order_phase), luego procede a lo largo de la curva de liquidez de LP. Los montos llenados actualizan tick.unfilled_ratio_x64 y tick.part_filled_orders_remaining para liquidación posterior; las órdenes en sí permanecen sin gastar hasta que su propietario llama a SettleLimitOrder.
  3. Enrutamiento de tarifa unilateral — cuando pool.fee_on = Token0Only o Token1Only, el paso de swap aún calcula el mismo comercio entrada-salida; la tarifa se enruta entonces al lado configurado. Para direcciones donde el lado de tarifa configurado es la salida, la tarifa se deduce de la salida del swap (el usuario recibe out − fee); para direcciones donde es la entrada, el comportamiento coincide con FromInput. Consulta is_fee_on_input(zero_for_one) e is_fee_on_token0(zero_for_one) en PoolState.
Swap (V1) implementa la misma tarifa dinámica, enrutamiento de tarifa unilateral y coincidencia de órdenes limitadas que SwapV2; la única característica que le falta es soporte para Token-2022 — ambas bóvedas deben ser Token SPL clásico. Los pools con cualquier mint de Token-2022 deben intercambiarse mediante SwapV2. El agregador y el SDK ya prefieren V2 para cada rama CLMM, por lo que los llamadores no tienen que ramificarse según 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 llena cuando el precio la cruza. Argumentos
Cuentas (resumidas) Cuentas restantes — [0] tick_array_bitmap_extension, requerida solo cuando se inicializa un array de ticks cuyo índice de inicio cae fuera del bitmap en línea del pool. No pases nada en caso contrario.
No hay cuenta rent: la estructura termina en system_program, 13 cuentas declaradas. Un rent extraviado en la posición 14 cae exactamente donde se lee la extensión de bitmap opcional, por lo que la orden parece funcionar hasta la primera vez que un array de ticks fuera del bitmap en línea tiene que crearse — y luego falla.
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 llenado pueda liquidarse realmente a la ATA de salida del propietario, lo que importa para mints de Token-2022 con lista de permitidos / congelados por defecto (por ejemplo, tokens con permisos) donde una cuenta puede no estar aún descongelada. Los clientes construidos contra la lista de cuentas unilateral más antigua deben añadir las tres cuentas de salida.
Precondiciones
  • Ni input_token_account ni output_token_account están congeladas (en caso contrario NotApproved).
  • pool_state.status permite tanto operaciones de swap (bit 4) como de orden limitada (bit 5) (en caso contrario NotApproved).
  • tick_index % pool.tick_spacing == 0 y dentro de [MIN_TICK, MAX_TICK].
  • tick_index está en el lado derecho de pool.tick_current para la dirección elegida (vender token0 → tick debe estar por encima del actual, y viceversa). Vender en un tick ya cruzado sería igualado inmediatamente y se rechaza.
Postcondiciones
  • limit_order existe, capturando tick.order_phase y tick.unfilled_ratio_x64 en el momento de apertura.
  • tick.orders_amount += amount (en la cohorte actual).
  • limit_order_nonce.order_nonce += 1.
  • OpenLimitOrderEvent emitido.
Errores comunes — NotApproved (cuenta de token de entrada o salida congelada, o el pool tiene swap / orden limitada deshabilitada), ZeroAmountSpecified (amount == 0 después de la tarifa de transferencia del lado de entrada), InvalidLimitOrderAmount (la cantidad produciría una salida por debajo de 1 unidad base en ese tick, u overflow 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
Cuentas — 8, solo lado de entrada. Elimina la cuenta nonce, las tres cuentas del lado de salida y 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 llenarse, la orden está parcialmente liquidada — el llamador debe llamar primero a DecreaseLimitOrder o SettleLimitOrder para avanzar.
Efecto
  • Transfiere amount desde la ATA del propietario a input_vault.
  • limit_order.total_amount += amount; tick.orders_amount += amount.

DecreaseLimitOrder

Reduce o cancela completamente una orden abierta. Devuelve el resto sin llenar al propietario, más cualquier salida ya liquidada por llenados parciales anteriores. Argumentos
Cuentas — ambos lados de token de entrada y salida: Efecto
  • Recalcula la cantidad llenada de la orden desde unfilled_ratio_x64 de la cohorte desde la apertura.
  • Envía salida llenada a output_token_account.
  • Envía amount de entrada sin llenar de vuelta a input_token_account.
  • Actualiza limit_order en consecuencia. Si el nuevo resto sin llenar es cero, el programa cierra la cuenta y reembolsa la renta a owner.

SettleLimitOrder

Transfiere tokens de salida completados al propietario sin cambiar el resto sin llenar de la orden. Útil cuando los guardianes auto_withdraw quieren hacer pagos graduales en llenados parciales de larga duración. Llamador — ya sea el owner de la orden, o el limit_order_admin del programa (una billetera operativa 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 enviar la salida completada a la ATA owner de la orden. 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; sigue abierta contra cualquier entrada restante.

CloseLimitOrder

Cierra una cuenta de orden completamente consumida. La renta 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 sin llenar (ya sea que amount == total_amount se llenó y liquidó, o el propietario disminuyó previamente la orden a cero y olvidó cerrarla).
Efecto
  • Cierra limit_order; la renta se envía a limit_order.owner.

CreateDynamicFeeConfig (admin)

Crea un conjunto de parámetros reutilizable bajo un índice u16. Argumentos
Cuentas Errores comunes — InvalidDynamicFeeConfigParams si decay_period <= filter_period o cualquier campo con valor 0 está fuera de los límites.

UpdateDynamicFeeConfig (admin)

Modifica un DynamicFeeConfig existente. Los pools que ya capturaron la configuración en el momento de la 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 tarifas de protocolo/fondo acumuladas de las bóvedas del pool a 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 de 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.
Cambio en 2026-09: las nuevas configuraciones ya no toman sus propietarios de tarifas del firmante. create_amm_config ahora escribe el protocol_fee_owner::ID codificado del programa en owner y fund_fee_owner::ID en fund_owner. Antes, copiaba la clave del firmante administrador en ambos. En mainnet estas son las mismas claves ya almacenadas en las 21 configuraciones existentes. Las direcciones están en reference/program-addresses.Los firmantes aceptados anteriormente no cambian. El administrador aún puede cobrar de cualquier configuración, y las cuentas AmmConfig existentes no se reescriben. Lee owner / fund_owner de la cuenta en lugar de asumir ninguno de los valores. Los parámetros UpdateAmmConfig 3 y 4 aún los rotan.

CollectExcessLamports

Barrido administrativo de lamports por encima del mínimo exento de renta en cuentas que CLMM controla. Se agregó en la actualización 2026-09 para recuperar el exceso de financiamiento que la reducción de renta SIMD-0437 deja en cuentas creadas antes de cada paso. Solo se mueve el exceso. Los saldos de tokens, datos de cuenta, propietarios, estado del pool y la curva de precios no se tocan. Una cuenta ya en su mínimo se deja como está, por lo que la instrucción se puede ejecutar nuevamente de forma segura después de cada paso de implementación. Argumentos: ninguno. Cuentas Alcance: un pool por llamada. CLMM no tiene autoridad de bóveda a nivel de programa. Las bóvedas de cada pool son propiedad de su propio PoolState. Por lo tanto, cada fuente del programa de tokens debe tener el pool_state en la ranura 2 como su autoridad: token_vault_0, token_vault_1, o una de las bóvedas de recompensa de ese pool. Si pasas la bóveda de otro pool o la cuenta de token de un usuario, la verificación de propietario del programa de tokens falla y toda la instrucción se revierte. No se omite. Cómo se maneja cada cuenta de origen El programa hace dos pasadas sobre remaining_accounts: primero cada CPI del programa de tokens, luego los débitos directos. Intercalar los dos aborta con el error UnbalancedInstruction del tiempo de ejecución, por lo que el orden se fija en el programa y no tienes que ordenar la lista tú mismo.
La pasada 2 cubre cuentas cuya renta pagó un usuario. Un PersonalPositionState o LimitOrderState pasado aquí cede su exceso como cualquier otra cuenta propiedad de CLMM. Permanece exento de renta y mantiene sus datos. Cuando se cierre más tarde, el propietario recupera lo que la cuenta tenga en ese momento, que después de un barrido es el mínimo de renta actual.
El tamaño de la transacción es el límite real de cuántas fuentes caben en una llamada. Es la misma restricción que el barrido del lado de la billetera descrito en solana-fundamentals/rent-and-reclaimable-rent. Errores comunes:
  • NotApproved (6000): firmante incorrecto.
  • LamportsCalculateError (6052): el viaje de ida y vuelta de wSOL no llegó a cero.
  • Un error de falta de coincidencia de propietario del programa de tokens: una fuente de token no es propiedad de pool_state.
  • InsufficientFunds: una cuenta propiedad del programa tiene menos que su propio mínimo de renta.
Sin constructor SDK. @raydium-io/raydium-sdk-v2 no incluye un constructor para esta ruta de administrador. Codifícalo a mano desde el IDL.

InitializeReward

Agrega un nuevo flujo de recompensa a un pool. Hasta 3 flujos pueden estar activos a la vez. Argumentos — una única estructura, param: InitializeRewardParam:
La codificación de cable es los tres campos uno tras otro, por lo que una instrucción construida a mano no se ve afectada — pero un cliente impulsado por IDL debe pasar un objeto param en lugar de tres argumentos posicionales. Cuentas Precondiciones
  • Menos de 3 flujos activos actualmente 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 recompensa 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 una instrucción independiente porque actores externos (UIs, cranks) a veces quieren activarlo.

Recopilación de recompensas

No hay instrucción independiente de recopilación de recompensas. El programa no expone ningún punto de entrada CollectReward, y el IDL publicado tampoco tiene ninguno.
Las recompensas adeudadas a una posición se pagan mediante DecreaseLiquidity / DecreaseLiquidityV2. Para recopilar sin cambiar la posición, llámalo con liquidity = 0, amount_0_min = 0, amount_1_min = 0. Las bóvedas de recompensa y las cuentas de destinatario van en remaining_accounts en grupos de tres por recompensa activa, en el orden reward_token_vault(W), recipient_token_account(W), reward_vault_mint. CollectRemainingRewards es algo diferente: permite al financiador de recompensas, después del end_time de un flujo, barrer tokens que nunca se asignaron a ninguna posición.

Matriz de cambios de estado

Próximos pasos

Fuentes: