diff --git a/frontend/src/components/explorer/BridgeMonitoringPage.tsx b/frontend/src/components/explorer/BridgeMonitoringPage.tsx index d72f1ca..4aff7e1 100644 --- a/frontend/src/components/explorer/BridgeMonitoringPage.tsx +++ b/frontend/src/components/explorer/BridgeMonitoringPage.tsx @@ -25,6 +25,11 @@ interface RelayLaneCard { failed: number lastPolled: string bridgeAddress: string + issueScope: string | null + issueMessage: string | null + inventoryShortfallWei: string | null + inventoryRequiredWei: string | null + inventoryAvailableWei: string | null } const relayOrder = ['mainnet_cw', 'mainnet_weth', 'bsc', 'avax', 'avax_cw', 'avax_to_138'] @@ -53,6 +58,9 @@ function resolveSnapshot(relay?: MissionControlRelayPayload): MissionControlRela function relayPolicyCue(snapshot: MissionControlRelaySnapshot | null): string | null { if (!snapshot) return null + if (snapshot.last_error?.scope === 'bridge_inventory') { + return 'Queued release waiting on bridge inventory' + } if (String(snapshot.status || '').toLowerCase() === 'paused' && snapshot.monitoring?.delivery_enabled === false) { return 'Delivery disabled by policy' } @@ -81,6 +89,18 @@ function statusPillClasses(status: string): string { return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-100' } +function formatWeiToToken(value?: string | null): string { + if (!value) return 'Unknown' + try { + const raw = BigInt(value) + const whole = raw / 10n ** 18n + const fractional = (raw % 10n ** 18n).toString().padStart(18, '0').slice(0, 6).replace(/0+$/, '') + return fractional ? `${whole.toString()}.${fractional}` : whole.toString() + } catch { + return value + } +} + function ActionLink({ href, label, @@ -171,7 +191,7 @@ export default function BridgeMonitoringPage({ return { key, label: getMissionControlRelayLabel(key), - status, + status: snapshot?.last_error?.scope === 'bridge_inventory' ? 'underfunded' : status, profile: snapshot?.service?.profile || key, sourceChain: snapshot?.source?.chain_name || 'Unknown', destinationChain: snapshot?.destination?.chain_name || 'Unknown', @@ -184,6 +204,11 @@ export default function BridgeMonitoringPage({ snapshot?.destination?.relay_bridge || snapshot?.source?.bridge_filter || '', + issueScope: snapshot?.last_error?.scope || null, + issueMessage: snapshot?.last_error?.message || null, + inventoryShortfallWei: snapshot?.last_error?.shortfall || null, + inventoryRequiredWei: snapshot?.last_error?.required_amount || null, + inventoryAvailableWei: snapshot?.last_error?.available_amount || null, } }) .sort((left, right) => { @@ -313,6 +338,17 @@ export default function BridgeMonitoringPage({ {relayPolicyCue(resolveSnapshot((getMissionControlRelays(bridgeStatus) || {})[lane.key]))} ) : null} + {lane.issueScope === 'bridge_inventory' ? ( +