上传文件至 document
This commit is contained in:
231
document/ytLp用户前端交互文档.md
Normal file
231
document/ytLp用户前端交互文档.md
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user