# Creación de un pool

Crea un pool CPMM de producto constante y arráncalo con liquidez inicial en una sola transacción.

Hay dos formas de crear un pool CPMM:

| Método           | Método del SDK               | Quién puede llamar         | Comisiones del creador   |
| ---------------- | ---------------------------- | -------------------------- | ------------------------ |
| **Sin permisos** | `createPool()`               | Cualquiera                 | Deshabilitado            |
| **Con permisos** | `createPoolWithPermission()` | Solo direcciones aprobadas | Habilitado, configurable |

La mayoría de los integradores usan la ruta sin permisos. La ruta con permisos está diseñada para launchpads y socios aprobados que necesitan ingresos por creator fee de los swaps.

***

### Obteniendo configuraciones de comisiones

Cada pool CPMM hace referencia a una `AmmConfig` en la cadena que define su nivel de comisión. Obtén las configuraciones disponibles antes de crear un pool.

```typescript
const feeConfigs = await raydium.api.getCpmmConfigs()
```

También puedes ver los IDs de configuración pública en:

* Mainnet: [api-v3.raydium.io/main/cpmm-config](https://api-v3.raydium.io/main/cpmm-config)
* Devnet: [api-v3-devnet.raydium.io/main/cpmm-config](https://api-v3-devnet.raydium.io/main/cpmm-config)

{% hint style="info" %}
También se admiten configuraciones de comisión personalizadas. Ponte en contacto con el equipo si necesitas personalizar las comisiones.
{% endhint %}

***

### Creación de un pool

Usa `raydium.cpmm.createPool()` para inicializar un nuevo pool con dos mint de tokens y montos de depósito iniciales.

```typescript
import {
  CREATE_CPMM_POOL_PROGRAM,
  CREATE_CPMM_POOL_FEE_ACC,
  DEVNET_PROGRAM_ID,
  getCpmmPdaAmmConfigId,
  TxVersion,
} from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import { initSdk } from '../config'

const createPool = async () => {
  const raydium = await initSdk({ loadToken: true })

  const mintA = await raydium.token.getTokenInfo('So11111111111111111111111111111111111111112')
  const mintB = await raydium.token.getTokenInfo('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')

  /**
   * También puedes proporcionar la información de mint directamente en lugar de recuperarla:
   * {
   *   address: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R',
   *   programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
   *   decimals: 6,
   * }
   */

  const feeConfigs = await raydium.api.getCpmmConfigs()

  // En devnet, vuelve a derivar los IDs de configuración desde el programa de devnet
  if (raydium.cluster === 'devnet') {
    feeConfigs.forEach((config) => {
      config.id = getCpmmPdaAmmConfigId(
        DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM,
        config.index
      ).publicKey.toBase58()
    })
  }

  const { execute, extInfo } = await raydium.cpmm.createPool({
    programId: CREATE_CPMM_POOL_PROGRAM,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM
    poolFeeAccount: CREATE_CPMM_POOL_FEE_ACC,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_FEE_ACC
    mintA,
    mintB,
    mintAAmount: new BN(1_000_000),
    mintBAmount: new BN(1_000_000),
    startTime: new BN(0),
    feeConfig: feeConfigs[0],
    associatedOnly: false,
    ownerInfo: {
      useSOLBalance: true,
    },
    txVersion: TxVersion.V0,
    // opcional: configura la comisión de prioridad aquí
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 46591500,
    // },
  })

  const { txId } = await execute({ sendAndConfirm: true })
  console.log('pool created', {
    txId: `https://explorer.solana.com/tx/${txId}`,
    poolId: extInfo.address.poolId.toBase58(),
  })
}

createPool()
```

***

### Parámetros

| Parámetro        | Tipo      | Descripción                                                                                                                                |
| ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `programId`      | PublicKey | ID del programa CPMM. Usa `CREATE_CPMM_POOL_PROGRAM` para mainnet, `DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM` para devnet.               |
| `poolFeeAccount` | PublicKey | Cuenta de comisiones del protocolo. Usa `CREATE_CPMM_POOL_FEE_ACC` para mainnet, `DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_FEE_ACC` para devnet. |
| `mintA`          | TokenInfo | Información del primer mint de token (address, programId, decimals).                                                                       |
| `mintB`          | TokenInfo | Información del segundo mint de token. Debe ser diferente de `mintA`.                                                                      |
| `mintAAmount`    | BN        | Monto de depósito inicial para el token A, en las unidades más pequeñas.                                                                   |
| `mintBAmount`    | BN        | Monto de depósito inicial para el token B, en las unidades más pequeñas.                                                                   |
| `startTime`      | BN        | Marca de tiempo Unix en la que se habilitan los swaps. `0` para inmediato.                                                                 |
| `feeConfig`      | object    | Configuración del nivel de comisiones de `getCpmmConfigs()`. Determina las comisiones de trading y la comisión de creación del pool.       |
| `associatedOnly` | boolean   | Si `true`, usa solo cuentas de token asociadas.                                                                                            |
| `ownerInfo`      | object    | `{ useSOLBalance: true }` para usar el saldo nativo de SOL para el wrapping.                                                               |
| `txVersion`      | TxVersion | Versión de la transacción. `TxVersion.V0` para transacciones versionadas, `TxVersion.LEGACY` para legacy.                                  |

### Valor de retorno

El `extInfo.address` objeto contiene las direcciones derivadas del pool:

| Campo    | Descripción                       |
| -------- | --------------------------------- |
| `poolId` | La clave pública del pool creado. |
| `mintA`  | Dirección mint del token A.       |
| `mintB`  | Dirección mint del token B.       |
| `lpMint` | Dirección mint del token LP.      |
| `vaultA` | Vault del pool para el token A.   |
| `vaultB` | Vault del pool para el token B.   |

***

### Crear un pool con permiso (creator fees)

La ruta con permisos usa la instrucción en la cadena `initialize_with_permission` . Requiere un **Permission PDA** que el administrador de Raydium ha creado para tu dirección. A cambio, obtienes:

* **Creator fees habilitadas** — una comisión por swap enviada al creador del pool, además de la comisión de trading normal.
* **Token de comisión configurable** — elige si la creator fee se toma de ambos tokens, solo del token A o solo del token B.
* **Dirección del creador separada** — el pagador y el creador del pool pueden ser wallets diferentes.

{% hint style="info" %}
Para solicitar un Permission PDA para tu dirección, contacta al equipo de Raydium. Sin uno, la `createPoolWithPermission()` llamada fallará.
{% endhint %}

Usa `raydium.cpmm.createPoolWithPermission()` para crear un pool con creator fees habilitadas.

```typescript
import {
  CREATE_CPMM_POOL_PROGRAM,
  CREATE_CPMM_POOL_FEE_ACC,
  DEVNET_PROGRAM_ID,
  getCpmmPdaAmmConfigId,
  FeeOn,
  TxVersion,
} from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import { initSdk } from '../config'

const createPoolWithPermission = async () => {
  const raydium = await initSdk({ loadToken: true })

  const mintA = await raydium.token.getTokenInfo('So11111111111111111111111111111111111111112')
  const mintB = await raydium.token.getTokenInfo('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')

  const feeConfigs = await raydium.api.getCpmmConfigs()

  if (raydium.cluster === 'devnet') {
    feeConfigs.forEach((config) => {
      config.id = getCpmmPdaAmmConfigId(
        DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM,
        config.index
      ).publicKey.toBase58()
    })
  }

  const { execute, extInfo } = await raydium.cpmm.createPoolWithPermission({
    programId: CREATE_CPMM_POOL_PROGRAM,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM
    poolFeeAccount: CREATE_CPMM_POOL_FEE_ACC,
    // devnet: DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_FEE_ACC
    mintA,
    mintB,
    mintAAmount: new BN(1_000_000),
    mintBAmount: new BN(1_000_000),
    startTime: new BN(0),
    feeConfig: feeConfigs[0],
    associatedOnly: false,
    ownerInfo: {
      useSOLBalance: true,
    },
    feeOn: FeeOn.BothToken, // BothToken | OnlyTokenA | OnlyTokenB
    txVersion: TxVersion.V0,
  })

  const { txId } = await execute({ sendAndConfirm: true })
  console.log('pool created with permission', {
    txId: `https://explorer.solana.com/tx/${txId}`,
    poolId: extInfo.address.poolId.toBase58(),
  })
}

createPoolWithPermission()
```

#### Parámetros adicionales (vs. sin permisos)

| Parámetro | Tipo  | Descripción                                                                                  |
| --------- | ----- | -------------------------------------------------------------------------------------------- |
| `feeOn`   | FeeOn | Controla sobre qué token se cobra la creator fee. `BothToken`, `OnlyTokenA`, o `OnlyTokenB`. |

Todos los demás parámetros son los mismos que en la versión sin permisos `createPool()`.

#### `FeeOn` enum

| Valor        | Comportamiento                                                       |
| ------------ | -------------------------------------------------------------------- |
| `BothToken`  | La creator fee se cobra sobre el token que sea el input del swap.    |
| `OnlyTokenA` | La creator fee solo se cobra cuando el token A es el input del swap. |
| `OnlyTokenB` | La creator fee solo se cobra cuando el token B es el input del swap. |

#### Diferencias clave frente a sin permisos

|                        | `createPool()`                              | `createPoolWithPermission()`                                               |
| ---------------------- | ------------------------------------------- | -------------------------------------------------------------------------- |
| Permiso requerido      | Ninguno                                     | El administrador de Raydium debe crear un Permission PDA para tu dirección |
| Comisiones del creador | Deshabilitado (`enable_creator_fee: false`) | Habilitado (`enable_creator_fee: true`)                                    |
| Modelo de creator fee  | Fijo (`BothToken`, sin uso)                 | Lo elige el llamador (`BothToken`, `OnlyTokenA`, `OnlyTokenB`)             |
| Pagador vs. creador    | La misma wallet                             | Pueden ser wallets diferentes                                              |

{% hint style="warning" %}
Cobro de creator fee (mediante `collectCreatorFees()`) solo funciona en pools creados a través de la ruta con permisos. Los pools creados con la opción estándar `createPool()` tienen las creator fees deshabilitadas a nivel del programa.
{% endhint %}
