Nav sitewide: Litepaper, Miner, App, Wallet, Live devnet, Ledger and the Download button; the rest in the sheet and the footer. /miner is the product page for the installers: the shipped app in its frame, the card picker with the live time to a block, the downloads with sizes, HiveOS, the fee in full view, three real shots. /app is new: the Igneum Ember app page by page (Overview, Cards with Ember, the chain drawn live by the module the app ships, Earnings, Prove, Settings, phone width, what keeps it mining), light and dark, every shot a real capture or a render from the RTX 5090 Windows rig's live state with the hostname painted out. /live is redrawn to show the system working: the step scene, six live cells, finality in plain words, miner lanes, provers paid, recent blocks landing, the light client in one line, the DAG below. site.css carries the shared product components (frames, download list, lines, your-card line, phone download bar); yourcard.js reads the network rate. The ledger and wallet pages no longer overflow at 390 px. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
17 lines
2.4 KiB
JavaScript
17 lines
2.4 KiB
JavaScript
/* The "your card" line: a measured card, and how often it finds a block at the network's hash rate right now. One block a
|
|
second is the target, so the wait is network hashes per second over the card's rate. The rates are the bench table's
|
|
measured numbers (site/miners.html); nothing here is a promise. Reads /api/live every 15 s. */
|
|
(function () {
|
|
var CARDS = [['NVIDIA RTX 5090', 127.7], ['NVIDIA RTX 4070', 28.8], ['Apple M5 Max', 26.7], ['AMD RX 9070 XT', 17.8]];
|
|
var els = document.querySelectorAll('[data-yourcard]'); if (!els.length) return;
|
|
var net = null, chosen = (function () { try { return localStorage.getItem('igneum-card'); } catch (e) { return null; } })();
|
|
function dur(sec) { if (!(sec > 0)) return 'pending'; if (sec < 90) return Math.round(sec) + ' s'; if (sec < 5400) return Math.round(sec / 60) + ' min'; if (sec < 172800) { var h = Math.floor(sec / 3600), m = Math.round((sec % 3600) / 60); return h + ' h' + (m ? ' ' + m + ' min' : ''); } return Math.round(sec / 86400) + ' days'; }
|
|
function render() { els.forEach(function (el) { var r = parseFloat(el.querySelector('select').value) * 1e6, eta = el.querySelector('.eta'); eta.textContent = net && r ? 'every ' + dur(net / r) : 'pending'; }); }
|
|
els.forEach(function (el) {
|
|
el.innerHTML = '<b>Your card</b><select aria-label="Your card">' + CARDS.map(function (c) { return '<option value="' + c[1] + '"' + (chosen === c[0] ? ' selected' : '') + '>' + c[0] + ' \u00b7 ' + c[1] + ' MH/s</option>'; }).join('') + '</select><span>finds a block about <span class="eta">pending</span> at the network\u2019s hash rate right now.</span>';
|
|
el.querySelector('select').addEventListener('change', function (e) { var name = e.target.options[e.target.selectedIndex].text.split(' \u00b7 ')[0]; try { localStorage.setItem('igneum-card', name); } catch (x) {} document.querySelectorAll('[data-yourcard] select').forEach(function (s) { s.value = e.target.value; }); render(); });
|
|
});
|
|
function poll() { fetch('/api/live?window=30', { cache: 'no-store' }).then(function (r) { return r.json(); }).then(function (d) { if (d && d.ok && d.state && d.state.hashes_per_second_estimate > 0) { net = d.state.hashes_per_second_estimate; render(); } }).catch(function () {}); }
|
|
poll(); setInterval(function () { if (!document.hidden) poll(); }, 15000);
|
|
window.IgneumYourCard = { update: function (h) { if (h > 0) { net = h; render(); } } };
|
|
})();
|