(function() { var C = window.ExplorerCommon; function fmtFee(ut) { if (!ut) return 'Free'; if (ut < 1000) return ut + ' µT'; return C.toToken(ut); } async function loadRelays() { C.setStatus('Loading…', 'warn'); try { var data = await C.fetchJSON('/api/relays'); var relays = Array.isArray(data) ? data : []; document.getElementById('relayCount').textContent = relays.length; var tbody = document.getElementById('relayBody'); if (!relays.length) { tbody.innerHTML = 'No relay nodes registered yet.'; C.setStatus('No relay nodes found.', 'warn'); return; } var rows = ''; relays.forEach(function(info, i) { var pubKey = info.pub_key || ''; var addr = info.address || '—'; var x25519 = (info.relay && info.relay.x25519_pub_key) || '—'; var feeUT = (info.relay && info.relay.fee_per_msg_ut) || 0; var multiaddr = (info.relay && info.relay.multiaddr) || ''; rows += '' + '' + (i + 1) + '' + '' + (pubKey ? '' + C.esc(addr) + '' : C.esc(addr)) + '' + '' + C.esc(C.short(x25519, 28)) + '' + '' + fmtFee(feeUT) + '' + '' + (multiaddr ? C.esc(multiaddr) : '') + '' + '' + (pubKey ? '' + ' Node' + '' : '') + '' + ''; }); tbody.innerHTML = rows; C.setStatus(relays.length + ' relay node' + (relays.length !== 1 ? 's' : '') + ' registered.', 'ok'); C.refreshIcons(); } catch (e) { C.setStatus('Load failed: ' + e.message, 'err'); } } document.getElementById('refreshBtn').addEventListener('click', loadRelays); loadRelays(); })();