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