Files
Heyue_test/document/ytLp用户前端交互文档.md
2025-12-15 14:45:51 +00:00

232 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ytLp用户前端交互文档
1.用户添加流动性
Solidity
function addLiquidity(
address _token, //YT代币或WUSD地址
uint256 _amount, //代币数量
uint256 _minUsdy, //最小USDY数量
uint256 _minYtLP //最小ytLP数量
)
_minUsdy和_minYtLP计算方式滑点可以让用户在界面选择
TypeScript
/**
* 计算添加流动性的 _minUsdy 和 _minYtLP 参数
* @param {string} token - 代币地址
* @param {BigNumber} amount - 代币数量
* @param {number} slippageTolerance - 滑点容忍度 (0.005 = 0.5%)
* @returns {Promise<{minUsdy, minYtLP, expectedYtLP, feeInfo}>}
*/
async function calculateAddLiquidityParams(token, amount, slippageTolerance = 0.005) {
const PRICE_PRECISION = ethers.BigNumber.from("1000000000000000000000000000000");
const BASIS_POINTS = 10000;
try {
// 1. 获取价格使用MinPrice
const tokenPrice = await ytVault.getMinPrice(token);
// 2. 计算理论USDY扣费前
const theoreticalUsdy = amount.mul(tokenPrice).div(PRICE_PRECISION);
// 3. 获取手续费率
const feeBasisPoints = await ytVault.getSwapFeeBasisPoints(
token,
USDY_ADDRESS,
theoreticalUsdy
);
// 4. 计算扣费后的代币和USDY
const amountAfterFees = amount
.mul(BASIS_POINTS - feeBasisPoints)
.div(BASIS_POINTS);
const usdyAmount = amountAfterFees.mul(tokenPrice).div(PRICE_PRECISION);
// 5. 获取AUM和供应量
const [aum, ytLPSupply] = await Promise.all([
ytPoolManager.getAumInUsdy(true), // 使用MaxPrice
ytLP.totalSupply()
]);
// 6. 计算预期ytLP
let expectedYtLP;
if (ytLPSupply.eq(0)) {
expectedYtLP = usdyAmount;
} else {
expectedYtLP = usdyAmount.mul(ytLPSupply).div(aum);
}
// 7. 应用滑点
const minUsdy = usdyAmount.mul(
ethers.BigNumber.from(Math.floor((1 - slippageTolerance) * 10000))
).div(10000);
const minYtLP = expectedYtLP.mul(
ethers.BigNumber.from(Math.floor((1 - slippageTolerance) * 10000))
).div(10000);
return {
minUsdy,
minYtLP,
expectedYtLP,
usdyAmount,
feeInfo: {
feeBasisPoints: feeBasisPoints.toNumber(),
feeAmount: amount.sub(amountAfterFees),
amountAfterFees
},
priceInfo: {
tokenPrice: ethers.utils.formatUnits(tokenPrice, 30),
aum: ethers.utils.formatEther(aum),
ytLPSupply: ethers.utils.formatEther(ytLPSupply)
}
};
} catch (error) {
console.error("计算添加流动性参数失败:", error);
throw error;
}
}
2.用户移除流动性
Solidity
function removeLiquidity(
address _tokenOut, //出代币地址
uint256 _ytLPAmount, //ytLP数量
uint256 _minOut, //最小输出数量
address _receiver //接收地址
)
_minOut计算方式滑点可以让用户在界面选择
TypeScript
/**
* 计算移除流动性的 _minOut 参数
* @param {string} tokenOut - 目标代币地址
* @param {BigNumber} ytLPAmount - ytLP数量
* @param {number} slippageTolerance - 滑点容忍度 (0.01 = 1%)
* @returns {Promise<{minOut, expectedOut, feeBps, priceInfo}>}
*/
async function calculateMinOut(tokenOut, ytLPAmount, slippageTolerance = 0.01) {
const PRICE_PRECISION = ethers.BigNumber.from("1000000000000000000000000000000");
const BASIS_POINTS = 10000;
try {
// 1. 获取AUM和供应量
const [aum, ytLPSupply] = await Promise.all([
ytPoolManager.getAumInUsdy(false),
ytLP.totalSupply()
]);
// 2. 计算USDY价值
const usdyAmount = ytLPAmount.mul(aum).div(ytLPSupply);
// 3. 获取代币价格和手续费(并行查询)
const [tokenPrice, feeBasisPoints] = await Promise.all([
ytVault.getMaxPrice(tokenOut),
ytVault.getRedemptionFeeBasisPoints(tokenOut, usdyAmount)
]);
// 4. 计算理论输出
const theoreticalOut = usdyAmount.mul(PRICE_PRECISION).div(tokenPrice);
// 5. 扣除手续费
const expectedOut = theoreticalOut
.mul(BASIS_POINTS - feeBasisPoints)
.div(BASIS_POINTS);
// 6. 应用滑点
const minOut = expectedOut.mul(
ethers.BigNumber.from(Math.floor((1 - slippageTolerance) * 10000))
).div(10000);
return {
minOut,
expectedOut,
theoreticalOut,
usdyAmount,
feeBasisPoints: feeBasisPoints.toNumber(),
priceInfo: {
tokenPrice: ethers.utils.formatUnits(tokenPrice, 30),
aum: ethers.utils.formatEther(aum),
ytLPSupply: ethers.utils.formatEther(ytLPSupply)
}
};
} catch (error) {
console.error("计算_minOut失败:", error);
throw error;
}
}
3.用户交换代币
TypeScript
function swapYT(
address _tokenIn, //输入代币地址
address _tokenOut, //输出代币地址
uint256 _amountIn, //输入数量
uint256 _minOut, //最小输出数量
address _receiver //接收地址
)
_minOut计算方式滑点可以让用户在界面选择
TypeScript
/**
* 计算 swapYT 的 _minOut 参数
* @param {string} tokenIn - 输入代币地址
* @param {string} tokenOut - 输出代币地址
* @param {BigNumber} amountIn - 输入数量
* @param {number} slippageTolerance - 滑点容忍度 (0.005 = 0.5%)
* @returns {Promise<{minOut, expectedOut, feeInfo, priceInfo}>}
*/
async function calculateSwapMinOut(tokenIn, tokenOut, amountIn, slippageTolerance = 0.005) {
const PRICE_PRECISION = ethers.BigNumber.from("1000000000000000000000000000000");
const BASIS_POINTS = 10000;
try {
// 1. 获取价格(并行查询)
const [priceIn, priceOut] = await Promise.all([
ytVault.getMinPrice(tokenIn), // 输入用MinPrice
ytVault.getMaxPrice(tokenOut) // 输出用MaxPrice
]);
// 2. 计算USDY价值
const usdyAmount = amountIn.mul(priceIn).div(PRICE_PRECISION);
// 3. 获取手续费率
const feeBasisPoints = await ytVault.getSwapFeeBasisPoints(
tokenIn,
tokenOut,
usdyAmount
);
// 4. 计算理论输出
const theoreticalOut = usdyAmount.mul(PRICE_PRECISION).div(priceOut);
// 5. 扣除手续费
const expectedOut = theoreticalOut
.mul(BASIS_POINTS - feeBasisPoints)
.div(BASIS_POINTS);
// 6. 应用滑点
const minOut = expectedOut.mul(
ethers.BigNumber.from(Math.floor((1 - slippageTolerance) * 10000))
).div(10000);
return {
minOut,
expectedOut,
theoreticalOut,
usdyAmount,
feeBasisPoints: feeBasisPoints.toNumber(),
priceInfo: {
priceIn: ethers.utils.formatUnits(priceIn, 30),
priceOut: ethers.utils.formatUnits(priceOut, 30),
effectiveRate: theoreticalOut.mul(10000).div(amountIn).toNumber() / 100
},
feeInfo: {
feeBps: feeBasisPoints.toNumber(),
feeAmount: theoreticalOut.sub(expectedOut)
}
};
} catch (error) {
console.error("计算 _minOut 失败:", error);
throw error;
}
}