Files
dchain/node/explorer/node.html
vsecoder 7e7393e4f8 chore: initial commit for v0.0.1
DChain single-node blockchain + React Native messenger client.

Core:
- PBFT consensus with multi-sig validator admission + equivocation slashing
- BadgerDB + schema migration scaffold (CurrentSchemaVersion=0)
- libp2p gossipsub (tx/v1, blocks/v1, relay/v1, version/v1)
- Native Go contracts (username_registry) alongside WASM (wazero)
- WebSocket gateway with topic-based fanout + Ed25519-nonce auth
- Relay mailbox with NaCl envelope encryption (X25519 + Ed25519)
- Prometheus /metrics, per-IP rate limit, body-size cap

Deployment:
- Single-node compose (deploy/single/) with Caddy TLS + optional Prometheus
- 3-node dev compose (docker-compose.yml) with mocked internet topology
- 3-validator prod compose (deploy/prod/) for federation
- Auto-update from Gitea via /api/update-check + systemd timer
- Build-time version injection (ldflags → node --version)
- UI / Swagger toggle flags (DCHAIN_DISABLE_UI, DCHAIN_DISABLE_SWAGGER)

Client (client-app/):
- Expo / React Native / NativeWind
- E2E NaCl encryption, typing indicator, contact requests
- Auto-discovery of canonical contracts, chain_id aware, WS reconnect on node switch

Documentation:
- README.md, CHANGELOG.md, CONTEXT.md
- deploy/single/README.md with 6 operator scenarios
- deploy/UPDATE_STRATEGY.md with 4-layer forward-compat design
- docs/contracts/*.md per contract
2026-04-17 14:16:44 +03:00

147 lines
6.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Node | DChain Explorer</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/explorer/style.css">
<script src="https://unpkg.com/lucide@latest"></script>
<script defer src="/assets/explorer/common.js"></script>
<script defer src="/assets/explorer/node.js"></script>
</head>
<body>
<header class="topnav">
<div class="topnav-inner">
<a class="topnav-brand" href="/">
<span class="brand-gem"></span>
<span class="brand-name">DChain</span>
</a>
<nav class="topnav-links">
<a href="/contract">Contracts</a>
<a href="/tokens">Tokens</a>
<a href="/validators">Validators</a>
<a href="/relays">Relay Nodes</a>
</nav>
</div>
</header>
<!-- search bar strip -->
<div class="addr-searchbar">
<div class="addr-searchbar-inner">
<div class="hero-search" style="max-width:640px">
<i data-lucide="search" class="hero-search-icon"></i>
<input id="nodeInput" type="text" placeholder="Node public key or DC address…">
<button id="nodeBtn" class="btn-hero">Load</button>
</div>
<div id="status" class="hero-status"></div>
</div>
</div>
<main class="page-body" id="mainContent" style="display:none">
<!-- ── Node profile card ──────────────────────────────────────────────── -->
<div class="addr-profile-card">
<div class="addr-profile-left">
<div class="addr-avatar" style="background:linear-gradient(135deg,#1a3a3a 0%,#0d2030 100%)">
<i data-lucide="server" style="width:22px;height:22px;color:var(--ok)"></i>
</div>
<div class="addr-profile-info">
<div class="addr-name" id="nodeNickname">Node</div>
<div class="addr-badges" id="nodeBadges"></div>
<div class="mono" style="font-size:12px;color:var(--muted);margin-top:4px" id="nodeAddressShort"></div>
</div>
</div>
<div class="addr-profile-right">
<div class="addr-bal-label">Node Balance</div>
<div class="addr-bal-val" id="nodeBalanceVal"></div>
<div class="addr-bal-sub" id="nodeReputationRank"></div>
</div>
</div>
<!-- ── Identity / binding details ────────────────────────────────────── -->
<div class="panel addr-detail-panel">
<div class="addr-kv-list">
<div class="addr-kv-row">
<div class="addr-kv-key"><i data-lucide="at-sign"></i> Node Address</div>
<div class="addr-kv-val">
<a class="mono" id="nodeAddress" href="#"></a>
<button class="copy-btn" data-copy-id="nodeAddressRaw" title="Copy"><i data-lucide="copy"></i></button>
<span id="nodeAddressRaw" style="display:none"></span>
</div>
</div>
<div class="addr-kv-row">
<div class="addr-kv-key"><i data-lucide="key-round"></i> Public Key</div>
<div class="addr-kv-val">
<span class="mono addr-pubkey-text" id="nodePubKey"></span>
<button class="copy-btn" data-copy-id="nodePubKey" title="Copy"><i data-lucide="copy"></i></button>
</div>
</div>
<div class="addr-kv-row" id="bindingRow" style="display:none">
<div class="addr-kv-key"><i data-lucide="wallet"></i> Bound Wallet</div>
<div class="addr-kv-val">
<a id="bindingLink" href="#"></a>
<span class="text-muted" style="margin-left:8px;font-size:12px" id="bindingBalance"></span>
</div>
</div>
</div>
</div>
<!-- ── Stats grid ─────────────────────────────────────────────────────── -->
<div class="panel addr-node-panel">
<h2><i data-lucide="bar-chart-3"></i> Performance</h2>
<div class="addr-node-grid" style="grid-template-columns:repeat(4,minmax(0,1fr))">
<div class="addr-node-cell">
<div class="addr-node-label">Reputation Score</div>
<div class="addr-node-val" id="repScore"></div>
<div class="addr-node-sub" id="repRank"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Blocks Produced</div>
<div class="addr-node-val" id="repBlocks"></div>
<div class="addr-node-sub" id="recentProduced"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Relay Proofs</div>
<div class="addr-node-val" id="repRelay"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Heartbeats</div>
<div class="addr-node-val" id="repHeartbeats"></div>
<div class="addr-node-sub" id="repSlash" style="color:var(--err)"></div>
</div>
</div>
</div>
<!-- ── Rewards ────────────────────────────────────────────────────────── -->
<div class="panel addr-node-panel">
<h2><i data-lucide="coins"></i> Rewards</h2>
<div class="addr-node-grid" style="grid-template-columns:repeat(3,minmax(0,1fr))">
<div class="addr-node-cell">
<div class="addr-node-label">Recent Rewards</div>
<div class="addr-node-val" id="recentRewards"></div>
<div class="addr-node-sub" id="windowBlocks"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Lifetime Base Reward</div>
<div class="addr-node-val" id="lifetimeReward"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Node Balance</div>
<div class="addr-node-val" id="nodeBalance"></div>
</div>
</div>
</div>
</main>
</body>
</html>