import React, { useState, useEffect } from 'react'; import { Users, Gavel, FileText, TrendingUpIcon, Shield } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; import { Badge } from '../ui/badge'; import { usePezkuwi } from '../../contexts/PezkuwiContext'; import { formatBalance } from '@pezkuwi/lib/wallet'; import { LoadingState } from '@pezkuwi/components/AsyncComponent'; import { getActiveElections, getActiveProposals, getParliamentMembers, getDiwanMembers } from '@pezkuwi/lib/welati'; interface GovernanceStats { activeProposals: number; activeElections: number; totalVoters: number; participationRate: number; parliamentMembers: number; parliamentMax: number; diwanMembers: number; diwanMax: number; pendingVotes: number; diwanPendingReviews: number; relayTreasuryBalance: string; pezTreasuryBalance: string; } // Treasury addresses derived from PalletId const RELAY_TREASURY = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z'; // py/trsry const PEZ_TREASURY = '5EYCAe5iipewaoUvoNr8ttcKqj5czZPBvVAex6uWbT6HxQNU'; // pez/trea (Asset Hub) const GovernanceOverview: React.FC = () => { const { api, isApiReady, assetHubApi, isAssetHubReady } = usePezkuwi(); const [stats, setStats] = useState({ activeProposals: 0, activeElections: 0, totalVoters: 0, participationRate: 0, parliamentMembers: 0, parliamentMax: 201, diwanMembers: 0, diwanMax: 9, pendingVotes: 0, diwanPendingReviews: 0, relayTreasuryBalance: '0 HEZ', pezTreasuryBalance: '0 PEZ' }); const [loading, setLoading] = useState(true); useEffect(() => { const fetchGovernanceData = async () => { if (!api || !isApiReady) { if (import.meta.env.DEV) console.log('API not ready for governance data'); return; } try { if (import.meta.env.DEV) console.log('Fetching governance data from blockchain...'); setLoading(true); // Fetch active proposals via welati let activeProposals = 0; let pendingVotes = 0; let diwanPendingReviews = 0; try { const proposals = await getActiveProposals(api); activeProposals = proposals.length; pendingVotes = proposals.length; diwanPendingReviews = proposals.filter( p => p.decisionType === 'ConstitutionalReview' || p.decisionType === 'ConstitutionalUnanimous' ).length; if (import.meta.env.DEV) console.log('Active proposals:', activeProposals); } catch (err) { if (import.meta.env.DEV) console.warn('Failed to fetch proposals:', err); } // Fetch active elections via welati let activeElections = 0; try { const elections = await getActiveElections(api); activeElections = elections.length; if (import.meta.env.DEV) console.log('Active elections:', activeElections); } catch (err) { if (import.meta.env.DEV) console.warn('Failed to fetch elections:', err); } // Fetch parliament members via welati let parliamentMembers = 0; try { const members = await getParliamentMembers(api); parliamentMembers = members.length; if (import.meta.env.DEV) console.log('Parliament members:', parliamentMembers); } catch (err) { if (import.meta.env.DEV) console.warn('Failed to fetch parliament members:', err); } // Fetch diwan members via welati let diwanMembers = 0; try { const members = await getDiwanMembers(api); diwanMembers = members.length; if (import.meta.env.DEV) console.log('Diwan members:', diwanMembers); } catch (err) { if (import.meta.env.DEV) console.warn('Failed to fetch diwan members:', err); } // Fetch Relay Chain treasury balance (native HEZ) let relayTreasuryBalance = '0 HEZ'; try { const treasuryAccount = await api.query.system.account(RELAY_TREASURY); const balance = treasuryAccount.data.free.toString(); relayTreasuryBalance = `${formatBalance(balance)} HEZ`; if (import.meta.env.DEV) console.log('Relay treasury balance:', relayTreasuryBalance); } catch (err) { if (import.meta.env.DEV) console.warn('Failed to fetch relay treasury balance:', err); } // Fetch PEZ Treasury balance (PEZ token, asset ID 1, on Asset Hub) let pezTreasuryBalance = '0 PEZ'; try { if (assetHubApi && isAssetHubReady) { const pezBalance = await assetHubApi.query.assets.account(1, PEZ_TREASURY); if (pezBalance.isSome) { const balanceData = (pezBalance.unwrap() as any).toJSON(); const rawBalance = (balanceData.balance ?? balanceData.free ?? '0').toString(); pezTreasuryBalance = `${formatBalance(rawBalance)} PEZ`; } if (import.meta.env.DEV) console.log('PEZ treasury balance:', pezTreasuryBalance); } } catch (err) { if (import.meta.env.DEV) console.warn('Failed to fetch PEZ treasury balance:', err); } setStats({ activeProposals, activeElections, totalVoters: 0, participationRate: 0, parliamentMembers, parliamentMax: 201, diwanMembers, diwanMax: 9, pendingVotes, diwanPendingReviews, relayTreasuryBalance, pezTreasuryBalance }); if (import.meta.env.DEV) console.log('Governance data updated:', { activeProposals, activeElections, parliamentMembers, diwanMembers, relayTreasuryBalance, pezTreasuryBalance }); } catch (error) { if (import.meta.env.DEV) console.error('Failed to fetch governance data:', error); } finally { setLoading(false); } }; fetchGovernanceData(); }, [api, isApiReady, assetHubApi, isAssetHubReady]); if (loading) { return ; } return (
{/* Stats Grid */}

Active Proposals

{stats.activeProposals}

Active Elections

{stats.activeElections}

Total Voters

{stats.totalVoters}

Treasury

{stats.pezTreasuryBalance}

{stats.relayTreasuryBalance}

{/* Government Bodies */}
Parliament Status
Active Members {stats.parliamentMembers}/{stats.parliamentMax}
{stats.activeElections > 0 && (
Elections Active
)}
Pending Votes {stats.pendingVotes}
Diwan (Constitutional Court)
Active Judges {stats.diwanMembers}/{stats.diwanMax}
Pending Reviews {stats.diwanPendingReviews}
); }; export default GovernanceOverview;