# 存入 / 提取流动性

将代币存入 CPMM 池以获得 LP 代币，或销毁 LP 代币以提取您在该池中的份额。

***

### 正在获取池信息

存入和提取操作都需要池信息。

```typescript
import {
  ApiV3PoolInfoStandardItemCpmm,
  CpmmKeys,
  CREATE_CPMM_POOL_PROGRAM,
  DEVNET_PROGRAM_ID,
} from '@raydium-io/raydium-sdk-v2'
import { initSdk } from '../config'

const VALID_PROGRAM_ID = new Set([
  CREATE_CPMM_POOL_PROGRAM.toBase58(),
  DEVNET_PROGRAM_ID.CREATE_CPMM_POOL_PROGRAM.toBase58(),
])
const isValidCpmm = (id: string) => VALID_PROGRAM_ID.has(id)

let poolInfo: ApiV3PoolInfoStandardItemCpmm
let poolKeys: CpmmKeys | undefined

const raydium = await initSdk()
const poolId = 'YOUR_POOL_ID'

if (raydium.cluster === 'mainnet') {
  const data = await raydium.api.fetchPoolById({ ids: poolId })
  poolInfo = data[0] as ApiV3PoolInfoStandardItemCpmm
  if (!isValidCpmm(poolInfo.programId)) throw new Error('target pool is not CPMM pool')
} else {
  const data = await raydium.cpmm.getPoolInfoFromRpc(poolId)
  poolInfo = data.poolInfo
  poolKeys = data.poolKeys
}
```

***

### 存入流动性

使用 `raydium.cpmm.addLiquidity()` 将代币存入池中。您只需指定一种代币数量，SDK 会根据当前池子比例计算所需的另一种代币数量。

```typescript
import { Percent } from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'
import Decimal from 'decimal.js'

const deposit = async () => {
  const raydium = await initSdk()
  // ... 按上文所示获取 poolInfo 和 poolKeys

  const uiInputAmount = '0.0001'
  const inputAmount = new BN(
    new Decimal(uiInputAmount).mul(10 ** poolInfo.mintA.decimals).toFixed(0)
  )
  const slippage = new Percent(1, 100) // 1%
  const baseIn = true // true = inputAmount 用于 mintA，false = 用于 mintB

  const { execute } = await raydium.cpmm.addLiquidity({
    poolInfo,
    poolKeys,
    inputAmount,
    slippage,
    baseIn,
    txVersion: TxVersion.V0,
    // 可选：在此设置优先费用
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 46591500,
    // },
  })

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

#### 计算配对数量（可选）

在存入之前，您可以预览用于 UI 展示的另一种代币所需数量：

```typescript
const rpcPoolInfos = await raydium.cpmm.getRpcPoolInfos([poolId])
const pool1Info = rpcPoolInfos[poolId]

const computeRes = await raydium.cpmm.computePairAmount({
  baseReserve: pool1Info.baseReserve,
  quoteReserve: pool1Info.quoteReserve,
  poolInfo,
  amount: uiInputAmount,
  slippage,
  baseIn,
  epochInfo: await raydium.fetchEpochInfo(),
})

// computeRes.anotherAmount.amount -> 所需的配对代币数量
// computeRes.anotherAmount.fee -> Token-2022 转账手续费（如适用）
```

#### 存入参数

| 参数            | 类型        | 描述                                                      |
| ------------- | --------- | ------------------------------------------------------- |
| `poolInfo`    | object    | 来自 API 或 RPC 的池信息。                                      |
| `poolKeys`    | object    | 池键，devnet 需要。mainnet 上可选（SDK 会推导它们）。                    |
| `inputAmount` | BN        | 要存入的基础代币或报价代币数量，单位为最小单位。                                |
| `slippage`    | Percent   | 滑点容忍度。 `new Percent(1, 100)` = 1%.                      |
| `baseIn`      | boolean   | `true` 如果 `inputAmount` 用于 token A， `false` 用于 token B。 |
| `txVersion`   | TxVersion | 交易版本。                                                   |

***

### 提取流动性

使用 `raydium.cpmm.withdrawLiquidity()` 销毁 LP 代币并取回您按比例分配的两种代币。

```typescript
import { Percent } from '@raydium-io/raydium-sdk-v2'
import BN from 'bn.js'

const withdraw = async () => {
  const raydium = await initSdk()
  // ... 按上文所示获取 poolInfo 和 poolKeys

  const slippage = new Percent(1, 100) // 1%
  const lpAmount = new BN(100) // 要提取的 LP 代币数量

  const { execute } = await raydium.cpmm.withdrawLiquidity({
    poolInfo,
    poolKeys,
    lpAmount,
    slippage,
    txVersion: TxVersion.V0,
    // 可选：在此设置优先费用
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 46591500,
    // },
  })

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

#### 提取参数

| 参数          | 类型        | 描述                    |
| ----------- | --------- | --------------------- |
| `poolInfo`  | object    | 来自 API 或 RPC 的池信息。    |
| `poolKeys`  | object    | 池键，devnet 需要。         |
| `lpAmount`  | BN        | 要销毁的 LP 代币数量，单位为最小单位。 |
| `slippage`  | Percent   | 接收的最小代币数量的滑点容忍度。      |
| `txVersion` | TxVersion | 交易版本。                 |

{% hint style="info" %}
默认情况下，SDK 会自动关闭 wSOL 账户并返回原生 SOL。要保持 wSOL 账户打开，请传入 `closeWsol: false`.
{% endhint %}
