From e5f038c9db1c06f338f3fb45f5e6f53f907c27de Mon Sep 17 00:00:00 2001 From: defiQUG Date: Sat, 28 Mar 2026 15:15:23 -0700 Subject: [PATCH] Prune explorer dead ends and harden route smoke --- frontend/public/explorer-spa.js | 81 +++++++++++++++++----- frontend/public/index.html | 4 +- frontend/scripts/smoke-routes.mjs | 109 +++++++++++++++++++----------- 3 files changed, 137 insertions(+), 57 deletions(-) diff --git a/frontend/public/explorer-spa.js b/frontend/public/explorer-spa.js index df42310..2e4ffa0 100644 --- a/frontend/public/explorer-spa.js +++ b/frontend/public/explorer-spa.js @@ -2232,29 +2232,77 @@ } window._showAddresses = renderAddressesView; - // Analytics view (Track 3+) + function buildAnalyticsViewHtml() { + var html = ''; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '

Live Network Analytics

'; + html += '
Analytics surfaces are consolidated into the live explorer dashboards instead of a separate unfinished panel. Use this page as a hub to the active gas, block, bridge, and route monitoring views.
'; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += '
'; + html += '
Gas & Network
Open the live home dashboard for gas price, TPS, block time, validator count, and latest-chain activity.
'; + html += '
Block cadence
Inspect live block production, miner attribution, gas usage, and exportable block history.
'; + html += '
Transaction flow
Review the recent transaction stream and drill into decoded execution details and internal calls.
'; + html += '
Route coverage
Open the dedicated route-decision tree for swap-path coverage, bridge branches, and missing quote-token diagnostics.
'; + html += '
'; + html += '
'; + return html; + } + + // Analytics view function renderAnalyticsView() { - if (!hasAccess(3)) { - showToast('Analytics features require Track 3 access. Please connect your wallet and ensure you are approved.', 'error'); - return; - } - switchToView('analytics'); + showView('analytics'); + if ((window.location.pathname || '').replace(/^\//, '').split('/')[0] !== 'analytics') updatePath('/analytics'); + var container = document.getElementById('analyticsContent'); + if (!container) return; + container.innerHTML = buildAnalyticsViewHtml(); } window._showAnalytics = renderAnalyticsView; - // Operator view (Track 4) + function buildOperatorViewHtml() { + var html = ''; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '

Operator Access Hub

'; + html += '
The explorer does not expose raw privileged controls here. Instead, this page collects the live operator-facing observability and execution surfaces that are safe to browse from the public UI.
'; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += '
'; + html += '
Bridge monitoring
Inspect bridge balances, fee-token posture, destination configuration, and live contract references.
'; + html += '
Liquidity access
Jump to partner payload routes, ingestion APIs, and public execution-plan endpoints without leaving the explorer.
'; + html += '
Pool inventory
Review canonical PMM addresses, funding state, registry status, and exportable pool snapshots.
'; + html += '
WETH utilities
Open the WETH9/WETH10 utilities, bridge contract references, and balance tools that operators often need during support.
'; + html += '
'; + html += '
'; + return html; + } + + // Operator view function renderOperatorView() { - if (!hasAccess(4)) { - showToast('Operator features require Track 4 access. Please connect your wallet and ensure you are approved.', 'error'); - return; - } - switchToView('operator'); + showView('operator'); + if ((window.location.pathname || '').replace(/^\//, '').split('/')[0] !== 'operator') updatePath('/operator'); + var container = document.getElementById('operatorContent'); + if (!container) return; + container.innerHTML = buildOperatorViewHtml(); } window._showOperator = renderOperatorView; function showView(viewName) { currentView = viewName; - var detailViews = ['blockDetail','transactionDetail','addressDetail','tokenDetail','nftDetail','watchlist','searchResults','tokens','addresses','pools','liquidity','more']; + var detailViews = ['blockDetail','transactionDetail','addressDetail','tokenDetail','nftDetail','watchlist','searchResults','tokens','addresses','pools','routes','liquidity','more','analytics','operator']; if (detailViews.indexOf(viewName) === -1) currentDetailKey = ''; document.querySelectorAll('.detail-view').forEach(v => v.classList.remove('active')); const homeView = document.getElementById('homeView'); @@ -3995,9 +4043,9 @@ key: 'explore', title: 'Explore', items: [ - { title: 'Gas Tracker', icon: 'fa-gas-pump', status: 'Live', badgeClass: 'badge-success', desc: 'Review live gas, block time, TPS, and chain health from the analytics and home dashboards.', action: 'showAnalytics();', href: '/analytics' }, + { title: 'Gas Tracker', icon: 'fa-gas-pump', status: 'Live', badgeClass: 'badge-success', desc: 'Review live gas, block time, TPS, and chain health from the home network dashboard.', action: 'showHome();', href: '/' }, { title: 'DEX Tracker', icon: 'fa-chart-line', status: 'Live', badgeClass: 'badge-success', desc: 'Open liquidity discovery, PMM pool status, live route trees, and partner payload access points.', action: 'showRoutes();', href: '/routes' }, - { title: 'Node Tracker', icon: 'fa-server', status: 'Live', badgeClass: 'badge-success', desc: 'Inspect bridge and operator infrastructure surfaces already exposed in the Bridge and Operator panels.', action: 'showOperator();', href: '/operator' }, + { title: 'Node Tracker', icon: 'fa-server', status: 'Live', badgeClass: 'badge-success', desc: 'Inspect bridge balances, destination configuration, and operator-facing chain references from the live bridge monitoring panel.', action: 'showBridgeMonitoring();', href: '/bridge' }, { title: 'Label Cloud', icon: 'fa-tags', status: 'Live', badgeClass: 'badge-success', desc: 'Browse labeled addresses, contracts, and address activity through the explorer address index.', action: 'showAddresses();', href: '/addresses' }, { title: 'Domain Name Lookup', icon: 'fa-magnifying-glass', status: 'Live', badgeClass: 'badge-success', desc: 'Use the smart search launcher to resolve ENS-style names, domains, addresses, hashes, and token symbols.', action: 'openSmartSearchModal(\'\');', href: '/more' } ] @@ -4010,7 +4058,7 @@ { title: 'Verified Signature', icon: 'fa-signature', status: 'Live', badgeClass: 'badge-success', desc: 'Use wallet sign-in and verified address flows already built into the explorer authentication surfaces.', action: 'showWalletModal();', href: '/more' }, { title: 'Input Data Messages', icon: 'fa-message', status: 'Live', badgeClass: 'badge-info', desc: 'Transaction detail pages already surface decoded input data, event logs, and contract interaction context.', action: 'showTransactionsList();', href: '/transactions' }, { title: 'Advanced Filter', icon: 'fa-filter', status: 'Live', badgeClass: 'badge-success', desc: 'Block, transaction, address, token, pool, bridge, and watchlist screens all support focused page-level filtering.', action: 'showTransactionsList();', href: '/transactions' }, - { title: 'Blockscan Chat', icon: 'fa-comments', status: 'Soon', badgeClass: 'badge-muted', desc: 'Messaging and collaborative address discussion are not exposed yet in SolaceScanScout.', disabled: true, href: '/more' } + { title: 'MetaMask Snap', icon: 'fa-wallet', status: 'Live', badgeClass: 'badge-success', desc: 'Open the Chain 138 MetaMask Snap companion for network setup, token list access, and wallet integration guidance.', action: 'window.location.href=\'/snap/\';', href: '/snap/' } ] } ]; @@ -4022,6 +4070,7 @@ html += '
'; html += '
Now live
Route matrix, ingestion APIs, smart search, pool exports, and live Mainnet stable bridge discovery.
'; html += '
Good entry points
'; + html += ''; html += ''; html += ''; html += ''; diff --git a/frontend/public/index.html b/frontend/public/index.html index 187ecff..372417a 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -1540,7 +1540,7 @@

Analytics Dashboard

-

Analytics dashboard (Track 3). Network stats, flow tracking, and bridge analytics coming soon.

+
Loading analytics access...
@@ -1552,7 +1552,7 @@

Operator Panel

-

Operator panel (Track 4). Configuration and operational controls coming soon.

+
Loading operator access...
diff --git a/frontend/scripts/smoke-routes.mjs b/frontend/scripts/smoke-routes.mjs index b9fd351..7370017 100644 --- a/frontend/scripts/smoke-routes.mjs +++ b/frontend/scripts/smoke-routes.mjs @@ -1,65 +1,96 @@ -const baseUrl = (process.env.BASE_URL || 'http://127.0.0.1:3000').replace(/\/$/, '') +import { chromium } from 'playwright'; + +const baseUrl = (process.env.BASE_URL || 'https://explorer.d-bis.org').replace(/\/$/, ''); const checks = [ - { path: '/', expect: ['/addresses', '/transactions', '/watchlist', '/pools'] }, - { path: '/blocks', expect: ['Latest Blocks', 'View blockchain blocks', 'Blocks'] }, - { path: '/transactions', expect: ['Latest Transactions', 'Recent Transactions', 'Transactions'] }, - { path: '/addresses', expect: ['Open An Address', 'Recently Active Addresses', 'Saved Watchlist'] }, - { path: '/tokens', expect: ['Find A Token', 'Common token searches', 'Tokens'] }, - { path: '/pools', expect: ['Canonical PMM routes', 'Pool operation shortcuts', 'Pools'] }, - { path: '/routes', expect: ['Live Route Decision Tree', 'Coverage sweep + priority route cards', 'Routes'] }, - { path: '/watchlist', expect: ['Saved Addresses', 'Watchlist', 'Export JSON'] }, - { path: '/search?q=cUSDT', expect: ['Search Results', 'Results for', 'Search'] }, - { path: '/blocks/1', expect: ['Loading block details', 'Block Details'] }, + { path: '/', homeVisible: true, expectTexts: ['Gas & Network', 'Latest Blocks', 'Latest Transactions'] }, + { path: '/blocks', activeView: 'blocksView', expectTexts: ['All Blocks'] }, + { path: '/transactions', activeView: 'transactionsView', expectTexts: ['All Transactions'] }, + { path: '/addresses', activeView: 'addressesView', expectTexts: ['All Addresses'] }, + { path: '/tokens', activeView: 'tokensView', expectTexts: ['Tokens'] }, + { path: '/pools', activeView: 'poolsView', expectTexts: ['Pools', 'Canonical PMM routes'] }, + { path: '/routes', activeView: 'routesView', expectTexts: ['Routes', 'Live Route Decision Tree'] }, + { path: '/watchlist', activeView: 'watchlistView', expectTexts: ['Watchlist'] }, + { path: '/bridge', activeView: 'bridgeView', expectTexts: ['Bridge Monitoring'] }, + { path: '/weth', activeView: 'wethView', expectTexts: ['WETH', 'Wrap ETH to WETH9'] }, + { path: '/liquidity', activeView: 'liquidityView', expectTexts: ['Liquidity Access', 'Public Explorer Access Points'] }, + { path: '/more', activeView: 'moreView', expectTexts: ['More', 'Tools & Services'] }, + { path: '/analytics', activeView: 'analyticsView', expectTexts: ['Analytics Dashboard', 'Live Network Analytics'] }, + { path: '/operator', activeView: 'operatorView', expectTexts: ['Operator Panel', 'Operator Access Hub'] }, + { path: '/block/1', activeView: 'blockDetailView', expectTexts: ['Block Details'] }, { - path: '/transactions/0x0000000000000000000000000000000000000000000000000000000000000000', - expect: ['Loading transaction details', 'Transaction Details', 'Transaction not found'], + path: '/tx/0x0000000000000000000000000000000000000000000000000000000000000000', + activeView: 'transactionDetailView', + expectTexts: ['Transaction Details', 'Transaction not found'], }, { - path: '/addresses/0x0000000000000000000000000000000000000000', - expect: ['Loading address details', 'Address Details', 'Open An Address'], + path: '/address/0x93E66202A11B1772E55407B32B44e5Cd8eda7f22', + activeView: 'addressDetailView', + expectTexts: ['Address Details', 'Address'], }, -] +]; -function hasExpectedBody(text, expectedSnippets) { - return expectedSnippets.some((snippet) => text.includes(snippet)) +function hasExpectedText(text, snippets) { + return snippets.some((snippet) => text.includes(snippet)); } -async function run() { - let failures = 0 +async function main() { + const browser = await chromium.launch({ headless: true }); + const page = await browser.newPage(); + let failures = 0; for (const check of checks) { - const url = `${baseUrl}${check.path}` + const url = `${baseUrl}${check.path}`; try { - const response = await fetch(url, { redirect: 'follow' }) - const body = await response.text() - - if (!response.ok) { - console.error(`FAIL ${check.path}: HTTP ${response.status}`) - failures += 1 - continue + const response = await page.goto(url, { waitUntil: 'networkidle' }); + if (!response || !response.ok()) { + console.error(`FAIL ${check.path}: HTTP ${response ? response.status() : 'no-response'}`); + failures += 1; + continue; } - if (!hasExpectedBody(body, check.expect)) { - console.error(`FAIL ${check.path}: expected one of ${check.expect.join(' | ')}`) - failures += 1 - continue + const bodyText = await page.textContent('body'); + if (check.homeVisible) { + const homeVisible = await page.$eval('#homeView', (el) => getComputedStyle(el).display !== 'none').catch(() => false); + if (!homeVisible) { + console.error(`FAIL ${check.path}: home view not visible`); + failures += 1; + continue; + } + } else { + const activeView = await page.$eval('.detail-view.active', (el) => el.id).catch(() => null); + if (activeView !== check.activeView) { + console.error(`FAIL ${check.path}: expected active view ${check.activeView}, got ${activeView}`); + failures += 1; + continue; + } } - console.log(`OK ${check.path}`) + if (!hasExpectedText(bodyText || '', check.expectTexts)) { + console.error(`FAIL ${check.path}: expected one of ${check.expectTexts.join(' | ')}`); + failures += 1; + continue; + } + + console.log(`OK ${check.path}`); } catch (error) { - console.error(`FAIL ${check.path}: ${error instanceof Error ? error.message : String(error)}`) - failures += 1 + console.error(`FAIL ${check.path}: ${error instanceof Error ? error.message : String(error)}`); + failures += 1; } } + await browser.close(); + if (failures > 0) { - process.exitCode = 1 - return + process.exitCode = 1; + return; } - console.log(`All ${checks.length} route checks passed for ${baseUrl}`) + console.log(`All ${checks.length} route checks passed for ${baseUrl}`); } -run() +main().catch((error) => { + console.error(error instanceof Error ? error.stack || error.message : String(error)); + process.exitCode = 1; +});