import React, { useState, useEffect } from 'react'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { useWallet } from '@/contexts/WalletContext'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { TrendingUp, Droplet, BarChart3, Search, Plus } from 'lucide-react'; import { PoolInfo } from '@/types/dex'; import { fetchPools, formatTokenBalance } from '@pezkuwi/utils/dex'; import { isFounderWallet } from '@pezkuwi/utils/auth'; import { LoadingState } from '@pezkuwi/components/AsyncComponent'; interface PoolBrowserProps { onAddLiquidity?: (pool: PoolInfo) => void; onRemoveLiquidity?: (pool: PoolInfo) => void; onSwap?: (pool: PoolInfo) => void; onCreatePool?: () => void; } export const PoolBrowser: React.FC = ({ onAddLiquidity, onRemoveLiquidity, onSwap, onCreatePool, }) => { const { api, isApiReady } = usePolkadot(); const { account } = useWallet(); const [pools, setPools] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); const [sortBy, setSortBy] = useState<'tvl' | 'volume' | 'apr'>('tvl'); const isFounder = account ? isFounderWallet(account.address) : false; useEffect(() => { const loadPools = async () => { if (!api || !isApiReady) return; try { setLoading(true); const poolsData = await fetchPools(api); setPools(poolsData); } catch (error) { console.error('Failed to load pools:', error); } finally { setLoading(false); } }; loadPools(); // Refresh pools every 10 seconds const interval = setInterval(loadPools, 10000); return () => clearInterval(interval); }, [api, isApiReady]); const filteredPools = pools.filter((pool) => { if (!searchTerm) return true; const search = searchTerm.toLowerCase(); return ( pool.asset1Symbol.toLowerCase().includes(search) || pool.asset2Symbol.toLowerCase().includes(search) || pool.id.toLowerCase().includes(search) ); }); if (loading && pools.length === 0) { return ; } return (
{/* Header with search and create */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 bg-gray-900 border border-gray-800 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500" />
{isFounder && onCreatePool && ( )}
{/* Pools grid */} {filteredPools.length === 0 ? (
{searchTerm ? 'No pools found matching your search' : 'No liquidity pools available yet'}
) : (
{filteredPools.map((pool) => ( ))}
)}
); }; interface PoolCardProps { pool: PoolInfo; onAddLiquidity?: (pool: PoolInfo) => void; onRemoveLiquidity?: (pool: PoolInfo) => void; onSwap?: (pool: PoolInfo) => void; } const PoolCard: React.FC = ({ pool, onAddLiquidity, onRemoveLiquidity, onSwap, }) => { const reserve1Display = formatTokenBalance( pool.reserve1, pool.asset1Decimals, 2 ); const reserve2Display = formatTokenBalance( pool.reserve2, pool.asset2Decimals, 2 ); // Calculate exchange rate const rate = BigInt(pool.reserve1) > BigInt(0) ? (Number(pool.reserve2) / Number(pool.reserve1)).toFixed(4) : '0'; return (
{pool.asset1Symbol} / {pool.asset2Symbol} Active
{/* Reserves */}
Reserve {pool.asset1Symbol} {reserve1Display} {pool.asset1Symbol}
Reserve {pool.asset2Symbol} {reserve2Display} {pool.asset2Symbol}
{/* Exchange rate */}
Exchange Rate 1 {pool.asset1Symbol} = {rate} {pool.asset2Symbol}
{/* Stats row */}
Fee
{pool.feeRate || '0.3'}%
Volume 24h
{pool.volume24h || 'N/A'}
APR
{pool.apr7d || 'N/A'}
{/* Action buttons */}
{onAddLiquidity && ( )} {onRemoveLiquidity && ( )} {onSwap && ( )}
); };