'use client'; import { useState, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { ArrowDownUp, ChevronDown } from 'lucide-react'; import { useAccount } from 'wagmi'; import { useTokenDetails, useGetPoolsByToken, type TokenDetails } from '@/hooks/usePartyPlanner'; import { formatUnits } from 'viem'; export function SwapForm() { const { t } = useTranslation(); const { isConnected, address } = useAccount(); const [fromAmount, setFromAmount] = useState(''); const [toAmount, setToAmount] = useState(''); const [selectedFromToken, setSelectedFromToken] = useState(null); const [selectedToToken, setSelectedToToken] = useState(null); const [isFromDropdownOpen, setIsFromDropdownOpen] = useState(false); const [isToDropdownOpen, setIsToDropdownOpen] = useState(false); const [slippage, setSlippage] = useState(0.5); // Default 0.5% const [customSlippage, setCustomSlippage] = useState(''); const [isCustomSlippage, setIsCustomSlippage] = useState(false); const fromDropdownRef = useRef(null); const toDropdownRef = useRef(null); // Use the custom hook to get all token details with a single batched RPC call const { tokenDetails, loading, error } = useTokenDetails(address); // Get available tokens for the selected "from" token const { availableTokens } = useGetPoolsByToken(selectedFromToken?.address); // Trigger the hook to fetch data when address is available useEffect(() => { if (tokenDetails) { console.log('Token details loaded in swap-form'); } }, [tokenDetails]); // Close dropdowns when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (fromDropdownRef.current && !fromDropdownRef.current.contains(event.target as Node)) { setIsFromDropdownOpen(false); } if (toDropdownRef.current && !toDropdownRef.current.contains(event.target as Node)) { setIsToDropdownOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); // Calculate and log limit price when amount or slippage changes useEffect(() => { if (fromAmount && parseFloat(fromAmount) > 0) { const amount = parseFloat(fromAmount); const slippagePercent = isCustomSlippage ? parseFloat(customSlippage) || 0 : slippage; const limitPrice = amount * (1 + slippagePercent / 100); console.log('Limit Price:', limitPrice); console.log('From Amount:', amount); console.log('Slippage %:', slippagePercent); console.log('Additional Amount from Slippage:', limitPrice - amount); } }, [fromAmount, slippage, customSlippage, isCustomSlippage]); const handleSwap = () => { // Swap logic will be implemented later console.log('Swap clicked'); }; const switchTokens = () => { // Switch tokens logic setFromAmount(toAmount); setToAmount(fromAmount); }; return ( {t('swap.title')} {/* From Token */}
{t('swap.balance')}: {selectedFromToken ? formatUnits(selectedFromToken.balance, selectedFromToken.decimals) : '0.00'}
setFromAmount(e.target.value)} className="text-2xl h-16" />
{isFromDropdownOpen && (
{tokenDetails && tokenDetails.length > 0 ? ( tokenDetails.map((token) => ( )) ) : (
{loading ? 'Loading tokens...' : 'No tokens available'}
)}
)}
{/* Switch Button */}
{/* To Token */}
{t('swap.balance')}: {selectedToToken ? formatUnits(selectedToToken.balance, selectedToToken.decimals) : '0.00'}
setToAmount(e.target.value)} className="text-2xl h-16" disabled={!selectedFromToken} />
{isToDropdownOpen && (
{availableTokens && availableTokens.length > 0 && tokenDetails ? ( // Filter tokenDetails to only show tokens in availableTokens tokenDetails .filter((token) => availableTokens.some((availToken) => availToken.toLowerCase() === token.address.toLowerCase() ) ) .map((token) => ( )) ) : selectedFromToken ? (
{loading ? 'Loading available tokens...' : 'No tokens available for swap'}
) : (
Select a token in "You Pay" first
)}
)}
{/* Slippage Tolerance */}
{isCustomSlippage ? customSlippage || '0' : slippage}%
{[0.1, 0.2, 0.3, 1, 2, 3].map((percent) => ( ))}
{ setCustomSlippage(e.target.value); setIsCustomSlippage(true); }} onFocus={() => setIsCustomSlippage(true)} className={`h-9 pr-6 ${isCustomSlippage ? 'border-primary' : ''}`} step="0.01" /> {isCustomSlippage && ( % )}
{/* Swap Button */}
); }