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

# Cuentas de CPMM

> Cada PDA y cuenta compartida que toca un pool de CPMM: PoolState, AmmConfig, autoridad, mint de LP, bóvedas de tokens y el búfer del anillo de observaciones.

<Info>
  **Esta página fue traducida automáticamente por IA. La versión en inglés es la fuente autorizada.**

  [Ver versión en inglés →](/products/cpmm/accounts)
</Info>

<Info>
  Los ID del programa y las semillas PDA para CPMM se enumeran canónicamente en [`reference/program-addresses`](/es/reference/program-addresses). Esta página se enfoca en **para qué sirve cada cuenta y los invariantes que mantiene**, no en las direcciones codificadas.
</Info>

## Las seis cuentas de un pool de CPMM

Cada pool de CPMM se describe completamente mediante seis direcciones derivadas del programa (PDA) bajo el programa CPMM, más una cuenta `AmmConfig` compartida a la que hace referencia. Una vez que tengas los dos mints, puedes derivar todo de forma determinística sin tocar la red.

| Cuenta        | Semilla(s)                                                                                                        | Propietario            | Propósito                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authority`   | `"vault_and_lp_mint_auth_seed"`                                                                                   | CPMM                   | El firmante para cada movimiento de bóveda y cada acuñación/quema de LP. Compartido entre **todos** los pools de CPMM.                                                                                                                                                                                                                                                                                                                                                                    |
| `poolState`   | `"pool"`, `ammConfig`, `token0Mint`, `token1Mint` **o** cualquier keypair aleatorio proporcionado por el firmante | CPMM                   | La estructura de estado del pool — par de mints, saldos de bóveda, suministro de LP, acumulación de comisiones, puntero de observación. La instrucción `Initialize` de CPMM acepta tanto el PDA canónico derivado de las cuatro semillas **como** un keypair arbitrario firmado por el creador. La ruta del keypair aleatorio existe para evitar un ataque de adelantamiento donde un adversario observa el mempool y se apresura a ocupar el PDA canónico antes que el creador legítimo. |
| `lpMint`      | `"pool_lp_mint"`, `poolState`                                                                                     | SPL Token              | El token LP del pool. Suministro = total de LP pendiente. Autoridad de acuñación = el PDA de autoridad de CPMM.                                                                                                                                                                                                                                                                                                                                                                           |
| `vault0`      | `"pool_vault"`, `poolState`, `token0Mint`                                                                         | SPL Token / Token-2022 | Contiene el saldo del token0 del pool. Propiedad del PDA de autoridad.                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `vault1`      | `"pool_vault"`, `poolState`, `token1Mint`                                                                         | SPL Token / Token-2022 | Contiene el saldo del token1 del pool. Propiedad del PDA de autoridad.                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `observation` | `"observation"`, `poolState`                                                                                      | CPMM                   | Búfer de anillo de muestras de precios utilizadas para el TWAP. Se escribe en cada swap.                                                                                                                                                                                                                                                                                                                                                                                                  |

Y la configuración compartida:

| Cuenta      | Semilla(s)                   | Propietario | Propósito                                                                                                                                                                                                     |
| ----------- | ---------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ammConfig` | `"amm_config"`, `index: u16` | CPMM        | Contiene las tasas de comisiones comerciales/protocolo/fondo/creador y las claves de administrador. Una por "nivel de tarifa". El estado del pool se vincula a uno en la creación y no puede cambiar después. |

## Derivar un pool a partir de solo dos mints

```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>
  **Siempre ordena los mints antes de derivar el PDA del pool.** La semilla codifica los dos mints en orden de bytes, no en orden de usuario. Dos pools con `(A, B)` y `(B, A)` colisionarían en la cadena — la ordenación es cómo el programa hace que la asignación sea canónica.
</Tip>

<Note>
  **El ID del pool no siempre es el PDA canónico.** `Initialize` acepta un keypair firmante arbitrario como `pool_state` además del PDA anterior. Si la cuenta pasada no coincide con el PDA canónico, el programa requiere que sea un firmante — es decir, el creador pasa un keypair fresco que firma. Esta es la defensa contra adelantamiento: cualquier tercero que intente tomar el PDA canónico puede ser eludido por el creador legítimo usando un keypair aleatorio en su lugar. Los PDA posteriores (`lpMint`, `vault0`, `vault1`, `observation`) aún se derivan de `poolState.key()`, por lo que permanecen únicos para cualquier dirección que se haya utilizado. Cuando indexas pools, siempre descubre el ID del pool desde el estado en cadena (por ejemplo, cuentas `PoolState` bajo el programa CPMM), no derivando el PDA canónico — este último perderá los pools con keypair aleatorio.
</Note>

## Diseños de cuentas

Las definiciones completas en Rust viven en la fuente de [`raydium-cp-swap`](https://github.com/raydium-io/raydium-cp-swap). Los campos a continuación son los que leerás desde una integración.

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

Qué leer realmente:

* **`lp_supply`** — el espejo interno del pool del suministro total del mint de LP. Úsalo para las matemáticas de participación de LP; el valor debe coincidir con el suministro en cadena del mint, pero leerlo desde `PoolState` evita una búsqueda de cuenta adicional.
* **`protocol_fees_token{0,1}`**, **`fund_fees_token{0,1}`** — comisiones *acumuladas* aún no barridas. Estas no afectan el precio del swap; se mantienen en las bóvedas hasta que se llame a `CollectProtocolFee` / `CollectFundFee`.
* **`status`** — una máscara de bits que controla si se permiten `Swap`, `Deposit`, `Withdraw`. Actualizado por el administrador mediante `UpdatePoolStatus`. El SDK verifica esto antes de construir una transacción; si estás haciendo CPI directamente, verifica por ti mismo.
* **`token0_program` / `token1_program`** — el programa de token en el que hacer CPI para cada bóveda. Uno puede ser SPL Token clásico y el otro Token-2022; son independientes.
* **`open_time`** — una marca de tiempo Unix. Los swaps antes de esta hora fallan. Los depósitos se permiten antes de `open_time` para que el pool pueda ser sembrado.
* **`creator_fee_on` / `enable_creator_fee`** — juntos controlan si la comisión del creador opcional está activa para este pool y de qué lado del swap se cobra. `enable_creator_fee == false` anula completamente la ruta de comisión del creador. Cuando está habilitado, `creator_fee_on` selecciona: `0` = cobrar comisión del token que sea la entrada del swap (`BothToken`); `1` = cobrar comisión solo de `token_0` (omitir en swaps `token_1 → token_0`); `2` = cobrar comisión solo de `token_1`. Se establece en la creación del pool mediante `InitializeWithPermission`; no puede cambiar después.
* **`creator_fees_token_{0,1}`** — comisiones del creador acumuladas, barridas por `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],
}
```

Tres cosas a tener cuidado:

1. **`trade_fee_rate` y `creator_fee_rate` son fracciones del volumen**, ambas denominadas en unidades de `1/1_000_000`. `2500` significa 0,25% del volumen comercial. **`protocol_fee_rate` y `fund_fee_rate` son fracciones de la *comisión comercial*** (no del volumen), con el mismo denominador `1/1_000_000`. La comisión del creador **no** es una fracción de la comisión comercial — es su propia tasa independiente. La aritmética completa está en [`products/cpmm/fees`](/es/products/cpmm/fees).
2. **`index` es un `u16`**, por lo que la semilla hash usa 2 bytes big-endian. Un error de uno en el orden de bytes es un error de integración común.
3. **`AmmConfig` es inmutable a nivel de pool.** Un pool apunta a un `AmmConfig` en la creación y nunca cambia. Los cambios de comisión se propagan porque el pool lee la configuración en cada swap — pero el pool no puede moverse entre niveles de tarifa.

Una nota sobre las comisiones del creador: la **tasa** misma (`creator_fee_rate`) vive en `AmmConfig` y se comparte entre el nivel de tarifa. Si un pool en particular realmente la cobra (`enable_creator_fee`) y de qué lado del swap cae (`creator_fee_on`) viven en `PoolState`. La comisión del creador es **independiente** de la comisión comercial — es su propia tasa, acumulada en sus propios contadores (`creator_fees_token_{0,1}`), y nunca reduce las participaciones de LP / protocolo / fondo de la comisión comercial. El barrido se realiza mediante `CollectCreatorFee`. Consulta [`products/cpmm/fees`](/es/products/cpmm/fees) para la mecánica completa.

### `Permission`

Una pequeña cuenta de control de acceso utilizada por `InitializeWithPermission`. El programa CPMM admite una ruta de creación de pool con permisos para que otros programas (por ejemplo, LaunchLab cuando gradúa un token a CPMM) puedan demostrar que tienen derecho a crear un pool contra un `AmmConfig` dado.

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

El PDA de Permission se crea por el administrador de CPMM mediante `CreatePermissionPda` y se revoca mediante `ClosePermissionPda`. Los usuarios finales no interactúan directamente con esta cuenta — es tubería para flujos entre programas.

### Bóvedas y Token-2022

`vault0` y `vault1` son propiedad del PDA de autoridad de CPMM, y su propietario del programa de token (`token_program`) es SPL Token o Token-2022, determinado en la creación del pool por el programa del mint. El pool maneja los dos casos de forma transparente — pasas el ID del programa de token correcto para cada lado en las cuentas de instrucción `Swap` / `Deposit` / `Withdraw`.

CPMM impone una **lista de extensiones permitidas** estricta en la creación del pool (`is_supported_mint` en `utils/token.rs`). Un mint de Token-2022 solo puede usarse en un pool de CPMM si **cada** extensión que lleva está en esta lista:

* **`TransferFeeConfig`.** Aplicado por el mint en cada transferencia. El pool está del lado receptor para depósitos `SwapBaseInput` y del lado de envío para retiros. El programa calcula la cantidad **neta** que llega a la bóveda y establece la curva en consecuencia. Consulta [`algorithms/token-2022-transfer-fees`](/es/algorithms/token-2022-transfer-fees).
* **`MetadataPointer`** y **`TokenMetadata`.** Metadatos estándar en mint. Sin efecto en las matemáticas del swap.
* **`InterestBearingConfig`.** El monto UI del mint acumula interés. La bóveda almacena montos brutos; la curva opera solo en montos brutos. Las IU que muestran APR deben llamar a los helpers de Token-2022 para renderizar el monto UI.
* **`ScaledUiAmount`.** Extensión de escalado de pantalla UI. El mismo tratamiento que `InterestBearingConfig` — la curva usa montos brutos.

Cualquier otra extensión — `PermanentDelegate`, `TransferHook`, `DefaultAccountState`, `NonTransferable`, `ConfidentialTransfer`, `Group`/`GroupMember`, `MintCloseAuthority`, etc. — causa que `Initialize` rechace con `NotSupportMint`. La excepción es una pequeña **lista blanca de mints** codificada en el programa (un puñado de pubkeys específicas) que omite la verificación de extensión; se utiliza para incorporar mints específicas caso por caso.

La lista de extensiones verificadas y la lista blanca de mints viven en la fuente de CP-Swap bajo `programs/cp-swap/src/utils/token.rs` y pueden cambiar con futuras actualizaciones del programa.

### Observation

La cuenta de observación es un búfer de anillo de entradas `ObservationState`, cada una almacenando un `block_timestamp` y un **precio acumulativo**. En cada swap, el programa añade una nueva observación si ha pasado suficiente tiempo desde la última. Los TWAP se calculan leyendo dos observaciones y dividiendo `Δ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],
}
```

El búfer de anillo tiene un tamaño para **100 observaciones**. Cada observación tiene 40 bytes, por lo que solo el array tiene 4,000 bytes; el PDA `ObservationState` completo tiene alrededor de 4,100 bytes después de los campos circundantes y el discriminador.

Dos reglas para consumidores:

* **No uses una observación única como precio.** Es un *acumulativo*, no un precio spot. Usa dos para calcular un TWAP.
* **Elige observaciones al menos un bloque separadas.** Los swaps dentro del mismo bloque pueden no producir una nueva observación; leer de forma consecutiva puede devolver el mismo registro.

Más matemáticas en [`products/clmm/accounts`](/es/products/clmm/accounts).

## Ciclo de vida de la cuenta

| Evento               | Cuentas creadas                                          | Cuentas destruidas |
| -------------------- | -------------------------------------------------------- | ------------------ |
| `Initialize`         | `poolState`, `lpMint`, `vault0`, `vault1`, `observation` | —                  |
| `Deposit`            | — (puede crear ATA de LP de usuario)                     | —                  |
| `Withdraw`           | —                                                        | —                  |
| `Swap`               | — (puede crear ATA de destino de usuario)                | —                  |
| `CollectProtocolFee` | —                                                        | —                  |
| `CollectFundFee`     | —                                                        | —                  |
| `UpdatePoolStatus`   | —                                                        | —                  |

Los pools de CPMM y sus PDA **nunca se cierran**. Incluso con liquidez cero, el `poolState` permanece. Esto es deliberado: resembrar el mismo pool más tarde preserva su búfer de observaciones histórico y su derivación PDA permanece estable.

## Qué leer dónde

* **Listas de cuentas de instrucción** (cuáles de las anteriores son escribibles/firmante para cada instrucción): [`products/cpmm/instructions`](/es/products/cpmm/instructions).
* **Semántica de acumulación de comisiones**: [`products/cpmm/fees`](/es/products/cpmm/fees).
* **Matemáticas de swap / regla de actualización de observación**: [`products/cpmm/math`](/es/products/cpmm/math).
* **Semillas canónicas / IDs de programa**: [`reference/program-addresses`](/es/reference/program-addresses).

Fuentes:

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