引入了一些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)
})
}
// 疑问 只有交易对和输出地址,输入地址是从交易对中获取,不用手动输入对吗?
也不知道是否准确~~小白个人理解 欢迎大家探讨