diff --git a/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json b/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json index deb34f8..48e71cb 100644 --- a/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json +++ b/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json @@ -1666,8 +1666,23 @@ "tags": [ "gru", "compliant", - "electronic-money" - ] + "electronic-money", + "fiat", + "cash" + ], + "extensions": { + "assetClass": "Cash & Equivalents", + "assetGroup": "MMF / Repo", + "instrumentType": "eMoney", + "underlying": "USD", + "gruLayer": "M1", + "rwaEligible": false, + "category": "gru-emoney", + "currency": "USD", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents" + } }, { "chainId": 138, @@ -1679,8 +1694,23 @@ "tags": [ "gru", "compliant", - "treasury-bond" - ] + "treasury-bond", + "fiat", + "cash" + ], + "extensions": { + "assetClass": "Cash & Equivalents", + "assetGroup": "MMF / Repo", + "instrumentType": "eMoney", + "underlying": "USD", + "gruLayer": "M1", + "rwaEligible": false, + "category": "gru-emoney", + "currency": "USD", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents" + } }, { "chainId": 138, @@ -1691,12 +1721,19 @@ "logoURI": "https://explorer.d-bis.org/token-icons/cXAUC.png", "tags": [ "gru", - "compliant", - "commodity" + "compliant" ], "extensions": { "unitOfAccount": "troy_ounce", - "unitDescription": "1 full token (10^decimals base units) = 1 troy oz fine gold" + "unitDescription": "1 full token (10^decimals base units) = 1 troy oz fine gold", + "assetClass": "Commodities", + "assetGroup": "Precious Metals", + "instrumentType": "eMoney", + "underlying": "Gold", + "gruLayer": "M1", + "rwaEligible": false, + "category": "gru-emoney", + "cashLike": false } }, { @@ -1708,12 +1745,19 @@ "logoURI": "https://explorer.d-bis.org/token-icons/cXAUT.png", "tags": [ "gru", - "compliant", - "commodity" + "compliant" ], "extensions": { "unitOfAccount": "troy_ounce", - "unitDescription": "1 full token (10^decimals base units) = 1 troy oz fine gold" + "unitDescription": "1 full token (10^decimals base units) = 1 troy oz fine gold", + "assetClass": "Commodities", + "assetGroup": "Precious Metals", + "instrumentType": "eMoney", + "underlying": "Gold", + "gruLayer": "M1", + "rwaEligible": false, + "category": "gru-emoney", + "cashLike": false } }, { diff --git a/config/explorer-bridge-proof-transfers.example.json b/config/explorer-bridge-proof-transfers.example.json new file mode 100644 index 0000000..05b238e --- /dev/null +++ b/config/explorer-bridge-proof-transfers.example.json @@ -0,0 +1,21 @@ +{ + "updated": "2026-05-23T13:07:00Z", + "sprint": "tier-a-week-3", + "note": "Example shape for MISSION_CONTROL_PROOF_TRANSFERS_JSON. Operator live file: reports/status/bridge-lane-proof-transfers-latest.json (gitignored). Populate with scripts/bridge/run-lane-proof-transfers.sh --execute.", + "lanes": { + "chain138": [ + { + "tx_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "amount_eth": "0.001", + "dest_chain": "mainnet", + "dest_selector": "5009297550715157269", + "bridge": "0xcacfd227A040002e49e2e01626363071324f820a", + "recorded_at": "2026-05-23T00:00:00Z" + } + ], + "gnosis": [], + "cronos": [], + "celo": [], + "wemix": [] + } +} diff --git a/frontend/src/components/explorer/OperationsHubPage.tsx b/frontend/src/components/explorer/OperationsHubPage.tsx index 7a2899d..8bbf96b 100644 --- a/frontend/src/components/explorer/OperationsHubPage.tsx +++ b/frontend/src/components/explorer/OperationsHubPage.tsx @@ -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({
{relayCount} managed lanes · queue {totalQueue}
+ {laneSummary ? ( +
+ {laneSummary.funded}/{laneSummary.total} config-ready funded + {laneSummary.unfunded > 0 ? ` · ${laneSummary.unfunded} unfunded` : ''} + {' · '} + {laneSummary.proofRecorded}/{laneSummary.total} proof-recorded +
+ ) : null} @@ -312,6 +340,23 @@ export default function OperationsHubPage({ + {laneSummary ? ( +
+
Config-ready lanes
+
+ {laneSummary.funded}/{laneSummary.total} funded · {laneSummary.proofRecorded}/{laneSummary.total} proof-recorded +
+
+ {mode === 'guided' + ? 'Remote CCIP bridge LINK balances and operator proof hashes. Full lane table below.' + : 'Lane funding and proof posture from bridge status API.'} + {' '} + + Open bridge monitoring + +
+
+ ) : null}
@@ -342,6 +387,8 @@ export default function OperationsHubPage({ + + ) diff --git a/scripts/deploy-explorer-ai-to-vmid5000.sh b/scripts/deploy-explorer-ai-to-vmid5000.sh old mode 100644 new mode 100755 diff --git a/scripts/e2e-sprint-smoke.spec.ts b/scripts/e2e-sprint-smoke.spec.ts index 9c9adce..278afec 100644 --- a/scripts/e2e-sprint-smoke.spec.ts +++ b/scripts/e2e-sprint-smoke.spec.ts @@ -37,6 +37,8 @@ test.describe('Explorer sprint smoke', () => { await page.goto(`${EXPLORER_URL}/operations`, { waitUntil: 'networkidle', timeout: 30000 }) await expect(page.getByRole('heading', { name: /Operations hub/i })).toBeVisible({ timeout: 10000 }) await expect(page.getByText(/Extended Metamask dual-chain catalog/i).first()).toBeVisible({ timeout: 10000 }) + await expect(page.getByText(/Config-ready lane health/i).first()).toBeVisible({ timeout: 15000 }) + await expect(page.getByText(/unfunded|funded/i).first()).toBeVisible({ timeout: 10000 }) }) test('bridge page loads CCIP route catalog', async ({ page }) => {