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

# Akun CLMM

> Setiap akun yang digunakan pool CLMM: PoolState, AmmConfig, TickArrayState, TickArrayBitmapExtension, PersonalPositionState, dan Observation.

<Info>
  **Halaman ini diterjemahkan secara otomatis oleh AI. Versi bahasa Inggris adalah acuan resmi.**

  [Lihat versi bahasa Inggris →](/products/clmm/accounts)
</Info>

<Info>
  Halaman ini menjelaskan **tata letak dan peran** setiap akun. Seed yang kanonik tercantum di [`reference/program-addresses`](/id/reference/program-addresses). Pool CLMM memiliki lebih banyak akun dibanding pool CPMM karena likuiditas disimpan secara jarang (*sparse*) di sepanjang rentang tick; memahami kejarangan tersebut adalah inti dari halaman ini.
</Info>

## Inventaris akun

Sebuah pool CLMM yang aktif terdiri dari keluarga akun berikut. Semuanya dimiliki oleh program CLMM, kecuali dua mint dan vault-nya.

| Akun                             | Tujuan                                                                                                                                                      | Jumlah per pool        |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `AmmConfig`                      | Tingkat biaya: trade-fee rate, bagian protokol, bagian dana, default tick-spacing. Dibagi bersama semua pool dalam tier ini.                                | 1 (bersama)            |
| `PoolState`                      | `sqrt_price_x64` saat ini, tick saat ini, total likuiditas, global pertumbuhan biaya, info reward, pointer observasi.                                       | 1                      |
| `TickArrayState`                 | Blok berisi `TICK_ARRAY_SIZE` tick yang berdekatan. Hanya diinisialisasi sesuai kebutuhan.                                                                  | 0 ≤ N ≤ range          |
| `TickArrayBitmapExtension`       | Bitmap overflow yang melacak array tick mana yang ada di luar bitmap inline pada `PoolState`.                                                               | 0 atau 1               |
| `PersonalPositionState`          | Satu per posisi LP. Menyimpan rentang, likuiditas, dan pertumbuhan biaya/reward terakhir yang diamati. Authority = pemilik NFT.                             | 1 per posisi           |
| Position NFT mint                | Mint dengan supply 1, terkait dengan `PersonalPositionState`. Memindahkan NFT berarti memindahkan posisi.                                                   | 1 per posisi           |
| `ObservationState`               | Ring buffer dari observasi harga untuk TWAP.                                                                                                                | 1                      |
| `token_0_vault`, `token_1_vault` | Akun token yang menyimpan saldo pool. Dimiliki oleh pool authority.                                                                                         | 2                      |
| `DynamicFeeConfig`               | Set parameter yang dapat digunakan ulang untuk mekanisme dynamic-fee. Pool yang dibuat melalui `create_customizable_pool` dapat ikut serta. Dikelola admin. | bersama (per indeks)   |
| `LimitOrderState`                | Satu per limit order yang terbuka. Mencatat pemilik, tick, sisi, jumlah total, snapshot output yang diselesaikan.                                           | 1 per order            |
| `LimitOrderNonce`                | Counter per `(wallet, nonce_index)` yang menghasilkan PDA order yang unik.                                                                                  | 1 per (wallet, indeks) |

## `PoolState`

State live pool, dibaca pada setiap swap dan setiap perubahan posisi.

```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,
    pub padding: [u8; 6],

    // 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],
}
```

Field yang akan sering Anda gunakan:

* **`sqrt_price_x64`** dan **`tick_current`** adalah state harga pool. Keduanya diperbarui bersama pada setiap swap. `tick_current` adalah floor dari `log_{1.0001}(price)`.
* **`liquidity`** adalah likuiditas **aktif** — jumlah nilai `L` dari semua posisi yang rentangnya mencakup `tick_current`. Nilainya berubah setiap kali swap melintasi sebuah tick dan setiap kali posisi dibuka/ditutup/diubah ukurannya.
* **`fee_growth_global_{0,1}_x64`** adalah biaya kumulatif yang diperoleh per unit likuiditas sepanjang seluruh riwayat pool. Posisi membaca nilai ini untuk menghitung jumlah yang terutang kepada mereka.
* **`tick_spacing`** dikunci ke `AmmConfig` saat inisialisasi dan tidak pernah berubah. Nilai ini menentukan indeks tick mana saja yang diizinkan menjadi endpoint posisi.
* **`tick_array_bitmap`** adalah bitmap **inline** yang mencakup rentang tick yang umum digunakan di sekitar harga spot. Untuk pool dengan posisi yang mencapai jangkauan jauh, pelacakan overflow disimpan di akun `TickArrayBitmapExtension` yang terpisah.
* **`fee_on`** ditetapkan saat pool dibuat. `0` (FromInput) mereproduksi perilaku klasik Uniswap-V3. `1` dan `2` mengarahkan biaya swap ke satu sisi buku — lihat [`products/clmm/fees`](/id/products/clmm/fees) untuk pertimbangannya.
* **`dynamic_fee_info`** menyimpan state volatilitas untuk surcharge dynamic-fee. Jika diaktifkan, setiap swap menghitung ulang `dynamic_fee_component` di atas `AmmConfig.trade_fee_rate`. Tata letak didokumentasikan di bawah `DynamicFeeInfo`; pool tanpa dynamic fee membiarkan seluruh struct bernilai nol.

## `AmmConfig`

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

    pub owner:             Pubkey,        // admin
    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,
    pub padding: [u64; 3],
}
```

Set tier biaya CLMM yang umum dipublikasikan (konfirmasi melalui `GET https://api-v3.raydium.io/main/clmm-config`):

| Indeks | `trade_fee_rate` | Tick spacing | Penggunaan umum             |
| ------ | ---------------- | ------------ | --------------------------- |
| 0      | `100` (0.01%)    | 1            | Pasangan stabil, USDC/USDT  |
| 1      | `500` (0.05%)    | 10           | Blue-chip yang berkorelasi  |
| 2      | `2_500` (0.25%)  | 60           | Pasangan standar            |
| 3      | `10_000` (1.00%) | 120          | Aset volatil atau long-tail |

`protocol_fee_rate` dan `fund_fee_rate` adalah fraksi dari trade fee; konvensinya sama dengan CPMM. Lihat [`products/clmm/fees`](/id/products/clmm/fees).

## `TickArrayState`

CLMM tidak menyimpan satu record per tick — pendekatan itu akan menghasilkan miliaran akun. Sebagai gantinya, **`TICK_ARRAY_SIZE` tick yang berdekatan** (umumnya 60 atau 88 tergantung versi program), baik yang sudah diinisialisasi maupun belum, dikelompokkan ke dalam sebuah `TickArrayState` yang dibuat secara lazy saat pertama kali digunakan.

```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],
}
```

Keempat field limit-order bernilai nol pada tick yang belum pernah digunakan untuk limit order. Ketika order dibuka pada sebuah tick, program melacaknya sebagai urutan kohort:

* `order_phase` adalah id kohort. Nilainya bertambah setiap kali sebuah kohort bertransisi dari "semua belum terisi" menjadi "sebagian terisi."
* `orders_amount` adalah total token input dari kohort saat ini (terbaru).
* `part_filled_orders_remaining` melacak kohort sebelumnya yang sedang diisi oleh swap yang sedang berjalan.
* `unfilled_ratio_x64` adalah multiplier Q64.64 yang dibawa pada kohort: ketika swap mengisi X% dari kohort, rasionya dikalikan dengan `(1 − X)`. Setiap order yang terbuka menyimpan snapshot `(order_phase, unfilled_ratio_x64)` saat dibuka, sehingga matematika penyelesaian cukup membandingkan snapshot.

Aturan:

* Tick endpoint posisi *t* harus memenuhi `t % tick_spacing == 0`. Program menolak posisi yang tidak sesuai spacing.
* **Array** dari sebuah tick berada pada `floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing)`.
* Array tick diinisialisasi secara lazy: posisi atau swap pertama yang menyentuh array yang belum diinisialisasi akan membuatnya sekaligus membayar rent.
* Array tick **tidak pernah ditutup** oleh program. Setelah dialokasikan, akun ini bertahan selama pool ada, bahkan setelah setiap tick di dalamnya kembali ke `liquidity_gross == 0`. Posisi dan swap berikutnya menggunakan kembali akun yang sudah ada tanpa biaya rent tambahan. Tidak ada jalur pembersihan berbasis `ClosePosition` untuk array tick.

### `TickArrayBitmapExtension`

`PoolState.tick_array_bitmap` (inline) mencakup rentang "dekat spot" — ±1.024 array tick. Di luar rentang tersebut (untuk nilai tick yang ekstrem), program memelihara akun extension:

```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],
}
```

Jika rentang posisi Anda "normal", Anda tidak perlu memikirkan akun extension ini. Posisi full-range (misalnya `(MIN_TICK, MAX_TICK)`) membutuhkannya; SDK akan menanganinya untuk Anda.

## Posisi

Sebuah posisi CLMM adalah **gabungan** dari tiga akun ditambah satu mint:

### Position NFT mint

Mint SPL Token dengan supply 1. Alamat mint adalah PDA deterministik; NFT posisi di wallet pemilik hanyalah ATA yang menyimpan satu token tersebut. Memindahkan NFT adalah cara suatu posisi berganti pemilik — program mengaitkan otorisasi ke **pemegang saldo ATA NFT saat ini**, bukan ke Pubkey yang tersimpan dalam state.

### `PersonalPositionState`

Satu per posisi yang terbuka. Dikunci berdasarkan NFT mint.

```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` (tidak digunakan lagi)

<Note>
  Rilis CLMM yang lebih lama menyimpan pembukuan agregat per `(pool, tick_lower, tick_upper)` dalam PDA `ProtocolPositionState`. **Rilis terbaru tidak lagi membuat atau membaca akun ini.** Slot tersebut masih muncul dalam daftar akun `OpenPosition` / `IncreaseLiquidity` / `DecreaseLiquidity` sebagai `UncheckedAccount` untuk kompatibilitas ABI, tetapi program tidak menulisi akun tersebut. Akun yang ada di on-chain bersifat vestigial; admin dapat memanggil `CloseProtocolPosition` untuk mengklaim kembali rent-nya.

  Pembukuan rentang agregat kini diturunkan langsung dari dua tick endpoint (`liquidity_gross`, `liquidity_net`, dan `fee_growth_outside_*` / `reward_growths_outside_x64` per tick) dalam `TickArrayState`. Formula fee-growth-inside `fee_growth_inside = global − outside_lower − outside_upper` tetap berfungsi tanpa akun posisi agregat.
</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],
}
```

Buffer observasi CLMM menyimpan **tick kumulatif**, bukan harga kumulatif. Konsumen eksternal menghitung harga rata-rata geometris dalam suatu interval dari `(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0)`, kemudian `price = 1.0001 ** tick`. Lihat [`algorithms/clmm-math`](/id/algorithms/clmm-math).

## `DynamicFeeConfig` dan `DynamicFeeInfo`

Parameter dynamic fee berada di dua tempat. Template yang dapat digunakan ulang — `DynamicFeeConfig` — dikelola admin dan dibagi bersama pool yang ikut serta. State runtime per pool — `DynamicFeeInfo` — tertanam dalam `PoolState` dan diperbarui oleh setiap 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],
}
```

PDA seed: `["dynamic_fee_config", index.to_be_bytes()]`. Dibuat melalui `create_dynamic_fee_config` (dibatasi admin) dan dimodifikasi melalui `update_dynamic_fee_config`. Pool yang dibuat dengan `enable_dynamic_fee = true` menyalin lima parameter kalibrasi konfigurasi (`filter_period`, `decay_period`, `reduction_factor`, `dynamic_fee_control`, `max_volatility_accumulator`) ke dalam `DynamicFeeInfo`-nya sendiri saat pembuatan; pengeditan selanjutnya pada `DynamicFeeConfig` tidak berlaku surut bagi pool yang sudah ada.

### `DynamicFeeInfo` (tertanam dalam `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],
}
```

Empat field terbawah adalah state; lima field teratas adalah kalibrasi yang disalin dari `DynamicFeeConfig`. Matematika biaya dan aturan decay didokumentasikan di [`products/clmm/math`](/id/products/clmm/math) dan [`products/clmm/fees`](/id/products/clmm/fees).

Konstanta yang digunakan dalam formula:

| Konstanta                         | Nilai     | Makna                                         |
| --------------------------------- | --------- | --------------------------------------------- |
| `VOLATILITY_ACCUMULATOR_SCALE`    | `10_000`  | Granularitas dari volatility accumulator      |
| `REDUCTION_FACTOR_DENOMINATOR`    | `10_000`  | Penyebut untuk `reduction_factor`             |
| `DYNAMIC_FEE_CONTROL_DENOMINATOR` | `100_000` | Penyebut untuk `dynamic_fee_control`          |
| `MAX_FEE_RATE_NUMERATOR`          | `100_000` | Batas keras 10% pada fee rate yang dihasilkan |

## `LimitOrderState`

Satu akun per limit order yang terbuka.

```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],
}
```

Siklus hidup:

1. **Buka** — pengguna memanggil `open_limit_order`, menyetor `total_amount` token input, order terikat ke kohort `TickState`.
2. **(opsional) Tambah / Kurangi** — `increase_limit_order` menambah `total_amount`; `decrease_limit_order` mengembalikan token yang belum terisi (dan output yang sudah diselesaikan hingga saat itu).
3. **Selesaikan** — ketika kohort terisi penuh atau sebagian, pemilik *atau* keeper operasional memanggil `settle_limit_order` untuk mendorong token output ke ATA pemilik.
4. **Tutup** — setelah `unfilled_amount == 0`, akun dapat ditutup. Rent selalu dikembalikan ke `owner`.

PDA seed: `[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]`. PDA order oleh karena itu unik per `(owner, nonce_index, order_nonce)`.

## `LimitOrderNonce`

Counter per `(wallet, nonce_index)` yang memungkinkan satu pengguna menjalankan beberapa pipeline limit order secara paralel tanpa bentrokan pada PDA.

```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],
}
```

PDA seed: `[user_wallet.as_ref(), &[nonce_index]]`. Sebagian besar klien menggunakan `nonce_index = 0` dan membiarkan `order_nonce` menangani kardinalitas.

## Menurunkan akun-akun utama

```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,
  );
  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 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;
}
```

String seed yang tepat harus selalu diverifikasi ulang terhadap IDL on-chain dan [`reference/program-addresses`](/id/reference/program-addresses).

## Referensi cepat siklus hidup

| Event                           | Akun yang dibuat                                                                                                             | Akun yang dihancurkan                                                                   |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `CreatePool`                    | `poolState`, `observation`, `token_0_vault`, `token_1_vault`                                                                 | —                                                                                       |
| `OpenPosition[WithToken22Nft]`  | NFT mint + ATA, `personalPosition`, kemungkinan `tickArrayState` baru, `tickArrayBitmapExtension` jika belum ada             | —                                                                                       |
| `IncreaseLiquidity`             | Kemungkinan `tickArrayState` baru                                                                                            | —                                                                                       |
| `DecreaseLiquidity`             | —                                                                                                                            | Kemungkinan membersihkan entri tick (tetapi `tickArrayState` itu sendiri tidak ditutup) |
| `ClosePosition`                 | —                                                                                                                            | NFT mint, `personalPosition`                                                            |
| `SwapV2`                        | Kemungkinan `tickArrayState` baru                                                                                            | —                                                                                       |
| `OpenLimitOrder`                | `limitOrderState`, kemungkinan `limitOrderNonce` (init-if-needed), kemungkinan `tickArrayState` baru                         | —                                                                                       |
| `IncreaseLimitOrder`            | —                                                                                                                            | —                                                                                       |
| `DecreaseLimitOrder`            | —                                                                                                                            | Menutup `limitOrderState` jika order sudah habis terisi                                 |
| `SettleLimitOrder`              | —                                                                                                                            | —                                                                                       |
| `CloseLimitOrder`               | —                                                                                                                            | `limitOrderState` (rent → `owner`)                                                      |
| `CreateDynamicFeeConfig`        | `dynamicFeeConfig`                                                                                                           | —                                                                                       |
| `CreateCustomizablePool`        | `poolState`, `observation`, vault — sama seperti `CreatePool`. Menyalin `dynamicFeeConfig` jika `enable_dynamic_fee = true`. | —                                                                                       |
| `CollectRewards`                | —                                                                                                                            | —                                                                                       |
| `UpdateRewardInfos`             | —                                                                                                                            | —                                                                                       |
| `CloseProtocolPosition` (admin) | —                                                                                                                            | `protocolPositionState` vestigial (rent → admin)                                        |

Akun `TickArrayState` **tidak pernah ditutup oleh program** — akun ini bertahan selama pool ada. Setelah sebuah array tick diinisialisasi, akun tersebut tetap ada di on-chain bahkan ketika setiap tick di dalamnya kembali ke `liquidity_gross == 0`. Menggunakan kembali array tick yang sudah ada tidak dikenakan biaya; hanya posisi pertama yang menyentuh array yang belum pernah diinisialisasi yang membayar rent-nya.

## Panduan referensi selanjutnya

* **Matematika tick dan mekanika rentang**: [`products/clmm/ticks-and-positions`](/id/products/clmm/ticks-and-positions).
* **Alur swap dan matematika pertumbuhan biaya**: [`products/clmm/math`](/id/products/clmm/math).
* **Daftar akun instruksi**: [`products/clmm/instructions`](/id/products/clmm/instructions).
* **Biaya dan akumulasi reward**: [`products/clmm/fees`](/id/products/clmm/fees).
* **Program ID dan seed yang kanonik**: [`reference/program-addresses`](/id/reference/program-addresses).

Sumber:

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