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

> Alle Accounts, die ein CLMM-Pool verwendet: PoolState, AmmConfig, TickArrayState, TickArrayBitmapExtension, PersonalPositionState und Observation.

<Info>
  **Diese Seite wurde mit KI automatisch übersetzt. Maßgeblich ist stets die englische Version.**

  [Englische Version ansehen →](/products/clmm/accounts)
</Info>

<Info>
  Diese Seite beschreibt das **Layout und die Rolle** jedes Accounts. Die Seeds sind kanonisch und unter [`reference/program-addresses`](/de/reference/program-addresses) aufgeführt. Ein CLMM-Pool benötigt mehr Accounts als ein CPMM-Pool, da Liquidität dünn verteilt über den Tick-Bereich gespeichert wird — das Verstehen dieser Verteilung ist der Kerninhalt dieser Seite.
</Info>

## Account-Übersicht

Ein aktiver CLMM-Pool wird durch folgende Account-Familien beschrieben. Alle gehören dem CLMM-Programm, mit Ausnahme der beiden Mints und ihrer Vaults.

| Account                          | Zweck                                                                                                                                                                        | Anzahl pro Pool       |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| `AmmConfig`                      | Fee-Tier: Handelsgebühr, Protokollanteil, Fondsanteil, Standard-Tick-Spacing. Wird von allen Pools dieses Tiers geteilt.                                                     | 1 (geteilt)           |
| `PoolState`                      | Aktueller `sqrt_price_x64`, aktueller Tick, Gesamtliquidität, globales Fee-Wachstum, Reward-Info, Observations-Zeiger.                                                       | 1                     |
| `TickArrayState`                 | Ein Block aus `TICK_ARRAY_SIZE` benachbarten Ticks. Wird nur bei Bedarf initialisiert.                                                                                       | 0 ≤ N ≤ Bereich       |
| `TickArrayBitmapExtension`       | Overflow-Bitmap, die nachverfolgt, welche Tick-Arrays außerhalb der inline-Bitmap in `PoolState` vorhanden sind.                                                             | 0 oder 1              |
| `PersonalPositionState`          | Einer pro LP-Position. Speichert den Bereich, die Liquidität und das zuletzt gesehene Fee-/Reward-Wachstum. Authority = NFT-Inhaber.                                         | 1 pro Position        |
| Position-NFT-Mint                | Mint mit Supply 1, verknüpft mit `PersonalPositionState`. Die Übertragung des NFTs überträgt die Position.                                                                   | 1 pro Position        |
| `ObservationState`               | Ringpuffer mit Preisbeobachtungen für den TWAP.                                                                                                                              | 1                     |
| `token_0_vault`, `token_1_vault` | Token-Accounts mit den Pool-Guthaben. Eigentümer: Pool-Authority.                                                                                                            | 2                     |
| `DynamicFeeConfig`               | Wiederverwendbarer Parametersatz für den dynamischen Gebührenmechanismus. Pools, die via `create_customizable_pool` erstellt wurden, können ihn aktivieren. Admin-verwaltet. | geteilt (pro Index)   |
| `LimitOrderState`                | Einer pro offenem Limit-Order. Enthält Inhaber, Tick, Richtung, Gesamtbetrag und Snapshot des abgerechneten Outputs.                                                         | 1 pro Order           |
| `LimitOrderNonce`                | Pro-`(wallet, nonce_index)`-Zähler, der eindeutige Order-PDAs ableitet.                                                                                                      | 1 pro (Wallet, Index) |

## `PoolState`

Der Live-Zustand des Pools, der bei jedem Swap und jeder Positionsänderung gelesen wird.

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

Felder, mit denen Sie in der Praxis arbeiten werden:

* **`sqrt_price_x64`** und **`tick_current`** stellen den Preisstatus des Pools dar. Sie werden bei jedem Swap gemeinsam aktualisiert. `tick_current` ist der ganzzahlige Anteil von `log_{1.0001}(price)`.
* **`liquidity`** ist die **aktive** Liquidität — die Summe der `L`-Werte aller Positionen, deren Bereich `tick_current` enthält. Sie ändert sich, sobald ein Swap einen Tick kreuzt oder eine Position geöffnet, geschlossen oder angepasst wird.
* **`fee_growth_global_{0,1}_x64`** sind die kumulierten Gebühren pro Liquiditätseinheit über die gesamte Pool-Geschichte. Positionen lesen diesen Wert, um ihren ausstehenden Anteil zu berechnen.
* **`tick_spacing`** wird bei der Initialisierung an den `AmmConfig` gebunden und ändert sich nie. Es legt fest, welche Tick-Indizes als Positionsendpunkte zulässig sind.
* **`tick_array_bitmap`** ist eine **inline** Bitmap, die den üblicherweise genutzten Tick-Bereich um den Spotpreis abdeckt. Für Pools, deren Positionen weiter außerhalb liegen, lebt die Overflow-Nachverfolgung im separaten `TickArrayBitmapExtension`-Account.
* **`fee_on`** wird bei der Pool-Erstellung festgelegt. `0` (FromInput) reproduziert das klassische Uniswap-V3-Verhalten. `1` und `2` leiten die Swap-Gebühr an eine einzelne Seite des Buches weiter — siehe [`products/clmm/fees`](/de/products/clmm/fees) für die jeweiligen Abwägungen.
* **`dynamic_fee_info`** enthält den Volatilitätsstatus für den dynamischen Gebührenzuschlag. Wenn aktiviert, berechnet jeder Swap einen `dynamic_fee_component` zusätzlich zu `AmmConfig.trade_fee_rate`. Das Layout ist unter `DynamicFeeInfo` weiter unten dokumentiert; Pools ohne dynamische Gebühr lassen die gesamte Struktur auf null.

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

Ein typischer veröffentlichter Satz von CLMM-Fee-Tiers (bitte gegen `GET https://api-v3.raydium.io/main/clmm-config` verifizieren):

| Index | `trade_fee_rate`  | Tick-Spacing | Typische Verwendung            |
| ----- | ----------------- | ------------ | ------------------------------ |
| 0     | `100` (0,01 %)    | 1            | Stabile Paare, USDC/USDT       |
| 1     | `500` (0,05 %)    | 10           | Korrelierte Blue-Chips         |
| 2     | `2_500` (0,25 %)  | 60           | Standardpaare                  |
| 3     | `10_000` (1,00 %) | 120          | Volatile oder Long-Tail-Assets |

`protocol_fee_rate` und `fund_fee_rate` sind Anteile der Handelsgebühr — gleiche Konvention wie bei CPMM. Siehe [`products/clmm/fees`](/de/products/clmm/fees).

## `TickArrayState`

CLMM speichert keinen einzelnen Eintrag pro Tick — das wären Milliarden von Accounts. Stattdessen fasst es **`TICK_ARRAY_SIZE` benachbarte, initialisierte oder nicht initialisierte Ticks** (typischerweise 60 oder 88, je nach Programmversion) in einem `TickArrayState` zusammen, der bei erster Verwendung lazily angelegt wird.

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

Die vier Limit-Order-Felder sind bei jedem Tick, der noch nie für eine Limit-Order verwendet wurde, auf null gesetzt. Sobald Orders auf einem Tick eröffnet werden, verwaltet das Programm sie als Folge von Kohorten:

* `order_phase` ist die Kohorten-ID. Sie wird jedes Mal erhöht, wenn eine Kohorte von „vollständig ungefüllt" auf „teilweise gefüllt" übergeht.
* `orders_amount` ist der Input-Token-Gesamtbetrag der aktuellen (neuesten) Kohorte.
* `part_filled_orders_remaining` verfolgt die vorherige Kohorte, die gerade durch laufende Swaps gefüllt wird.
* `unfilled_ratio_x64` ist ein Q64.64-Multiplikator der Kohorte: Wenn ein Swap X % der Kohorte füllt, wird das Verhältnis mit `(1 − X)` multipliziert. Jede offene Order speichert ihren eigenen `(order_phase, unfilled_ratio_x64)`-Snapshot zum Eröffnungszeitpunkt, sodass die Abrechnungsrechnung auf einen Snapshot-Vergleich reduziert wird.

Regeln:

* Ein Positionsendpunkt-Tick *t* muss `t % tick_spacing == 0` erfüllen. Das Programm lehnt Positionen mit ungültigem Spacing ab.
* Das **Array** eines Ticks befindet sich bei `floor(t / (TICK_ARRAY_SIZE * tick_spacing)) * (TICK_ARRAY_SIZE * tick_spacing)`.
* Ein Tick-Array wird lazily initialisiert: Die erste Position oder der erste Swap, der ein nicht initialisiertes Array berührt, legt es an und übernimmt die Miete.
* Ein Tick-Array wird **vom Programm nie geschlossen**. Einmal angelegt, bleibt er für die Lebensdauer des Pools bestehen, auch wenn alle darin enthaltenen Ticks wieder `liquidity_gross == 0` erreichen. Folgende Positionen und Swaps nutzen den bestehenden Account ohne zusätzliche Miete. Es gibt keinen `ClosePosition`-gesteuerten Bereinigungspfad für Tick-Arrays.

### `TickArrayBitmapExtension`

`PoolState.tick_array_bitmap` (inline) deckt den „nahe am Spotpreis"-Bereich ab — ±1.024 Tick-Arrays. Außerhalb dieses Bereichs (für extreme Tick-Werte) verwaltet das Programm einen Extension-Account:

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

Wenn der Bereich Ihrer Position „normal" ist, müssen Sie sich nie um den Extension-Account kümmern. Full-Range-Positionen (z. B. `(MIN_TICK, MAX_TICK)`) benötigen ihn; das SDK löst ihn für Sie auf.

## Positionen

Eine CLMM-Position ist ein **Bündel** aus drei Accounts plus einem Mint:

### Position-NFT-Mint

Ein SPL-Token-Mint mit Supply 1. Die Adresse des Mints ist ein deterministischer PDA; das Position-NFT im Wallet des Inhabers ist lediglich ein ATA, das dieses einzelne Token hält. Die Übertragung des NFTs ist der Mechanismus, über den eine Position den Besitzer wechselt — das Programm knüpft die Autorisierung an den **aktuellen Inhaber des ATA-Guthabens des NFTs**, nicht an einen in State gespeicherten Pubkey.

### `PersonalPositionState`

Einer pro offener Position. Abgeleitet vom 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` (veraltet)

<Note>
  Ältere CLMM-Versionen speicherten aggregierte Buchführung pro `(pool, tick_lower, tick_upper)` in einem `ProtocolPositionState`-PDA. **Neuere Versionen erstellen oder lesen diesen Account nicht mehr.** Der Slot erscheint in den Account-Listen von `OpenPosition` / `IncreaseLiquidity` / `DecreaseLiquidity` noch als `UncheckedAccount` für ABI-Kompatibilität, aber das Programm schreibt nicht mehr darin. Bestehende Accounts on-chain sind Relikte; der Admin kann `CloseProtocolPosition` aufrufen, um die Miete zurückzugewinnen.

  Die aggregierte Bereichsbuchführung wird jetzt direkt aus den beiden Endpunkt-Ticks (`liquidity_gross`, `liquidity_net` sowie die Tick-spezifischen `fee_growth_outside_*` / `reward_growths_outside_x64`) im `TickArrayState` abgeleitet. Die Fee-Growth-Inside-Formel `fee_growth_inside = global − outside_lower − outside_upper` funktioniert weiterhin ohne aggregierten Positions-Account.
</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],
}
```

Der Observations-Puffer von CLMM speichert einen **kumulierten Tick**, keinen kumulierten Preis. Externe Verbraucher berechnen den geometrischen Mittelpreis über ein Intervall aus `(tick_cumulative[t1] − tick_cumulative[t0]) / (t1 − t0)` und anschließend `price = 1.0001 ** tick`. Siehe [`algorithms/clmm-math`](/de/algorithms/clmm-math).

## `DynamicFeeConfig` und `DynamicFeeInfo`

Dynamische Gebührenparameter befinden sich an zwei Stellen. Die wiederverwendbare Vorlage — `DynamicFeeConfig` — wird vom Admin verwaltet und von Pools geteilt, die sich anmelden. Der Pool-spezifische Laufzeitzustand — `DynamicFeeInfo` — ist in `PoolState` eingebettet und wird bei jedem Swap aktualisiert.

### `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()]`. Wird über `create_dynamic_fee_config` (Admin-gesperrt) erstellt und über `update_dynamic_fee_config` geändert. Ein Pool, der mit `enable_dynamic_fee = true` erstellt wird, übernimmt die fünf Kalibrierungsparameter (`filter_period`, `decay_period`, `reduction_factor`, `dynamic_fee_control`, `max_volatility_accumulator`) bei der Erstellung in seine eigene `DynamicFeeInfo`; spätere Änderungen am `DynamicFeeConfig` wirken sich nicht rückwirkend auf bestehende Pools aus.

### `DynamicFeeInfo` (eingebettet in `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],
}
```

Die unteren vier Felder sind Zustandsfelder; die oberen fünf sind Kalibrierungsparameter, die aus `DynamicFeeConfig` kopiert wurden. Die Gebührenberechnung und die Decay-Regeln sind unter [`products/clmm/math`](/de/products/clmm/math) und [`products/clmm/fees`](/de/products/clmm/fees) dokumentiert.

Von der Formel verwendete Konstanten:

| Konstante                         | Wert      | Bedeutung                                                    |
| --------------------------------- | --------- | ------------------------------------------------------------ |
| `VOLATILITY_ACCUMULATOR_SCALE`    | `10_000`  | Granularität des Volatilitätsakkumulators                    |
| `REDUCTION_FACTOR_DENOMINATOR`    | `10_000`  | Nenner für `reduction_factor`                                |
| `DYNAMIC_FEE_CONTROL_DENOMINATOR` | `100_000` | Nenner für `dynamic_fee_control`                             |
| `MAX_FEE_RATE_NUMERATOR`          | `100_000` | Harte Obergrenze von 10 % für die resultierende Gebührenrate |

## `LimitOrderState`

Einer pro offener Limit-Order.

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

Lebenszyklus:

1. **Eröffnen** — Der Nutzer ruft `open_limit_order` auf, hinterlegt `total_amount` des Input-Tokens; die Order wird an eine `TickState`-Kohorte gebunden.
2. **(optional) Erhöhen / Verringern** — `increase_limit_order` erhöht `total_amount`; `decrease_limit_order` gibt ungefüllte Token zurück (und jeden bis dahin abgerechneten Output).
3. **Abrechnen** — Wenn die Kohorte vollständig oder teilweise gefüllt ist, ruft der Inhaber *oder* der operationale Keeper `settle_limit_order` auf, um Output-Token an das ATA des Inhabers zu übertragen.
4. **Schließen** — Sobald `unfilled_amount == 0`, kann der Account geschlossen werden. Die Miete geht immer an `owner` zurück.

PDA-Seed: `[owner.as_ref(), limit_order_nonce.key().as_ref(), limit_order_nonce.order_nonce.to_be_bytes().as_ref()]`. Der Order-PDA ist daher eindeutig pro `(owner, nonce_index, order_nonce)`.

## `LimitOrderNonce`

Pro-`(wallet, nonce_index)`-Zähler, der es einem einzelnen Nutzer ermöglicht, mehrere parallele Pipelines von Limit-Orders zu betreiben, ohne PDA-Kollisionen zu verursachen.

```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]]`. Die meisten Clients verwenden `nonce_index = 0` und lassen `order_nonce` die Kardinalität tragen.

## Ableitung der wichtigsten Accounts

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

Die genauen Seed-Strings sollten stets gegen das On-Chain-IDL und [`reference/program-addresses`](/de/reference/program-addresses) gegengeprüft werden.

## Kurzreferenz Lebenszyklus

| Ereignis                        | Erstellte Accounts                                                                                                       | Gelöschte Accounts                                                                      |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| `CreatePool`                    | `poolState`, `observation`, `token_0_vault`, `token_1_vault`                                                             | —                                                                                       |
| `OpenPosition[WithToken22Nft]`  | NFT-Mint + ATA, `personalPosition`, ggf. neue `tickArrayState`(s), `tickArrayBitmapExtension` falls noch nicht vorhanden | —                                                                                       |
| `IncreaseLiquidity`             | Ggf. neue `tickArrayState`(s)                                                                                            | —                                                                                       |
| `DecreaseLiquidity`             | —                                                                                                                        | Ggf. Tick-Einträge werden geleert (aber `tickArrayState` selbst wird nicht geschlossen) |
| `ClosePosition`                 | —                                                                                                                        | NFT-Mint, `personalPosition`                                                            |
| `SwapV2`                        | Ggf. neuer `tickArrayState`                                                                                              | —                                                                                       |
| `OpenLimitOrder`                | `limitOrderState`, ggf. `limitOrderNonce` (init-if-needed), ggf. neuer `tickArrayState`                                  | —                                                                                       |
| `IncreaseLimitOrder`            | —                                                                                                                        | —                                                                                       |
| `DecreaseLimitOrder`            | —                                                                                                                        | Schließt `limitOrderState`, wenn die Order vollständig verbraucht ist                   |
| `SettleLimitOrder`              | —                                                                                                                        | —                                                                                       |
| `CloseLimitOrder`               | —                                                                                                                        | `limitOrderState` (Miete → `owner`)                                                     |
| `CreateDynamicFeeConfig`        | `dynamicFeeConfig`                                                                                                       | —                                                                                       |
| `CreateCustomizablePool`        | `poolState`, `observation`, Vaults — wie `CreatePool`. Übernimmt `dynamicFeeConfig`, wenn `enable_dynamic_fee = true`.   | —                                                                                       |
| `CollectRewards`                | —                                                                                                                        | —                                                                                       |
| `UpdateRewardInfos`             | —                                                                                                                        | —                                                                                       |
| `CloseProtocolPosition` (Admin) | —                                                                                                                        | Veralteter `protocolPositionState` (Miete → Admin)                                      |

`TickArrayState`-Accounts werden **vom Programm nie geschlossen** — sie bleiben für die gesamte Lebensdauer des Pools bestehen. Einmal initialisiert, verbleibt ein Tick-Array on-chain, auch wenn jeder darin enthaltene Tick wieder `liquidity_gross == 0` erreicht. Die Wiederverwendung eines bestehenden Tick-Arrays ist kostenlos; nur die erste Position, die ein noch nie initialisiertes Array berührt, übernimmt dessen Miete.

## Was wo nachzulesen ist

* **Tick-Mathematik und Bereichsmechanik**: [`products/clmm/ticks-and-positions`](/de/products/clmm/ticks-and-positions).
* **Swap-Walk und Fee-Growth-Mathematik**: [`products/clmm/math`](/de/products/clmm/math).
* **Instruction-Account-Listen**: [`products/clmm/instructions`](/de/products/clmm/instructions).
* **Gebühren und Reward-Ansammlung**: [`products/clmm/fees`](/de/products/clmm/fees).
* **Kanonische Programm-IDs und Seeds**: [`reference/program-addresses`](/de/reference/program-addresses).

Quellen:

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