/** * LPS-1 Public Mint Console — live edition status + verify + backfill + mint buttons. */ (function () { const statusEl = document.getElementById('lps-console-status'); const tableEl = document.getElementById('lps-console-table'); const metaEl = document.getElementById('lps-console-meta'); const btnRefresh = document.getElementById('lps-btn-refresh'); const btnBackfill = document.getElementById('lps-btn-backfill'); function esc(s) { const d = document.createElement('div'); d.textContent = s == null ? '' : String(s); return d.innerHTML; } function pill(status) { const s = (status || 'pending').toLowerCase(); const cls = s === 'anchored' ? 'st-live' : s === 'digest_only' ? 'st-partial' : 'st-partial'; return '' + esc(status || 'pending') + ''; } function setMonitor(id, text, on) { const el = document.getElementById(id); if (!el) return; el.textContent = text; if (on) el.classList.add('on'); else el.classList.remove('on'); } async function loadMonitor() { try { const r = await fetch('/api/lps/monitor', { signal: AbortSignal.timeout(12000) }); if (!r.ok) return; const m = await r.json(); setMonitor('lps-mon-reset', m.reset_mode ? 'ON' : 'OFF', m.reset_mode); } catch (_) {} } async function loadStatus() { if (statusEl) statusEl.textContent = 'Loading live mint status…'; try { const r = await fetch('/api/lps/mint-status', { signal: AbortSignal.timeout(20000) }); const data = await r.json(); render(data); loadMonitor(); } catch (e) { if (statusEl) statusEl.textContent = 'Console offline: ' + e.message; } } function render(data) { const p = data.provenance || {}; if (statusEl) { statusEl.innerHTML = '' + (p.anchored_count || 0) + '/' + (p.total || 0) + ' articles anchored · settlement ' + esc(p.settlement || '—') + ' · ' + esc(p.compliance_level || 'L5'); } setMonitor('lps-mon-anchored', (p.anchored_count || 0) + '/' + (p.total || 0), (p.anchored_count || 0) > 0); setMonitor('lps-mon-settlement', (p.settlement || '—').replace('atomic-mint-anchored', 'anchored'), true); const ed = data.edition || {}; setMonitor( 'lps-mon-nig', ed.nig_composite != null ? (ed.nig_composite >= 0 ? '+' + ed.nig_composite : String(ed.nig_composite)) : '—', ed.nig_composite != null, ); if (metaEl) { metaEl.innerHTML = '

Lead brief: ' + esc(ed.lead_title || '—') + '

' + '

Edition mode: ' + esc(ed.mode || 'live') + ' · Brief count: ' + esc(ed.brief_count != null ? ed.brief_count : '—') + '

' + '

Latest IPFS: ' + (data.ipfs_snapshot?.cid ? '' + esc(data.ipfs_snapshot.cid.slice(0, 18)) + '…' : '—') + (data.yield_layer?.status === 'live' ? ' · Yield layer: LIVE' : '') + '

'; } if (tableEl && Array.isArray(p.articles)) { tableEl.innerHTML = '' + p.articles .map(function (a) { return ( '' ); }) .join('') + '
ArticleLPS-1 IDStatusMintVerify
' + esc((a.title || a.id).slice(0, 72)) + '
' + esc(a.desk) + ' · ' + esc(a.author_id) + '
' + esc(a.lps1_registration_id || '—') + '' + pill(a.provenance_status) + 'JSON' + (a.ipfs_gateway ? ' · IPFS' : '') + '
'; if (window.GMIIELpsMint) { tableEl.querySelectorAll('tr[data-article-id]').forEach(function (row) { var id = row.getAttribute('data-article-id'); var host = row.querySelector('.lps-console-mint'); if (!id || !host) return; window.GMIIELpsMint.renderButton(host, { briefId: id, title: row.querySelector('strong')?.textContent || id, compact: true, }); }); } } } async function runBackfill() { if (btnBackfill) { btnBackfill.disabled = true; btnBackfill.textContent = 'Attesting…'; } try { const r = await fetch('/api/lps/backfill', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ limit: 20 }), signal: AbortSignal.timeout(120000), }); const data = await r.json(); if (statusEl) { statusEl.textContent = 'Backfill complete: ' + (data.attested || 0) + ' attested, ' + (data.skipped_already_anchored || 0) + ' skipped, ' + (data.failed || 0) + ' failed'; } await loadStatus(); } catch (e) { if (statusEl) statusEl.textContent = 'Backfill error: ' + e.message; } finally { if (btnBackfill) { btnBackfill.disabled = false; btnBackfill.textContent = 'Backfill unattested'; } } } btnRefresh?.addEventListener('click', loadStatus); btnBackfill?.addEventListener('click', runBackfill); loadStatus(); setInterval(loadStatus, 30000); })();