上传文件至 document

This commit is contained in:
xie
2025-12-15 14:45:51 +00:00
parent faeb8e2f45
commit c3e0bafe1a
5 changed files with 9647 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
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;
}
}