slippage for swapMint and burnSwap

This commit is contained in:
2025-12-02 18:56:25 -04:00
parent 7b8114267e
commit 068286919a
2 changed files with 135 additions and 86 deletions

View File

@@ -8,7 +8,6 @@ import IPartyPoolABI from '@/contracts/IPartyPoolABI';
import IPartyPoolViewerABI from '@/contracts/IPartyPoolViewerABI';
import IPartyInfoABI from '@/contracts/IPartyInfoABI';
import { ERC20ABI } from '@/contracts/ERC20ABI';
import { calculateSlippage } from './usePartyPool';
// Helper function to format large numbers with K, M, B suffixes
function formatTVL(value: number): string {
@@ -466,7 +465,6 @@ export function useGetAllPools(offset: number = 0, limit: number = 100) {
if (isWorking) {
// Fetch pool price (use first token as quote, index 0)
console.log('fetching pool price')
try {
const priceRaw = await publicClient.readContract({
address: partyInfoAddress as `0x${string}`,
@@ -580,8 +578,7 @@ export function useSwapMintAmounts(
poolAddress: `0x${string}` | undefined,
inputTokenIndex: number | undefined,
maxAmountIn: bigint | undefined,
lpTokenPrice?: number, // Market price of the LP token in decimal format
inputTokenDecimals?: number // Decimals of the input token
inputTokenDecimals: number | undefined // Decimals of the input token
) {
const publicClient = usePublicClient();
const [mounted, setMounted] = useState(false);
@@ -602,8 +599,11 @@ export function useSwapMintAmounts(
}
const fetchSwapMintAmounts = async () => {
if (!publicClient) {
setLoading(false);
if (!publicClient) return;
// Early validation
if (inputTokenDecimals === undefined) {
setError('inputTokenDecimals is required but was undefined');
return;
}
@@ -611,9 +611,7 @@ export function useSwapMintAmounts(
setLoading(true);
setError(null);
// Get chain ID and contract address
const chainId = await publicClient.getChainId();
// @ts-ignore
const partyInfoAddress = (chainInfo as Record<string, { v1: { PartyInfo: string } }>)[chainId.toString()]?.v1?.PartyInfo;
if (!partyInfoAddress) {
@@ -622,7 +620,6 @@ export function useSwapMintAmounts(
return;
}
// Call swapMintAmounts function
const result = await publicClient.readContract({
address: partyInfoAddress as `0x${string}`,
abi: IPartyPoolViewerABI,
@@ -630,45 +627,34 @@ export function useSwapMintAmounts(
args: [poolAddress, BigInt(inputTokenIndex), maxAmountIn],
}) as readonly [bigint, bigint, bigint];
// Fetch the market price if not provided
let marketPrice = lpTokenPrice;
if (marketPrice === undefined) {
try {
console.log('input token index', inputTokenIndex)
// Get the pool price (price of the pool in terms of the input token)
const poolPriceInt128 = await publicClient.readContract({
address: partyInfoAddress as `0x${string}`,
abi: IPartyInfoABI,
functionName: 'poolPrice',
args: [poolAddress, BigInt(inputTokenIndex)],
}) as bigint;
// Convert Q64 format to decimal (price = priceValue / 2^64)
// poolPrice returns how much 1 LP token is worth in terms of the input token
marketPrice = Number(poolPriceInt128) / 2 ** 64;
console.log('swapMintAmounts fetched marketPrice (poolPrice)', marketPrice);
} catch (priceErr) {
console.error('Error fetching poolPrice:', priceErr);
}
}
// Calculate slippage if market price is available
// Fetch and calculate pool price
let poolPrice: number | undefined;
let calculatedSlippage: number | undefined;
if (marketPrice !== undefined) {
try {
// For swapMint:
// - marketPrice: how much 1 LP token is worth in input tokens (from poolPrice)
// - swapOutputAmount: LP tokens minted (result[2])
// - swapInputAmount: input token amount used (maxAmountIn)
// - inFee: fee charged (result[1])
console.log('LP minted', result[1])
// Convert result[1] to token price using poolPrice: result[1] * poolPrice
const lpMintedInTokenPrice = BigInt(Math.floor(Number(result[1]) * marketPrice));
calculatedSlippage = calculateSlippage(marketPrice, lpMintedInTokenPrice, result[0], result[2]);
console.log('🎯 swapMint calculatedSlippage: ' + calculatedSlippage.toFixed(4) + '%');
} catch (slippageErr) {
console.error(`Error calculating slippage for swapMint:`, slippageErr);
}
try {
console.log('input token index', inputTokenIndex);
const poolPriceInt128 = await publicClient.readContract({
address: partyInfoAddress as `0x${string}`,
abi: IPartyInfoABI,
functionName: 'poolPrice',
args: [poolAddress, BigInt(inputTokenIndex)],
}) as bigint;
const basePrice = Number(poolPriceInt128) / (2 ** 64);
poolPrice = 1 / (basePrice * Math.pow(10, 18 - inputTokenDecimals));
// Calculate slippage
const decimalsMultiplier = Math.pow(10, inputTokenDecimals);
const lpMinted = Number(result[1]) / Math.pow(10, 18);
const amountIn = Number(result[0]) / decimalsMultiplier;
const fee = Number(result[2]) / decimalsMultiplier;
const swapPrice = lpMinted / (amountIn - fee);
calculatedSlippage = ((poolPrice - swapPrice) / poolPrice) * 100;
} catch (priceErr) {
console.error('Error fetching poolPrice or calculating slippage:', priceErr);
}
setSwapMintAmounts({
@@ -687,7 +673,7 @@ export function useSwapMintAmounts(
};
fetchSwapMintAmounts();
}, [publicClient, mounted, poolAddress, inputTokenIndex, maxAmountIn, lpTokenPrice]);
}, [publicClient, mounted, poolAddress, inputTokenIndex, maxAmountIn, inputTokenDecimals]);
return {
swapMintAmounts,
@@ -701,8 +687,7 @@ export function useBurnSwapAmounts(
poolAddress: `0x${string}` | undefined,
lpAmount: bigint | undefined,
inputTokenIndex: number | undefined,
lpTokenPrice?: number, // Market price of the LP token in decimal format
tokenDecimals?: number // Decimals of the output token
tokenDecimals: number | undefined // Decimals of the output token
) {
const publicClient = usePublicClient();
const [mounted, setMounted] = useState(false);
@@ -744,18 +729,6 @@ export function useBurnSwapAmounts(
return;
}
console.log('fetching swap amounts 2')
// Log inputs
console.log('🔍 burnSwapAmounts INPUTS:', {
chainId: chainId.toString(),
rpcUrl: publicClient.transport?.url || 'Unknown',
poolAddress,
lpAmount: lpAmount.toString(),
inputTokenIndex,
partyInfoAddress,
});
// Call burnSwapAmounts function - returns [amountOut, outFee]
const result = await publicClient.readContract({
address: partyInfoAddress as `0x${string}`,
@@ -764,12 +737,6 @@ export function useBurnSwapAmounts(
args: [poolAddress, lpAmount, BigInt(inputTokenIndex)],
}) as readonly [bigint, bigint];
// Log raw result
console.log('📊 burnSwapAmounts RAW RESULT:', {
resultArray: result,
amountOut: result[0].toString(),
outFee: result[1].toString(),
});
// Calculate slippage for burnSwap using poolPrice
let calculatedSlippage: number | undefined;
if (tokenDecimals !== undefined) {
@@ -783,7 +750,8 @@ export function useBurnSwapAmounts(
}) as bigint;
// Convert Q64 format to decimal (price = priceValue / 2^64)
const marketPrice = Number(poolPriceInt128) / 2 ** 64;
let poolPrice = Number(poolPriceInt128) / 2 ** 64;
poolPrice = (poolPrice * Math.pow(10, 18 - tokenDecimals));
// For burnSwap: swapPrice = (outAmount + fee) / lpAmount
// Need to apply decimal corrections: outAmount and fee are in token decimals, lpAmount is in 18 decimals
@@ -792,12 +760,10 @@ export function useBurnSwapAmounts(
const lpAmountDecimal = Number(lpAmount) / Math.pow(10, 18); // LP tokens have 18 decimals
const swapPrice = (outAmountDecimal + feeDecimal) / lpAmountDecimal;
// Calculate slippage percentage: ((swapPrice - marketPrice) / marketPrice) * 100
calculatedSlippage = ((swapPrice - marketPrice) / marketPrice) * 100;
calculatedSlippage = ((poolPrice - swapPrice) / poolPrice) * 100;
console.log('burnSwap slippage calculation:', {
marketPrice,
poolPrice,
swapPrice,
calculatedSlippage,
outAmountDecimal,
@@ -818,13 +784,6 @@ export function useBurnSwapAmounts(
calculatedSlippage,
};
// Log parsed result
console.log('✅ burnSwapAmounts PARSED:', {
amountOut: parsedAmounts.amountOut.toString(),
outFee: parsedAmounts.outFee.toString(),
calculatedSlippage: parsedAmounts.calculatedSlippage,
});
setBurnSwapAmounts(parsedAmounts);
} catch (err) {
console.error('Error calling burnSwapAmounts:', err);
@@ -836,7 +795,7 @@ export function useBurnSwapAmounts(
};
fetchBurnSwapAmounts();
}, [publicClient, mounted, poolAddress, lpAmount, inputTokenIndex, lpTokenPrice, tokenDecimals]);
}, [publicClient, mounted, poolAddress, lpAmount, inputTokenIndex, tokenDecimals]);
return {
burnSwapAmounts,