import { useEffect, useMemo, useState } from 'react' import Link from 'next/link' import { Card } from '@/libs/frontend-ui-primitives' import { getMissionControlRelayLabel, getMissionControlRelays, missionControlApi, type MissionControlBridgeStatusResponse, type MissionControlRelayPayload, type MissionControlRelaySnapshot, } from '@/services/api/missionControl' import { explorerFeaturePages } from '@/data/explorerOperations' type FeedState = 'connecting' | 'live' | 'fallback' interface RelayLaneCard { key: string label: string status: string profile: string sourceChain: string destinationChain: string queueSize: number processed: number failed: number lastPolled: string bridgeAddress: string } const relayOrder = ['mainnet_cw', 'mainnet_weth', 'bsc', 'avax', 'avax_cw', 'avax_to_138'] function relativeAge(isoString?: string): string { if (!isoString) return 'Unknown' const parsed = Date.parse(isoString) if (!Number.isFinite(parsed)) return 'Unknown' const seconds = Math.max(0, Math.round((Date.now() - parsed) / 1000)) if (seconds < 60) return `${seconds}s ago` const minutes = Math.round(seconds / 60) if (minutes < 60) return `${minutes}m ago` const hours = Math.round(minutes / 60) return `${hours}h ago` } function shortAddress(value?: string): string { if (!value) return 'Unspecified' if (value.length <= 14) return value return `${value.slice(0, 6)}...${value.slice(-4)}` } function resolveSnapshot(relay?: MissionControlRelayPayload): MissionControlRelaySnapshot | null { return relay?.url_probe?.body || relay?.file_snapshot || null } function laneToneClasses(status: string): string { const normalized = status.toLowerCase() if (['degraded', 'stale', 'stopped', 'down', 'snapshot-error'].includes(normalized)) { return 'border-red-200 bg-red-50/80 dark:border-red-900/60 dark:bg-red-950/20' } if (['paused', 'starting'].includes(normalized)) { return 'border-amber-200 bg-amber-50/80 dark:border-amber-900/60 dark:bg-amber-950/20' } return 'border-emerald-200 bg-emerald-50/80 dark:border-emerald-900/60 dark:bg-emerald-950/20' } function statusPillClasses(status: string): string { const normalized = status.toLowerCase() if (['degraded', 'stale', 'stopped', 'down', 'snapshot-error'].includes(normalized)) { return 'bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-100' } if (['paused', 'starting'].includes(normalized)) { return 'bg-amber-100 text-amber-800 dark:bg-amber-900/50 dark:text-amber-100' } return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-100' } function ActionLink({ href, label, external, }: { href: string label: string external?: boolean }) { const className = 'inline-flex items-center text-sm font-semibold text-primary-600 hover:underline' const text = `${label} ->` if (external) { return ( {text} ) } return ( {text} ) } export default function BridgeMonitoringPage() { const [bridgeStatus, setBridgeStatus] = useState(null) const [feedState, setFeedState] = useState('connecting') const page = explorerFeaturePages.bridge useEffect(() => { let cancelled = false const loadSnapshot = async () => { try { const snapshot = await missionControlApi.getBridgeStatus() if (!cancelled) { setBridgeStatus(snapshot) } } catch (error) { if (!cancelled && process.env.NODE_ENV !== 'production') { console.warn('Failed to load bridge monitoring snapshot:', error) } } } loadSnapshot() const unsubscribe = missionControlApi.subscribeBridgeStatus( (status) => { if (!cancelled) { setBridgeStatus(status) setFeedState('live') } }, (error) => { if (!cancelled) { setFeedState('fallback') } if (process.env.NODE_ENV !== 'production') { console.warn('Bridge monitoring live stream issue:', error) } } ) return () => { cancelled = true unsubscribe() } }, []) const relayLanes = useMemo((): RelayLaneCard[] => { const relays = getMissionControlRelays(bridgeStatus) if (!relays) return [] const orderIndex = new Map(relayOrder.map((key, index) => [key, index])) return Object.entries(relays) .map(([key, relay]) => { const snapshot = resolveSnapshot(relay) const status = String(snapshot?.status || (relay.file_snapshot_error ? 'snapshot-error' : 'configured')).toLowerCase() return { key, label: getMissionControlRelayLabel(key), status, profile: snapshot?.service?.profile || key, sourceChain: snapshot?.source?.chain_name || 'Unknown', destinationChain: snapshot?.destination?.chain_name || 'Unknown', queueSize: snapshot?.queue?.size ?? 0, processed: snapshot?.queue?.processed ?? 0, failed: snapshot?.queue?.failed ?? 0, lastPolled: relativeAge(snapshot?.last_source_poll?.at), bridgeAddress: snapshot?.destination?.relay_bridge_default || snapshot?.destination?.relay_bridge || snapshot?.source?.bridge_filter || '', } }) .sort((left, right) => { const leftIndex = orderIndex.get(left.key) ?? Number.MAX_SAFE_INTEGER const rightIndex = orderIndex.get(right.key) ?? Number.MAX_SAFE_INTEGER return leftIndex - rightIndex || left.label.localeCompare(right.label) }) }, [bridgeStatus]) const chainStatus = bridgeStatus?.data?.chains?.['138'] const overallStatus = bridgeStatus?.data?.status || 'unknown' const checkedAt = relativeAge(bridgeStatus?.data?.checked_at) return (
{page.eyebrow}

{page.title}

{page.description}

{page.note ? (

{page.note}

) : null}
Relay Fleet
{overallStatus}
{relayLanes.length} managed lanes visible
Feed: {feedState === 'live' ? 'Live SSE' : feedState === 'fallback' ? 'Snapshot fallback' : 'Connecting'}
Chain 138 RPC
{chainStatus?.status || 'unknown'}
Head age: {chainStatus?.head_age_sec != null ? `${chainStatus.head_age_sec.toFixed(1)}s` : 'Unknown'}
Latency: {chainStatus?.latency_ms != null ? `${chainStatus.latency_ms}ms` : 'Unknown'}
Last Check
{checkedAt}
Public status JSON and live stream are both active.
{relayLanes.map((lane) => (
{lane.label}
{`${lane.sourceChain} -> ${lane.destinationChain}`}
{lane.status}
Profile
{lane.profile}
Queue
{lane.queueSize}
Processed
{lane.processed}
Failed
{lane.failed}
Last polled: {lane.lastPolled}
Bridge: {shortAddress(lane.bridgeAddress)}
))}
{page.actions.map((action) => (
{action.title}

{action.description}

))}
) }