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

# CLMM 帳戶

> CLMM 資金池涉及的每個帳戶：PoolState、AmmConfig、TickArrayState、TickArrayBitmapExtension、PersonalPositionState 和 Observation。

<Info>
  **本頁內容由 AI 自動翻譯，所有內容以英文版本為準。**

  [查看英文版 →](/products/clmm/accounts)
</Info>

## 帳戶清單

一個運作中的 CLMM 資金池由以下帳戶族群組成。除了兩個代幣鑄造和它們的金庫外，所有帳戶都由 CLMM 程式擁有。

| 帳戶                              | 用途                                                                 | 每個資金池的數量     |
| ------------------------------- | ------------------------------------------------------------------ | ------------ |
| `AmmConfig`                     | 費用等級：交易費率、協議份額、基金份額、預設 tick 間距。在此等級的所有資金池間共享。                      | 1（共享）        |
| `PoolState`                     | 目前的 `sqrt_price_x64`、目前 tick、總流動性、費用增長全局值、獎勵資訊、觀察指標。               | 1            |
| `TickArrayState`                | 一個包含 `TICK_ARRAY_SIZE` 個相鄰 tick 的區塊。僅在需要時初始化。                      | 0 ≤ N ≤ 範圍   |
| `TickArrayBitmapExtension`      | 溢出位圖，追蹤 `PoolState` 中內聯位圖之外存在的 tick 陣列。                            | 0 或 1        |
| `PersonalPositionState`         | 每個 LP 頭寸一個。儲存範圍、流動性和最後看到的費用/獎勵增長。授權 = NFT 擁有者。                     | 每個頭寸 1 個     |
| Position NFT 鑄造                 | 供應量為 1 的鑄造，與 `PersonalPositionState` 相關聯。轉移 NFT 即轉移頭寸。             | 每個頭寸 1 個     |
| `ObservationState`              | TWAP 價格觀察的環形緩衝區。                                                   | 1            |
| `token_0_vault`、`token_1_vault` | 持有資金池餘額的代幣帳戶。由資金池授權擁有。                                             | 2            |
| `DynamicFeeConfig`              | 動態費用機制的可重複使用參數集。透過 `create_customizable_pool` 建立的資金池可以選擇加入。由管理員管理。 | 共享（每個索引）     |
| `LimitOrderState`               | 每個開放限價單一個。記錄擁有者、tick、方向、總金額、已結算輸出快照。                               | 每個訂單 1 個     |
| `LimitOrderNonce`               | 每個 `(wallet, nonce_index)` 計數器，衍生唯一的訂單 PDA。                        | 每個（錢包、索引）1 個 |
| `Permission`                    | 授予其授權呼叫 `CreatePermissionedPool` 的權利。PDA 的存在**就是**授權。由管理員管理。       | 每個授權建立者 1 個  |

## `PoolState`

資金池的即時狀態，在每次交換和每次頭寸變更時讀取。

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

你實際會接觸的欄位：

* **`sqrt_price_x64`** 和 **`tick_current`** 是資金池的價格狀態。它們在每次交換時一起更新。`tick_current` 是 `log_{1.0001}(price)` 的下限。
* **`liquidity`** 是**活躍**流動性——所有範圍包含 `tick_current` 的頭寸的 `L` 值之和。每次交換跨越 tick 時以及每次頭寸開啟/關閉/調整大小時都會變更。
* **`fee_growth_global_{0,1}_x64`** 是整個資金池歷史中每單位流動性累積的費用。頭寸讀取此值以計算應付給它們的費用。
* **`tick_spacing`** 在初始化時鎖定到 `AmmConfig`，永遠不會改變。它決定了哪些 tick 索引被允許作為頭寸端點。
* **`tick_array_bitmap`** 是一個**內聯**位圖，涵蓋現貨價格周圍常用的 tick 範圍。對於頭寸延伸很遠的資金池，溢出追蹤位於單獨的 `TickArrayBitmapExtension`。
* **`fee_on`** 在資金池建立時固定。`0`（FromInput）重現經典 Uniswap-V3 行為。`1` 和 `2` 將交換費路由到書籍的單一側——參見 [`/zh-Hant/products/clmm/fees`](/zh-Hant/products/clmm/fees) 以了解權衡。
* **`seed_index`** 對於透過 `CreatePool` / `CreateCustomizablePool` 建立的每個資金池都是 `[0, 0]`（每對一個規範資金池）。**非零**值表示資金池是透過 `CreatePermissionedPool` 建立的，索引是資金池 PDA 種子的一部分，允許多個資金池為相同的 `(config, mint0, mint1)` 共存。要重新衍生這樣的資金池地址，你必須知道它的 `seed_index`。
* **`dynamic_fee_info`** 攜帶動態費用浮動的波動性狀態。啟用時，每次交換都會在 `AmmConfig.trade_fee_rate` 之上重新計算 `dynamic_fee_component`。佈局在下面的 `DynamicFeeInfo` 中記錄；沒有動態費用的資金池將整個結構保留為零。

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

一個典型的已發佈 CLMM 費用等級集合（確認對比 `GET https://api-v3.raydium.io/main/clmm-config`）：

| 索引 | `trade_fee_rate` | Tick 間距 | 典型用途          |
| -- | ---------------- | ------- | ------------- |
| 0  | `100`（0.01%）     | 1       | 穩定對，USDC/USDT |
| 1  | `500`（0.05%）     | 10      | 相關藍籌股         |
| 2  | `2_500`（0.25%）   | 60      | 標準對           |
| 3  | `10_000`（1.00%）  | 120     | 波動或長尾         |

`protocol_fee_rate` 和 `fund_fee_rate` 是交易費的分數；與 CPMM 相同的慣例。參見 [`/zh-Hant/products/clmm/fees`](/zh-Hant/products/clmm/fees)。

## `TickArrayState`

CLMM 不為每個 tick 儲存單一記錄。那樣會有數十億個帳戶。相反，它將\*\*`TICK_ARRAY_SIZE` 個相鄰的已初始化或未初始化 tick\*\*（通常為 60 或 88，取決於程式版本）分組到一個 `TickArrayState` 中，該狀態在首次使用時延遲建立。

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

四個限價單欄位在任何從未用於限價單的 tick 上都是零。當訂單在 tick 上開啟時，程式將它們追蹤為一系列群組：

* `order_phase` 是群組 id。每次群組從「全部未填充」轉換為「部分填充」時遞增。
* `orders_amount` 是目前（最新）群組的輸入代幣總額。
* `part_filled_orders_remaining` 追蹤目前正在被進行中交換填充的前一個群組。
* `unfilled_ratio_x64` 是在群組上攜帶的 Q64.64 乘數：當交換填充群組的 X% 時，比率乘以 `(1 − X)`。每個開放訂單在開啟時儲存自己的 `(order_phase, unfilled_ratio_x64)` 快照，因此結算數學簡化為比較快照。

規則：

* 頭寸端點 tick *t* 必須滿足 `t % tick_spacing == 0`。程式拒絕不符合間距的頭寸。
* tick 的**陣列**位於 `floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing)`。
* tick 陣列延遲初始化：首次觸及未初始化陣列的頭寸或交換會建立它，支付租金。
* tick 陣列**永遠不會被程式關閉**。一旦分配，它就會在資金池的整個生命週期內持續存在，即使其中的每個 tick 都回到 `liquidity_gross == 0`。後續頭寸和交換重複使用現有帳戶，無需額外租金。沒有 `ClosePosition` 驅動的 tick 陣列清理路徑。

### `TickArrayBitmapExtension`

`PoolState.tick_array_bitmap`（內聯）涵蓋「接近現貨」範圍——±1,024 個 tick 陣列。超出該範圍（對於極端 tick 值），程式維護一個擴展帳戶：

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

如果你的頭寸範圍是「正常的」，你永遠不會考慮擴展帳戶。全範圍頭寸（例如 `(MIN_TICK, MAX_TICK)`）需要它；SDK 為你解決它。

## 頭寸

CLMM 頭寸是三個帳戶加一個鑄造的**組合**：

### Position NFT 鑄造

一個供應量為 1 的 SPL Token 鑄造。鑄造的地址是一個確定性 PDA；擁有者錢包中的頭寸 NFT 只是持有該單一代幣的 ATA。轉移 NFT 是頭寸如何易手的方式——程式將授權鑰匙設定為 **NFT ATA 餘額的目前持有者**，而不是儲存在狀態中的 Pubkey。

### `PersonalPositionState`

每個開放頭寸一個。以 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`（已棄用）

<Note>
  較舊的 CLMM 版本在 `ProtocolPositionState` PDA 中儲存每個 `(pool, tick_lower, tick_upper)` 的聚合簿記。**較新的版本不再建立或讀取此帳戶。** 該位置仍然作為 `UncheckedAccount` 出現在 `OpenPosition` / `IncreaseLiquidity` / `DecreaseLiquidity` 帳戶列表中以保持 ABI 相容性，但程式不會寫入它。鏈上現有帳戶是遺留的；管理員可以呼叫 `CloseProtocolPosition` 來回收它們的租金。

  聚合範圍簿記現在直接從兩個端點 tick（`liquidity_gross`、`liquidity_net` 和每個 tick 的 `fee_growth_outside_*` / `reward_growths_outside_x64`）在 `TickArrayState` 中衍生。費用增長內部公式 `fee_growth_inside = global − outside_lower − outside_upper` 繼續在沒有聚合頭寸帳戶的情況下工作。
</Note>

## 觀察

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

CLMM 的觀察緩衝區儲存**累積 tick**，而不是累積價格。外部消費者從 `(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0)` 計算區間上的幾何平均價格，然後 `price = 1.0001 ** tick`。參見 [`/zh-Hant/algorithms/clmm-math`](/zh-Hant/algorithms/clmm-math)。

## `DynamicFeeConfig` 和 `DynamicFeeInfo`

動態費用參數位於兩個地方。可重複使用的範本——`DynamicFeeConfig`——由管理員管理並在選擇加入的資金池間共享。每個資金池的執行時狀態——`DynamicFeeInfo`——嵌入在 `PoolState` 中並由每次交換更新。

### `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 種子：`["dynamic_fee_config", index.to_be_bytes()]`。透過 `create_dynamic_fee_config`（管理員門控）建立並透過 `update_dynamic_fee_config` 修改。使用 `enable_dynamic_fee = true` 透過 `create_customizable_pool` 建立的資金池在建立時將配置的五個校準參數（`filter_period`、`decay_period`、`reduction_factor`、`dynamic_fee_control`、`max_volatility_accumulator`）快照到自己的 `DynamicFeeInfo` 中；稍後對 `DynamicFeeConfig` 的編輯不會追溯影響現有資金池。

### `DynamicFeeInfo`（嵌入在 `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],
}
```

底部四個欄位是狀態；頂部五個是從 `DynamicFeeConfig` 複製的校準。費用數學和衰減規則在 [`/zh-Hant/products/clmm/math`](/zh-Hant/products/clmm/math) 和 [`/zh-Hant/products/clmm/fees`](/zh-Hant/products/clmm/fees) 下記錄。

公式使用的常數：

| 常數                                | 值         | 含義                        |
| --------------------------------- | --------- | ------------------------- |
| `VOLATILITY_ACCUMULATOR_SCALE`    | `10_000`  | 波動性累積器的粒度                 |
| `REDUCTION_FACTOR_DENOMINATOR`    | `10_000`  | `reduction_factor` 的分母    |
| `DYNAMIC_FEE_CONTROL_DENOMINATOR` | `100_000` | `dynamic_fee_control` 的分母 |
| `MAX_FEE_RATE_NUMERATOR`          | `100_000` | 結果費率的硬上限 10%              |

## `LimitOrderState`

每個開放限價單一個帳戶。

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

生命週期：

1. **開啟**——使用者呼叫 `open_limit_order`，存入 `total_amount` 的輸入代幣，訂單綁定到 `TickState` 群組。
2. **（可選）增加/減少**——`increase_limit_order` 添加到 `total_amount`；`decrease_limit_order` 返回未填充的代幣（以及到該點為止的任何已結算輸出）。
3. **結算**——當群組被完全或部分填充時，擁有者*或*操作保管人呼叫 `settle_limit_order` 將輸出代幣推送到擁有者的 ATA。
4. **關閉**——一旦 `unfilled_amount == 0`，帳戶就可以關閉。租金始終返回給 `owner`。

PDA 種子：`[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]`。訂單 PDA 因此對每個 `(owner, nonce_index, order_nonce)` 是唯一的。

## `LimitOrderNonce`

每個 `(wallet, nonce_index)` 計數器，讓單一使用者執行多個平行的限價單管道而不會在 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 種子：`[user_wallet.as_ref(), &[nonce_index]]`。大多數客戶端使用 `nonce_index = 0` 並讓 `order_nonce` 攜帶基數。

## `Permission`

一個能力帳戶，其**存在就是授權**：如果為給定的授權衍生 `Permission` PDA，該授權可能呼叫 `CreatePermissionedPool`。它除了它被建立的授權外不儲存任何內容。

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

PDA 種子：`["permission", authority.as_ref()]`。由管理員透過 `CreatePermissionPda` 建立並透過 `ClosePermissionPda` 拆除（租金退款給呼叫者）。兩個管理員指令都接受程式 `admin` 或專用 `permission_pda_admin` 鑰匙。關閉 PDA 撤銷授權——授權不再能建立額外的資金池，但它已建立的資金池不受影響。

## 衍生關鍵帳戶

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

確切的種子字串應始終對照鏈上 IDL 和 [`/zh-Hant/reference/program-addresses`](/zh-Hant/reference/program-addresses) 進行雙重檢查。

## 生命週期快速參考

| 事件                                           | 建立的帳戶                                                                                                  | 銷毀的帳戶                                   |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------- |
| `CreatePool`                                 | `poolState`、`observation`、`token_0_vault`、`token_1_vault`                                              | —                                       |
| `OpenPosition[WithToken22Nft]`               | NFT 鑄造 + ATA、`personalPosition`、可能的新 `tickArrayState`(s)、`tickArrayBitmapExtension`（如果尚不存在）            | —                                       |
| `IncreaseLiquidity`                          | 可能的新 `tickArrayState`(s)                                                                               | —                                       |
| `DecreaseLiquidity`                          | —                                                                                                      | 可能清除 tick 條目（但 `tickArrayState` 本身不會關閉） |
| `ClosePosition`                              | —                                                                                                      | NFT 鑄造、`personalPosition`               |
| `SwapV2`                                     | 可能的新 `tickArrayState`                                                                                  | —                                       |
| `OpenLimitOrder`                             | `limitOrderState`、可能的 `limitOrderNonce`（初始化如需）、可能的新 `tickArrayState`                                   | —                                       |
| `IncreaseLimitOrder`                         | —                                                                                                      | —                                       |
| `DecreaseLimitOrder`                         | —                                                                                                      | 如果訂單已完全消耗則關閉 `limitOrderState`          |
| `SettleLimitOrder`                           | —                                                                                                      | —                                       |
| `CloseLimitOrder`                            | —                                                                                                      | `limitOrderState`（租金 → `owner`）         |
| `CreateDynamicFeeConfig`                     | `dynamicFeeConfig`                                                                                     | —                                       |
| `CreateCustomizablePool`                     | `poolState`、`observation`、金庫——與 `CreatePool` 相同。如果 `enable_dynamic_fee = true` 則快照 `dynamicFeeConfig`。 | —                                       |
| `CreatePermissionedPool`                     | `poolState`（在 `seed_index` 衍生的地址）、`observation`、金庫——如 `CreateCustomizablePool`。需要現有 `permission`。      | —                                       |
| `CreatePermissionPda` / `ClosePermissionPda` | `permission`（管理員授權）                                                                                    | `permission`（管理員撤銷，租金 → 呼叫者）            |
| `CollectRewards`                             | —                                                                                                      | —                                       |
| `UpdateRewardInfos`                          | —                                                                                                      | —                                       |
| `CloseProtocolPosition`（管理員）                 | —                                                                                                      | 遺留的 `protocolPositionState`（租金 → 管理員）   |

`TickArrayState` 帳戶**永遠不會被程式關閉**——它們在資金池的整個生命週期內持續存在。一旦 tick 陣列被初始化，即使其中的每個 tick 都回到 `liquidity_gross == 0`，它也會保留在鏈上。重複使用現有 tick 陣列是免費的；只有首次觸及從未初始化陣列的頭寸才支付其租金。

## 在哪裡閱讀什麼

* **Tick 數學和範圍機制**：[`/zh-Hant/products/clmm/ticks-and-positions`](/zh-Hant/products/clmm/ticks-and-positions)。
* **交換遍歷和費用增長數學**：[`/zh-Hant/products/clmm/math`](/zh-Hant/products/clmm/math)。
* **指令帳戶列表**：[`/zh-Hant/products/clmm/instructions`](/zh-Hant/products/clmm/instructions)。
* **費用和獎勵應計**：[`/zh-Hant/products/clmm/fees`](/zh-Hant/products/clmm/fees)。
* **規範程式 ID 和種子**：[`/zh-Hant/reference/program-addresses`](/zh-Hant/reference/program-addresses)。

來源：

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