import { useEffect, useMemo, useState } from 'react' import { Card } from '@/libs/frontend-ui-primitives' import Link from 'next/link' import { explorerFeaturePages } from '@/data/explorerOperations' import { blocksApi, type Block } from '@/services/api/blocks' import { missionControlApi, type MissionControlBridgeStatusResponse, type MissionControlChainStatus, } from '@/services/api/missionControl' import { statsApi, type ExplorerRecentActivitySnapshot, type ExplorerStats, type ExplorerTransactionTrendPoint, } from '@/services/api/stats' import { transactionsApi, type Transaction } from '@/services/api/transactions' import { formatWeiAsEth } from '@/utils/format' import OperationsPageShell, { MetricCard, StatusBadge, formatNumber, relativeAge, truncateMiddle, } from './OperationsPageShell' interface AnalyticsOperationsPageProps { initialStats?: ExplorerStats | null initialTransactionTrend?: ExplorerTransactionTrendPoint[] initialActivitySnapshot?: ExplorerRecentActivitySnapshot | null initialBlocks?: Block[] initialTransactions?: Transaction[] initialBridgeStatus?: MissionControlBridgeStatusResponse | null } function getChainStatus(bridgeStatus: MissionControlBridgeStatusResponse | null): MissionControlChainStatus | null { const chains = bridgeStatus?.data?.chains if (!chains) return null const [firstChain] = Object.values(chains) return firstChain || null } export default function AnalyticsOperationsPage({ initialStats = null, initialTransactionTrend = [], initialActivitySnapshot = null, initialBlocks = [], initialTransactions = [], initialBridgeStatus = null, }: AnalyticsOperationsPageProps) { const [stats, setStats] = useState(initialStats) const [transactionTrend, setTransactionTrend] = useState(initialTransactionTrend) const [activitySnapshot, setActivitySnapshot] = useState(initialActivitySnapshot) const [blocks, setBlocks] = useState(initialBlocks) const [transactions, setTransactions] = useState(initialTransactions) const [bridgeStatus, setBridgeStatus] = useState(initialBridgeStatus) const [loadingError, setLoadingError] = useState(null) const page = explorerFeaturePages.analytics useEffect(() => { let cancelled = false const load = async () => { const [statsResult, trendResult, snapshotResult, blocksResult, transactionsResult, bridgeResult] = await Promise.allSettled([ statsApi.get(), statsApi.getTransactionTrend(), statsApi.getRecentActivitySnapshot(), blocksApi.list({ chain_id: 138, page: 1, page_size: 5 }), transactionsApi.list(138, 1, 5), missionControlApi.getBridgeStatus(), ]) if (cancelled) return if (statsResult.status === 'fulfilled') setStats(statsResult.value) if (trendResult.status === 'fulfilled') setTransactionTrend(trendResult.value) if (snapshotResult.status === 'fulfilled') setActivitySnapshot(snapshotResult.value) if (blocksResult.status === 'fulfilled') setBlocks(blocksResult.value.data) if (transactionsResult.status === 'fulfilled') setTransactions(transactionsResult.value.data) if (bridgeResult.status === 'fulfilled') setBridgeStatus(bridgeResult.value) const failedCount = [statsResult, trendResult, snapshotResult, blocksResult, transactionsResult, bridgeResult].filter( (result) => result.status === 'rejected' ).length if (failedCount === 6) { setLoadingError('Analytics data is temporarily unavailable from the public explorer APIs.') } } load().catch((error) => { if (!cancelled) { setLoadingError(error instanceof Error ? error.message : 'Analytics data is temporarily unavailable from the public explorer APIs.') } }) return () => { cancelled = true } }, []) const chainStatus = useMemo(() => getChainStatus(bridgeStatus), [bridgeStatus]) const trailingWindow = useMemo(() => transactionTrend.slice(0, 7), [transactionTrend]) const sevenDayAverage = useMemo(() => { if (trailingWindow.length === 0) return 0 const total = trailingWindow.reduce((sum, point) => sum + point.transaction_count, 0) return total / trailingWindow.length }, [trailingWindow]) const topDay = useMemo(() => { if (trailingWindow.length === 0) return null return trailingWindow.reduce((best, point) => (point.transaction_count > best.transaction_count ? point : best)) }, [trailingWindow]) const averageGasUtilization = useMemo(() => { if (blocks.length === 0) return 0 return blocks.reduce((sum, block) => { const ratio = block.gas_limit > 0 ? block.gas_used / block.gas_limit : 0 return sum + ratio }, 0) / blocks.length }, [blocks]) const trendPeak = useMemo( () => trailingWindow.reduce((max, point) => Math.max(max, point.transaction_count), 0), [trailingWindow], ) return ( {loadingError ? (

{loadingError}

) : null}
Peak Day
{topDay ? formatNumber(topDay.transaction_count) : 'Unknown'}
{topDay?.date || 'No trend data yet'}
Contract Creations
{formatNumber(activitySnapshot?.contract_creations)}
Within the sampled recent transaction feed.
Avg Sample Fee
{activitySnapshot ? formatWeiAsEth(Math.round(activitySnapshot.average_fee_wei).toString(), 6) : 'Unknown'}
Average fee from the recent public transaction sample.
{activitySnapshot ? (
Token Transfer Share
{Math.round(activitySnapshot.token_transfer_share * 100)}%
Sampled transactions involving token transfers.
Contract Call Share
{Math.round(activitySnapshot.contract_call_share * 100)}%
Sampled transactions calling contracts.
Creation Share
{Math.round(activitySnapshot.contract_creation_share * 100)}%
Sampled transactions deploying contracts.
) : null}
{trailingWindow.map((point) => { const width = trendPeak > 0 ? Math.max(8, Math.round((point.transaction_count / trendPeak) * 100)) : 0 return (
{point.date} {formatNumber(point.transaction_count)} tx
) })} {trailingWindow.length === 0 ? (

Trend data is temporarily unavailable.

) : null}
{blocks.map((block) => (
Block {formatNumber(block.number)}
{truncateMiddle(block.hash)} · miner{' '} {truncateMiddle(block.miner)}
{formatNumber(block.transaction_count)} tx · {Math.round((block.gas_limit > 0 ? block.gas_used / block.gas_limit : 0) * 100)}% gas · {relativeAge(block.timestamp)}
))} {blocks.length === 0 ? (

No recent block data available.

) : null}
{transactions.map((transaction) => (
{truncateMiddle(transaction.hash, 12, 10)}
Block{' '} {formatNumber(transaction.block_number)} {' '}· from{' '} {truncateMiddle(transaction.from_address)} {transaction.to_address ? ( <> {' '}· to{' '} {truncateMiddle(transaction.to_address)} ) : null}
{relativeAge(transaction.created_at)}
{transaction.method ? : null} {transaction.contract_address ? : null} {transaction.token_transfers && transaction.token_transfers.length > 0 ? ( ) : null}
))} {transactions.length === 0 ? (

No recent transaction data available.

) : null}
) }