> ## 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.

# Contas CLMM

> Cada conta que um pool CLMM toca: PoolState, AmmConfig, TickArrayState, TickArrayBitmapExtension, PersonalPositionState e Observation.

<Info>
  **Esta página foi traduzida automaticamente por IA. A versão em inglês é a fonte oficial.**

  [Ver versão em inglês →](/products/clmm/accounts)
</Info>

<Info>
  Esta página descreve o **layout e o papel** de cada conta. As seeds são canônicas e estão listadas em [`reference/program-addresses`](/pt/reference/program-addresses). Um pool CLMM é mais pesado em contas do que um pool CPMM porque a liquidez é armazenada de forma esparsa ao longo do intervalo de ticks; entender essa esparsidade é a maior parte desta página.
</Info>

## Inventário de contas

Um pool CLMM ativo é descrito pelas seguintes famílias de contas. Todas são de propriedade do programa CLMM, exceto os dois mints e seus vaults.

| Conta | Propósito | Quantidade por pool |
| - | - | - |
| `AmmConfig` | Camada de taxa: taxa de negociação, compartilhamento de protocolo, compartilhamento de fundo, espaçamento de tick padrão. Compartilhado entre todos os pools nesta camada. | 1 (compartilhado) |
| `PoolState` | `sqrt_price_x64` atual, tick atual, liquidez total, globals de crescimento de taxa, informações de recompensa, ponteiro de observação. | 1 |
| `TickArrayState` | Um bloco de `TICK_ARRAY_SIZE` ticks adjacentes. Inicializado apenas sob demanda. | 0 ≤ N ≤ intervalo |
| `TickArrayBitmapExtension` | Bitmap de overflow rastreando quais arrays de ticks existem além do bitmap inline em `PoolState`. | 0 ou 1 |
| `PersonalPositionState` | Um por posição de LP. Armazena o intervalo, liquidez e último crescimento de taxa/recompensa visto. Authority = proprietário do NFT. | 1 por posição |
| Mint de NFT de posição | Mint com suprimento 1, associado a `PersonalPositionState`. Sua conta de token é descongelada por padrão; uma V2 aberta a congela apenas quando um mint subjacente corresponde ao filtro de emissor restrito. | 1 por posição |
| `ObservationState` | Buffer circular de observações de preço para o TWAP. | 1 |
| `token_0_vault`, `token_1_vault` | Contas de token mantendo os saldos do pool. De propriedade da autoridade do pool. | 2 |
| `DynamicFeeConfig` | Conjunto de parâmetros reutilizável para o mecanismo de taxa dinâmica. Pools criados via `create_customizable_pool` podem optar por participar. Gerenciado por admin. | compartilhado (por índice) |
| `LimitOrderState` | Um por ordem de limite aberta. Registra proprietário, tick, lado, quantidade total, snapshot de saída liquidada. | 1 por ordem |
| `LimitOrderNonce` | Contador por `(wallet, nonce_index)` que deriva PDAs de ordem únicos. | 1 por (wallet, índice) |
| `Permission` | Concede à sua autoridade o direito de chamar `CreatePermissionedPool`. A existência do PDA **é** a concessão. Gerenciado por admin. | 1 por criador autorizado |

## `PoolState`

O estado ativo do pool, lido em cada swap e cada mudança de posição.

```rust theme={null}
// programs/amm/src/states/pool.rs
pub struct PoolState {
    pub bump:           [u8; 1],
    pub amm_config:     Pubkey,            // fee tier binding
    pub owner:          Pubkey,            // admin (multisig)
    pub token_mint_0:   Pubkey,
    pub token_mint_1:   Pubkey,
    pub token_vault_0:  Pubkey,
    pub token_vault_1:  Pubkey,
    pub observation_key: Pubkey,

    pub mint_decimals_0: u8,
    pub mint_decimals_1: u8,
    pub tick_spacing:   u16,               // inherited from amm_config at init

    pub liquidity:      u128,              // total active (in-range) liquidity
    pub sqrt_price_x64: u128,              // Q64.64 of sqrt(price)
    pub tick_current:   i32,               // current tick index

    pub padding3:       u16,
    pub padding4:       u16,

    // Global fee growth per unit of liquidity, Q64.64.
    pub fee_growth_global_0_x64: u128,
    pub fee_growth_global_1_x64: u128,

    // Accrued-but-not-swept protocol fees (per mint).
    pub protocol_fees_token_0: u64,
    pub protocol_fees_token_1: u64,

    // Reserved padding for future upgrades.
    pub padding5: [u128; 4],

    // Status bitmask. Bits 0-5: open-position, decrease-liquidity,
    // collect-fee, collect-reward, swap, limit-order. A set bit disables
    // the corresponding operation.
    pub status:  u8,

    // Fee-collection mode (CollectFeeOn).
    //   0 = FromInput (deduct fee from the swap input — Uniswap-V3 default)
    //   1 = Token0Only (always deduct fee from token0 vault)
    //   2 = Token1Only (always deduct fee from token1 vault)
    pub fee_on: u8,

    // Client-supplied index (u16 LE) folded into the pool PDA seeds by
    // create_permissioned_pool. [0, 0] for pools created via CreatePool /
    // CreateCustomizablePool (the seed component collapses to empty).
    pub seed_index: [u8; 2],
    pub padding: [u8; 4],

    // Live reward streams (up to REWARD_NUM = 3).
    pub reward_infos: [RewardInfo; 3],

    // Inline bitmap tracking initialized tick-arrays in the primary range.
    pub tick_array_bitmap: [u64; 16],

    // Reserved padding for future upgrades.
    pub padding6: [u64; 4],

    pub fund_fees_token_0: u64,
    pub fund_fees_token_1: u64,

    pub open_time:    u64,                 // currently disabled by the program
    pub recent_epoch: u64,

    // Per-pool dynamic-fee state. Zero-valued unless the pool was
    // created with `enable_dynamic_fee = true` via create_customizable_pool.
    pub dynamic_fee_info: DynamicFeeInfo,

    // Reserved for future upgrades.
    pub padding1: [u64; 14],
    pub padding2: [u64; 32],
}
```

Campos que você realmente vai tocar:

* **`sqrt_price_x64`** e **`tick_current`** são o estado de preço do pool. Eles são atualizados juntos em cada swap. `tick_current` é o piso de `log_{1.0001}(price)`.
* **`liquidity`** é a liquidez **ativa** — a soma dos valores `L` para todas as posições cujo intervalo contém `tick_current`. Muda toda vez que um swap cruza um tick e toda vez que uma posição é aberta/fechada/redimensionada.
* **`fee_growth_global_{0,1}_x64`** são as taxas cumulativas ganhas por unidade de liquidez em todo o histórico do pool. As posições leem isso para calcular o que lhes é devido.
* **`tick_spacing`** é bloqueado no `AmmConfig` na inicialização e nunca muda. Determina quais índices de tick são permitidos como endpoints de posição.
* **`tick_array_bitmap`** é um bitmap **inline** cobrindo o intervalo de ticks comumente usado ao redor do preço spot. Para pools cujas posições alcançam muito longe, o rastreamento de overflow vive na `TickArrayBitmapExtension` separada.
* **`fee_on`** é fixo na criação do pool. `0` (FromInput) reproduz o comportamento clássico do Uniswap-V3. `1` e `2` roteiam a taxa de swap para um único lado do livro — veja [`products/clmm/fees`](/pt/products/clmm/fees) para trade-offs.
* **`seed_index`** é `[0, 0]` para cada pool criado através de `CreatePool` / `CreateCustomizablePool` (um pool canônico por par). Um valor **não-zero** significa que o pool foi criado via `CreatePermissionedPool` e o índice faz parte das seeds do PDA do pool, permitindo que vários pools coexistam para o mesmo `(config, mint0, mint1)`. Para re-derivar o endereço de tal pool você deve conhecer seu `seed_index`.
* **`dynamic_fee_info`** carrega o estado de volatilidade para a sobretaxa de taxa dinâmica. Quando habilitado, cada swap recalcula um `dynamic_fee_component` além de `AmmConfig.trade_fee_rate`. O layout é documentado sob `DynamicFeeInfo` abaixo; pools sem taxa dinâmica deixam toda a struct em zero.

## `AmmConfig`

```rust theme={null}
pub struct AmmConfig {
    pub bump: u8,
    pub index: u16,                       // uses "amm_config"+u16 seed

    pub owner:             Pubkey,        // protocol-fee owner (CollectProtocolFee)
    pub protocol_fee_rate: u32,           // fraction of trade fee to protocol, denom 1e6
    pub trade_fee_rate:    u32,           // trade fee in 1e6ths of volume
    pub tick_spacing:      u16,           // default spacing for pools using this config
    pub fund_fee_rate:     u32,           // fraction of trade fee to fund, denom 1e6
    pub padding_u32: u32,

    pub fund_owner: Pubkey,               // fund-fee owner (CollectFundFee)
    pub padding: [u64; 3],
}
```

Desde a atualização de 2026-09, `CreateAmmConfig` escreve o `protocol_fee_owner::ID` codificado do programa em `owner` e `fund_fee_owner::ID` em `fund_owner`. Antes disso, copiava a chave do signatário admin em ambos. As configs existentes mantêm o que foram criadas ou rotacionadas para, então leia ambos os campos da conta. Os parâmetros `UpdateAmmConfig` `3` / `4` ainda os rotacionam. Os endereços estão em [`reference/program-addresses`](/pt/reference/program-addresses#clmm-fee-owner-wallets).

Um conjunto típico publicado de camadas de taxa CLMM (confirme contra `GET https://api-v3.raydium.io/main/clmm-config`):

| Índice | `trade_fee_rate` | Espaçamento de tick | Uso típico |
| - | - | - | - |
| 0 | `100` (0.01%) | 1 | Pares estáveis, USDC/USDT |
| 1 | `500` (0.05%) | 10 | Blue-chips correlacionados |
| 2 | `2_500` (0.25%) | 60 | Pares padrão |
| 3 | `10_000` (1.00%) | 120 | Volátil ou long-tail |

`protocol_fee_rate` e `fund_fee_rate` são frações da taxa de negociação; mesma convenção que CPMM. Veja [`products/clmm/fees`](/pt/products/clmm/fees).

## `TickArrayState`

CLMM não armazena um único registro por tick. Isso seria bilhões de contas. Em vez disso, agrupa **`TICK_ARRAY_SIZE` ticks adjacentes inicializados ou não** (tipicamente 60 ou 88 dependendo da versão do programa) em um `TickArrayState` que é criado preguiçosamente no primeiro uso.

```rust theme={null}
pub const TICK_ARRAY_SIZE: usize = 60;
pub const TICK_ARRAY_SIZE_USIZE: usize = 60;

pub struct TickArrayState {
    pub pool_id:                Pubkey,
    pub start_tick_index:       i32,                            // lowest tick in this array
    pub ticks:                  [TickState; TICK_ARRAY_SIZE],   // 60 entries
    pub initialized_tick_count: u8,
    pub recent_epoch:           u64,
    pub padding:                [u8; 107],
}

pub struct TickState {
    pub tick:                       i32,
    pub liquidity_net:              i128,                       // ΔL when crossing this tick upward
    pub liquidity_gross:            u128,                       // total L referencing this tick
    pub fee_growth_outside_0_x64:   u128,                       // see math.mdx
    pub fee_growth_outside_1_x64:   u128,
    pub reward_growths_outside_x64: [u128; 3],

    // Limit-order bookkeeping. All zero for ticks that have never carried
    // a limit order. See products/clmm/math for the matching algorithm.
    pub order_phase:                  u64,                      // monotonic FIFO cohort id
    pub orders_amount:                u64,                      // unfilled tokens in current cohort
    pub part_filled_orders_remaining: u64,                      // remaining tokens of partially-filled cohort
    pub unfilled_ratio_x64:           u128,                     // Q64.64; starts at 1.0 and shrinks as fills occur

    pub padding:                    [u32; 3],
}
```

Os quatro campos de ordem de limite são zero em qualquer tick que nunca foi usado para uma ordem de limite. Quando ordens são abertas em um tick, o programa as rastreia como uma sequência de coortes:

* `order_phase` é o id da coorte. Incrementa toda vez que uma coorte faz a transição de "totalmente não preenchida" para "parcialmente preenchida".
* `orders_amount` é o total de token de entrada da coorte atual (mais nova).
* `part_filled_orders_remaining` rastreia a coorte anterior que está sendo preenchida por swaps contínuos.
* `unfilled_ratio_x64` é um multiplicador Q64.64 carregado na coorte: quando um swap preenche X% da coorte, a razão é multiplicada por `(1 − X)`. Cada ordem aberta armazena seu próprio snapshot `(order_phase, unfilled_ratio_x64)` no tempo de abertura, então a matemática de liquidação se reduz a comparar snapshots.

Regras:

* Um tick de endpoint de posição *t* deve satisfazer `t % tick_spacing == 0`. O programa rejeita posições fora do espaçamento.
* O **array** do tick está localizado em `floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing)`.
* Um array de ticks é inicializado preguiçosamente: a primeira posição ou swap que toca um array não inicializado o cria, pagando o aluguel.
* Um array de ticks é **nunca fechado** pelo programa. Uma vez alocado, persiste pela vida do pool, mesmo depois que cada tick dentro dele retorna a `liquidity_gross == 0`. Posições e swaps subsequentes reutilizam a conta existente sem aluguel extra. Não há caminho de limpeza acionado por `ClosePosition` para arrays de ticks.

### `TickArrayBitmapExtension`

`PoolState.tick_array_bitmap` (inline) cobre o intervalo "perto do spot" — **±512** arrays de ticks (`TICK_ARRAY_BITMAP_SIZE = 512`; o campo `[u64; 16]` é 1.024 bits divididos uniformemente entre índices de início negativos e positivos, então índices de array −512 … +511). Fora desse intervalo (para valores de tick extremos), o programa mantém uma conta de extensão:

```rust theme={null}
pub struct TickArrayBitmapExtension {
    pub pool_id: Pubkey,
    pub positive_tick_array_bitmap: [[u64; 8]; 14],
    pub negative_tick_array_bitmap: [[u64; 8]; 14],
}
```

Se o intervalo da sua posição é "normal", você nunca pensa na conta de extensão. Posições de intervalo completo (por exemplo, `(MIN_TICK, MAX_TICK)`) a requerem; o SDK a resolve para você.

## Posições

Uma posição CLMM é um **pacote** de três contas mais um mint:

### Mint de NFT de posição

Um mint SPL Token ou Token-2022 com suprimento 1. O NFT de posição na carteira do proprietário é uma ATA mantendo esse único token. O programa vincula a autorização ao **detentor atual do saldo da ATA do NFT**, não a uma Pubkey armazenada no estado.

Novos mints de NFT de posição definem `pool_state` como sua autoridade de congelamento antes de cunhar o único token e remover a autoridade de mint. **Definir uma autoridade de congelamento não congela a conta do NFT por si só.** A conta permanece descongelada e transferível a menos que ambas as condições se mantenham: o chamador usa `OpenPositionV2` ou `OpenPositionWithToken22Nft`, e a autoridade de congelamento de pelo menos um mint de vault subjacente aparece na lista de emissores restritos do CLMM. Apenas então o CLMM congela a conta do NFT após cunhar. Isso não muda nenhum byte de `PersonalPositionState` ou `PoolState`.

### `PersonalPositionState`

Um por posição aberta. Chaveado no mint do NFT.

```rust theme={null}
pub struct PersonalPositionState {
    pub bump: [u8; 1],
    pub nft_mint: Pubkey,                 // this position's NFT mint
    pub pool_id:  Pubkey,

    pub tick_lower_index: i32,
    pub tick_upper_index: i32,

    pub liquidity: u128,                  // this position's L

    // Fee-growth snapshots at last time the position was touched.
    pub fee_growth_inside_0_last_x64: u128,
    pub fee_growth_inside_1_last_x64: u128,
    pub token_fees_owed_0: u64,           // accrued since last collect
    pub token_fees_owed_1: u64,

    pub reward_infos: [PositionRewardInfo; 3],
    pub recent_epoch: u64,
    pub padding: [u64; 7],
}

pub struct PositionRewardInfo {
    pub growth_inside_last_x64: u128,
    pub reward_amount_owed: u64,
}
```

### `ProtocolPositionState` (descontinuado)

<Note>
  Versões mais antigas do CLMM armazenavam agregação por `(pool, tick_lower, tick_upper)` em um PDA `ProtocolPositionState`. **Versões mais novas não criam ou leem mais essa conta.** O slot ainda aparece nas listas de contas `OpenPosition` / `IncreaseLiquidity` / `DecreaseLiquidity` como uma `UncheckedAccount` para compatibilidade de ABI, mas o programa não escreve nela. Contas existentes on-chain são vestigiais; o admin pode chamar `CloseProtocolPosition` para recuperar aluguel para elas.

  A agregação de bookkeeping de intervalo agora é derivada diretamente dos dois ticks de endpoint (`liquidity_gross`, `liquidity_net` e os `fee_growth_outside_*` / `reward_growths_outside_x64` por tick) em `TickArrayState`. A fórmula de crescimento de taxa dentro `fee_growth_inside = global − outside_lower − outside_upper` continua funcionando sem uma conta de posição agregada.
</Note>

## Observation

```rust theme={null}
pub const OBSERVATION_NUM: usize = 100;

pub struct Observation {
    pub block_timestamp: u32,
    pub tick_cumulative: i64,                            // Σ tick_current × Δt
    pub padding:         [u64; 4],
}

pub struct ObservationState {
    pub initialized:       bool,
    pub recent_epoch:      u64,
    pub observation_index: u16,
    pub pool_id:           Pubkey,
    pub observations:      [Observation; OBSERVATION_NUM], // 100 entries
    pub padding:           [u64; 4],
}
```

O buffer de observação do CLMM armazena um **tick cumulativo**, não um preço cumulativo. Consumidores externos calculam o preço de média geométrica em um intervalo de `(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0)` e então `price = 1.0001 ** tick`. Veja [`algorithms/clmm-math`](/pt/algorithms/clmm-math).

## `DynamicFeeConfig` e `DynamicFeeInfo`

Os parâmetros de taxa dinâmica vivem em dois lugares. O template reutilizável — `DynamicFeeConfig` — é gerenciado por admin e compartilhado entre pools que optam por participar. O estado de tempo de execução por pool — `DynamicFeeInfo` — é incorporado em `PoolState` e atualizado por cada swap.

### `DynamicFeeConfig`

```rust theme={null}
// programs/amm/src/states/pool_fee.rs
pub struct DynamicFeeConfig {
    pub index:                       u16,    // identifier; PDA seed component
    pub filter_period:               u16,    // seconds — within this window the volatility reference is held
    pub decay_period:                u16,    // seconds — beyond this window the reference fully decays
    pub reduction_factor:            u16,    // fixed-point in [1, 10_000); applied at decay
    pub dynamic_fee_control:         u32,    // fixed-point in (0, 100_000); fee-rate gain
    pub max_volatility_accumulator:  u32,    // ceiling on the volatility accumulator
    pub padding:                     [u64; 8],
}
```

Seed do PDA: `["dynamic_fee_config", index.to_be_bytes()]`. Criado via `create_dynamic_fee_config` (com gate de admin) e modificado via `update_dynamic_fee_config`. Um pool criado com `enable_dynamic_fee = true` captura os cinco parâmetros de calibração da config (`filter_period`, `decay_period`, `reduction_factor`, `dynamic_fee_control`, `max_volatility_accumulator`) em seu próprio `DynamicFeeInfo` no tempo de criação; edições posteriores ao `DynamicFeeConfig` não afetam retroativamente pools existentes.

### `DynamicFeeInfo` (incorporado em `PoolState`)

```rust theme={null}
pub struct DynamicFeeInfo {
    pub filter_period:                u16,
    pub decay_period:                 u16,
    pub reduction_factor:             u16,
    pub dynamic_fee_control:          u32,
    pub max_volatility_accumulator:   u32,
    pub tick_spacing_index_reference: i32,    // tick-spacing-units; reference for next swap
    pub volatility_reference:         u32,    // running floor for the accumulator
    pub volatility_accumulator:       u32,    // current cumulative volatility (capped)
    pub last_update_timestamp:        u64,
    pub padding:                      [u8; 46],
}
```

Os quatro campos inferiores são estado; os cinco superiores são calibração copiada de `DynamicFeeConfig`. A matemática de taxa e as regras de decaimento são documentadas sob [`products/clmm/math`](/pt/products/clmm/math) e [`products/clmm/fees`](/pt/products/clmm/fees).

Constantes usadas pela fórmula:

| Constante | Valor | Significado |
| - | - | - |
| `VOLATILITY_ACCUMULATOR_SCALE` | `10_000` | Granularidade do acumulador de volatilidade |
| `REDUCTION_FACTOR_DENOMINATOR` | `10_000` | Denominador para `reduction_factor` |
| `DYNAMIC_FEE_CONTROL_DENOMINATOR` | `100_000` | Denominador para `dynamic_fee_control` |
| `MAX_FEE_RATE_NUMERATOR` | `100_000` | Limite rígido de 10% na taxa de taxa resultante |

## `LimitOrderState`

Uma conta por ordem de limite aberta.

```rust theme={null}
// programs/amm/src/states/limit_order.rs
pub struct LimitOrderState {
    pub pool_id:            Pubkey,
    pub owner:              Pubkey,
    pub tick_index:         i32,
    pub zero_for_one:       bool,    // direction: true sells token0 for token1
    pub order_phase:        u64,     // snapshot of TickState.order_phase at open time
    pub total_amount:       u64,     // input-token amount placed
    pub filled_amount:      u64,     // informational; computed precisely on settle
    pub settle_base:        u64,     // unfilled remainder at last settle/decrease
    pub settled_output:     u64,     // cumulative output-token paid to owner
    pub open_time:          u64,
    pub unfilled_ratio_x64: u128,    // Q64.64 snapshot of TickState.unfilled_ratio_x64 at open
    pub padding:            [u64; 4],
}
```

Ciclo de vida:

1. **Abrir** — usuário chama `open_limit_order`, deposita `total_amount` do token de entrada, a ordem é vinculada a uma coorte `TickState`.
2. **(opcional) Aumentar / Diminuir** — `increase_limit_order` adiciona a `total_amount`; `decrease_limit_order` retorna tokens não preenchidos (e qualquer saída liquidada até esse ponto).
3. **Liquidar** — quando a coorte é totalmente ou parcialmente preenchida, o proprietário *ou* o operador chamador chama `settle_limit_order` para enviar tokens de saída para a ATA do proprietário.
4. **Fechar** — uma vez que `unfilled_amount == 0`, a conta é fechável. O aluguel sempre retorna para `owner`.

Seed do PDA: `[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]`. O PDA de ordem é portanto único por `(owner, nonce_index, order_nonce)`.

## `LimitOrderNonce`

Contador por `(wallet, nonce_index)` que permite que um único usuário execute múltiplos pipelines paralelos de ordens de limite sem colidir em PDAs.

```rust theme={null}
pub struct LimitOrderNonce {
    pub user_wallet: Pubkey,
    pub nonce_index: u8,             // user-chosen, 0..255
    pub order_nonce: u64,            // monotonic, incremented every time a new order is opened
    pub padding:     [u64; 4],
}
```

Seed do PDA: `[user_wallet.as_ref(), &[nonce_index]]`. A maioria dos clientes usa `nonce_index = 0` e deixa `order_nonce` carregar a cardinalidade.

## `Permission`

Uma conta de capacidade cuja **existência é a concessão**: se um PDA `Permission` é derivado para uma determinada autoridade, essa autoridade pode chamar `CreatePermissionedPool`. Ela não armazena nada além da autoridade para a qual foi criada.

```rust theme={null}
// programs/amm/src/states/permission.rs
pub struct Permission {
    pub authority: Pubkey,       // the account this PDA authorizes
    pub padding:   [u64; 30],
}
```

Seed do PDA: `["permission", authority.as_ref()]`. Criado por um admin via `CreatePermissionPda` e destruído via `ClosePermissionPda` (aluguel reembolsado ao chamador). Ambas as instruções de admin aceitam o `admin` do programa ou uma chave dedicada `permission_pda_admin`. Fechar o PDA revoga a concessão — a autoridade não pode mais criar pools adicionais, mas pools que já criou não são afetados.

## Derivando as contas-chave

```ts theme={null}
import { PublicKey } from "@solana/web3.js";

const CLMM_PROGRAM_ID = new PublicKey(
  "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK"
); // see reference/program-addresses

function i32ToBytes(n: number): Buffer {
  const b = Buffer.alloc(4);
  b.writeInt32BE(n);
  return b;
}

export function deriveClmmAccounts(
  ammConfig: PublicKey,
  token0Mint: PublicKey,           // must already be sorted
  token1Mint: PublicKey,
) {
  const [poolState] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool"), ammConfig.toBuffer(),
     token0Mint.toBuffer(), token1Mint.toBuffer()],
    CLMM_PROGRAM_ID,
  );
  // NOTE: pools created via CreatePermissionedPool append a non-zero u16
  // seed_index (LE) as a 5th seed — see derivePermissionedPool below.
  const [observation] = PublicKey.findProgramAddressSync(
    [Buffer.from("observation"), poolState.toBuffer()],
    CLMM_PROGRAM_ID,
  );
  const [tickArrayBitmapExtension] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_tick_array_bitmap_extension"), poolState.toBuffer()],
    CLMM_PROGRAM_ID,
  );
  return { poolState, observation, tickArrayBitmapExtension };
}

export function deriveTickArray(
  pool: PublicKey,
  startTickIndex: number,
) {
  const [tickArray] = PublicKey.findProgramAddressSync(
    [Buffer.from("tick_array"), pool.toBuffer(), i32ToBytes(startTickIndex)],
    CLMM_PROGRAM_ID,
  );
  return tickArray;
}

export function deriveDynamicFeeConfig(index: number) {
  const idx = Buffer.alloc(2);
  idx.writeUInt16BE(index);
  const [pda] = PublicKey.findProgramAddressSync(
    [Buffer.from("dynamic_fee_config"), idx],
    CLMM_PROGRAM_ID,
  );
  return pda;
}

export function derivePermissionedPool(
  ammConfig: PublicKey,
  token0Mint: PublicKey,           // must already be sorted
  token1Mint: PublicKey,
  seedIndex: number,               // non-zero u16
) {
  const idx = Buffer.alloc(2);
  idx.writeUInt16LE(seedIndex);    // little-endian, unlike the u16 seeds above
  const [pool] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool"), ammConfig.toBuffer(),
     token0Mint.toBuffer(), token1Mint.toBuffer(), idx],
    CLMM_PROGRAM_ID,
  );
  return pool;
}

export function derivePermission(authority: PublicKey) {
  const [pda] = PublicKey.findProgramAddressSync(
    [Buffer.from("permission"), authority.toBuffer()],
    CLMM_PROGRAM_ID,
  );
  return pda;
}

export function deriveLimitOrderNonce(
  wallet: PublicKey,
  nonceIndex: number,
) {
  const [pda] = PublicKey.findProgramAddressSync(
    [wallet.toBuffer(), Buffer.from([nonceIndex & 0xff])],
    CLMM_PROGRAM_ID,
  );
  return pda;
}

export function deriveLimitOrder(
  wallet: PublicKey,
  nonceAccount: PublicKey,
  orderNonce: bigint,
) {
  const nonceBytes = Buffer.alloc(8);
  nonceBytes.writeBigUInt64BE(orderNonce);
  const [pda] = PublicKey.findProgramAddressSync(
    [wallet.toBuffer(), nonceAccount.toBuffer(), nonceBytes],
    CLMM_PROGRAM_ID,
  );
  return pda;
}

export function derivePersonalPosition(nftMint: PublicKey) {
  const [personalPosition] = PublicKey.findProgramAddressSync(
    [Buffer.from("position"), nftMint.toBuffer()],
    CLMM_PROGRAM_ID,
  );
  return personalPosition;
}
```

As strings de seed exatas devem sempre ser verificadas novamente contra o IDL on-chain e [`reference/program-addresses`](/pt/reference/program-addresses).

## Referência rápida de ciclo de vida

| Evento | Contas criadas | Contas destruídas |
| - | - | - |
| `CreatePool` | `poolState`, `observation`, `token_0_vault`, `token_1_vault` | — |
| `OpenPosition[V2]` / `OpenPositionWithToken22Nft` | Mint de NFT + ATA, `personalPosition`, possivelmente novo(s) `tickArrayState`(s), `tickArrayBitmapExtension` se ainda não existente; pode congelar a ATA do NFT para um pool de emissor restrito | — |
| `IncreaseLiquidity` | Possivelmente novo(s) `tickArrayState`(s) | — |
| `DecreaseLiquidity` | — | Possivelmente limpa entradas de tick (mas o `tickArrayState` em si não é fechado) |
| `ClosePosition` | — | ATA do NFT, `personalPosition` e mint de NFT Token-2022; um mint de NFT SPL clássico permanece com suprimento zero. O caminho congelado primeiro descongelado via o pool passado em contas restantes. |
| `SwapV2` | Possivelmente novo(s) `tickArrayState` | — |
| `OpenLimitOrder` | `limitOrderState`, possivelmente `limitOrderNonce` (init-if-needed), possivelmente novo(s) `tickArrayState` | — |
| `IncreaseLimitOrder` | — | — |
| `DecreaseLimitOrder` | — | Fecha `limitOrderState` se a ordem for totalmente consumida |
| `SettleLimitOrder` | — | — |
| `CloseLimitOrder` | — | `limitOrderState` (aluguel → `owner`) |
| `CreateDynamicFeeConfig` | `dynamicFeeConfig` | — |
| `CreateCustomizablePool` | `poolState`, `observation`, vaults — igual a `CreatePool`. Captura `dynamicFeeConfig` se `enable_dynamic_fee = true`. | — |
| `CreatePermissionedPool` | `poolState` (em um endereço derivado de `seed_index`), `observation`, vaults — como `CreateCustomizablePool`. Requer um `permission` existente. | — |
| `CreatePermissionPda` / `ClosePermissionPda` | `permission` (concessão de admin) | `permission` (revogação de admin, aluguel → chamador) |
| `CollectRewards` | — | — |
| `UpdateRewardInfos` | — | — |
| `CloseProtocolPosition` (admin) | — | `protocolPositionState` vestigial (aluguel → admin) |

Contas `TickArrayState` são **nunca fechadas pelo programa** — elas persistem pela vida do pool. Uma vez que um array de ticks foi inicializado, ele permanece on-chain mesmo quando cada tick dentro dele retorna a `liquidity_gross == 0`. Reutilizar um array de ticks existente é gratuito; apenas a primeira posição a tocar um array nunca inicializado paga seu aluguel.

## O que ler onde

* **Matemática de tick e mecânica de intervalo**: [`products/clmm/ticks-and-positions`](/pt/products/clmm/ticks-and-positions).
* **Caminhada de swap e matemática de crescimento de taxa**: [`products/clmm/math`](/pt/products/clmm/math).
* **Listas de contas de instrução**: [`products/clmm/instructions`](/pt/products/clmm/instructions).
* **Taxas e acúmulo de recompensa**: [`products/clmm/fees`](/pt/products/clmm/fees).
* **IDs de programa canônicos e seeds**: [`reference/program-addresses`](/pt/reference/program-addresses).

Fontes:

* [`raydium-io/raydium-clmm` — `programs/amm/src/states`](https://github.com/raydium-io/raydium-clmm)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.