feat(explorer): mission-control resilience, ops token labels, and CI validate
Some checks failed
Deploy Explorer Live / deploy (push) Failing after 14s
Validate Explorer / frontend (push) Successful in 1m34s
Validate Explorer / smoke-e2e (push) Failing after 1m26s

Add SSE reconnect with backoff, fallback REST polling, visibility-aware refresh,
extended token-list labels on operations pages, validate-on-pr workflow, and smoke coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-05-22 20:40:11 -07:00
parent e3ec87c324
commit 7a7dfca221
17 changed files with 268 additions and 42 deletions

View File

@@ -0,0 +1,13 @@
import { TOKEN_LIST_SURFACE_LABELS, type TokenListSurface } from '@/services/api/tokenListSurfaces'
interface TokenListSurfaceNoteProps {
surface?: TokenListSurface
className?: string
}
export default function TokenListSurfaceNote({
surface = 'extended',
className = 'text-sm text-gray-600 dark:text-gray-400',
}: TokenListSurfaceNoteProps) {
return <p className={className}>{TOKEN_LIST_SURFACE_LABELS[surface]}</p>
}

View File

@@ -3,7 +3,8 @@
import { useEffect, useMemo, useState } from 'react'
import Link from 'next/link'
import { Card } from '@/libs/frontend-ui-primitives'
import { configApi, type TokenListResponse } from '@/services/api/config'
import { type TokenListResponse } from '@/services/api/config'
import { tokensApi } from '@/services/api/tokens'
import {
aggregateLiquidityPools,
featuredLiquiditySymbols,
@@ -22,6 +23,7 @@ import ActivityContextPanel from '@/components/common/ActivityContextPanel'
import FreshnessTrustNote from '@/components/common/FreshnessTrustNote'
import MarketEvidenceNote from '@/components/common/MarketEvidenceNote'
import SubsystemPosturePanel from '@/components/common/SubsystemPosturePanel'
import TokenListSurfaceNote from '@/components/common/TokenListSurfaceNote'
import { resolveEffectiveFreshness } from '@/utils/explorerFreshness'
import {
formatCurrency,
@@ -98,7 +100,7 @@ export default function LiquidityOperationsPage({
const load = async () => {
const [tokenListResult, routeMatrixResult, plannerCapabilitiesResult, planResult, statsResult, bridgeResult] =
await Promise.allSettled([
configApi.getTokenList(),
tokensApi.listForSurface('extended', 138).then(({ ok, data }) => ({ tokens: ok ? data : [] })),
routesApi.getRouteMatrix(),
plannerApi.getCapabilities(),
plannerApi.getInternalExecutionPlan(),
@@ -273,6 +275,7 @@ export default function LiquidityOperationsPage({
public route matrix, planner capabilities, and mission-control token pool inventory together
so integrators can inspect what Chain 138 is actually serving right now.
</p>
<TokenListSurfaceNote className="mt-3 text-sm text-gray-600 dark:text-gray-400" />
</div>
{loadingError ? (

View File

@@ -3,6 +3,7 @@ import Link from 'next/link'
import { Card } from '@/libs/frontend-ui-primitives'
import { explorerFeaturePages } from '@/data/explorerOperations'
import { configApi, type CapabilitiesResponse, type NetworksConfigResponse, type TokenListResponse } from '@/services/api/config'
import { tokensApi } from '@/services/api/tokens'
import { getMissionControlRelays, missionControlApi, type MissionControlBridgeStatusResponse } from '@/services/api/missionControl'
import { routesApi, type RouteMatrixResponse } from '@/services/api/routes'
import { useUiMode } from '@/components/common/UiModeContext'
@@ -10,6 +11,7 @@ import { summarizeChainActivity } from '@/utils/activityContext'
import ActivityContextPanel from '@/components/common/ActivityContextPanel'
import FreshnessTrustNote from '@/components/common/FreshnessTrustNote'
import SubsystemPosturePanel from '@/components/common/SubsystemPosturePanel'
import TokenListSurfaceNote from '@/components/common/TokenListSurfaceNote'
import { resolveEffectiveFreshness } from '@/utils/explorerFreshness'
import { statsApi, type ExplorerStats } from '@/services/api/stats'
@@ -88,7 +90,7 @@ export default function OperationsHubPage({
missionControlApi.getBridgeStatus(),
routesApi.getRouteMatrix(),
configApi.getNetworks(),
configApi.getTokenList(),
tokensApi.listForSurface('extended', 138).then(({ ok, data }) => ({ tokens: ok ? data : [] })),
configApi.getCapabilities(),
statsApi.get(),
])
@@ -248,6 +250,7 @@ export default function OperationsHubPage({
<div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
Chains · {(tokenList?.tokens || []).length} tokens across {tokenChainCoverage} networks
</div>
<TokenListSurfaceNote className="mt-2 text-xs text-gray-500 dark:text-gray-400" />
</Card>
<Card className="border border-gray-200 dark:border-gray-700">

View File

@@ -3,7 +3,9 @@
import { useEffect, useMemo, useState } from 'react'
import Link from 'next/link'
import { Card } from '@/libs/frontend-ui-primitives'
import { configApi, type TokenListResponse } from '@/services/api/config'
import { type TokenListResponse } from '@/services/api/config'
import { tokensApi } from '@/services/api/tokens'
import TokenListSurfaceNote from '@/components/common/TokenListSurfaceNote'
import {
aggregateLiquidityPools,
getRouteBackedPoolAddresses,
@@ -28,7 +30,7 @@ export default function PoolsOperationsPage() {
const load = async () => {
const [tokenListResult, routeMatrixResult] = await Promise.allSettled([
configApi.getTokenList(),
tokensApi.listForSurface('extended', 138).then(({ ok, data }) => ({ tokens: ok ? data : [] })),
routesApi.getRouteMatrix(),
])
@@ -100,6 +102,7 @@ export default function PoolsOperationsPage() {
This page now summarizes the live pool inventory discovered through mission-control token
pool endpoints and cross-checks it against the current route matrix.
</p>
<TokenListSurfaceNote className="mt-3 text-sm text-gray-600 dark:text-gray-400" />
</div>
{loadingError ? (

View File

@@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from 'react'
import { Card } from '@/libs/frontend-ui-primitives'
import { explorerFeaturePages } from '@/data/explorerOperations'
import { configApi, type CapabilitiesResponse, type NetworksConfigResponse, type TokenListResponse } from '@/services/api/config'
import { tokensApi } from '@/services/api/tokens'
import { getMissionControlRelays, missionControlApi, type MissionControlBridgeStatusResponse } from '@/services/api/missionControl'
import { routesApi, type RouteMatrixResponse } from '@/services/api/routes'
import { statsApi, type ExplorerStats } from '@/services/api/stats'
@@ -11,6 +12,7 @@ import OperationsPageShell, {
formatNumber,
relativeAge,
} from './OperationsPageShell'
import TokenListSurfaceNote from '@/components/common/TokenListSurfaceNote'
interface SystemOperationsPageProps {
initialBridgeStatus?: MissionControlBridgeStatusResponse | null
@@ -46,7 +48,7 @@ export default function SystemOperationsPage({
await Promise.allSettled([
missionControlApi.getBridgeStatus(),
configApi.getNetworks(),
configApi.getTokenList(),
tokensApi.listForSurface('extended', 138).then(({ ok, data }) => ({ tokens: ok ? data : [] })),
configApi.getCapabilities(),
routesApi.getRouteMatrix(),
statsApi.get(),
@@ -125,6 +127,7 @@ export default function SystemOperationsPage({
description={`${formatNumber(capabilities?.tracing?.supportedMethods?.length)} tracing methods published.`}
/>
</div>
<TokenListSurfaceNote className="mb-6 text-xs text-gray-500 dark:text-gray-400" />
<div className="mb-8 grid gap-6 lg:grid-cols-[1fr_1fr]">
<Card title="Topology Snapshot">

View File

@@ -32,6 +32,7 @@ import {
HOME_PRICE_FEED_REFRESH_MS,
resolveHomePriceFeedAddresses,
} from '@/utils/featuredTokens'
import { createVisibilityAwarePoller } from '@/utils/visibilityRefresh'
type HomeStats = ExplorerStats
@@ -180,14 +181,11 @@ export default function Home({
}, [chainId])
useEffect(() => {
loadDashboard()
const timer = window.setInterval(() => {
void loadDashboard()
}, HOME_DASHBOARD_REFRESH_MS)
return () => {
window.clearInterval(timer)
}
void loadDashboard()
return createVisibilityAwarePoller({
intervalMs: HOME_DASHBOARD_REFRESH_MS,
task: loadDashboard,
})
}, [loadDashboard])
useEffect(() => {
@@ -210,7 +208,6 @@ export default function Home({
useEffect(() => {
let cancelled = false
let timer: ReturnType<typeof setTimeout> | null = null
const refreshFeaturedPrices = async () => {
try {
@@ -221,20 +218,18 @@ export default function Home({
if (!cancelled && process.env.NODE_ENV !== 'production') {
console.warn('Failed to load featured token prices:', error)
}
} finally {
if (!cancelled) {
timer = setTimeout(() => {
void refreshFeaturedPrices()
}, HOME_PRICE_FEED_REFRESH_MS)
}
}
}
void refreshFeaturedPrices()
const stop = createVisibilityAwarePoller({
intervalMs: HOME_PRICE_FEED_REFRESH_MS,
task: refreshFeaturedPrices,
})
return () => {
cancelled = true
if (timer) clearTimeout(timer)
stop()
}
}, [loadFeaturedPrices])
@@ -307,6 +302,31 @@ export default function Home({
}
}, [])
useEffect(() => {
if (relayFeedState !== 'fallback') return
let cancelled = false
const refreshSnapshot = async () => {
try {
const status = await missionControlApi.getBridgeStatus()
if (!cancelled) {
setBridgeStatus(status)
setRelaySummary(summarizeMissionControlRelay(status))
}
} catch (error) {
if (!cancelled && process.env.NODE_ENV !== 'production') {
console.warn('Failed to refresh mission control snapshot:', error)
}
}
}
return createVisibilityAwarePoller({
intervalMs: HOME_DASHBOARD_REFRESH_MS,
task: refreshSnapshot,
})
}, [relayFeedState])
const relayToneClasses =
relaySummary?.tone === 'danger'
? 'border-red-200 bg-red-50 text-red-900 dark:border-red-900/60 dark:bg-red-950/40 dark:text-red-100'

View File

@@ -18,6 +18,7 @@ import {
type TransactionSummary,
} from '@/services/api/addresses'
import { WALLET_SNAPSHOT_REFRESH_MS } from '@/utils/featuredTokens'
import { createVisibilityAwarePoller } from '@/utils/visibilityRefresh'
import { formatRelativeAge, formatTokenAmount } from '@/utils/format'
import {
isWatchlistEntry,
@@ -146,8 +147,6 @@ export default function WalletPage(props: WalletPageProps) {
useEffect(() => {
let cancelled = false
let timer: ReturnType<typeof setTimeout> | null = null
if (!walletSession?.address) {
setAddressInfo(null)
setRecentAddressTransactions([])
@@ -170,20 +169,18 @@ export default function WalletPage(props: WalletPageProps) {
setTokenBalances([])
setTokenTransfers([])
}
} finally {
if (!cancelled) {
timer = setTimeout(() => {
void refreshSnapshot()
}, WALLET_SNAPSHOT_REFRESH_MS)
}
}
}
void refreshSnapshot()
const stop = createVisibilityAwarePoller({
intervalMs: WALLET_SNAPSHOT_REFRESH_MS,
task: refreshSnapshot,
})
return () => {
cancelled = true
if (timer) clearTimeout(timer)
stop()
}
}, [loadWalletSnapshot, walletSession?.address])