Raydium-SDK-V1-DEMO之 swapOnlyAmm

701 阅读4分钟

引入了一些Raydium的一些包 , 内部引入了config util等类。

第一步吧 创建了两个类型 WalletTokenAccounts和TestTxInputInfo

第二步

使用
formatAmmKeysById(input.targetPool)
获取交易池信息,获取交易对的AMM数据和市场数据
转换为walletTokenAccounts的内部格式
const poolKeys = jsonInfo2PoolKeys(targetPoolInfo) as LiquidityPoolKeys

第三步 根据获取到的 AMM数据和市场数据, 计算价格

使用
Liquidity.computeAmountOut({
    PoolKeys: poolKeys //(第一步获取到的walletTokenAccounts内部格式的poolKeys),
    poolInfo: await Liquidity.fetchInfo({connnection,poolKeys}),//传入RPC连接和PoolKeys
    amountIn: input.inputTokenAmount,//输入代币数量
    currencyOunt: input.outputToken,//期望接受的输出代币类型
    slippage: input.slippage,//输入滑点 如 new Percent(1, 100)//百分之1的滑点
})

Liquidity.computeAmountOut的返回值就是计算出来的价格啦 const {amountOut,minAmountOut} 取的是这两个值 无滑点的金额和带滑点的金额,就是说一个是最大能获得的金额, 一个是最小能获得的金额

第四步 构建RPC交易(构建SDK指令)


  // -------- step 2: create instructions by SDK function --------
  // 
  const { innerTransactions } = await Liquidity.makeSwapInstructionSimple({// innerTransactions 内部交易
    connection,//RPC连接
    poolKeys,//交易对的AMM数据和市场数据的LiquidityPollKeys类型数据
    userKeys: {
      tokenAccounts: input.walletTokenAccounts,//钱包的代币账户
      owner: input.wallet.publicKey,//钱包公钥
    },
    amountIn: input.inputTokenAmount,//输入代币数量 如果 `fixedSide` 为 'in',则为固定输入量
    amountOut: minAmountOut,//最低能获得的金额 如果 `fixedSide` 为 'out',则为固定输出量
//     概念解释
// fixedSide: 'in':表示你希望交易的输入量是固定的。例如,你想交换固定数量的 SOL(0.1 SOL),然后根据市场条件得到相应数量的 USDC。
// fixedSide: 'out':表示你希望交易的输出量是固定的。例如,你想获得固定数量的 USDC(100 USDC),然后根据市场条件支付相应数量的 SOL。
    fixedSide: 'in',//交易的方向和确定滑点的计算方式
    makeTxVersion,// 版本号V0 
  })

最后 发送交易并返回

  console.log('amountOut:', amountOut.toFixed(), '  minAmountOut: ', minAmountOut.toFixed())
// 构建并发送交易 并返回txids (应该是返回交易ID 可能多个 所以有S )
  return { txids: await buildAndSendTx(innerTransactions) }

完整代码

import assert from 'assert';

import {
  jsonInfo2PoolKeys,
  Liquidity,
  LiquidityPoolKeys,
  Percent,
  Token,
  TokenAmount,
} from '@raydium-io/raydium-sdk';
import { Keypair } from '@solana/web3.js';

import {
  connection,
  DEFAULT_TOKEN,
  makeTxVersion,
  wallet
} from '../config';
import { formatAmmKeysById } from './formatAmmKeysById';
import {
  buildAndSendTx,
  getWalletTokenAccount,
} from './util';

//根据钱包地址 递归的获取钱包代币账户   (所有类型的数据都在map)
type WalletTokenAccounts = Awaited<ReturnType<typeof getWalletTokenAccount>>
type TestTxInputInfo = {
  outputToken: Token
  targetPool: string
  inputTokenAmount: TokenAmount
  slippage: Percent
  walletTokenAccounts: WalletTokenAccounts
  wallet: Keypair
}

async function swapOnlyAmm(input: TestTxInputInfo) {
  // -------- pre-action: get pool info --------
  // 获取池信息,  获取改交易对的  AMM数据和市场数据 (获取 存储与流动性池和市场操作相关的数据)
  const targetPoolInfo = await formatAmmKeysById(input.targetPool)
  assert(targetPoolInfo, 'cannot find the target pool')
  // jsonInfo2PoolKeys 函数用于将 JSON 格式的流动性池信息转换为 Raydium SDK 内部的 LiquidityPoolKeys 类型。
  const poolKeys = jsonInfo2PoolKeys(targetPoolInfo) as LiquidityPoolKeys   //as 断言  确保targetPoolInfo 一定是LiquidityPoolKeys类型的

  // -------- step 1: coumpute amount out --------
  // 根据输入input , 先获取池信息,  再计算出价格:需要的参数 :池信息,根据RPC连接和oolKeys获取流动性,再根据输入的代币数量,输出的token,输入的滑点计算出价格
  const { amountOut, minAmountOut } = Liquidity.computeAmountOut({
    poolKeys: poolKeys,//Raydium SDK 内部的 LiquidityPoolKeys 类型
    poolInfo: await Liquidity.fetchInfo({ connection, poolKeys }),//传入RPC连接和oolKeys(AMM数据和市场数据 ) 获取流动性信息
    amountIn: input.inputTokenAmount,//输入代币数量
    currencyOut: input.outputToken,//这是你期望接收的输出代币类型。这个参数告诉计算函数你希望用输入代币换取哪种输出代币。
    slippage: input.slippage,//输入 滑点
  })

  // -------- step 2: create instructions by SDK function --------
  // 
  const { innerTransactions } = await Liquidity.makeSwapInstructionSimple({// innerTransactions 内部交易
    connection,//RPC连接
    poolKeys,//交易对的AMM数据和市场数据的LiquidityPollKeys类型数据
    userKeys: {
      tokenAccounts: input.walletTokenAccounts,//钱包的代币账户
      owner: input.wallet.publicKey,//钱包公钥
    },
    amountIn: input.inputTokenAmount,//输入代币数量 如果 `fixedSide` 为 'in',则为固定输入量
    amountOut: minAmountOut,//最低能获得的金额 如果 `fixedSide` 为 'out',则为固定输出量
//     概念解释
// fixedSide: 'in':表示你希望交易的输入量是固定的。例如,你想交换固定数量的 SOL(0.1 SOL),然后根据市场条件得到相应数量的 USDC。
// fixedSide: 'out':表示你希望交易的输出量是固定的。例如,你想获得固定数量的 USDC(100 USDC),然后根据市场条件支付相应数量的 SOL。
    fixedSide: 'in',//交易的方向和确定滑点的计算方式
    makeTxVersion,// 版本号V0
  })

  console.log('amountOut:', amountOut.toFixed(), '  minAmountOut: ', minAmountOut.toFixed())
// 构建并发送交易 并返回txids (应该是返回交易ID 可能多个 所以有S )
  return { txids: await buildAndSendTx(innerTransactions) }
}

async function howToUse() {
  const inputToken = DEFAULT_TOKEN.USDC // USDC 精度6 输入
  const outputToken = DEFAULT_TOKEN.RAY // RAY   输出
  const targetPool = 'pool id' // USDC-RAY pool
  const inputTokenAmount = new TokenAmount(inputToken, 10000)//代币数量   参数1是代币的token ,右边是数量  精度6   1000000是1  inputTokenAmount的结果会是0.01
  const slippage = new Percent(1, 100)//百分之1的滑点
  const walletTokenAccounts = await getWalletTokenAccount(connection, wallet.publicKey) //钱包代币账户

  swapOnlyAmm({
    outputToken,
    targetPool,
    inputTokenAmount,
    slippage,
    walletTokenAccounts,
    wallet: wallet,
  }).then(({ txids }) => {
    /** continue with txids */
    console.log('txids', txids)
  })
}


// 疑问 只有交易对和输出地址,输入地址是从交易对中获取,不用手动输入对吗?

也不知道是否准确~~小白个人理解 欢迎大家探讨