From c69f0a47de72999f43e89f13dd604645c1c0e4dd Mon Sep 17 00:00:00 2001 From: surbhi Date: Tue, 11 Nov 2025 17:15:26 -0400 Subject: [PATCH] showing burn amounts in the redeem all function. ALso adding an isworking flag for staking and ustaking --- src/components/stake-form.tsx | 21 +++++-- src/hooks/usePartyPlanner.ts | 115 ++++++++++++++++++++++++++++------ 2 files changed, 110 insertions(+), 26 deletions(-) diff --git a/src/components/stake-form.tsx b/src/components/stake-form.tsx index 4e2edf9..37a4180 100644 --- a/src/components/stake-form.tsx +++ b/src/components/stake-form.tsx @@ -7,7 +7,7 @@ import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { ChevronDown, CheckCircle, XCircle, Loader2, ArrowDownUp } from 'lucide-react'; import { useAccount, usePublicClient } from 'wagmi'; -import { useGetAllPools, useTokenDetails, useSwapMintAmounts, useBurnSwapAmounts, useLPTokenBalance, type PoolDetails, type TokenDetails, type BurnSwapAmounts } from '@/hooks/usePartyPlanner'; +import { useGetAllPools, useTokenDetails, useSwapMintAmounts, useBurnSwapAmounts, useLPTokenBalance, useBurnAmounts, type PoolDetails, type TokenDetails, type BurnSwapAmounts } from '@/hooks/usePartyPlanner'; import { useSwapMint, useBurnSwap, useBurn, type ActualSwapMintAmounts, type ActualBurnSwapAmounts, type ActualBurnAmounts } from '@/hooks/usePartyPool'; import { formatUnits, parseUnits } from 'viem'; import IPartyPoolABI from '@/contracts/IPartyPoolABI'; @@ -143,6 +143,12 @@ export function StakeForm({ defaultMode = 'stake' }: StakeFormProps) { mode === 'unstake' && !redeemAll ? inputTokenIndex : undefined ); + // Fetch burn amounts (for unstake mode when redeeming all) + const { burnAmounts, loading: burnAmountsLoading } = useBurnAmounts( + mode === 'unstake' && redeemAll ? selectedPool?.address : undefined, + mode === 'unstake' && redeemAll ? maxAmountIn : undefined + ); + // Fetch token details for the selected pool when Redeem All is active useEffect(() => { if (!publicClient || !selectedPool || mode !== 'unstake' || !redeemAll) { @@ -618,15 +624,18 @@ export function StakeForm({ defaultMode = 'stake' }: StakeFormProps) { )} {/* Redeem All Tokens Display */} - {mode === 'unstake' && redeemAll && poolTokens.length > 0 && ( + {mode === 'unstake' && redeemAll && poolTokens.length > 0 && !isAmountExceedingBalance && (
You will receive:
- {poolTokens.map((token) => ( + {poolTokens.map((token, index) => (
- {token.symbol} - - (proportional to pool composition) + {token.symbol}: + + {burnAmountsLoading ? 'Calculating...' : burnAmounts && burnAmounts[index] + ? `${Number(formatUnits(burnAmounts[index], token.decimals)).toLocaleString('en-US', { maximumFractionDigits: 6 })}` + : '(proportional to pool composition)' + }
))} diff --git a/src/hooks/usePartyPlanner.ts b/src/hooks/usePartyPlanner.ts index 12271b9..5fe9740 100644 --- a/src/hooks/usePartyPlanner.ts +++ b/src/hooks/usePartyPlanner.ts @@ -6,6 +6,7 @@ import chainInfo from '@/contracts/liqp-deployments.json'; import IPartyPlannerABI from '@/contracts/IPartyPlannerABI'; import IPartyPoolABI from '@/contracts/IPartyPoolABI'; import IPartyPoolViewerABI from '@/contracts/IPartyPoolViewerABI'; +import IPartyInfoABI from '@/contracts/IPartyInfoABI'; import { ERC20ABI } from '@/contracts/ERC20ABI'; export function useGetAllTokens(offset: number = 0, limit: number = 100) { @@ -360,12 +361,13 @@ export function useGetAllPools(offset: number = 0, limit: number = 100) { setLoading(true); setError(null); - // Get chain ID and contract address + // Get chain ID and contract addresses const chainId = await publicClient.getChainId(); - const address = (chainInfo as Record)[chainId.toString()]?.v1?.PartyPlanner; + const plannerAddress = (chainInfo as Record)[chainId.toString()]?.v1?.PartyPlanner; + const partyInfoAddress = (chainInfo as Record)[chainId.toString()]?.v1?.PartyInfo; - if (!address) { - setError('IPartyPlanner contract not found for current chain'); + if (!plannerAddress || !partyInfoAddress) { + setError('IPartyPlanner or PartyInfo contract not found for current chain'); setPools([]); setPoolDetails([]); return; @@ -373,7 +375,7 @@ export function useGetAllPools(offset: number = 0, limit: number = 100) { // Call getAllPools function const result = await publicClient.readContract({ - address: address as `0x${string}`, + address: plannerAddress as `0x${string}`, abi: IPartyPlannerABI, functionName: 'getAllPools', args: [BigInt(offset), BigInt(limit)], @@ -381,11 +383,11 @@ export function useGetAllPools(offset: number = 0, limit: number = 100) { setPools(result); - // Fetch details for each pool + // Fetch details for each pool and check if it's working const details: PoolDetails[] = []; for (const poolAddress of result) { try { - const [name, symbol, tokens] = await Promise.all([ + const [name, symbol, tokens, isWorking] = await Promise.all([ publicClient.readContract({ address: poolAddress, abi: ERC20ABI, @@ -401,23 +403,26 @@ export function useGetAllPools(offset: number = 0, limit: number = 100) { abi: IPartyPoolABI, functionName: 'allTokens', }).catch(() => [] as readonly `0x${string}`[]), + publicClient.readContract({ + address: partyInfoAddress as `0x${string}`, + abi: IPartyInfoABI, + functionName: 'working', + args: [poolAddress], + }).catch(() => false), ]); - details.push({ - address: poolAddress, - name: name as string, - symbol: symbol as string, - tokens: tokens as readonly `0x${string}`[], - }); + // Only add pool if it's working + if (isWorking) { + details.push({ + address: poolAddress, + name: name as string, + symbol: symbol as string, + tokens: tokens as readonly `0x${string}`[], + }); + } } catch (err) { console.error('Error fetching pool details for', poolAddress, err); - // Add pool with fallback values - details.push({ - address: poolAddress, - name: 'Unknown Pool', - symbol: 'POOL', - tokens: [], - }); + // Skip pools that fail to load } } @@ -688,4 +693,74 @@ export function useLPTokenBalance( error, isReady: mounted, }; +} + +export function useBurnAmounts( + poolAddress: `0x${string}` | undefined, + lpTokenAmount: bigint | undefined +) { + const publicClient = usePublicClient(); + const [mounted, setMounted] = useState(false); + const [burnAmounts, setBurnAmounts] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + if (!mounted || !poolAddress || !lpTokenAmount || lpTokenAmount === 0n) { + setBurnAmounts(null); + setLoading(false); + return; + } + + const fetchBurnAmounts = async () => { + if (!publicClient) { + setLoading(false); + return; + } + + try { + setLoading(true); + setError(null); + + // Get chain ID and PartyInfo contract address + const chainId = await publicClient.getChainId(); + const partyInfoAddress = (chainInfo as Record)[chainId.toString()]?.v1?.PartyInfo; + + if (!partyInfoAddress) { + setError('PartyInfo contract not found for current chain'); + setBurnAmounts(null); + return; + } + + // Call burnAmounts function + const amounts = await publicClient.readContract({ + address: partyInfoAddress as `0x${string}`, + abi: IPartyPoolViewerABI, + functionName: 'burnAmounts', + args: [poolAddress, lpTokenAmount], + }) as bigint[]; + + setBurnAmounts(amounts); + } catch (err) { + console.error('Error fetching burn amounts:', err); + setError(err instanceof Error ? err.message : 'Failed to fetch burn amounts'); + setBurnAmounts(null); + } finally { + setLoading(false); + } + }; + + fetchBurnAmounts(); + }, [publicClient, mounted, poolAddress, lpTokenAmount]); + + return { + burnAmounts, + loading, + error, + isReady: mounted, + }; } \ No newline at end of file