import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Progress } from '@/components/ui/progress'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Separator } from '@/components/ui/separator'; import { TrendingUp, TrendingDown, Wallet, Clock, AlertTriangle, CheckCircle, XCircle, Calculator, Shield, Zap, Star, Info, ArrowUpRight, ArrowDownRight, Coins, BarChart3, PieChart, Activity } from 'lucide-react'; import { useWallet } from '@/hooks/use-wallet'; import { useToast } from '@/hooks/use-toast'; import { formatDistanceToNow, format } from 'date-fns'; interface Stake { stake_id: string; staker_address: string; agent_wallet: string; amount: number; lock_period: number; start_time: string; end_time: string; status: 'active' | 'unbonding' | 'completed' | 'slashed'; accumulated_rewards: number; last_reward_time: string; current_apy: number; agent_tier: 'bronze' | 'silver' | 'gold' | 'platinum' | 'diamond'; performance_multiplier: number; auto_compound: boolean; unbonding_time?: string; early_unbond_penalty: number; lock_bonus_multiplier: number; } interface AgentMetrics { agent_wallet: string; total_staked: number; staker_count: number; total_rewards_distributed: number; average_accuracy: number; total_submissions: number; successful_submissions: number; success_rate: number; current_tier: 'bronze' | 'silver' | 'gold' | 'platinum' | 'diamond'; tier_score: number; reputation_score: number; last_update_time: string; average_response_time?: number; energy_efficiency_score?: number; } interface StakingPool { agent_wallet: string; total_staked: number; total_rewards: number; pool_apy: number; staker_count: number; active_stakers: string[]; last_distribution_time: string; min_stake_amount: number; max_stake_amount: number; auto_compound_enabled: boolean; pool_performance_score: number; volatility_score: number; } const StakingDashboard: React.FC = () => { const { address, isConnected } = useWallet(); const { toast } = useToast(); const [stakes, setStakes] = useState([]); const [supportedAgents, setSupportedAgents] = useState([]); const [stakingPools, setStakingPools] = useState([]); const [loading, setLoading] = useState(true); const [activeTab, setActiveTab] = useState('my-stakes'); const [showCreateStakeModal, setShowCreateStakeModal] = useState(false); const [selectedAgent, setSelectedAgent] = useState(null); const [stakeForm, setStakeForm] = useState({ agent_wallet: '', amount: '', lock_period: '30', auto_compound: false }); const [totalRewards, setTotalRewards] = useState(0); const [totalStaked, setTotalStaked] = useState(0); // Load data on component mount useEffect(() => { if (isConnected) { loadMyStakes(); loadMyRewards(); } loadSupportedAgents(); loadStakingPools(); }, [isConnected]); const loadMyStakes = async () => { try { const response = await fetch('/api/v1/staking/my-positions', { headers: { 'Authorization': `Bearer ${address}` } }); if (response.ok) { const data = await response.json(); setStakes(data); // Calculate total staked const total = data.reduce((sum: number, stake: Stake) => sum + stake.amount, 0); setTotalStaked(total); } } catch (error) { console.error('Error loading stakes:', error); } }; const loadMyRewards = async () => { try { const response = await fetch('/api/v1/staking/my-rewards?period=monthly', { headers: { 'Authorization': `Bearer ${address}` } }); if (response.ok) { const data = await response.json(); setTotalRewards(data.total_rewards); } } catch (error) { console.error('Error loading rewards:', error); } }; const loadSupportedAgents = async () => { try { setLoading(true); const response = await fetch('/api/v1/staking/agents/supported?limit=50'); if (response.ok) { const data = await response.json(); setSupportedAgents(data.agents); } } catch (error) { console.error('Error loading agents:', error); } finally { setLoading(false); } }; const loadStakingPools = async () => { try { const response = await fetch('/api/v1/staking/pools'); if (response.ok) { const data = await response.json(); setStakingPools(data); } } catch (error) { console.error('Error loading pools:', error); } }; const handleCreateStake = async () => { if (!isConnected) { toast({ title: 'Wallet Required', description: 'Please connect your wallet to create stakes', variant: 'destructive' }); return; } try { const response = await fetch('/api/v1/stake', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${address}` }, body: JSON.stringify(stakeForm) }); if (response.ok) { const newStake = await response.json(); setStakes(prev => [newStake, ...prev]); setShowCreateStakeModal(false); setStakeForm({ agent_wallet: '', amount: '', lock_period: '30', auto_compound: false }); toast({ title: 'Stake Created', description: `Successfully staked ${stakeForm.amount} AITBC`, }); // Reload data loadMyStakes(); loadStakingPools(); } else { throw new Error('Failed to create stake'); } } catch (error) { console.error('Error creating stake:', error); toast({ title: 'Error', description: 'Failed to create stake', variant: 'destructive' }); } }; const handleUnbondStake = async (stakeId: string) => { try { const response = await fetch(`/api/v1/stake/${stakeId}/unbond`, { method: 'POST', headers: { 'Authorization': `Bearer ${address}` } }); if (response.ok) { toast({ title: 'Unbonding Initiated', description: 'Your stake is now in the unbonding period', }); // Reload stakes loadMyStakes(); } else { throw new Error('Failed to unbond stake'); } } catch (error) { console.error('Error unbonding stake:', error); toast({ title: 'Error', description: 'Failed to unbond stake', variant: 'destructive' }); } }; const handleCompleteUnbonding = async (stakeId: string) => { try { const response = await fetch(`/api/v1/stake/${stakeId}/complete`, { method: 'POST', headers: { 'Authorization': `Bearer ${address}` } }); if (response.ok) { const result = await response.json(); toast({ title: 'Unbonding Completed', description: `Received ${result.total_amount + result.total_rewards} AITBC`, }); // Reload stakes and rewards loadMyStakes(); loadMyRewards(); } else { throw new Error('Failed to complete unbonding'); } } catch (error) { console.error('Error completing unbonding:', error); toast({ title: 'Error', description: 'Failed to complete unbonding', variant: 'destructive' }); } }; const getTierColor = (tier: string) => { const colors = { bronze: 'bg-orange-100 text-orange-800 border-orange-200', silver: 'bg-gray-100 text-gray-800 border-gray-200', gold: 'bg-yellow-100 text-yellow-800 border-yellow-200', platinum: 'bg-purple-100 text-purple-800 border-purple-200', diamond: 'bg-blue-100 text-blue-800 border-blue-200' }; return colors[tier as keyof typeof colors] || colors.bronze; }; const getStatusColor = (status: string) => { const colors = { active: 'bg-green-100 text-green-800', unbonding: 'bg-yellow-100 text-yellow-800', completed: 'bg-blue-100 text-blue-800', slashed: 'bg-red-100 text-red-800' }; return colors[status as keyof typeof colors] || colors.active; }; const getTimeRemaining = (endTime: string) => { const endDate = new Date(endTime); const now = new Date(); const timeRemaining = endDate.getTime() - now.getTime(); if (timeRemaining <= 0) return 'Expired'; return formatDistanceToNow(endDate, { addSuffix: true }); }; const calculateAPY = (agent: AgentMetrics, lockPeriod: number) => { const baseAPY = 5.0; const tierMultipliers = { bronze: 1.0, silver: 1.2, gold: 1.5, platinum: 2.0, diamond: 3.0 }; const lockMultipliers = { 30: 1.1, 90: 1.25, 180: 1.5, 365: 2.0 }; const tierMultiplier = tierMultipliers[agent.current_tier as keyof typeof tierMultipliers]; const lockMultiplier = lockMultipliers[lockPeriod as keyof typeof lockMultipliers] || 1.0; const apy = baseAPY * tierMultiplier * lockMultiplier; return Math.min(apy, 20.0); // Cap at 20% }; const getRiskLevel = (agent: AgentMetrics) => { if (agent.success_rate >= 90 && agent.average_accuracy >= 90) return 'low'; if (agent.success_rate >= 70 && agent.average_accuracy >= 70) return 'medium'; return 'high'; }; const getRiskColor = (risk: string) => { const colors = { low: 'text-green-600', medium: 'text-yellow-600', high: 'text-red-600' }; return colors[risk as keyof typeof colors] || colors.medium; }; if (loading) { return (
); } return (
{/* Header */}

Staking Dashboard

Stake AITBC tokens on AI agents and earn rewards based on performance

{isConnected && ( )}
{/* Stats Cards */}

Total Staked

{totalStaked.toLocaleString()}

AITBC

Total Rewards

{totalRewards.toLocaleString()}

AITBC

Active Stakes

{stakes.filter(s => s.status === 'active').length}

Positions

Average APY

{stakes.length > 0 ? (stakes.reduce((sum, s) => sum + s.current_apy, 0) / stakes.length).toFixed(1) : '0.0' }%

Annual Yield

{/* Tabs */} My Stakes Available Agents Staking Pools {isConnected && Rewards} {/* My Stakes Tab */} {!isConnected ? ( Connect your wallet to view your staking positions ) : stakes.length === 0 ? (

No Stakes Found

Start staking on AI agents to earn rewards

) : (
{stakes.map((stake) => (
{stake.agent_wallet.slice(0, 8)}...{stake.agent_wallet.slice(-6)}
{stake.agent_tier.charAt(0).toUpperCase() + stake.agent_tier.slice(1)} {stake.status.charAt(0).toUpperCase() + stake.status.slice(1)} {stake.auto_compound && ( Auto-Compound )}

{stake.amount.toLocaleString()}

AITBC

{stake.current_apy.toFixed(1)}% APY

Lock Period

{stake.lock_period} days

Time Remaining

{getTimeRemaining(stake.end_time)}

Accumulated Rewards

{stake.accumulated_rewards.toFixed(2)} AITBC

Performance Multiplier

{stake.performance_multiplier}x

{/* Progress bar for lock period */}
Lock Progress {Math.max(0, 100 - ((new Date(stake.end_time).getTime() - Date.now()) / (stake.lock_period * 24 * 60 * 60 * 1000) * 100)).toFixed(1)}%
{stake.status === 'active' && new Date(stake.end_time) <= new Date() && ( )} {stake.status === 'unbonding' && ( )}
))}
)}
{/* Available Agents Tab */}
{supportedAgents.map((agent) => (
{agent.agent_wallet.slice(0, 8)}...{agent.agent_wallet.slice(-6)}
{agent.current_tier.charAt(0).toUpperCase() + agent.current_tier.slice(1)} {getRiskLevel(agent).toUpperCase()} RISK

{calculateAPY(agent, 30).toFixed(1)}%

APY

Total Staked

{agent.total_staked.toLocaleString()}

Stakers

{agent.staker_count}

Accuracy

{agent.average_accuracy.toFixed(1)}%

Success Rate

{agent.success_rate.toFixed(1)}%

Total Submissions {agent.total_submissions}
Rewards Distributed {agent.total_rewards_distributed.toLocaleString()} AITBC
{/* Performance indicators */}
Performance Score: {agent.tier_score.toFixed(1)}
))}
{/* Staking Pools Tab */} Agent Total Staked Pool APY Stakers Total Rewards Performance Volatility {stakingPools.map((pool) => ( {pool.agent_wallet.slice(0, 8)}...{pool.agent_wallet.slice(-6)} {pool.total_staked.toLocaleString()} AITBC {pool.pool_apy.toFixed(1)}% {pool.staker_count} {pool.total_rewards.toLocaleString()} AITBC
{pool.pool_performance_score.toFixed(0)}
{pool.volatility_score < 30 ? 'Low' : pool.volatility_score < 70 ? 'Medium' : 'High'}
))}
{/* Rewards Tab */} {!isConnected ? ( Connect your wallet to view your rewards ) : (
Reward Summary
Total Earned {totalRewards.toLocaleString()} AITBC
Pending Rewards {stakes.reduce((sum, s) => sum + s.accumulated_rewards, 0).toLocaleString()} AITBC
Average APY {stakes.length > 0 ? (stakes.reduce((sum, s) => sum + s.current_apy, 0) / stakes.length).toFixed(1) : '0.0' }%
Reward History

Reward history will be available soon

)}
{/* Create Stake Modal */} {showCreateStakeModal && (
Create New Stake Stake AITBC tokens on an AI agent to earn rewards
setStakeForm(prev => ({ ...prev, amount: e.target.value }))} min="100" max="100000" />

Min: 100 AITBC, Max: 100,000 AITBC

{selectedAgent && (

Estimated Returns

Base APY: 5.0%
Tier Multiplier: {selectedAgent.current_tier} tier
Lock Multiplier: {stakeForm.lock_period === '30' ? '1.1x' : stakeForm.lock_period === '90' ? '1.25x' : stakeForm.lock_period === '180' ? '1.5x' : '2.0x'}
Estimated APY: {calculateAPY(selectedAgent, parseInt(stakeForm.lock_period)).toFixed(1)}%
)}
setStakeForm(prev => ({ ...prev, auto_compound: e.target.checked }))} />
)}
); }; export default StakingDashboard;