7.9 KiB
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; } }