# Swap

Ejecuta swaps de tokens en pools CLMM. El SDK admite tanto **base-input** (cantidad de entrada fija) como **base-output** (cantidad de salida fija) swaps.

***

### Swap base-input (entrada exacta)

Especifica la cantidad exacta de tokens a vender. El SDK calcula la ruta del swap a través de los tick arrays y calcula cuántos tokens recibes.

```typescript
import {
  ApiV3PoolInfoConcentratedItem,
  ClmmKeys,
  ComputeClmmPoolInfo,
  PoolUtils,
  ReturnTypeFetchMultiplePoolTickArrays,
  RAYMint,
} from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import { initSdk, txVersion } from '../config'
import { isValidClmm } from './utils'

const swap = async () => {
  const raydium = await initSdk()
  let poolInfo: ApiV3PoolInfoConcentratedItem
  const poolId = 'DiwsGxJYoRZURvyCtMsJVyxR86yZBBbSYeeWNm7YCmT6'
  const inputMint = RAYMint.toBase58()
  let poolKeys: ClmmKeys | undefined
  let clmmPoolInfo: ComputeClmmPoolInfo
  let tickCache: ReturnTypeFetchMultiplePoolTickArrays

  const inputAmount = new BN(100)

  if (raydium.cluster === 'mainnet') {
    const data = await raydium.api.fetchPoolById({ ids: poolId })
    poolInfo = data[0] as ApiV3PoolInfoConcentratedItem
    if (!isValidClmm(poolInfo.programId)) throw new Error('el pool de destino no es un pool CLMM')

    clmmPoolInfo = await PoolUtils.fetchComputeClmmInfo({
      connection: raydium.connection,
      poolInfo,
    })
    tickCache = await PoolUtils.fetchMultiplePoolTickArrays({
      connection: raydium.connection,
      poolKeys: [clmmPoolInfo],
    })
  } else {
    const data = await raydium.clmm.getPoolInfoFromRpc(poolId)
    poolInfo = data.poolInfo
    poolKeys = data.poolKeys
    clmmPoolInfo = data.computePoolInfo
    tickCache = data.tickData
  }

  if (inputMint !== poolInfo.mintA.address && inputMint !== poolInfo.mintB.address)
    throw new Error('el mint de entrada no coincide con el pool')

  const baseIn = inputMint === poolInfo.mintA.address

  const { minAmountOut, remainingAccounts } = await PoolUtils.computeAmountOutFormat({
    poolInfo: clmmPoolInfo,
    tickArrayCache: tickCache[poolId],
    amountIn: inputAmount,
    tokenOut: poolInfo[baseIn ? 'mintB' : 'mintA'],
    slippage: 0.01,
    epochInfo: await raydium.fetchEpochInfo(),
  })

  const { execute } = await raydium.clmm.swap({
    poolInfo,
    poolKeys,
    inputMint: poolInfo[baseIn ? 'mintA' : 'mintB'].address,
    amountIn: inputAmount,
    amountOutMin: minAmountOut.amount.raw,
    observationId: clmmPoolInfo.observationId,
    ownerInfo: {
      useSOLBalance: true,
    },
    remainingAccounts,
    txVersion,
    // opcional: configura aquí la comisión de prioridad
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 465915,
    // },
  })

  const { txId } = await execute({ sendAndConfirm: true })
  console.log(`swapped: ${poolInfo.mintA.symbol} to ${poolInfo.mintB.symbol}:`, {
    txId: `https://explorer.solana.com/tx/${txId}`,
  })
}

swap()
```

***

### Swap base-output (salida exacta)

Especifica la cantidad exacta de tokens a recibir. El SDK calcula cuántos tokens necesitas vender.

```typescript
import {
  ApiV3PoolInfoConcentratedItem,
  ClmmKeys,
  ComputeClmmPoolInfo,
  PoolUtils,
  ReturnTypeFetchMultiplePoolTickArrays,
  USDCMint,
} from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import Decimal from 'decimal.js'
import { NATIVE_MINT } from '@solana/spl-token'
import { initSdk, txVersion } from '../config'
import { isValidClmm } from './utils'

const swapBaseOut = async () => {
  const raydium = await initSdk()
  let poolInfo: ApiV3PoolInfoConcentratedItem
  const poolId = '2QdhepnKRTLjjSqPL1PtKNwqrUkoLee5Gqs8bvZhRdMv'
  let poolKeys: ClmmKeys | undefined
  let clmmPoolInfo: ComputeClmmPoolInfo
  let tickCache: ReturnTypeFetchMultiplePoolTickArrays

  const outputMint = NATIVE_MINT
  const amountOut = new BN(1000000)

  if (raydium.cluster === 'mainnet') {
    const data = await raydium.api.fetchPoolById({ ids: poolId })
    poolInfo = data[0] as ApiV3PoolInfoConcentratedItem
    if (!isValidClmm(poolInfo.programId)) throw new Error('el pool de destino no es un pool CLMM')

    clmmPoolInfo = await PoolUtils.fetchComputeClmmInfo({
      connection: raydium.connection,
      poolInfo,
    })
    tickCache = await PoolUtils.fetchMultiplePoolTickArrays({
      connection: raydium.connection,
      poolKeys: [clmmPoolInfo],
    })
  } else {
    const data = await raydium.clmm.getPoolInfoFromRpc(poolId)
    poolInfo = data.poolInfo
    poolKeys = data.poolKeys
    clmmPoolInfo = data.computePoolInfo
    tickCache = data.tickData
  }

  if (
    outputMint.toBase58() !== poolInfo.mintA.address &&
    outputMint.toBase58() !== poolInfo.mintB.address
  )
    throw new Error('el mint de salida no coincide con el pool')

  const { remainingAccounts, ...res } = await PoolUtils.computeAmountIn({
    poolInfo: clmmPoolInfo,
    tickArrayCache: tickCache[poolId],
    amountOut,
    baseMint: outputMint,
    slippage: 0.01,
    epochInfo: await raydium.fetchEpochInfo(),
  })

  const { execute } = await raydium.clmm.swapBaseOut({
    poolInfo,
    poolKeys,
    outputMint,
    amountInMax: res.maxAmountIn.amount,
    amountOut: res.realAmountOut.amount,
    observationId: clmmPoolInfo.observationId,
    ownerInfo: {
      useSOLBalance: true,
    },
    remainingAccounts,
    txVersion,
    // opcional: configura aquí la comisión de prioridad
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 465915,
    // },
  })

  const { txId } = await execute({ sendAndConfirm: true })
  console.log('swapped in clmm pool:', { txId: `https://explorer.solana.com/tx/${txId}` })
}

swapBaseOut()
```

***

### Parámetros de swap (base-input)

| Parámetro           | Tipo                | Descripción                                                                               |
| ------------------- | ------------------- | ----------------------------------------------------------------------------------------- |
| `poolInfo`          | object              | Información del pool desde la API o RPC.                                                  |
| `poolKeys`          | object              | Claves del pool. Requeridas para devnet.                                                  |
| `inputMint`         | string \| PublicKey | Dirección mint del token de entrada.                                                      |
| `amountIn`          | BN                  | Cantidad de tokens de entrada, en las unidades más pequeñas.                              |
| `amountOutMin`      | BN                  | Cantidad mínima de tokens de salida que se aceptará (protección contra slippage).         |
| `observationId`     | PublicKey           | Cuenta de observación del oráculo desde `clmmPoolInfo.observationId`.                     |
| `remainingAccounts` | array               | Cuentas de tick array necesarias para la ruta del swap, desde `computeAmountOutFormat()`. |
| `txVersion`         | TxVersion           | Versión de la transacción.                                                                |

### Parámetros de swap (base-output)

| Parámetro           | Tipo                | Descripción                                                                        |
| ------------------- | ------------------- | ---------------------------------------------------------------------------------- |
| `poolInfo`          | object              | Información del pool desde la API o RPC.                                           |
| `poolKeys`          | object              | Claves del pool. Requeridas para devnet.                                           |
| `outputMint`        | string \| PublicKey | Dirección mint del token de salida deseado.                                        |
| `amountInMax`       | BN                  | Cantidad máxima de tokens de entrada a gastar (protección contra slippage).        |
| `amountOut`         | BN                  | Cantidad de salida deseada, en las unidades más pequeñas.                          |
| `observationId`     | PublicKey           | Cuenta de observación del oráculo desde `clmmPoolInfo.observationId`.              |
| `remainingAccounts` | array               | Cuentas de tick array necesarias para la ruta del swap, desde `computeAmountIn()`. |
| `txVersion`         | TxVersion           | Versión de la transacción.                                                         |

### Tick arrays y cálculo del swap

Los swaps CLMM recorren **tick arrays** para moverse entre rangos de precios. Antes de enviar un swap, debes:

1. Obtener la información de cálculo del pool mediante `PoolUtils.fetchComputeClmmInfo()`.
2. Obtener los tick arrays relevantes mediante `PoolUtils.fetchMultiplePoolTickArrays()`.
3. Calcular el resultado del swap mediante `PoolUtils.computeAmountOutFormat()` (base-input) o `PoolUtils.computeAmountIn()` (base-output).

El paso de cálculo devuelve los `remainingAccounts` (cuentas de tick array) que deben pasarse a la instrucción de swap.

{% hint style="info" %}
Obtén siempre datos recientes de tick array antes de calcular swaps para tener el precio y la distribución de Liquidity más actualizados.
{% endhint %}
