Files
dchain/node/explorer/address.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

225 lines
9.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Wallet | 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/address.js"></script>
</head>
<body>
<!-- top nav -->
<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 (collapsed under nav) -->
<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="addressInput" type="text" placeholder="Enter address (DC…) or public key…">
<button id="addressBtn" class="btn-hero">Load</button>
</div>
<div id="status" class="hero-status"></div>
</div>
</div>
<!-- empty state (shown when no address loaded, toggled by JS) -->
<div id="emptyState" class="page-body" style="display:none">
<div class="addr-empty-state">
<div class="addr-empty-icon"><i data-lucide="wallet"></i></div>
<div class="addr-empty-title">Search for a wallet</div>
<div class="addr-empty-sub">Enter a DC address (e.g. <span class="mono" style="color:var(--accent)">DC1abc…</span>) or a 64-character hex public key above to view balance and transaction history.</div>
</div>
</div>
<main class="page-body" id="mainContent" style="display:none">
<!-- ── Error banner (hidden unless load failed) ──────────────────────── -->
<div id="errorBanner" class="addr-error-banner" style="display:none">
<div class="addr-error-icon"><i data-lucide="alert-circle"></i></div>
<div class="addr-error-body">
<div class="addr-error-title">Could not load wallet</div>
<div class="addr-error-msg" id="errorMsg">Unknown error</div>
</div>
</div>
<!-- ── Profile card (hidden on error) ───────────────────────────────── -->
<div id="profileSection">
<div class="addr-profile-card">
<!-- left: avatar + name + badges -->
<div class="addr-profile-left">
<div class="addr-avatar" id="addrAvatar"></div>
<div class="addr-profile-info">
<div class="addr-name" id="addrNickname">Unknown Wallet</div>
<div class="addr-badges" id="addrBadges"><!-- filled by JS --></div>
</div>
</div>
<!-- right: balance -->
<div class="addr-profile-right">
<div class="addr-bal-label">Balance</div>
<div class="addr-bal-val" id="walletBalance"></div>
<div class="addr-bal-sub" id="walletBalanceSub"></div>
</div>
</div>
<!-- ── Identity details grid ─────────────────────────────────────────── -->
<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> Address</div>
<div class="addr-kv-val">
<span class="mono" id="walletAddress"></span>
<button class="copy-btn" data-copy-id="walletAddress" title="Copy"><i data-lucide="copy"></i></button>
</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="walletPubKey"></span>
<button class="copy-btn" data-copy-id="walletPubKey" title="Copy"><i data-lucide="copy"></i></button>
</div>
</div>
<div class="addr-kv-row" id="x25519Row" style="display:none">
<div class="addr-kv-key"><i data-lucide="message-square-lock"></i> Messaging Key (X25519)</div>
<div class="addr-kv-val">
<span class="mono addr-pubkey-text" id="walletX25519"></span>
<button class="copy-btn" data-copy-id="walletX25519" title="Copy"><i data-lucide="copy"></i></button>
</div>
</div>
<div class="addr-kv-row" id="nodeLinkRow" style="display:none">
<div class="addr-kv-key"><i data-lucide="server"></i> Node Page</div>
<div class="addr-kv-val"><a id="nodePageLink" href="#">View node stats →</a></div>
</div>
<div class="addr-kv-row" id="walletBindingRow" style="display:none">
<div class="addr-kv-key"><i data-lucide="wallet"></i> Bound Wallet</div>
<div class="addr-kv-val"><a id="walletBindingLink" href="#"></a></div>
</div>
</div>
</div>
<!-- ── Node stats (shown only for validators / relay nodes) ─────────── -->
<div class="panel addr-node-panel" id="nodeStatsPanel" style="display:none">
<h2><i data-lucide="server"></i> Node Stats</h2>
<div class="addr-node-grid">
<div class="addr-node-cell">
<div class="addr-node-label">Blocks Produced</div>
<div class="addr-node-val" id="nodeBlocks"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Relay Proofs</div>
<div class="addr-node-val" id="nodeRelayProofs"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Reputation</div>
<div class="addr-node-val" id="nodeRepScore"></div>
<div class="addr-node-sub" id="nodeRepRank"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Heartbeats</div>
<div class="addr-node-val" id="nodeHeartbeats"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Slashes</div>
<div class="addr-node-val" id="nodeSlashes"></div>
</div>
<div class="addr-node-cell">
<div class="addr-node-label">Recent Rewards</div>
<div class="addr-node-val" id="nodeRecentRewards"></div>
<div class="addr-node-sub" id="nodeRecentWindow"></div>
</div>
</div>
</div>
<!-- ── Token Balances ───────────────────────────────────────────────── -->
<div class="panel" id="tokenBalPanel" style="display:none">
<div class="addr-hist-head">
<h2><i data-lucide="coins"></i> Token Balances</h2>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Symbol</th>
<th>Name</th>
<th style="text-align:right">Balance</th>
<th style="width:90px"></th>
</tr>
</thead>
<tbody id="tokenBalBody"></tbody>
</table>
</div>
</div>
<!-- ── NFT Collection ────────────────────────────────────────────────── -->
<div class="panel" id="nftPanel" style="display:none">
<div class="addr-hist-head">
<h2><i data-lucide="image"></i> NFTs</h2>
<span class="addr-hist-count" id="nftOwnedCount"></span>
</div>
<div id="addrNFTGrid" class="nft-grid" style="padding:1rem"></div>
</div>
<!-- ── Transaction History ───────────────────────────────────────────── -->
<div class="panel">
<div class="addr-hist-head">
<h2><i data-lucide="history"></i> History</h2>
<span class="addr-hist-count" id="walletTxCount"></span>
</div>
<div class="table-wrap">
<table id="walletTxTable">
<thead>
<tr>
<th>Time</th>
<th>Type</th>
<th>From → To</th>
<th>Memo / Block</th>
<th style="text-align:right">Amount</th>
</tr>
</thead>
<tbody id="walletTxBody">
<tr><td colspan="5" class="tbl-empty">No transactions yet.</td></tr>
</tbody>
</table>
</div>
<div class="addr-load-more">
<button id="loadMoreBtn" class="btn" style="display:none">
<i data-lucide="chevron-down"></i> Load more
</button>
</div>
</div>
</div><!-- /#profileSection -->
</main>
</body>
</html>