feat: bridge lane health API and dual-chain token list updates
Some checks failed
Deploy Explorer Live / deploy (push) Failing after 13s
Validate Explorer / frontend (push) Failing after 19s
Validate Explorer / smoke-e2e (push) Has been skipped

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-05-25 00:33:08 -07:00
parent 228fa0eef6
commit 2eae47b0d1
5 changed files with 124 additions and 10 deletions

View File

@@ -14,6 +14,7 @@ import SubsystemPosturePanel from '@/components/common/SubsystemPosturePanel'
import TokenListSurfaceNote from '@/components/common/TokenListSurfaceNote'
import OperationsSurfaceNav from '@/components/explorer/OperationsSurfaceNav'
import OperationsActionGrid from '@/components/explorer/OperationsActionGrid'
import BridgeLaneHealthPanel from '@/components/explorer/BridgeLaneHealthPanel'
import { resolveEffectiveFreshness } from '@/utils/explorerFreshness'
import { statsApi, type ExplorerStats } from '@/services/api/stats'
@@ -156,6 +157,25 @@ export default function OperationsHubPage({
new Set((tokenList?.tokens || []).map((token) => token.symbol).filter(Boolean) as string[])
).slice(0, 8)
}, [tokenList])
const laneSummary = useMemo(() => {
const lanes = bridgeStatus?.data?.bridge_lanes?.lanes || []
if (lanes.length === 0) return null
const funded = lanes.filter((lane) => String(lane.status || '').toLowerCase() === 'funded').length
const unfunded = lanes.filter((lane) => String(lane.status || '').toLowerCase() === 'unfunded').length
const proofRecorded = lanes.filter(
(lane) => String(lane.proof_status || '').toLowerCase() === 'proof-recorded'
).length
return {
total: lanes.length,
funded,
unfunded,
proofRecorded,
updatedAt: bridgeStatus?.data?.bridge_lanes?.updated_at,
}
}, [bridgeStatus])
const activityContext = useMemo(
() =>
summarizeChainActivity({
@@ -231,6 +251,14 @@ export default function OperationsHubPage({
<div className="mt-2 text-sm text-gray-700 dark:text-gray-300">
{relayCount} managed lanes · queue {totalQueue}
</div>
{laneSummary ? (
<div className="mt-1 text-sm text-gray-700 dark:text-gray-300">
{laneSummary.funded}/{laneSummary.total} config-ready funded
{laneSummary.unfunded > 0 ? ` · ${laneSummary.unfunded} unfunded` : ''}
{' · '}
{laneSummary.proofRecorded}/{laneSummary.total} proof-recorded
</div>
) : null}
</Card>
<Card className="border border-emerald-200 bg-emerald-50/70 dark:border-emerald-900/50 dark:bg-emerald-950/20">
@@ -312,6 +340,23 @@ export default function OperationsHubPage({
</div>
</div>
</div>
{laneSummary ? (
<div className="mt-4 rounded-2xl border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/40">
<div className="text-sm text-gray-500 dark:text-gray-400">Config-ready lanes</div>
<div className="mt-1 text-lg font-semibold text-gray-900 dark:text-white">
{laneSummary.funded}/{laneSummary.total} funded · {laneSummary.proofRecorded}/{laneSummary.total} proof-recorded
</div>
<div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
{mode === 'guided'
? 'Remote CCIP bridge LINK balances and operator proof hashes. Full lane table below.'
: 'Lane funding and proof posture from bridge status API.'}
{' '}
<Link href="/bridge" className="font-semibold text-primary-600 hover:underline">
Open bridge monitoring
</Link>
</div>
</div>
) : null}
</Card>
<Card title="Public Config Highlights">
@@ -342,6 +387,8 @@ export default function OperationsHubPage({
</Card>
</div>
<BridgeLaneHealthPanel laneHealth={bridgeStatus?.data?.bridge_lanes} />
<OperationsActionGrid actions={page.actions} />
</div>
)