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

> Setiap PDA dan akun bersama yang disentuh pool CPMM: PoolState, AmmConfig, authority, LP mint, token vaults, dan ring buffer observasi.

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

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

<Info>
  ID program dan seed PDA untuk CPMM tercantum secara kanonik di [`reference/program-addresses`](/id/reference/program-addresses). Halaman ini fokus pada **apa kegunaan setiap akun dan invarian yang dipertahankannya**, bukan alamat yang dikodekan.
</Info>

## Enam akun dari pool CPMM

Setiap pool CPMM sepenuhnya dijelaskan oleh enam program-derived addresses (PDA) di bawah program CPMM, ditambah satu akun `AmmConfig` bersama yang dirujuknya. Setelah Anda memiliki dua mint, Anda dapat menurunkan semuanya secara deterministik tanpa menyentuh jaringan.

| Akun          | Seed(s)                                                                                                | Pemilik                | Tujuan                                                                                                                                                                                                                                                                                                                                                                                                     |
| ------------- | ------------------------------------------------------------------------------------------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authority`   | `"vault_and_lp_mint_auth_seed"`                                                                        | CPMM                   | Penanda tangan untuk setiap pergerakan vault dan setiap LP mint/burn. Dibagikan di **semua** pool CPMM.                                                                                                                                                                                                                                                                                                    |
| `poolState`   | `"pool"`, `ammConfig`, `token0Mint`, `token1Mint` **atau** keypair acak yang disediakan penanda tangan | CPMM                   | Struct state pool — pasangan mint, saldo vault, pasokan LP, akrual biaya, pointer observasi. Instruksi CPMM `Initialize` menerima baik PDA kanonik yang diturunkan dari empat seed **atau** keypair arbitrer yang ditandatangani oleh pembuat. Jalur keypair acak ada untuk mengalahkan serangan front-running di mana penyerang mengawasi mempool dan berlomba menempati PDA kanonik sebelum pembuat sah. |
| `lpMint`      | `"pool_lp_mint"`, `poolState`                                                                          | SPL Token              | Token LP pool. Pasokan = total LP yang beredar. Mint authority = CPMM authority PDA.                                                                                                                                                                                                                                                                                                                       |
| `vault0`      | `"pool_vault"`, `poolState`, `token0Mint`                                                              | SPL Token / Token-2022 | Menyimpan saldo token0 pool. Dimiliki oleh authority PDA.                                                                                                                                                                                                                                                                                                                                                  |
| `vault1`      | `"pool_vault"`, `poolState`, `token1Mint`                                                              | SPL Token / Token-2022 | Menyimpan saldo token1 pool. Dimiliki oleh authority PDA.                                                                                                                                                                                                                                                                                                                                                  |
| `observation` | `"observation"`, `poolState`                                                                           | CPMM                   | Ring buffer sampel harga yang digunakan untuk TWAP. Ditulis pada setiap swap.                                                                                                                                                                                                                                                                                                                              |

Dan konfigurasi bersama:

| Akun        | Seed(s)                      | Pemilik | Tujuan                                                                                                                                                                 |
| ----------- | ---------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ammConfig` | `"amm_config"`, `index: u16` | CPMM    | Menyimpan tingkat biaya trade/protocol/fund/creator dan kunci admin. Satu per "fee tier". Poolstate terikat pada satu saat pembuatan dan tidak dapat berubah kemudian. |

## Menurunkan pool dari tidak ada selain dua mint

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

const CPMM_PROGRAM_ID = new PublicKey(
  "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"
); // mainnet — see reference/program-addresses

function u16ToBytes(n: number): Buffer {
  const b = Buffer.alloc(2);
  b.writeUInt16BE(n);
  return b;
}

// token0 < token1 by byte order. Getting this wrong yields a valid PDA
// that points at a nonexistent pool.
function sortMints(a: PublicKey, b: PublicKey): [PublicKey, PublicKey] {
  return Buffer.compare(a.toBuffer(), b.toBuffer()) < 0 ? [a, b] : [b, a];
}

export function deriveCpmmAccounts(
  mintA: PublicKey,
  mintB: PublicKey,
  ammConfigIndex = 0,
) {
  const [token0Mint, token1Mint] = sortMints(mintA, mintB);

  const [ammConfig] = PublicKey.findProgramAddressSync(
    [Buffer.from("amm_config"), u16ToBytes(ammConfigIndex)],
    CPMM_PROGRAM_ID,
  );
  const [authority] = PublicKey.findProgramAddressSync(
    [Buffer.from("vault_and_lp_mint_auth_seed")],
    CPMM_PROGRAM_ID,
  );
  const [poolState] = PublicKey.findProgramAddressSync(
    [
      Buffer.from("pool"),
      ammConfig.toBuffer(),
      token0Mint.toBuffer(),
      token1Mint.toBuffer(),
    ],
    CPMM_PROGRAM_ID,
  );
  const [lpMint] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_lp_mint"), poolState.toBuffer()],
    CPMM_PROGRAM_ID,
  );
  const [vault0] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_vault"), poolState.toBuffer(), token0Mint.toBuffer()],
    CPMM_PROGRAM_ID,
  );
  const [vault1] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_vault"), poolState.toBuffer(), token1Mint.toBuffer()],
    CPMM_PROGRAM_ID,
  );
  const [observation] = PublicKey.findProgramAddressSync(
    [Buffer.from("observation"), poolState.toBuffer()],
    CPMM_PROGRAM_ID,
  );

  return {
    ammConfig,
    authority,
    poolState,
    lpMint,
    token0Mint,
    token1Mint,
    vault0,
    vault1,
    observation,
  };
}
```

<Tip>
  **Selalu urutkan mint sebelum menurunkan PDA pool.** Seed melakukan hash dua mint dalam urutan byte, bukan urutan pengguna. Dua pool dengan `(A, B)` dan `(B, A)` akan bertabrakan on-chain — pengurutan adalah cara program membuat pemetaan kanonik.
</Tip>

<Note>
  **ID pool tidak selalu PDA kanonik.** `Initialize` menerima keypair penanda tangan arbitrer sebagai `pool_state` selain PDA di atas. Jika akun yang dilewatkan tidak cocok dengan PDA kanonik, program memerlukan itu menjadi penanda tangan — yaitu, pembuat melewatkan keypair segar yang mereka tandatangani. Ini adalah pertahanan front-run: pihak ketiga apa pun yang berlomba merebut PDA kanonik dapat dihindari oleh pembuat sah menggunakan keypair acak sebagai gantinya. PDA hilir (`lpMint`, `vault0`, `vault1`, `observation`) masih diturunkan dari `poolState.key()`, sehingga mereka tetap unik untuk alamat mana pun yang digunakan. Ketika Anda mengindeks pool, selalu temukan ID pool dari state on-chain (mis., akun `PoolState` di bawah program CPMM), bukan dengan menurunkan PDA kanonik — yang terakhir akan melewatkan pool keypair acak.
</Note>

## Tata letak akun

Definisi Rust lengkap ada di sumber [`raydium-cp-swap`](https://github.com/raydium-io/raydium-cp-swap). Bidang di bawah adalah yang akan Anda baca dari integrasi.

### `PoolState`

```rust theme={null}
// programs/cp-swap/src/states/pool.rs
pub struct PoolState {
    pub amm_config: Pubkey,               // binds this pool to an AmmConfig
    pub pool_creator: Pubkey,             // who ran initialize
    pub token_0_vault: Pubkey,            // == vault0 PDA
    pub token_1_vault: Pubkey,            // == vault1 PDA

    pub lp_mint: Pubkey,
    pub token_0_mint: Pubkey,
    pub token_1_mint: Pubkey,

    pub token_0_program: Pubkey,          // SPL Token or Token-2022 program
    pub token_1_program: Pubkey,

    pub observation_key: Pubkey,          // == observation PDA
    pub auth_bump: u8,
    pub status: u8,                       // bitmask: deposit | withdraw | swap
    pub lp_mint_decimals: u8,
    pub mint_0_decimals: u8,
    pub mint_1_decimals: u8,

    pub lp_supply: u64,                   // mirrors lp_mint supply
    pub protocol_fees_token_0: u64,
    pub protocol_fees_token_1: u64,
    pub fund_fees_token_0: u64,
    pub fund_fees_token_1: u64,

    pub open_time: u64,                   // unix; swaps rejected before this
    pub recent_epoch: u64,

    // Creator-fee state (added after the original layout):
    pub creator_fee_on: u8,               // 0=BothToken, 1=OnlyToken0, 2=OnlyToken1
    pub enable_creator_fee: bool,
    pub padding1: [u8; 6],
    pub creator_fees_token_0: u64,
    pub creator_fees_token_1: u64,

    pub padding: [u64; 28],
}
```

Apa yang sebenarnya harus dibaca:

* **`lp_supply`** — cerminan internal pool dari pasokan total LP mint. Gunakan untuk matematis LP-share; nilainya harus cocok dengan pasokan on-chain mint, tetapi membacanya dari `PoolState` menghindari pengambilan akun tambahan.
* **`protocol_fees_token{0,1}`**, **`fund_fees_token{0,1}`** — biaya yang *terakrual* yang belum disapu. Ini tidak mempengaruhi pricing swap; mereka duduk di vault hingga `CollectProtocolFee` / `CollectFundFee` dipanggil.
* **`status`** — bitmask yang mengontrol apakah `Swap`, `Deposit`, `Withdraw` diizinkan. Diperbarui oleh admin melalui `UpdatePoolStatus`. SDK memeriksa ini sebelum membangun transaksi; jika Anda langsung CPI-ing, periksa sendiri.
* **`token0_program` / `token1_program`** — program token untuk CPI ke dalam untuk setiap vault. Satu dapat berupa SPL Token klasik dan yang lain Token-2022; mereka independen.
* **`open_time`** — timestamp Unix. Swap sebelum waktu ini gagal. Deposit diizinkan sebelum `open_time` jadi pool dapat disemai.
* **`creator_fee_on` / `enable_creator_fee`** — bersama-sama mengontrol apakah biaya creator opsional aktif untuk pool ini dan sisi swap mana ia dikumpulkan. `enable_creator_fee == false` mengosongkan jalur biaya creator sepenuhnya. Ketika diaktifkan, `creator_fee_on` memilih: `0` = ambil biaya dari token mana pun yang merupakan input swap (`BothToken`); `1` = ambil biaya dari `token_0` saja (lewati di swap `token_1 → token_0`); `2` = ambil biaya dari `token_1` saja. Ditetapkan saat pembuatan pool melalui `InitializeWithPermission`; tidak dapat berubah kemudian.
* **`creator_fees_token_{0,1}`** — biaya creator yang terakrual, disapu oleh `CollectCreatorFee`.

### `AmmConfig`

```rust theme={null}
pub struct AmmConfig {
    pub bump: u8,
    pub disable_create_pool: bool,
    pub index: u16,                       // matches the seed
    pub trade_fee_rate: u64,              // e.g., 2500 = 0.25%
    pub protocol_fee_rate: u64,           // fraction of trade fee to protocol
    pub fund_fee_rate: u64,               // fraction of trade fee to fund
    pub create_pool_fee: u64,             // paid once at init (in SOL or token)
    pub protocol_owner: Pubkey,           // can call CollectProtocolFee
    pub fund_owner: Pubkey,               // can call CollectFundFee
    pub creator_fee_rate: u64,            // optional pool-creator fee rate (1/1_000_000 of volume)
    pub padding: [u64; 15],
}
```

Tiga hal yang perlu diperhatikan:

1. **`trade_fee_rate` dan `creator_fee_rate` adalah fraksi dari volume**, keduanya dinyatakan dalam unit `1/1_000_000`. `2500` berarti 0,25% dari volume trade. **`protocol_fee_rate` dan `fund_fee_rate` adalah fraksi dari *trade fee*** (bukan dari volume), dalam denominator `1/1_000_000` yang sama. Biaya creator **bukan** fraksi dari trade fee — ini adalah tingkat independen sendiri. Aritmetika lengkap ada di [`products/cpmm/fees`](/id/products/cpmm/fees).
2. **`index` adalah `u16`**, jadi seed hash menggunakan 2 byte big-endian. Kesalahan urutan byte adalah bug integrasi umum.
3. **`AmmConfig` tidak dapat diubah di tingkat pool.** Pool menunjuk satu `AmmConfig` saat pembuatan dan tidak pernah berpindah. Perubahan biaya menyebar karena pool membaca konfigurasi setiap swap — tetapi pool tidak dapat dipindahkan di antara fee tier.

Catatan tentang biaya creator: **tingkat** sendiri (`creator_fee_rate`) ada di `AmmConfig` dan dibagikan di seluruh fee tier. Apakah pool tertentu benar-benar mengenakan biayanya (`enable_creator_fee`) dan sisi swap mana yang dikenakannya (`creator_fee_on`) ada di `PoolState`. Biaya creator **independen** dari trade fee — ini adalah tingkat sendiri, terakrual ke penghitung sendiri (`creator_fees_token_{0,1}`), dan tidak pernah mengurangi bagian LP / protocol / fund dari trade fee. Penyapuan melalui `CollectCreatorFee`. Lihat [`products/cpmm/fees`](/id/products/cpmm/fees) untuk mekanika lengkap.

### `Permission`

Akun kontrol akses kecil yang digunakan oleh `InitializeWithPermission`. Program CPMM mendukung jalur pembuatan pool berupa izin sehingga program lain (mis. LaunchLab saat meluluskan token ke CPMM) dapat membuktikan mereka berhak membuat pool terhadap `AmmConfig` yang diberikan.

```rust theme={null}
pub struct Permission {
    pub authority: Pubkey,    // who is allowed to call InitializeWithPermission
    pub padding: [u64; 8],
}
```

PDA Permission dibuat oleh admin CPMM melalui `CreatePermissionPda` dan dibatalkan melalui `ClosePermissionPda`. Pengguna akhir tidak berinteraksi dengan akun ini secara langsung — ini adalah pipa untuk alur lintas program.

### Vault dan Token-2022

`vault0` dan `vault1` dimiliki oleh CPMM authority PDA, dan pemilik token-program mereka (`token_program`) adalah baik SPL Token atau Token-2022, ditentukan saat pembuatan pool oleh program mint. Pool menangani dua kasus secara transparan — Anda melewatkan token-program ID yang benar untuk setiap sisi di akun instruksi `Swap` / `Deposit` / `Withdraw`.

CPMM menerapkan **daftar whitelist ekstensi** yang ketat saat pembuatan pool (`is_supported_mint` di `utils/token.rs`). Mint Token-2022 dapat digunakan dalam pool CPMM hanya jika **setiap** ekstensi yang dibawanya ada di daftar ini:

* **`TransferFeeConfig`.** Diterapkan oleh mint di setiap transfer. Pool berada di sisi penerima untuk deposit `SwapBaseInput` dan sisi pengirim untuk penarikan. Program menghitung jumlah **bersih** yang masuk ke vault dan mengatur kurva sesuai. Lihat [`algorithms/token-2022-transfer-fees`](/id/algorithms/token-2022-transfer-fees).
* **`MetadataPointer`** dan **`TokenMetadata`.** Metadata on-mint standar. Tidak ada pengaruh pada swap math.
* **`InterestBearingConfig`.** Jumlah UI mint terakrual bunga. Vault menyimpan jumlah mentah; kurva beroperasi hanya pada jumlah mentah. UI yang menampilkan APR harus memanggil pembantu Token-2022 untuk merender jumlah UI.
* **`ScaledUiAmount`.** Ekstensi penskalaan tampilan UI. Perlakuan yang sama dengan `InterestBearingConfig` — kurva menggunakan jumlah mentah.

Ekstensi lain apa pun — `PermanentDelegate`, `TransferHook`, `DefaultAccountState`, `NonTransferable`, `ConfidentialTransfer`, `Group`/`GroupMember`, `MintCloseAuthority`, dll. — menyebabkan `Initialize` ditolak dengan `NotSupportMint`. Pengecualiannya adalah **whitelist mint** hard-coded kecil di program (beberapa pubkey spesifik) yang melewati pemeriksaan ekstensi; ini digunakan untuk mengonboardkan mint spesifik kasus per kasus.

Daftar ekstensi terverifikasi dan whitelist mint ada di sumber CP-Swap di `programs/cp-swap/src/utils/token.rs` dan dapat berubah dengan upgrade program di masa depan.

### Observation

Akun observasi adalah ring buffer dari entri `ObservationState`, masing-masing menyimpan `block_timestamp` dan **harga kumulatif**. Pada setiap swap, program menambahkan observasi baru jika waktu yang cukup telah berlalu sejak yang terakhir. TWAP dihitung dengan membaca dua observasi dan membagi `Δcumulative / Δtime`.

```rust theme={null}
// OBSERVATION_NUM is hardcoded in the program to 100.
pub const OBSERVATION_NUM: usize = 100;

pub struct Observation {
    pub block_timestamp:              u64,
    pub cumulative_token_0_price_x32: u128,   // Q32.32, top 64 bits left for overflow
    pub cumulative_token_1_price_x32: u128,
}

pub struct ObservationState {
    pub initialized:           bool,
    pub observation_index:     u16,                            // circular index
    pub pool_id:               Pubkey,
    pub observations:          [Observation; OBSERVATION_NUM], // 100 entries
    pub last_update_timestamp: u64,                            // timestamp of the most recent append
    pub padding:               [u64; 3],
}
```

Ring buffer diukur untuk **100 observasi**. Setiap observasi 40 byte, jadi array saja 4.000 byte; PDA `ObservationState` lengkap sekitar 4.100 byte setelah bidang sekitarnya dan discriminator.

Dua aturan konsumen:

* **Jangan gunakan observasi tunggal sebagai harga.** Itu adalah *kumulatif*, bukan harga spot. Gunakan dua di antaranya untuk menghitung TWAP.
* **Pilih observasi setidaknya satu blok terpisah.** Swap dalam blok yang sama mungkin tidak menghasilkan observasi baru; membaca back-to-back dapat mengembalikan record yang sama.

Lebih banyak math di [`products/clmm/accounts`](/id/products/clmm/accounts).

## Daur hidup akun

| Acara                | Akun dibuat                                              | Akun dihancurkan |
| -------------------- | -------------------------------------------------------- | ---------------- |
| `Initialize`         | `poolState`, `lpMint`, `vault0`, `vault1`, `observation` | —                |
| `Deposit`            | — (mungkin membuat LP ATA pengguna)                      | —                |
| `Withdraw`           | —                                                        | —                |
| `Swap`               | — (mungkin membuat ATA tujuan pengguna)                  | —                |
| `CollectProtocolFee` | —                                                        | —                |
| `CollectFundFee`     | —                                                        | —                |
| `UpdatePoolStatus`   | —                                                        | —                |

Pool CPMM dan PDA mereka **tidak pernah ditutup**. Bahkan dengan likuiditas nol `poolState` tetap ada. Ini disengaja: menabur ulang pool yang sama nanti mempertahankan buffer observasi historikal dan derivasi PDA-nya tetap stabil.

## Apa yang harus dibaca di mana

* **Daftar akun instruksi** (yang dari di atas dapat ditulis/penanda tangan untuk setiap instruksi): [`products/cpmm/instructions`](/id/products/cpmm/instructions).
* **Semantik akrual biaya**: [`products/cpmm/fees`](/id/products/cpmm/fees).
* **Math swap / aturan pembaruan observasi**: [`products/cpmm/math`](/id/products/cpmm/math).
* **Seed kanonik / ID program**: [`reference/program-addresses`](/id/reference/program-addresses).

Sumber:

* [`raydium-io/raydium-cp-swap` — PoolState, AmmConfig, ObservationState](https://github.com/raydium-io/raydium-cp-swap)
