代币交换

在 CPMM 池中执行代币交换。SDK 支持两种类型: base-input (固定输入数量)和 base-output (固定输出数量)交换。


Base-input swap(精确输入)

指定要卖出的代币精确数量。SDK 会计算你将收到多少代币。

import {
  ApiV3PoolInfoStandardItemCpmm,
  CpmmKeys,
  CpmmParsedRpcData,
  CurveCalculator,
  FeeOn,
  TxVersion,
} from '@raydium-io/raydium-sdk-v2'
import { NATIVE_MINT } from '@solana/spl-token'
import BN from 'bn.js'
import { initSdk } from '../config'

const swap = async () => {
  const raydium = await initSdk()

  const poolId = '7JuwJuNU88gurFnyWeiyGKbFmExMWcmRZntn9imEzdny'
  const inputAmount = new BN(100)
  const inputMint = NATIVE_MINT.toBase58()

  let poolInfo: ApiV3PoolInfoStandardItemCpmm
  let poolKeys: CpmmKeys | undefined
  let rpcData: CpmmParsedRpcData

  if (raydium.cluster === 'mainnet') {
    const data = await raydium.api.fetchPoolById({ ids: poolId })
    poolInfo = data[0] as ApiV3PoolInfoStandardItemCpmm
    rpcData = await raydium.cpmm.getRpcPoolInfo(poolInfo.id, true)
  } else {
    const data = await raydium.cpmm.getPoolInfoFromRpc(poolId)
    poolInfo = data.poolInfo
    poolKeys = data.poolKeys
    rpcData = data.rpcData
  }

  if (inputMint !== poolInfo.mintA.address && inputMint !== poolInfo.mintB.address)
    throw new Error('input mint does not match pool')

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

  // 在链下计算交换
  const swapResult = CurveCalculator.swapBaseInput(
    inputAmount,
    baseIn ? rpcData.baseReserve : rpcData.quoteReserve,
    baseIn ? rpcData.quoteReserve : rpcData.baseReserve,
    rpcData.configInfo!.tradeFeeRate,
    rpcData.configInfo!.creatorFeeRate,
    rpcData.configInfo!.protocolFeeRate,
    rpcData.configInfo!.fundFeeRate,
    rpcData.feeOn === FeeOn.BothToken || rpcData.feeOn === FeeOn.OnlyTokenB
  )

  /**
   * swapResult.inputAmount   -> 手续费后的实际输入量
   * swapResult.outputAmount  -> 收到的代币数量
   * swapResult.tradeFee      -> 针对 input mint 收取的手续费
   */

  const { execute } = await raydium.cpmm.swap({
    poolInfo,
    poolKeys,
    inputAmount,
    swapResult,
    slippage: 0.001, // 0.1% — 范围:1(100%)到 0.0001(0.01%)
    baseIn,
    txVersion: TxVersion.V0,
    // 可选:在此设置优先费
    // computeBudgetConfig: {
    //   units: 600000,
    //   microLamports: 4659150,
    // },
  })

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

swap()

Base-output swap(精确输出)

指定要收到的代币精确数量。SDK 会计算你需要卖出多少代币。


Swap 参数

参数
类型
描述

poolInfo

object

来自 API 或 RPC 的池信息。

poolKeys

object

池的 keys。devnet 需要。

inputAmount

BN

输入代币数量(base-input)。当 fixedOut: true.

fixedOut

boolean

为 base-output 交换设置为 true 。默认值 false.

swapResult

object

预先计算的交换结果,来自 CurveCalculator.swapBaseInput()CurveCalculator.swapBaseOutput().

slippage

number

以小数表示的滑点容忍度。 0.001 = 0.1%。范围: 1 (100%)到 0.0001 (0.01%).

baseIn

boolean

true 如果是 mintA → mintB 交换, false 则用于 mintB → mintA。

txVersion

TxVersion

交易版本。

CurveCalculator

CurveCalculator 在提交交易前离链计算交换数量。

方法
描述

swapBaseInput()

给定精确输入数量,计算输出和手续费。

swapBaseOutput()

给定期望输出数量,计算所需输入。

这两种方法都使用池中相同的手续费参数: configInfo:

参数
描述

tradeFeeRate

从交换输入中收取的手续费,单位为 1e-6。

creatorFeeRate

发送给池创建者的额外手续费。

protocolFeeRate

发送给 Raydium protocol 的交易手续费份额。

fundFeeRate

发送给 Raydium treasury 的交易手续费份额。

circle-info

在计算交换前,始终获取最新的 RPC 数据(getRpcPoolInfo)以获得最新储备并避免过期报价。

最后更新于

这有帮助吗?