From ef93735ef4b21fba2dede6ec70389fe241d93f10 Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Sun, 22 Feb 2026 06:36:15 +0300 Subject: [PATCH] fix: query nominators from Asset Hub, treasury balances from both chains NetworkStats now queries staking.nominators from Asset Hub instead of Relay Chain (staking migrated to AH). Treasury hook fetches HEZ from RC and PEZ from AH (asset 1) for accurate balance display. --- web/src/components/NetworkStats.tsx | 12 +++--- .../components/treasury/TreasuryOverview.tsx | 5 ++- web/src/hooks/useTreasury.ts | 43 +++++++++++++++---- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/web/src/components/NetworkStats.tsx b/web/src/components/NetworkStats.tsx index c6a706d6..93086d78 100644 --- a/web/src/components/NetworkStats.tsx +++ b/web/src/components/NetworkStats.tsx @@ -81,15 +81,17 @@ export const NetworkStats: React.FC = () => { if (import.meta.env.DEV) console.warn('Failed to fetch People Chain collators', err); } - // 3. Count Nominators + // 3. Count Nominators from Asset Hub (staking migrated to AH) let nCount = 0; try { - const nominators = await api.query.staking?.nominators.entries(); - if (nominators) { - nCount = nominators.length; + if (isAssetHubReady && assetHubApi?.query.staking?.nominators) { + const nominators = await assetHubApi.query.staking.nominators.entries(); + if (nominators) { + nCount = nominators.length; + } } } catch { - if (import.meta.env.DEV) console.warn('Staking pallet not available, nominators = 0'); + if (import.meta.env.DEV) console.warn('Staking pallet not available on AH, nominators = 0'); } setValidatorCount(vCount); diff --git a/web/src/components/treasury/TreasuryOverview.tsx b/web/src/components/treasury/TreasuryOverview.tsx index 8b5c65d7..fd8130af 100644 --- a/web/src/components/treasury/TreasuryOverview.tsx +++ b/web/src/components/treasury/TreasuryOverview.tsx @@ -77,7 +77,7 @@ export const TreasuryOverview: React.FC = () => { {t('treasury.liveData')} - {t('treasury.activeProposals', { count: proposals.length })} • {t('treasury.hezInTreasury', { amount: metrics.totalBalance.toFixed(2) })} + {t('treasury.activeProposals', { count: proposals.length })} • {metrics.pezBalance.toLocaleString(undefined, { maximumFractionDigits: 2 })} PEZ • {metrics.hezBalance.toLocaleString(undefined, { maximumFractionDigits: 4 })} HEZ @@ -117,7 +117,8 @@ export const TreasuryOverview: React.FC = () => {

{t('treasury.totalBalance')}

-

${(metrics.totalBalance / 1000000).toFixed(2)}M

+

{metrics.pezBalance.toLocaleString(undefined, { maximumFractionDigits: 2 })} PEZ

+

{metrics.hezBalance.toLocaleString(undefined, { maximumFractionDigits: 4 })} HEZ

{t('treasury.thisMonth', { percent: '12.5' })} diff --git a/web/src/hooks/useTreasury.ts b/web/src/hooks/useTreasury.ts index 40208bd1..6802ffed 100644 --- a/web/src/hooks/useTreasury.ts +++ b/web/src/hooks/useTreasury.ts @@ -3,6 +3,8 @@ import { usePezkuwi } from '@/contexts/PezkuwiContext'; export interface TreasuryMetrics { totalBalance: number; + pezBalance: number; + hezBalance: number; monthlyIncome: number; monthlyExpenses: number; pendingProposals: number; @@ -21,9 +23,11 @@ export interface TreasuryProposal { } export function useTreasury() { - const { api, isConnected } = usePezkuwi(); + const { api, assetHubApi, isConnected, isAssetHubReady } = usePezkuwi(); const [metrics, setMetrics] = useState({ totalBalance: 0, + pezBalance: 0, + hezBalance: 0, monthlyIncome: 0, monthlyExpenses: 0, pendingProposals: 0, @@ -45,14 +49,34 @@ export function useTreasury() { setLoading(true); setError(null); - // Get treasury account balance - const treasuryAccount = await api.query.treasury?.treasury?.(); - let totalBalance = 0; + const TREASURY_ACCOUNT = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z'; // py/trsry - if (treasuryAccount) { - totalBalance = parseInt(treasuryAccount.toString()) / 1e12; // Convert from planck to tokens + // Get HEZ balance from Relay Chain treasury account + let hezBalance = 0; + try { + const rcAccount = await api.query.system.account(TREASURY_ACCOUNT); + hezBalance = parseInt(rcAccount.data.free.toString()) / 1e12; + } catch { + if (import.meta.env.DEV) console.warn('Failed to fetch RC treasury HEZ balance'); } + // Get PEZ balance from Asset Hub (asset ID 1) + let pezBalance = 0; + try { + if (isAssetHubReady && assetHubApi?.query.assets) { + const pezAccount = await assetHubApi.query.assets.account(1, TREASURY_ACCOUNT); + if (pezAccount && !pezAccount.isEmpty) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const unwrapped = (pezAccount as any).unwrap?.() ? (pezAccount as any).unwrap() : pezAccount; + pezBalance = parseInt(unwrapped.balance?.toString() || '0') / 1e12; + } + } + } catch { + if (import.meta.env.DEV) console.warn('Failed to fetch AH treasury PEZ balance'); + } + + const totalBalance = hezBalance + pezBalance; + // Fetch all treasury proposals const proposalsData = await api.query.treasury?.proposals?.entries(); const proposalsList: TreasuryProposal[] = []; @@ -60,7 +84,8 @@ export function useTreasury() { let pendingCount = 0; if (proposalsData) { - proposalsData.forEach(([key, value]: [unknown, unknown]) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + proposalsData.forEach(([key, value]: [any, any]) => { const index = key.args[0].toNumber(); const proposal = value.unwrap(); const valueAmount = parseInt(proposal.value.toString()) / 1e12; @@ -86,6 +111,8 @@ export function useTreasury() { setMetrics({ totalBalance, + pezBalance, + hezBalance, monthlyIncome: 0, // This would require historical data monthlyExpenses: 0, // This would require historical data pendingProposals: pendingCount, @@ -108,7 +135,7 @@ export function useTreasury() { // Subscribe to updates const interval = setInterval(fetchTreasuryData, 30000); // Refresh every 30 seconds return () => clearInterval(interval); - }, [api, isConnected]); + }, [api, assetHubApi, isConnected, isAssetHubReady]); return { metrics,