Files
defiQUG d4f922c26e
Some checks failed
Deploy Explorer Live / deploy (push) Failing after 12s
chore: metamask networks, explorer SPA, nginx scripts; ignore Python cache
- Dual-chain / GRU deployment JSON sync
- Frontend explorer SPA + MetaMask components
- Scripts: nginx fixes, link deploy, local SPA serve helper
- Token icon chain-138.png; .gitignore __pycache__

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 13:00:43 -07:00

1965 lines
101 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<!-- CSP: unsafe-eval required by ethers.js v5 UMD from CDN (uses new Function for ABI). Our code avoids eval/string setTimeout. Can be removed when moving to ethers v6 build (no UMD eval). -->
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self' data: https:; connect-src 'self' https://blockscout.defi-oracle.io https://explorer.d-bis.org https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org http://192.168.11.221:8545 ws://192.168.11.221:8546;">
<title>DBIS Explorer | Chain 138 Explorer by DBIS</title>
<meta name="description" content="DBIS Explorer - Chain 138 Explorer by DBIS. Public explorer surfaces for blocks, transactions, addresses, routes, wallet tools, and bridge monitoring.">
<meta name="keywords" content="blockchain explorer, ChainID 138, DBIS, DBIS Explorer, bridge monitoring, wallet tools, blockchain, ethereum, blockscout">
<meta name="author" content="DBIS Explorer">
<meta name="application-name" content="DBIS Explorer">
<meta name="theme-color" content="#667eea">
<script>
(function(){function t(){var e=document.getElementById('navLinks'),n=document.getElementById('navToggle'),r=document.getElementById('navToggleIcon');if(e&&n){var o=e.classList.toggle('nav-open');n.setAttribute('aria-expanded',o?'true':'false');if(r)r.className=o?'fas fa-times':'fas fa-bars';}}function c(){var e=document.getElementById('navLinks'),n=document.getElementById('navToggle'),r=document.getElementById('navToggleIcon');if(e)e.classList.remove('nav-open');if(n)n.setAttribute('aria-expanded','false');if(r)r.className='fas fa-bars';}window.toggleNavMenu=t;window.closeNavMenu=c;})();
</script>
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://blockscout.defi-oracle.io/">
<meta property="og:title" content="DBIS Explorer - Chain 138 Explorer by DBIS">
<meta property="og:description" content="Comprehensive blockchain explorer for ChainID 138 with cross-chain bridge monitoring and WETH utilities.">
<meta property="og:image" content="https://blockscout.defi-oracle.io/og-image.png">
<meta property="og:site_name" content="DBIS Explorer">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="https://blockscout.defi-oracle.io/">
<meta name="twitter:title" content="DBIS Explorer - Chain 138 Explorer by DBIS">
<meta name="twitter:description" content="Comprehensive blockchain explorer for ChainID 138 with cross-chain bridge monitoring and WETH utilities.">
<meta name="twitter:image" content="https://blockscout.defi-oracle.io/og-image.png">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Load ethers.js with multiple fallback CDNs -->
<script>
(function() {
var ethersLoaded = false;
var cdnIndex = 0;
var cdns = [
'https://cdn.jsdelivr.net/npm/ethers@5.7.2/dist/ethers.umd.min.js',
'https://unpkg.com/ethers@5.7.2/dist/ethers.umd.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/ethers/5.7.2/ethers.umd.min.js'
];
function loadEthers() {
if (ethersLoaded || typeof ethers !== 'undefined') {
window.ethersReady = true;
console.log('✅ Ethers.js library loaded successfully');
window.dispatchEvent(new Event('ethersReady'));
return;
}
if (cdnIndex >= cdns.length) {
console.error('❌ All ethers.js CDNs failed to load');
// Try one more time with a different approach
setTimeout(function() {
if (typeof ethers === 'undefined') {
console.error('Ethers.js failed to load from all sources');
} else {
window.ethersReady = true;
window.dispatchEvent(new Event('ethersReady'));
}
}, 1000);
return;
}
var script = document.createElement('script');
script.src = cdns[cdnIndex];
script.async = false; // Load synchronously to ensure it's available
script.onload = function() {
// Double check after load
setTimeout(function() {
if (typeof ethers !== 'undefined') {
ethersLoaded = true;
window.ethersReady = true;
console.log('✅ Ethers.js loaded from:', cdns[cdnIndex]);
window.dispatchEvent(new Event('ethersReady'));
} else {
console.warn('Script loaded but ethers not defined, trying next CDN...');
cdnIndex++;
loadEthers();
}
}, 100);
};
script.onerror = function() {
console.warn('Failed to load from:', cdns[cdnIndex]);
cdnIndex++;
loadEthers();
};
document.head.appendChild(script);
}
// Start loading immediately
loadEthers();
// Also check periodically in case it loads via another method
var checkInterval = setInterval(function() {
if (typeof ethers !== 'undefined' && !ethersLoaded) {
clearInterval(checkInterval);
ethersLoaded = true;
window.ethersReady = true;
console.log('✅ Ethers.js detected');
window.dispatchEvent(new Event('ethersReady'));
}
}, 100);
// Clear interval after 20 seconds
setTimeout(function() {
clearInterval(checkInterval);
}, 20000);
})();
</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--primary: #667eea;
--secondary: #764ba2;
--success: #10b981;
--warning: #f59e0b;
--danger: #ef4444;
--bridge-blue: #3b82f6;
--dark: #1f2937;
--light: #f9fafb;
--card-bg: #ffffff;
--muted-surface: rgba(15, 23, 42, 0.04);
--muted-surface-strong: rgba(15, 23, 42, 0.08);
--border: #e5e7eb;
--text: #111827;
--text-light: #6b7280;
}
body.dark-theme {
--light: #111827;
--card-bg: #1e293b;
--muted-surface: rgba(148, 163, 184, 0.08);
--muted-surface-strong: rgba(148, 163, 184, 0.14);
--border: #374151;
--text: #f9fafb;
--text-light: #9ca3af;
background: #0f172a;
color: var(--text);
}
body.dark-theme .stat-card,
body.dark-theme .card,
body.dark-theme .block-card {
background: #1e293b;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
body.dark-theme .table th { background: #334155; color: var(--text); }
body.dark-theme .table tr:hover { background: #1e293b; }
body.dark-theme .skeleton { background: linear-gradient(90deg, #334155 25%, #475569 50%, #334155 75%); }
body.explorer-compact-table-rows .table tbody td,
body.explorer-compact-table-rows .table tbody th {
padding: 0.35rem 0.5rem;
font-size: 0.85rem;
}
body.explorer-compact-table-rows .table thead th {
padding: 0.45rem 0.55rem;
font-size: 0.82rem;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: var(--light);
color: var(--text);
line-height: 1.6;
}
.navbar {
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
color: white;
padding: 0.85rem 2rem;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 1000;
}
.nav-container {
max-width: 1400px;
margin: 0 auto;
display: flex;
gap: 1rem;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.45rem 0.7rem;
border-radius: 14px;
transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
text-decoration: none;
color: inherit;
}
.logo:hover,
.logo:focus-visible {
background: rgba(255,255,255,0.12);
transform: translateY(-1px);
box-shadow: 0 8px 20px rgba(0,0,0,0.08);
outline: none;
}
.logo i {
width: 1.2rem;
text-align: center;
}
.nav-links {
display: flex;
gap: 0.5rem;
list-style: none;
align-items: center;
}
.nav-links > li { position: relative; }
.nav-links a, .nav-dropdown-trigger {
color: white;
text-decoration: none;
transition: opacity 0.2s, background 0.2s;
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.45rem 0.7rem;
border-radius: 999px;
}
.nav-links a:hover, .nav-dropdown-trigger:hover { opacity: 1; background: rgba(255,255,255,0.12); }
.nav-dropdown-trigger {
background: none;
border: none;
cursor: pointer;
font: inherit;
padding: 0.45rem 0.7rem;
}
.nav-dropdown-trigger i.fa-chevron-down {
font-size: 0.7rem;
transition: transform 0.2s;
}
.nav-dropdown.open .nav-dropdown-trigger i.fa-chevron-down { transform: rotate(180deg); }
.nav-dropdown-menu {
position: absolute;
top: 100%;
left: 0;
min-width: 200px;
background: rgba(30, 41, 59, 0.98);
border-radius: 8px;
box-shadow: 0 10px 40px rgba(0,0,0,0.25);
padding: 0.5rem 0;
list-style: none;
opacity: 0;
visibility: hidden;
transform: translateY(-6px);
transition: opacity 0.2s, transform 0.2s, visibility 0.2s;
z-index: 1001;
margin-top: 0.25rem;
}
.nav-dropdown.open .nav-dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.nav-dropdown-menu a {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.6rem 1rem;
color: rgba(255,255,255,0.95);
white-space: nowrap;
}
.nav-dropdown-menu a:hover {
background: rgba(255,255,255,0.1);
opacity: 1;
}
.nav-dropdown-menu li { margin: 0; }
.nav-dropdown-menu li.user-menu-meta {
padding: 0.55rem 1rem 0.65rem;
font-size: 0.8rem;
color: rgba(255,255,255,0.72);
border-bottom: 1px solid rgba(255,255,255,0.12);
margin-bottom: 0.15rem;
}
.nav-links a:focus-visible,
.nav-dropdown-trigger:focus-visible,
.nav-actions button:focus-visible,
.nav-actions select:focus-visible {
outline: 2px solid rgba(255,255,255,0.95);
outline-offset: 2px;
}
body.dark-theme .nav-links a:focus-visible,
body.dark-theme .nav-dropdown-trigger:focus-visible {
outline-color: #fbbf24;
}
.nav-actions {
flex-wrap: wrap;
justify-content: flex-end;
}
@media (max-width: 1100px) {
.nav-actions #walletConnect { width: 100%; justify-content: flex-end; margin-top: 0.35rem; }
}
.search-box {
flex: 1;
max-width: 560px;
margin: 0 1.25rem;
}
.search-box .btn {
flex-shrink: 0;
}
.search-box .btn,
.search-box .search-hint {
white-space: nowrap;
}
.search-box .search-label {
display: inline;
}
.nav-actions {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
justify-content: flex-end;
}
.search-input {
width: 100%;
padding: 0.75rem 1rem;
border: none;
border-radius: 8px;
font-size: 1rem;
background: rgba(255,255,255,0.2);
color: white;
backdrop-filter: blur(10px);
}
.search-input::placeholder { color: rgba(255,255,255,0.7); }
.search-input:focus {
outline: none;
background: rgba(255,255,255,0.3);
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
margin-bottom: 1rem;
}
.stat-card {
background: white;
padding: 1rem;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
/* Block animation */
@keyframes blockPulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.02); opacity: 0.95; }
}
@keyframes slideInFromTop {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.table tbody tr {
animation: slideInFromTop 0.3s ease-out;
}
.table tbody tr.new-block {
animation: blockPulse 1s ease-in-out;
background: rgba(74, 144, 226, 0.05);
}
.table tbody tr.new-transaction {
animation: slideInFromTop 0.5s ease-out;
background: rgba(74, 144, 226, 0.05);
}
/* Horizontal scrolling blocks */
.blocks-scroll-container {
display: flex;
overflow-x: hidden;
overflow-y: hidden;
gap: 1rem;
padding: 0.5rem 0;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
position: relative;
width: 100%;
}
.blocks-scroll-container::-webkit-scrollbar {
display: none;
}
.blocks-scroll-content {
display: flex;
gap: 1rem;
will-change: transform;
}
.blocks-scroll-container::-webkit-scrollbar {
height: 8px;
}
.blocks-scroll-container::-webkit-scrollbar-track {
background: var(--light);
border-radius: 4px;
}
.blocks-scroll-container::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 4px;
}
.blocks-scroll-container::-webkit-scrollbar-thumb:hover {
background: var(--primary-dark);
}
.block-card {
min-width: 200px;
max-width: 200px;
background: white;
border-radius: 8px;
padding: 1rem;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
border: 2px solid transparent;
flex-shrink: 0;
}
.block-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
border-color: var(--primary);
}
.block-card.new-block {
animation: blockPulse 1s ease-in-out;
border-color: var(--primary);
background: rgba(74, 144, 226, 0.05);
}
.block-number {
font-size: 1.25rem;
font-weight: bold;
color: var(--primary);
margin-bottom: 0.5rem;
}
.block-hash {
font-size: 0.75rem;
color: var(--text-light);
font-family: monospace;
margin-bottom: 0.5rem;
word-break: break-all;
}
.block-info {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.875rem;
}
.block-info-item {
display: flex;
justify-content: space-between;
color: var(--text);
}
.block-info-label {
color: var(--text-light);
font-size: 0.75rem;
}
.block-info-value {
font-weight: 600;
color: var(--text);
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.stat-card.bridge-card {
border-left: 4px solid var(--bridge-blue);
}
.stat-label {
color: var(--text-light);
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 0.5rem;
}
.stat-value {
font-size: 2rem;
font-weight: bold;
color: var(--primary);
}
.stat-value.bridge-value {
color: var(--bridge-blue);
}
.card {
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 1.25rem;
margin-bottom: 1rem;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
padding-bottom: 0.75rem;
border-bottom: 2px solid var(--border);
}
.card-title {
font-size: 1.5rem;
font-weight: bold;
color: var(--text);
}
.tabs {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
border-bottom: 2px solid var(--border);
flex-wrap: wrap;
}
.tab {
padding: 1rem 1.5rem;
background: none;
border: none;
cursor: pointer;
font-size: 1rem;
color: var(--text-light);
border-bottom: 3px solid transparent;
transition: all 0.2s;
}
.tab.active {
color: var(--primary);
border-bottom-color: var(--primary);
font-weight: 600;
}
.bridge-tab.active {
color: var(--bridge-blue);
border-bottom-color: var(--bridge-blue);
}
.weth-tab.active {
color: var(--success);
border-bottom-color: var(--success);
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th {
text-align: left;
padding: 0.5rem 0.75rem;
background: var(--light);
font-weight: 600;
color: var(--text);
border-bottom: 2px solid var(--border);
font-size: 0.875rem;
}
.table td {
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--border);
font-size: 0.875rem;
}
.table tr:hover { background: var(--light); }
.hash {
font-family: 'Courier New', monospace;
font-size: 0.875rem;
color: var(--primary);
word-break: break-all;
}
.hash:hover { text-decoration: underline; cursor: pointer; }
.badge {
display: inline-block;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 600;
}
.badge-success { background: #d1fae5; color: var(--success); }
.badge-warning { background: #fef3c7; color: var(--warning); }
.badge-danger { background: #fee2e2; color: var(--danger); }
.badge-chain {
background: #dbeafe;
color: var(--bridge-blue);
}
.loading {
text-align: center;
padding: 3rem;
color: var(--text-light);
}
.loading i {
font-size: 2rem;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Skeleton Loaders */
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s ease-in-out infinite;
border-radius: 4px;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.skeleton-text {
height: 1em;
margin: 0.5rem 0;
}
.skeleton-title {
height: 1.5em;
width: 60%;
margin-bottom: 1rem;
}
.skeleton-table-row {
height: 3rem;
margin: 0.5rem 0;
}
/* Breadcrumb Navigation */
.breadcrumb {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 1rem 0;
margin-bottom: 1rem;
font-size: 0.9rem;
}
.breadcrumb a {
color: var(--primary);
text-decoration: none;
transition: opacity 0.2s;
}
.breadcrumb a:hover {
opacity: 0.7;
}
.breadcrumb-separator {
color: var(--text-light);
}
.breadcrumb-current {
color: var(--text);
font-weight: 600;
}
.error {
background: #fee2e2;
color: var(--danger);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
.success {
background: #d1fae5;
color: var(--success);
padding: 1rem;
border-radius: 8px;
margin: 1rem 0;
}
.bridge-chain-card {
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
padding: 1.5rem;
border-radius: 12px;
margin-bottom: 1rem;
}
.weth-card {
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
padding: 1.5rem;
border-radius: 12px;
margin-bottom: 1.5rem;
}
.weth-form {
background: white;
padding: 1.5rem;
border-radius: 8px;
margin-top: 1rem;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: var(--text);
}
.form-input {
width: 100%;
padding: 0.75rem;
border: 2px solid var(--border);
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.2s;
}
.form-input:focus {
outline: none;
border-color: var(--primary);
}
.form-input-group {
display: flex;
gap: 0.5rem;
}
.form-input-group .form-input {
flex: 1;
}
.btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
transition: all 0.2s;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background: var(--primary);
color: white;
}
.btn-primary:hover { background: var(--secondary); }
.btn-bridge {
background: var(--bridge-blue);
color: white;
}
.btn-bridge:hover { background: #2563eb; }
.btn-success {
background: var(--success);
color: white;
}
.btn-success:hover { background: #059669; }
.btn-warning {
background: var(--warning);
color: white;
}
.btn-warning:hover { background: #d97706; }
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-add-token-wallet {
padding: 0.35rem 0.5rem;
margin-left: 0.35rem;
border: none;
border-radius: 6px;
background: var(--primary);
color: white;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
transition: background 0.2s;
}
.btn-add-token-wallet:hover {
background: var(--secondary);
}
.btn-add-token-wallet:focus {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
.btn-add-token-wallet-prominent {
padding: 0.6rem 1rem;
font-size: 1rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.balance-display {
background: var(--light);
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
}
.balance-row {
display: flex;
justify-content: space-between;
padding: 0.5rem 0;
border-bottom: 1px solid var(--border);
}
.balance-row:last-child {
border-bottom: none;
}
.balance-label {
color: var(--text-light);
}
.balance-value {
font-weight: bold;
color: var(--text);
}
.chain-name {
font-size: 1.25rem;
font-weight: bold;
color: var(--bridge-blue);
margin-bottom: 0.5rem;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.chain-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-top: 1rem;
}
.chain-stat {
font-size: 0.875rem;
}
.chain-stat-label {
color: var(--text-light);
}
.chain-stat-value {
font-weight: bold;
color: var(--text);
margin-top: 0.25rem;
}
.detail-view {
display: none;
}
.detail-view.active { display: block; }
.info-row {
display: flex;
padding: 1rem;
border-bottom: 1px solid var(--border);
}
.info-label {
font-weight: 600;
min-width: 200px;
color: var(--text-light);
}
.info-value {
flex: 1;
word-break: break-all;
}
.metamask-status {
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.metamask-status.connected {
background: #d1fae5;
color: var(--success);
}
.metamask-status.disconnected {
background: #fee2e2;
color: var(--danger);
}
.nav-toggle { display: none; background: none; border: none; color: white; padding: 0.5rem; cursor: pointer; font-size: 1.5rem; }
.nav-toggle:focus { outline: 2px solid rgba(255,255,255,0.5); }
@media (max-width: 900px) {
.nav-toggle { display: block; }
.nav-links { display: none; flex-direction: column; align-items: stretch; position: absolute; top: 100%; left: 0; right: 0; background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%); padding: 1rem; gap: 0; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 999; }
.nav-links.nav-open { display: flex; }
.nav-container { position: relative; flex-wrap: wrap; }
.nav-dropdown { position: static; }
.nav-dropdown-menu { position: static; opacity: 1; visibility: visible; transform: none; background: rgba(0,0,0,0.2); border-radius: 6px; margin: 0.25rem 0 0 0.5rem; padding: 0.25rem 0; max-height: 0; overflow: hidden; transition: max-height 0.2s; }
.nav-dropdown.open .nav-dropdown-menu { max-height: 400px; }
.nav-dropdown-trigger { width: 100%; justify-content: space-between; padding: 0.6rem 0.5rem; }
}
@media (max-width: 768px) {
.nav-container { flex-direction: column; gap: 0.75rem; align-items: stretch; }
.logo {
align-self: flex-start;
padding: 0.3rem 0.5rem;
font-size: 1.2rem;
border-radius: 12px;
}
.logo > div > span:first-child { line-height: 1.1; }
.logo > div > span:last-child { font-size: 0.68rem !important; }
.search-box { max-width: 100%; margin: 0; width: 100%; gap: 0.4rem; }
.search-box .btn {
padding: 0.55rem 0.7rem !important;
min-width: 2.75rem;
justify-content: center;
}
.search-box .search-label { display: none; }
.search-box .search-hint { display: none; }
.nav-actions { width: 100%; justify-content: space-between; gap: 0.5rem; }
.nav-actions > * { flex: 0 0 auto; }
.nav-actions #walletConnect { margin-left: auto; }
.nav-actions #walletConnectBtn,
.nav-actions #themeToggle,
.nav-actions #localeSelect { padding-left: 0.55rem; padding-right: 0.55rem; }
.nav-links { flex-wrap: wrap; justify-content: center; }
}
.gas-network-card { margin-bottom: 1rem; }
.gas-network-header {
display: flex;
flex-direction: column;
gap: 0.75rem;
align-items: stretch;
}
.gas-network-row,
.gas-network-compact,
.gas-network-pill,
.gas-network-spark {
display: flex;
}
.gas-network-row,
.gas-network-pill,
.gas-network-spark {
align-items: center;
}
.gas-network-row {
justify-content: space-between;
gap: 1rem;
flex-wrap: wrap;
}
.gas-network-compact { align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.gas-network-pill { gap: 0.4rem; padding: 0.45rem 0.7rem; border-radius: 999px; background: rgba(37, 99, 235, 0.08); color: var(--text); font-size: 0.86rem; border: 1px solid rgba(37, 99, 235, 0.12); white-space: nowrap; }
.gas-network-pill strong { font-size: 0.92rem; }
.gas-network-spark { align-items: flex-end; gap: 3px; height: 36px; min-width: 110px; }
.gas-network-spark span {
width: 8px;
border-radius: 4px 4px 0 0;
background: var(--primary);
opacity: 0.85;
}
.gas-network-subtle { color: var(--text-light); font-size: 0.82rem; white-space: nowrap; }
.btn-copy {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
background: rgba(255, 255, 255, 0.06);
border: 1px solid var(--border);
border-radius: 10px;
cursor: pointer;
padding: 0;
margin: 0;
color: var(--text-light);
vertical-align: middle;
transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
flex: 0 0 auto;
}
.btn-copy:hover {
color: var(--primary);
border-color: rgba(59, 130, 246, 0.35);
background: rgba(59, 130, 246, 0.08);
}
.tx-chip-row {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tx-chip {
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.3rem 0.6rem;
border-radius: 999px;
background: var(--muted-surface);
border: 1px solid var(--border);
color: var(--text);
font-size: 0.8rem;
}
.tx-chip-emphasis {
background: rgba(59, 130, 246, 0.1);
border-color: rgba(59, 130, 246, 0.18);
}
.tx-chip-label {
color: var(--text-light);
text-transform: uppercase;
letter-spacing: 0.04em;
font-size: 0.72rem;
}
.tx-inspector-stack {
display: grid;
gap: 0.75rem;
}
.tx-inspector-entry {
border: 1px solid var(--border);
border-radius: 12px;
background: var(--muted-surface);
overflow: hidden;
}
.tx-inspector-entry summary {
list-style: none;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 1rem;
padding: 0.85rem 1rem;
font-weight: 600;
}
.tx-inspector-entry summary::-webkit-details-marker {
display: none;
}
.tx-inspector-entry[open] summary {
border-bottom: 1px solid var(--border);
}
.tx-inspector-summary-value {
color: var(--text-light);
font-size: 0.82rem;
text-align: right;
font-weight: 500;
}
.tx-inspector-entry-body {
display: grid;
gap: 0.75rem;
padding: 0.9rem 1rem 1rem;
}
.tx-inspector-note {
color: var(--text-light);
font-size: 0.84rem;
line-height: 1.5;
}
.tx-inspector-structured {
display: grid;
gap: 0.6rem;
padding: 0.85rem;
border-radius: 12px;
border: 1px solid rgba(59, 130, 246, 0.16);
background: rgba(59, 130, 246, 0.05);
}
.tx-inspector-structured-title {
color: var(--text-light);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.72rem;
font-weight: 700;
}
.tx-inspector-line {
display: grid;
grid-template-columns: minmax(110px, 140px) minmax(0, 1fr);
gap: 0.75rem;
align-items: start;
}
.tx-inspector-label {
color: var(--text-light);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.72rem;
padding-top: 0.15rem;
}
.tx-inspector-content {
min-width: 0;
}
.tx-inspector-copy-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 0.65rem;
align-items: start;
}
.tx-inspector-copy-action {
display: flex;
align-items: flex-start;
justify-content: flex-end;
}
.tx-inspector-scroll {
overflow-x: auto;
min-width: 0;
}
.tx-inspector-mono {
font-family: 'Courier New', monospace;
font-size: 0.82rem;
line-height: 1.55;
white-space: pre-wrap;
word-break: break-all;
}
.tx-inspector-pre {
margin: 0;
padding: 0.85rem;
border-radius: 10px;
background: rgba(15, 23, 42, 0.06);
border: 1px solid var(--border);
font-family: 'Courier New', monospace;
font-size: 0.8rem;
line-height: 1.55;
white-space: pre-wrap;
word-break: break-word;
}
.tx-inspector-topic-list {
display: grid;
gap: 0.55rem;
}
.tx-inspector-topic-row {
display: grid;
gap: 0.35rem;
padding: 0.8rem;
border-radius: 10px;
border: 1px solid var(--border);
background: rgba(255, 255, 255, 0.45);
}
.tx-inspector-topic-index {
color: var(--text-light);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.7rem;
}
.tx-empty {
color: var(--text-light);
font-size: 0.9rem;
}
body.dark-theme .tx-inspector-pre {
background: rgba(15, 23, 42, 0.72);
}
body.dark-theme .tx-inspector-topic-row {
background: rgba(15, 23, 42, 0.44);
}
body.dark-theme .tx-inspector-structured {
background: rgba(30, 41, 59, 0.45);
border-color: rgba(96, 165, 250, 0.18);
}
@media (max-width: 768px) {
.tx-inspector-line {
grid-template-columns: 1fr;
gap: 0.35rem;
}
.tx-inspector-copy-row {
grid-template-columns: 1fr;
}
.tx-inspector-copy-action {
justify-content: flex-start;
}
.tx-inspector-entry summary {
flex-direction: column;
align-items: stretch;
}
.tx-inspector-summary-value {
text-align: left;
}
}
.site-footer {
margin-top: 2.5rem;
padding: 2rem 0 2.5rem;
border-top: 1px solid var(--border);
background: rgba(255, 255, 255, 0.65);
backdrop-filter: blur(8px);
}
body.dark-theme .site-footer {
background: rgba(15, 23, 42, 0.78);
}
.site-footer-grid {
display: grid;
grid-template-columns: minmax(0, 1.6fr) repeat(2, minmax(0, 1fr));
gap: 1.5rem;
align-items: start;
}
.site-footer-title {
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-light);
margin-bottom: 0.6rem;
}
.site-footer-links {
display: grid;
gap: 0.45rem;
font-size: 0.92rem;
}
.site-footer-links a {
color: var(--text);
}
.site-footer-links a:hover {
color: var(--primary);
}
.site-footer-note {
color: var(--text-light);
font-size: 0.9rem;
line-height: 1.65;
}
@media (max-width: 900px) {
.site-footer-grid { grid-template-columns: 1fr; }
}
body.dark-theme #smartSearchModal .btn.btn-secondary {
background: rgba(148, 163, 184, 0.12);
color: var(--text);
border-color: rgba(148, 163, 184, 0.24);
}
body.dark-theme #smartSearchModal aside {
background: linear-gradient(180deg, var(--muted-surface), var(--muted-surface-strong));
}
body.dark-theme #smartSearchModal main > div:first-of-type {
background: rgba(15, 23, 42, 0.72);
}
body.dark-theme #smartSearchModal #smartSearchPreview .loading {
color: var(--text-light);
}
</style>
</head>
<body>
<script>
(function() {
function doToggleNav() {
var links = document.getElementById('navLinks');
var btn = document.getElementById('navToggle');
var icon = document.getElementById('navToggleIcon');
if (!links || !btn) return;
var isOpen = links.classList.toggle('nav-open');
btn.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
if (icon) icon.className = isOpen ? 'fas fa-times' : 'fas fa-bars';
}
function doCloseNav() {
var links = document.getElementById('navLinks');
var btn = document.getElementById('navToggle');
var icon = document.getElementById('navToggleIcon');
if (links) links.classList.remove('nav-open');
if (btn) btn.setAttribute('aria-expanded', 'false');
if (icon) icon.className = 'fas fa-bars';
}
window.toggleNavMenu = doToggleNav;
window.closeNavMenu = doCloseNav;
document.addEventListener('click', function(e) {
if (e.target.closest('#navToggle')) { doToggleNav(); }
});
})();
</script>
<nav class="navbar">
<div class="nav-container">
<a class="logo" href="/" aria-label="Go to explorer home" style="text-decoration:none; color:inherit;">
<i class="fas fa-cube"></i>
<div style="display: flex; flex-direction: column; gap: 0.25rem;">
<span>DBIS Explorer</span>
<span style="font-size: 0.75rem; font-weight: normal; opacity: 0.9;">Chain 138 Explorer by DBIS</span>
</div>
</a>
<div class="search-box" style="display: flex; gap: 0.5rem; align-items: center;">
<button id="searchLauncherBtn" type="button" class="btn btn-primary" style="padding: 0.5rem 1rem; white-space: nowrap;" aria-label="Open explorer search">
<i class="fas fa-search" aria-hidden="true"></i>
<span class="search-label" style="margin-left: 0.4rem;">Search</span>
</button>
<span class="search-hint" style="font-size: 0.82rem; opacity: 0.9;">Press <strong>/</strong> or <strong>Ctrl+K</strong></span>
</div>
<button type="button" class="nav-toggle" id="navToggle" aria-label="Toggle menu" aria-expanded="false"><i class="fas fa-bars" id="navToggleIcon"></i></button>
<ul class="nav-links" id="navLinks">
<li class="nav-dropdown" id="navDropdownExplore">
<button type="button" class="nav-dropdown-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="navMenuExplore" id="navTriggerExplore"><i class="fas fa-compass" aria-hidden="true"></i> <span data-i18n="explore">Explore</span> <i class="fas fa-chevron-down" aria-hidden="true"></i></button>
<ul class="nav-dropdown-menu" id="navMenuExplore" role="menu">
<li role="none"><a href="/" role="menuitem" onclick="event.preventDefault(); showHome(); updatePath('/'); closeNavMenu();" aria-label="Navigate to home page"><i class="fas fa-home" aria-hidden="true"></i> <span data-i18n="home">Home</span></a></li>
<li role="none"><a href="/blocks" role="menuitem" onclick="event.preventDefault(); showBlocks(); updatePath('/blocks'); closeNavMenu();" aria-label="View all blocks"><i class="fas fa-cubes" aria-hidden="true"></i> <span data-i18n="blocks">Blocks</span></a></li>
<li role="none"><a href="/transactions" role="menuitem" onclick="event.preventDefault(); showTransactions(); updatePath('/transactions'); closeNavMenu();" aria-label="View all transactions"><i class="fas fa-exchange-alt" aria-hidden="true"></i> <span data-i18n="transactions">Transactions</span></a></li>
<li role="none"><a href="/addresses" role="menuitem" onclick="event.preventDefault(); showAddresses(); updatePath('/addresses'); closeNavMenu();" aria-label="View all addresses"><i class="fas fa-address-book" aria-hidden="true"></i> <span data-i18n="addresses">Addresses</span></a></li>
</ul>
</li>
<li class="nav-dropdown" id="navDropdownTools">
<button type="button" class="nav-dropdown-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="navMenuTools" id="navTriggerTools"><i class="fas fa-tools" aria-hidden="true"></i> <span data-i18n="tools">Tools</span> <i class="fas fa-chevron-down" aria-hidden="true"></i></button>
<ul class="nav-dropdown-menu" id="navMenuTools" role="menu">
<li role="none"><a href="/bridge" role="menuitem" onclick="event.preventDefault(); showBridgeMonitoring(); updatePath('/bridge'); closeNavMenu();" aria-label="View bridge monitoring"><i class="fas fa-bridge" aria-hidden="true"></i> <span data-i18n="bridge">Bridge</span></a></li>
<li role="none"><a href="/weth" role="menuitem" onclick="event.preventDefault(); showWETHUtilities(); updatePath('/weth'); closeNavMenu();" aria-label="View WETH utilities"><i class="fas fa-coins" aria-hidden="true"></i> <span data-i18n="weth">WETH</span></a></li>
<li role="none"><a href="/liquidity" role="menuitem" onclick="event.preventDefault(); showLiquidityAccess(); updatePath('/liquidity'); closeNavMenu();" aria-label="View liquidity access"><i class="fas fa-wave-square" aria-hidden="true"></i> <span>Liquidity</span></a></li>
<li role="none"><a href="/routes" role="menuitem" onclick="event.preventDefault(); showRoutes(); updatePath('/routes'); closeNavMenu();" aria-label="View route decision tree"><i class="fas fa-diagram-project" aria-hidden="true"></i> <span>Routes</span></a></li>
<li role="none"><a href="/tokens" role="menuitem" onclick="event.preventDefault(); if(typeof showTokensList==='function')showTokensList();else focusSearchWithHint('token'); updatePath('/tokens'); closeNavMenu();" aria-label="View token list"><i class="fas fa-tag" aria-hidden="true"></i> <span data-i18n="tokens">Tokens</span></a></li>
<li role="none"><a href="/pools" role="menuitem" onclick="event.preventDefault(); showPools(); updatePath('/pools'); closeNavMenu();" aria-label="View pools"><i class="fas fa-water" aria-hidden="true"></i> <span data-i18n="pools">Pools</span> <span id="poolsMissingQuoteBadge" class="badge badge-warning" style="display:none; margin-left:0.35rem; vertical-align:middle;">0</span></a></li>
<li role="none"><a href="/system" role="menuitem" onclick="event.preventDefault(); showSystemTopology(); closeNavMenu();" aria-label="System topology"><i class="fas fa-sitemap" aria-hidden="true"></i> <span>System</span></a></li>
<li role="none"><a href="/watchlist" role="menuitem" onclick="event.preventDefault(); showWatchlist(); updatePath('/watchlist'); closeNavMenu();" aria-label="Watchlist"><i class="fas fa-star" aria-hidden="true"></i> <span data-i18n="watchlist">Watchlist</span></a></li>
</ul>
</li>
<li><a href="/snap/" aria-label="Chain 138 MetaMask Snap"><i class="fas fa-wallet" aria-hidden="true"></i> <span>MetaMask Snap</span></a></li>
<li role="none"><a href="/operations" role="menuitem" onclick="event.preventDefault(); showMore(); updatePath('/operations'); closeNavMenu();" aria-label="View operations hub"><i class="fas fa-compass-drafting" aria-hidden="true"></i> <span>Operations</span></a></li>
<li class="nav-dropdown" id="userAccountNav" style="display: none;">
<button type="button" class="nav-dropdown-trigger" aria-expanded="false" aria-haspopup="true" aria-controls="userAccountMenu" id="userAccountTrigger"><i class="fas fa-user-circle" aria-hidden="true"></i> <span>User</span> <i class="fas fa-chevron-down" aria-hidden="true"></i></button>
<ul class="nav-dropdown-menu" id="userAccountMenu" role="menu">
<li role="none" class="user-menu-meta"><span id="userMenuIdentityLabel">Signed in</span></li>
<li role="none" id="userMenuInstitutionRow" style="display: none;"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof showInstitutionConsole === 'function') showInstitutionConsole(); closeNavMenu(); return false;"><i class="fas fa-building-columns" aria-hidden="true"></i> Institution console</a></li>
<li role="none" id="userMenuCompareRow" style="display: none;"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof showCompareAddresses === 'function') showCompareAddresses(); closeNavMenu(); return false;"><i class="fas fa-columns" aria-hidden="true"></i> Compare addresses</a></li>
<li role="none" id="userMenuKeyboardRow" style="display: none;"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof showKeyboardShortcutsModal === 'function') showKeyboardShortcutsModal(); closeNavMenu(); return false;"><i class="fas fa-keyboard" aria-hidden="true"></i> Keyboard shortcuts</a></li>
<li role="none" id="userMenuDiagnosticsRow" style="display: none;"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof copyExplorerDiagnosticsBundle === 'function') copyExplorerDiagnosticsBundle(); closeNavMenu(); return false;"><i class="fas fa-clipboard-list" aria-hidden="true"></i> Copy diagnostics bundle</a></li>
<li role="none" id="userMenuIncidentsRow" style="display: none;"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof showIncidentLinksModal === 'function') showIncidentLinksModal(); closeNavMenu(); return false;"><i class="fas fa-triangle-exclamation" aria-hidden="true"></i> Incident &amp; ops links</a></li>
<li role="none" id="userMenuVerifyContractsRow" style="display: none;"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof showContractVerificationHelp === 'function') showContractVerificationHelp(); closeNavMenu(); return false;"><i class="fas fa-file-contract" aria-hidden="true"></i> Verify &amp; publish contracts</a></li>
<li role="none"><a href="#" role="menuitem" onclick="event.preventDefault(); if (typeof disconnectExplorerWallet === 'function') disconnectExplorerWallet(); closeNavMenu(); return false;"><i class="fas fa-right-from-bracket" aria-hidden="true"></i> Sign out</a></li>
</ul>
</li>
</ul>
<div class="nav-actions">
<select id="localeSelect" onchange="setLocale(this.value)" style="padding: 0.35rem 0.5rem; border-radius: 6px; background: rgba(255,255,255,0.2); color: white; border: 1px solid rgba(255,255,255,0.3); font-size: 0.875rem;" aria-label="Language">
<option value="en">EN</option>
<option value="de">DE</option>
<option value="fr">FR</option>
</select>
<button id="themeToggle" type="button" class="btn btn-primary" onclick="toggleDarkMode()" style="padding: 0.5rem 0.75rem; background: rgba(255,255,255,0.2);" aria-label="Toggle dark mode" title="Toggle dark/light theme"><i class="fas fa-moon" id="themeIcon"></i></button>
<div id="walletConnect" style="display: flex; align-items: center; gap: 0.5rem;">
<button id="walletConnectBtn" class="btn btn-primary" onclick="connectWallet()" style="display: none;" aria-label="Connect wallet">Connect Wallet</button>
<div id="walletStatus" style="display: none; padding: 0.5rem 1rem; background: var(--success); color: white; border-radius: 8px; font-size: 0.875rem;">
<i class="fas fa-wallet"></i> <span id="walletAddress"></span>
</div>
</div>
</div>
</div>
</nav>
<div id="smartSearchModal" class="smart-search-modal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="smartSearchTitle" style="display:none; position:fixed; inset:0; z-index:20000;">
<div id="smartSearchBackdrop" style="position:absolute; inset:0; background: rgba(8, 15, 32, 0.62); backdrop-filter: blur(10px);"></div>
<div style="position:relative; z-index:1; display:flex; justify-content:center; align-items:flex-start; padding: 6vh 1rem 2rem; min-height:100%;">
<div style="width:min(920px, 100%); background: var(--card-bg, var(--light)); color: var(--text); border:1px solid var(--border); border-radius: 24px; box-shadow: 0 24px 80px rgba(0,0,0,0.35); overflow:hidden;">
<div style="padding: 1.1rem 1.25rem; border-bottom:1px solid var(--border); display:flex; align-items:flex-start; justify-content:space-between; gap:1rem;">
<div>
<div id="smartSearchTitle" style="font-size:1.05rem; font-weight:700;">Search Explorer</div>
<div style="margin-top:0.3rem; color:var(--text-light); font-size:0.9rem;">Type an address, transaction, block, token, or contract. Press Esc to close.</div>
</div>
<div style="display:flex; gap:0.5rem; align-items:center;">
<span style="padding:0.3rem 0.55rem; border:1px solid var(--border); border-radius:999px; font-size:0.8rem; color:var(--text-light);">Esc</span>
<button id="smartSearchCloseBtn" type="button" class="btn btn-secondary" style="padding:0.45rem 0.75rem;">Close</button>
</div>
</div>
<div style="padding:1.1rem 1.25rem 1.25rem;">
<div style="display:grid; grid-template-columns: 160px minmax(0, 1fr); gap:1rem; align-items:start;">
<aside style="border:1px solid var(--border); border-radius:18px; background: linear-gradient(180deg, rgba(0,0,0,0.02), rgba(0,0,0,0.05)); padding:0.9rem; position:sticky; top:1rem;">
<div style="font-size:0.78rem; text-transform:uppercase; letter-spacing:0.08em; color:var(--text-light); margin-bottom:0.65rem;">Quick Filters</div>
<div style="display:grid; gap:0.5rem;">
<button type="button" class="btn btn-secondary smart-search-scope-btn" data-scope="all" onclick="setSmartSearchScope('all'); updateSmartSearchPreview(document.getElementById('smartSearchInput') ? document.getElementById('smartSearchInput').value : '')" style="justify-content:flex-start; padding:0.62rem 0.75rem;">All</button>
<button type="button" class="btn btn-secondary smart-search-scope-btn" data-scope="addresses" onclick="setSmartSearchScope('addresses'); updateSmartSearchPreview(document.getElementById('smartSearchInput') ? document.getElementById('smartSearchInput').value : '')" style="justify-content:flex-start; padding:0.62rem 0.75rem;">Addresses</button>
<button type="button" class="btn btn-secondary smart-search-scope-btn" data-scope="tokens" onclick="setSmartSearchScope('tokens'); updateSmartSearchPreview(document.getElementById('smartSearchInput') ? document.getElementById('smartSearchInput').value : '')" style="justify-content:flex-start; padding:0.62rem 0.75rem;">Tokens</button>
<button type="button" class="btn btn-secondary smart-search-scope-btn" data-scope="blocks" onclick="setSmartSearchScope('blocks'); updateSmartSearchPreview(document.getElementById('smartSearchInput') ? document.getElementById('smartSearchInput').value : '')" style="justify-content:flex-start; padding:0.62rem 0.75rem;">Blocks</button>
<button type="button" class="btn btn-secondary smart-search-scope-btn" data-scope="transactions" onclick="setSmartSearchScope('transactions'); updateSmartSearchPreview(document.getElementById('smartSearchInput') ? document.getElementById('smartSearchInput').value : '')" style="justify-content:flex-start; padding:0.62rem 0.75rem;">Transactions</button>
</div>
<div style="margin-top:0.9rem; padding-top:0.9rem; border-top:1px solid var(--border);">
<div style="font-size:0.78rem; text-transform:uppercase; letter-spacing:0.08em; color:var(--text-light); margin-bottom:0.55rem;">Mode</div>
<div id="smartSearchDetected" class="badge" style="display:inline-block; background: var(--accent, #2563eb); color:#fff;">All</div>
</div>
<div style="margin-top:0.9rem; padding-top:0.9rem; border-top:1px solid var(--border);">
<div style="font-size:0.78rem; text-transform:uppercase; letter-spacing:0.08em; color:var(--text-light); margin-bottom:0.55rem;">Keys</div>
<div style="display:grid; gap:0.45rem; color:var(--text-light); font-size:0.84rem; line-height:1.45;">
<div style="display:flex; justify-content:space-between; gap:0.75rem;"><span>Tab</span><span>Move focus</span></div>
<div style="display:flex; justify-content:space-between; gap:0.75rem;"><span>Enter</span><span>Run search</span></div>
<div style="display:flex; justify-content:space-between; gap:0.75rem;"><span>Esc</span><span>Close</span></div>
</div>
</div>
</aside>
<main style="min-width:0;">
<label for="smartSearchInput" class="sr-only">Search blockchain explorer</label>
<div style="display:flex; gap:0.75rem; align-items:center; padding:0.9rem 1rem; border:1px solid var(--border); border-radius:16px; background: var(--light);">
<i class="fas fa-search" aria-hidden="true" style="color:var(--text-light);"></i>
<input type="text" id="smartSearchInput" placeholder="Search address, tx, block, token, contract..." aria-label="Search blockchain explorer" autocomplete="off" spellcheck="false" style="flex:1; border:none; background:transparent; outline:none; color:var(--text); font-size:1rem;">
<button id="smartSearchSubmitBtn" type="button" class="btn btn-primary" style="padding:0.5rem 0.85rem;">Search</button>
</div>
<div style="display:flex; flex-wrap:wrap; gap:0.5rem; margin-top:0.85rem; align-items:center;">
<span style="color:var(--text-light); font-size:0.88rem;">Recent searches, trending tokens, and scoped matches appear below.</span>
</div>
<div id="smartSearchPreview" style="margin-top:1rem; display:grid; gap:1rem;">
<div class="loading"><i class="fas fa-spinner"></i> Waiting for a query...</div>
</div>
</main>
</div>
</div>
</div>
</div>
</div>
<div id="contractVerifyHelpModal" class="contract-verify-help-modal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="contractVerifyHelpTitle" style="display:none; position:fixed; inset:0; z-index:20001;">
<div id="contractVerifyHelpBackdrop" style="position:absolute; inset:0; background: rgba(8, 15, 32, 0.62); backdrop-filter: blur(10px);"></div>
<div style="position:relative; z-index:1; display:flex; justify-content:center; align-items:flex-start; padding: 6vh 1rem 2rem; min-height:100%;">
<div style="width:min(640px, 100%); background: var(--card-bg, var(--light)); color: var(--text); border:1px solid var(--border); border-radius: 20px; box-shadow: 0 24px 80px rgba(0,0,0,0.35); overflow:hidden;">
<div style="padding: 1.1rem 1.25rem; border-bottom:1px solid var(--border); display:flex; align-items:flex-start; justify-content:space-between; gap:1rem;">
<div>
<div id="contractVerifyHelpTitle" style="font-size:1.05rem; font-weight:700;">Verify and publish smart contracts</div>
<div style="margin-top:0.35rem; color:var(--text-light); font-size:0.9rem;">For operator-approved accounts: submit sources in Blockscout or run the LAN verification script from the Proxmox repo.</div>
</div>
<button id="contractVerifyHelpCloseBtn" type="button" class="btn btn-secondary" style="padding:0.45rem 0.75rem;">Close</button>
</div>
<div style="padding:1.1rem 1.25rem 1.35rem; display:grid; gap:1rem;">
<div>
<label for="contractVerifyAddressInput" style="display:block; font-weight:600; margin-bottom:0.35rem;">Contract address (optional)</label>
<input type="text" id="contractVerifyAddressInput" placeholder="0x…" autocomplete="off" spellcheck="false" style="width:100%; padding:0.55rem 0.75rem; border-radius:10px; border:1px solid var(--border); background:var(--light); color:var(--text); font-size:0.95rem;">
<div style="margin-top:0.5rem; display:flex; flex-wrap:wrap; gap:0.5rem;">
<a id="contractVerifyBlockscoutLink" href="#" class="btn btn-primary" style="text-decoration:none; display:inline-flex; align-items:center; gap:0.4rem;" target="_blank" rel="noopener noreferrer"><i class="fas fa-external-link-alt" aria-hidden="true"></i> Open in Blockscout (verify tab)</a>
</div>
</div>
<div style="border:1px solid var(--border); border-radius:12px; padding:0.85rem 1rem; background:var(--muted-surface);">
<div style="font-weight:600; margin-bottom:0.4rem;"><i class="fas fa-terminal" aria-hidden="true"></i> Proxmox repo (LAN + Foundry)</div>
<p style="color:var(--text-light); font-size:0.88rem; line-height:1.5; margin-bottom:0.65rem;">From the repository root on a host that can reach Blockscout and your RPC (see <code style="font-size:0.85em;">forge-verification-proxy</code> in-repo):</p>
<div style="display:flex; gap:0.5rem; align-items:stretch; flex-wrap:wrap;">
<code id="contractVerifyScriptCommand" style="flex:1; min-width:0; display:block; padding:0.55rem 0.65rem; border-radius:8px; background:var(--card-bg); border:1px solid var(--border); font-size:0.8rem; word-break:break-all;">./scripts/verify/run-contract-verification-with-proxy.sh</code>
<button type="button" id="contractVerifyCopyCommandBtn" class="btn btn-secondary" style="white-space:nowrap;">Copy</button>
</div>
</div>
<p style="color:var(--text-light); font-size:0.85rem; margin:0;">The public SPA cannot run <code>forge verify</code>. Use Blockscouts form or the script above. Optional alternate bridge verify: set <code>VERIFY_ALTERNATE_CCIPWETH9_BRIDGE=1</code> when using <code>scripts/verify-contracts-blockscout.sh</code> (see repo docs).</p>
</div>
</div>
</div>
</div>
<div id="keyboardShortcutsModal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="keyboardShortcutsTitle" style="display:none; position:fixed; inset:0; z-index:20002;">
<div id="keyboardShortcutsBackdrop" style="position:absolute; inset:0; background: rgba(8, 15, 32, 0.62); backdrop-filter: blur(10px);"></div>
<div style="position:relative; z-index:1; display:flex; justify-content:center; align-items:flex-start; padding: 6vh 1rem 2rem; min-height:100%;">
<div style="width:min(520px, 100%); background: var(--card-bg, var(--light)); color: var(--text); border:1px solid var(--border); border-radius: 20px; box-shadow: 0 24px 80px rgba(0,0,0,0.35);">
<div style="padding: 1.1rem 1.25rem; border-bottom:1px solid var(--border); display:flex; justify-content:space-between; align-items:center; gap:1rem;">
<div id="keyboardShortcutsTitle" style="font-size:1.05rem; font-weight:700;">Keyboard shortcuts</div>
<button type="button" id="keyboardShortcutsCloseBtn" class="btn btn-secondary">Close</button>
</div>
<div style="padding:1rem 1.25rem 1.25rem; font-size:0.92rem; line-height:1.55;">
<table class="table" style="margin:0;"><tbody>
<tr><td><kbd style="padding:0.2rem 0.45rem;border-radius:6px;border:1px solid var(--border);">/</kbd> or <kbd style="padding:0.2rem 0.45rem;border-radius:6px;border:1px solid var(--border);">Ctrl</kbd>+<kbd style="padding:0.2rem 0.45rem;border-radius:6px;border:1px solid var(--border);">K</kbd></td><td>Open search</td></tr>
<tr><td><kbd style="padding:0.2rem 0.45rem;border-radius:6px;border:1px solid var(--border);">Esc</kbd></td><td>Close modals</td></tr>
</tbody></table>
<p style="margin-top:0.75rem; color:var(--text-light); margin-bottom:0;">Institution users: open the User menu for session tools, diagnostics export, and the institution console.</p>
</div>
</div>
</div>
</div>
<div id="incidentLinksModal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="incidentLinksTitle" style="display:none; position:fixed; inset:0; z-index:20002;">
<div id="incidentLinksBackdrop" style="position:absolute; inset:0; background: rgba(8, 15, 32, 0.62); backdrop-filter: blur(10px);"></div>
<div style="position:relative; z-index:1; display:flex; justify-content:center; align-items:flex-start; padding: 6vh 1rem 2rem; min-height:100%;">
<div style="width:min(560px, 100%); background: var(--card-bg, var(--light)); color: var(--text); border:1px solid var(--border); border-radius: 20px; box-shadow: 0 24px 80px rgba(0,0,0,0.35);">
<div style="padding: 1.1rem 1.25rem; border-bottom:1px solid var(--border); display:flex; justify-content:space-between; align-items:center; gap:1rem;">
<div id="incidentLinksTitle" style="font-size:1.05rem; font-weight:700;">Incident &amp; ops bookmarks</div>
<button type="button" id="incidentLinksCloseBtn" class="btn btn-secondary">Close</button>
</div>
<div style="padding:1rem 1.25rem 1.25rem; display:grid; gap:0.65rem; font-size:0.92rem;">
<p style="color:var(--text-light); margin:0;">Read-only shortcuts for operator response (no secrets). Adjust hosts to match your deployment.</p>
<a class="btn btn-secondary" href="https://explorer.d-bis.org/" target="_blank" rel="noopener noreferrer" style="text-align:center; text-decoration:none;">Public explorer</a>
<a class="btn btn-secondary" href="http://192.168.11.140:4000/" target="_blank" rel="noopener noreferrer" style="text-align:center; text-decoration:none;">Blockscout (LAN template)</a>
<a class="btn btn-secondary" href="https://gitea.d-bis.org/d-bis/explorer-monorepo/src/branch/main/docs/EXPLORER_API_ACCESS.md" target="_blank" rel="noopener noreferrer" style="text-align:center; text-decoration:none;">Explorer API access doc</a>
</div>
</div>
</div>
</div>
<div id="explorerLiveRegion" aria-live="polite" aria-atomic="true" class="sr-only" role="status"></div>
<div class="container" id="mainContent">
<!-- Home View -->
<div id="homeView">
<div class="stats-grid" id="statsGrid">
<!-- Stats loaded dynamically -->
</div>
<div class="card gas-network-card" id="gasNetworkCard">
<div class="card-header gas-network-header">
<div class="gas-network-row">
<h2 class="card-title"><i class="fas fa-gas-pump"></i> Gas &amp; Network</h2>
<button type="button" class="btn btn-secondary" onclick="loadGasAndNetworkStats()" aria-label="Refresh gas and network"><i class="fas fa-sync-alt"></i> Refresh</button>
</div>
<div class="gas-network-row">
<div class="gas-network-compact">
<div class="gas-network-pill"><span class="gas-network-subtle">Base fee</span> <strong id="gasCurrentValue"></strong></div>
<div class="gas-network-pill"><span class="gas-network-subtle">Block time</span> <strong id="gasBlockTimeValue"></strong></div>
<div class="gas-network-pill"><span class="gas-network-subtle">TPS</span> <strong id="gasTpsValue"></strong></div>
<div class="gas-network-pill"><span class="gas-network-subtle">Failed</span> <strong id="gasFailedRateValue"></strong></div>
</div>
<div style="display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap;">
<div>
<div style="font-size: 0.78rem; color: var(--text-light); margin-bottom: 0.25rem;">History (10 blocks)</div>
<div id="gasHistoryBars" class="gas-network-spark"></div>
</div>
<div id="gasNetworkSummary" class="gas-network-subtle">Live chain health for Chain 138.</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="card-title">Latest Blocks</h2>
<button class="btn btn-primary" onclick="showBlocks()" aria-label="View all blocks">View All</button>
</div>
<div id="latestBlocks">
<div class="loading"><i class="fas fa-spinner"></i> Loading blocks...</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="card-title">Latest Transactions</h2>
<button class="btn btn-primary" onclick="showTransactions()" aria-label="View all transactions">View All</button>
</div>
<div id="latestTransactions">
<div class="loading"><i class="fas fa-spinner"></i> Loading transactions...</div>
</div>
</div>
</div>
<!-- WETH Utilities View -->
<div id="wethView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-coins"></i> WETH9 & WETH10 Utilities</h2>
<button class="btn btn-success" onclick="refreshWETHBalances()" aria-label="Refresh WETH balances"><i class="fas fa-sync-alt" aria-hidden="true"></i> Refresh</button>
</div>
<!-- MetaMask Connection Status -->
<div id="metamaskStatus" class="metamask-status disconnected">
<i class="fas fa-wallet"></i>
<span>MetaMask not connected</span>
<button class="btn btn-success" onclick="connectMetaMask()" style="margin-left: auto;" aria-label="Connect MetaMask wallet">Connect MetaMask</button>
</div>
<div class="tabs">
<button class="tab weth-tab active" onclick="showWETHTab('weth9', this)" aria-label="Switch to WETH9 tab" role="tab" aria-selected="true">WETH9</button>
<button class="tab weth-tab" onclick="showWETHTab('weth10', this)" aria-label="Switch to WETH10 tab" role="tab" aria-selected="false">WETH10</button>
<button class="tab weth-tab" onclick="showWETHTab('info', this)" aria-label="Switch to information tab" role="tab" aria-selected="false">Information</button>
</div>
<!-- WETH9 Tab -->
<div id="weth9Tab" class="weth-tab-content">
<div class="weth-card">
<div class="chain-name">WETH9 Token</div>
<div style="color: var(--text-light); margin-bottom: 1rem;">
Contract: <a class="hash" href="/addresses/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" onclick="event.preventDefault(); showAddressDetail('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')" style="color: inherit; text-decoration: none;">0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2</a>
<button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'WETH', 18, 'Wrapped Ether');" aria-label="Add WETH9 to wallet" title="Add to wallet"><i class="fas fa-wallet" aria-hidden="true"></i></button>
</div>
<div class="balance-display" id="weth9Balance">
<div class="balance-row">
<span class="balance-label">ETH Balance:</span>
<span class="balance-value" id="weth9EthBalance">-</span>
</div>
<div class="balance-row">
<span class="balance-label">WETH9 Balance:</span>
<span class="balance-value" id="weth9TokenBalance">-</span>
</div>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Wrap ETH → WETH9</h3>
<div class="form-group">
<label for="weth9WrapAmount" class="form-label">Amount (ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth9WrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH9 wrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH9('wrap')" aria-label="Set maximum WETH9 wrap amount">MAX</button>
</div>
</div>
<button class="btn btn-success" onclick="wrapWETH9()" id="weth9WrapBtn" disabled aria-label="Wrap ETH to WETH9">
<i class="fas fa-arrow-right"></i> Wrap ETH to WETH9
</button>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Unwrap WETH9 → ETH</h3>
<div class="form-group">
<label for="weth9UnwrapAmount" class="form-label">Amount (WETH9 in ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth9UnwrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH9 unwrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH9('unwrap')" aria-label="Set maximum WETH9 unwrap amount">MAX</button>
</div>
</div>
<button class="btn btn-warning" onclick="unwrapWETH9()" id="weth9UnwrapBtn" disabled aria-label="Unwrap WETH9 to ETH">
<i class="fas fa-arrow-left"></i> Unwrap WETH9 to ETH
</button>
</div>
</div>
</div>
<!-- WETH10 Tab -->
<div id="weth10Tab" class="weth-tab-content" style="display: none;">
<div class="weth-card">
<div class="chain-name">WETH10 Token</div>
<div style="color: var(--text-light); margin-bottom: 1rem;">
Contract: <a class="hash" href="/addresses/0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f" onclick="event.preventDefault(); showAddressDetail('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f')" style="color: inherit; text-decoration: none;">0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f</a>
<button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f', 'WETH', 18, 'Wrapped Ether v10');" aria-label="Add WETH10 to wallet" title="Add to wallet"><i class="fas fa-wallet" aria-hidden="true"></i></button>
</div>
<div class="balance-display" id="weth10Balance">
<div class="balance-row">
<span class="balance-label">ETH Balance:</span>
<span class="balance-value" id="weth10EthBalance">-</span>
</div>
<div class="balance-row">
<span class="balance-label">WETH10 Balance:</span>
<span class="balance-value" id="weth10TokenBalance">-</span>
</div>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Wrap ETH → WETH10</h3>
<div class="form-group">
<label for="weth10WrapAmount" class="form-label">Amount (ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth10WrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH10 wrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH10('wrap')" aria-label="Set maximum WETH10 wrap amount">MAX</button>
</div>
</div>
<button class="btn btn-success" onclick="wrapWETH10()" id="weth10WrapBtn" disabled aria-label="Wrap ETH to WETH10">
<i class="fas fa-arrow-right"></i> Wrap ETH to WETH10
</button>
</div>
<div class="weth-form">
<h3 style="margin-bottom: 1rem;">Unwrap WETH10 → ETH</h3>
<div class="form-group">
<label for="weth10UnwrapAmount" class="form-label">Amount (WETH10 in ETH or wei)</label>
<div class="form-input-group">
<input type="text" inputmode="decimal" class="form-input" id="weth10UnwrapAmount" placeholder="e.g. 100 or 100000000000000000000 (wei)" aria-label="WETH10 unwrap amount in ETH or wei">
<button class="btn btn-primary" onclick="setMaxWETH10('unwrap')" aria-label="Set maximum WETH10 unwrap amount">MAX</button>
</div>
</div>
<button class="btn btn-warning" onclick="unwrapWETH10()" id="weth10UnwrapBtn" disabled aria-label="Unwrap WETH10 to ETH">
<i class="fas fa-arrow-left"></i> Unwrap WETH10 to ETH
</button>
</div>
</div>
</div>
<!-- Information Tab -->
<div id="wethInfoTab" class="weth-tab-content" style="display: none;">
<div class="card">
<h3>About WETH9 and WETH10</h3>
<div style="margin-top: 1rem; line-height: 1.8;">
<p><strong>WETH9</strong> and <strong>WETH10</strong> are wrapped versions of native ETH (Ether) that allow you to use ETH in smart contracts and DeFi protocols.</p>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">What is Wrapping?</h4>
<p>Wrapping ETH converts your native ETH into an ERC-20 token (WETH9 or WETH10) that can be used in DeFi applications, smart contracts, and cross-chain bridging.</p>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">Contract Addresses</h4>
<ul style="margin-left: 2rem; margin-top: 0.5rem;">
<li><strong>WETH9:</strong> <a class="hash" href="/addresses/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" onclick="event.preventDefault(); showAddressDetail('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')" style="color: inherit; text-decoration: none;">0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2</a> <button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'WETH', 18);" aria-label="Add WETH9 to wallet" title="Add to wallet"><i class="fas fa-wallet"></i></button></li>
<li><strong>WETH10:</strong> <a class="hash" href="/addresses/0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f" onclick="event.preventDefault(); showAddressDetail('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f')" style="color: inherit; text-decoration: none;">0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f</a> <button type="button" class="btn-add-token-wallet" onclick="event.stopPropagation(); window.addTokenToWallet && window.addTokenToWallet('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f', 'WETH', 18);" aria-label="Add WETH10 to wallet" title="Add to wallet"><i class="fas fa-wallet"></i></button></li>
</ul>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">How to Use</h4>
<ol style="margin-left: 2rem; margin-top: 0.5rem;">
<li>Connect your MetaMask wallet</li>
<li>Select WETH9 or WETH10 tab</li>
<li>Enter the amount to wrap or unwrap</li>
<li>Confirm the transaction in MetaMask</li>
</ol>
<h4 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">Cross-Chain Bridging</h4>
<p>Both WETH9 and WETH10 can be bridged to other chains using the CCIP bridge contracts:</p>
<ul style="margin-left: 2rem; margin-top: 0.5rem;">
<li><strong>WETH9 Bridge:</strong> <span class="hash">0x971cD9D156f193df8051E48043C476e53ECd4693</span></li>
<li><strong>WETH10 Bridge:</strong> <span class="hash">0xe0E93247376aa097dB308B92e6Ba36bA015535D0</span></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Bridge Monitoring View -->
<div id="bridgeView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title"><i class="fas fa-bridge"></i> Bridge Monitoring</h2>
<button class="btn btn-primary" onclick="refreshBridgeData()" aria-label="Refresh bridge data"><i class="fas fa-sync-alt" aria-hidden="true"></i> Refresh</button>
</div>
<div id="bridgeContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading bridge data...</div>
</div>
</div>
</div>
<!-- Other views -->
<div id="blocksView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title">All Blocks</h2>
<button type="button" class="btn btn-primary" onclick="exportBlocksCSV()" style="padding: 0.5rem 1rem;"><i class="fas fa-file-csv"></i> Export CSV</button>
</div>
<div id="blocksList">
<div class="loading"><i class="fas fa-spinner"></i> Loading blocks...</div>
</div>
</div>
</div>
<div id="transactionsView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title">All Transactions</h2>
<button type="button" class="btn btn-primary" onclick="exportTransactionsListCSV()" style="padding: 0.5rem 1rem;"><i class="fas fa-file-csv"></i> Export CSV</button>
</div>
<div id="transactionsList">
<div class="loading"><i class="fas fa-spinner"></i> Loading transactions...</div>
</div>
</div>
</div>
<div id="blockDetailView" class="detail-view">
<div class="breadcrumb" id="blockDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showBlocks()" aria-label="Go back to blocks view"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title">Block Details</h2>
</div>
<div id="blockDetail"></div>
</div>
</div>
<div id="transactionDetailView" class="detail-view">
<div class="breadcrumb" id="transactionDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showTransactions()" aria-label="Go back to transactions view"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title">Transaction Details</h2>
</div>
<div id="transactionDetail"></div>
</div>
</div>
<div id="addressesView" class="detail-view">
<div class="card">
<div class="card-header">
<h2 class="card-title">All Addresses</h2>
</div>
<div id="addressesList">
<div class="loading"><i class="fas fa-spinner"></i> Loading addresses...</div>
</div>
</div>
</div>
<div id="addressDetailView" class="detail-view">
<div class="breadcrumb" id="addressDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showAddresses()" aria-label="Go back to addresses list"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title">Address Details</h2>
</div>
<div id="addressDetail"></div>
</div>
</div>
<div id="tokenDetailView" class="detail-view">
<div class="breadcrumb" id="tokenDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title">Token</h2>
</div>
<div id="tokenDetail"></div>
</div>
</div>
<div id="nftDetailView" class="detail-view">
<div class="breadcrumb" id="nftDetailBreadcrumb"></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title">NFT</h2>
</div>
<div id="nftDetail"></div>
</div>
</div>
<div id="searchResultsView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title">Search results</h2>
</div>
<div id="searchResultsContent"></div>
</div>
</div>
<div id="tokensView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-coins"></i> Tokens</h2>
</div>
<div id="tokensListContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading...</div>
</div>
</div>
</div>
<div id="watchlistView" class="detail-view">
<div class="breadcrumb" id="watchlistBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Watchlist</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-star"></i> Watchlist</h2>
</div>
<div id="watchlistContent">
<p style="color: var(--text-light);">Add addresses from their detail page to track them here.</p>
</div>
</div>
</div>
<div id="poolsView" class="detail-view">
<div class="breadcrumb" id="poolsBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Pools</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-water"></i> Pools</h2>
<div style="display:flex; gap:0.5rem; margin-left:auto; flex-wrap:wrap;">
<button type="button" class="btn btn-primary" onclick="exportPoolsCSV()" style="padding: 0.5rem 1rem;"><i class="fas fa-file-csv"></i> Export CSV</button>
<button type="button" class="btn btn-secondary" onclick="exportPoolsJSON()" style="padding: 0.5rem 1rem;"><i class="fas fa-download"></i> Export JSON</button>
</div>
</div>
<div id="poolsContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading pools...</div>
</div>
</div>
</div>
<div id="liquidityView" class="detail-view">
<div class="breadcrumb" id="liquidityBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Liquidity</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-wave-square"></i> Liquidity Access</h2>
<div style="display:flex; gap:0.5rem; margin-left:auto; flex-wrap:wrap;">
<button type="button" class="btn btn-primary" onclick="renderLiquidityAccessView()" style="padding: 0.5rem 1rem;"><i class="fas fa-sync-alt"></i> Refresh</button>
</div>
</div>
<div id="liquidityContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading liquidity access...</div>
</div>
</div>
</div>
<div id="routesView" class="detail-view">
<div class="breadcrumb" id="routesBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Routes</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-diagram-project"></i> Routes</h2>
<div style="display:flex; gap:0.5rem; margin-left:auto; flex-wrap:wrap;">
<button type="button" class="btn btn-primary" onclick="renderRoutesView()" style="padding: 0.5rem 1rem;"><i class="fas fa-sync-alt"></i> Refresh</button>
</div>
</div>
<div id="routesContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading routes...</div>
</div>
</div>
</div>
<div id="moreView" class="detail-view">
<div class="breadcrumb" id="moreBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">More</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back to home page"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-ellipsis-h"></i> More</h2>
</div>
<div id="moreContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading more pages...</div>
</div>
</div>
</div>
<div id="analyticsView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-chart-line"></i> Analytics Dashboard</h2>
</div>
<div id="analyticsContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading analytics access...</div>
</div>
</div>
</div>
<div id="operatorView" class="detail-view">
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left"></i> Back</button>
<h2 class="card-title"><i class="fas fa-cog"></i> Operator Panel</h2>
</div>
<div id="operatorContent">
<div class="loading"><i class="fas fa-spinner"></i> Loading operator access...</div>
</div>
</div>
</div>
<div id="systemView" class="detail-view">
<div class="breadcrumb" id="systemBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">System</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-sitemap" aria-hidden="true"></i> System topology</h2>
<div style="display:flex; gap:0.5rem; margin-left:auto; flex-wrap:wrap;">
<a class="btn btn-secondary" href="/chain138-command-center.html" target="_blank" rel="noopener noreferrer">Command center</a>
<button type="button" class="btn btn-primary" onclick="if(window._showSystemTopology) window._showSystemTopology();" aria-label="Reload topology"><i class="fas fa-sync-alt" aria-hidden="true"></i> Reload</button>
</div>
</div>
<div id="systemTopologyContent">
<div class="loading"><i class="fas fa-spinner" aria-hidden="true"></i> Loading graph…</div>
</div>
</div>
</div>
<div id="institutionView" class="detail-view">
<div class="breadcrumb" id="institutionBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Institution</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-building-columns" aria-hidden="true"></i> Institution console</h2>
</div>
<div id="institutionContent">
<div class="loading"><i class="fas fa-spinner" aria-hidden="true"></i> Loading…</div>
</div>
</div>
</div>
<div id="compareView" class="detail-view">
<div class="breadcrumb" id="compareBreadcrumb"><a href="/">Home</a><span class="breadcrumb-separator">/</span><span class="breadcrumb-current">Compare addresses</span></div>
<div class="card">
<div class="card-header">
<button class="btn btn-secondary" onclick="showHome()" aria-label="Go back"><i class="fas fa-arrow-left" aria-hidden="true"></i> Back</button>
<h2 class="card-title"><i class="fas fa-columns" aria-hidden="true"></i> Compare addresses</h2>
</div>
<div id="compareContent">
<div class="loading"><i class="fas fa-spinner" aria-hidden="true"></i> Loading…</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<div class="container">
<div class="site-footer-grid">
<div>
<div style="font-size: 1.05rem; font-weight: 700; margin-bottom: 0.5rem;">DBIS Explorer</div>
<div class="site-footer-note">
Built on Blockscout foundations for the DBIS Chain 138 explorer surface.
Explorer data, block indexing, and public chain visibility are powered by Blockscout,
Chain 138 RPC, and the MetaMask Snap companion.
</div>
<div class="site-footer-note" style="margin-top: 0.8rem;">
© 2026 DBIS. All rights reserved.
</div>
</div>
<div>
<div class="site-footer-title">Documentation</div>
<div class="site-footer-links">
<a href="/docs">Docs landing page</a>
<a href="/liquidity">Liquidity access</a>
<a href="/routes">Routes</a>
<a href="/privacy.html">Privacy Policy</a>
<a href="/terms.html">Terms of Service</a>
</div>
</div>
<div>
<div class="site-footer-title">Acknowledgments & Contact</div>
<div class="site-footer-links">
<a href="/acknowledgments.html">Acknowledgments</a>
<a href="mailto:support@d-bis.org">support@d-bis.org</a>
<a href="/snap/">MetaMask Snap companion</a>
</div>
</div>
</div>
</div>
</footer>
<script src="/explorer-spa.js?v=38"></script>
</body>
</html>