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
This commit is contained in:
58
node/explorer/validators.js
Normal file
58
node/explorer/validators.js
Normal file
@@ -0,0 +1,58 @@
|
||||
(function() {
|
||||
var C = window.ExplorerCommon;
|
||||
|
||||
async function loadValidators() {
|
||||
C.setStatus('Loading…', 'warn');
|
||||
try {
|
||||
var data = await C.fetchJSON('/api/validators');
|
||||
var validators = (data && Array.isArray(data.validators)) ? data.validators : [];
|
||||
var quorum = validators.length > 0 ? Math.floor(2 * validators.length / 3) + 1 : 0;
|
||||
|
||||
document.getElementById('valCount').textContent = validators.length;
|
||||
document.getElementById('quorumCount').textContent = quorum || '—';
|
||||
|
||||
var tbody = document.getElementById('valBody');
|
||||
if (!validators.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="4" class="tbl-empty">No validators found.</td></tr>';
|
||||
C.setStatus('No validators registered.', 'warn');
|
||||
return;
|
||||
}
|
||||
|
||||
var rows = '';
|
||||
validators.forEach(function(v, i) {
|
||||
var addr = v.address || '—';
|
||||
var pubKey = v.pub_key || '—';
|
||||
rows +=
|
||||
'<tr>' +
|
||||
'<td class="text-muted" style="font-size:12px">' + (i + 1) + '</td>' +
|
||||
'<td>' +
|
||||
'<a class="mono" href="/address?address=' + encodeURIComponent(pubKey) + '">' +
|
||||
C.esc(addr) +
|
||||
'</a>' +
|
||||
'</td>' +
|
||||
'<td class="mono" style="color:var(--muted);font-size:12px">' +
|
||||
C.esc(C.short(pubKey, 32)) +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
'<a href="/node?node=' + encodeURIComponent(pubKey) + '" class="pill-link" style="font-size:12px;padding:4px 10px">' +
|
||||
'<i data-lucide="server"></i> Node' +
|
||||
'</a>' +
|
||||
'</td>' +
|
||||
'</tr>';
|
||||
});
|
||||
tbody.innerHTML = rows;
|
||||
|
||||
C.setStatus(
|
||||
validators.length + ' validator' + (validators.length !== 1 ? 's' : '') +
|
||||
' · quorum: ' + quorum,
|
||||
'ok'
|
||||
);
|
||||
C.refreshIcons();
|
||||
} catch (e) {
|
||||
C.setStatus('Load failed: ' + e.message, 'err');
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('refreshBtn').addEventListener('click', loadValidators);
|
||||
loadValidators();
|
||||
})();
|
||||
Reference in New Issue
Block a user