666 lines
70 KiB
HTML
666 lines
70 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||
<title>Igneum live devnet</title>
|
||
<meta name="description" content="The Igneum network observatory: every block and its connections, the miners, the provers paid and the finality rule, read from a node every two seconds.">
|
||
<link rel="canonical" href="https://igneum.network/live">
|
||
<meta name="theme-color" content="#0C0C0E">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:site_name" content="Igneum">
|
||
<meta property="og:title" content="Igneum live devnet">
|
||
<meta property="og:description" content="The Igneum devnet as it happens: every block, the miners, the provers paid and the finality rule, read from a node every two seconds.">
|
||
<meta property="og:url" content="https://igneum.network/live">
|
||
<meta property="og:image" content="https://igneum.network/og-small.png?v=3">
|
||
<meta property="og:image:width" content="256">
|
||
<meta property="og:image:height" content="256">
|
||
<meta property="og:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
|
||
<meta name="twitter:card" content="summary">
|
||
<meta name="twitter:title" content="Igneum live devnet">
|
||
<meta name="twitter:description" content="The Igneum devnet as it happens: every block, the miners, the provers paid and the finality rule, read from a node every two seconds.">
|
||
<meta name="twitter:image" content="https://igneum.network/og-small.png?v=3">
|
||
<meta name="twitter:image:alt" content="Igneum. Mined by GPUs. Proven by fire.">
|
||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Crect width='1024' height='1024' fill='%230C0C0E'/%3E%3Cg transform='translate(166.95 166.95) scale(6.901)'%3E%3Cpolygon points='50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34' fill='%23F2541B'/%3E%3Cpolygon points='50,42 59,58 50,82 41,58' fill='%230C0C0E'/%3E%3C/g%3E%3C/svg%3E" type="image/svg+xml">
|
||
<link rel="icon" href="/favicon.ico" sizes="48x48">
|
||
<link rel="icon" href="/favicon-32.png" type="image/png" sizes="32x32">
|
||
<link rel="icon" href="/icon-192.png" type="image/png" sizes="192x192">
|
||
<link rel="icon" href="/icon-512.png" type="image/png" sizes="512x512">
|
||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
|
||
<link rel="manifest" href="/site.webmanifest">
|
||
<!-- head:start -->
|
||
<link rel="preload" href="/fonts/unbounded-900.woff2" as="font" type="font/woff2" crossorigin>
|
||
<link rel="preload" href="/fonts/plex-sans-400.woff2" as="font" type="font/woff2" crossorigin>
|
||
<meta name="color-scheme" content="dark light">
|
||
<link rel="stylesheet" href="/site.css">
|
||
<style>
|
||
/* Shared by every page: the head partial, injected by the build between the head markers. Edit the partial, not the page. */
|
||
/* Fonts, self-hosted (latin subsets, OFL): Unbounded 500/700/900, IBM Plex Sans 400/500/600, IBM Plex Mono 400/500. Fallbacks carry size and ascent overrides so the swap does not move the layout. The tokens, type and components are in /site.css (docs/plans/site-ui-3.md). */
|
||
@font-face{font-family:'Unbounded';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/unbounded-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'Unbounded';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/unbounded-700.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'Unbounded';font-style:normal;font-weight:900;font-display:swap;src:url(/fonts/unbounded-900.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/plex-sans-400.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/plex-sans-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/plex-sans-600.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/plex-mono-400.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/plex-mono-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
|
||
@font-face{font-family:'Unbounded Fallback';src:local('Arial Black'),local('Arial-Black'),local('Impact');size-adjust:114%;ascent-override:87.5%;descent-override:21.5%;line-gap-override:0%}
|
||
@font-face{font-family:'Plex Sans Fallback';src:local('Arial'),local('Helvetica Neue'),local('Helvetica');size-adjust:100.5%;ascent-override:102%;descent-override:27.4%;line-gap-override:0%}
|
||
@font-face{font-family:'Plex Mono Fallback';src:local('Courier New'),local('Menlo');size-adjust:100%;ascent-override:102.5%;descent-override:27.5%;line-gap-override:0%}
|
||
</style>
|
||
<script>
|
||
/* theme before first paint: ?theme=light|dark for one view (the capture tool), else the stored choice under igneum-theme, else the system setting; ?motion=off marks the page data-motion=off so every .reveal is drawn at once (a headless render never scrolls) */
|
||
(function(){var t=null;try{t=new URLSearchParams(location.search).get("theme");}catch(e){}if(t!=="light"&&t!=="dark"){try{t=localStorage.getItem("igneum-theme");}catch(e){t=null;}}if(t!=="light"&&t!=="dark")t=window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches?"light":"dark";document.documentElement.setAttribute("data-theme",t);try{if(new URLSearchParams(location.search).get("motion")==="off")document.documentElement.setAttribute("data-motion","off");}catch(e){}})();
|
||
</script>
|
||
<!-- head:end -->
|
||
<style>
|
||
/* live page block (7 Oct 2026, site-ui-4: the observatory composition, every number read from the observer); tokens and components are in /site.css */
|
||
.obs{--pr:12px;--hair:1px solid var(--line)}
|
||
.obs-head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:16px 40px;padding:65px 0 45px}
|
||
.obs-head .eyebrow{display:flex;align-items:center;gap:8px;margin-bottom:var(--s-3)}
|
||
.obs-head .eyebrow i{width:7px;height:7px;background:var(--ember);transform:rotate(45deg);display:inline-block}
|
||
.obs-head h1{font-size:clamp(36px,4.2vw,56px);max-width:22ch;margin:0}
|
||
.obs-head h1 b{color:var(--ember-text)}
|
||
.obs-head p{margin:24px 0 0;color:var(--ink-2);max-width:67ch;font-size:18px;line-height:1.65}
|
||
.obs-head .side{display:flex;flex-direction:column;align-items:flex-end;gap:var(--s-2)}
|
||
.obs-head .side .state{font-size:var(--t-xs)}
|
||
.tiles6{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));border:var(--hair);border-radius:12px;background:var(--row);overflow:hidden}
|
||
.tiles6>div{padding:22px 25px;border-right:var(--hair);min-width:0}
|
||
.tiles6>div:last-child{border-right:0}
|
||
.tiles6 .k{display:flex;justify-content:space-between;align-items:center;font:10px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--ash)}
|
||
.tiles6 .k i{color:var(--ash);font:400 12px/1 var(--f-mono)}
|
||
.tiles6 .v{font:700 clamp(21px,2.2vw,29px)/1.15 var(--display);letter-spacing:-.04em;color:var(--bone);margin:11px 0 8px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
|
||
.tiles6 .v.word{font:500 15px/1.3 var(--f-mono);color:var(--ash)}
|
||
.tiles6 .d{font:10px/1.5 var(--mono);color:var(--ash)}
|
||
@media (max-width:1100px){.tiles6{grid-template-columns:repeat(3,minmax(0,1fr))}.tiles6>div:nth-child(3){border-right:0}.tiles6>div:nth-child(-n+3){border-bottom:var(--hair)}}
|
||
@media (max-width:600px){.tiles6{grid-template-columns:repeat(2,minmax(0,1fr))}.tiles6>div{border-right:var(--hair)!important;border-bottom:var(--hair)}.tiles6>div:nth-child(2n){border-right:0!important}.tiles6>div:nth-last-child(-n+2){border-bottom:0}}
|
||
.panel{border:var(--hair);border-radius:16px;background:var(--row);margin-top:18px;overflow:hidden}
|
||
.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:21px 25px;border-bottom:var(--hair);background:var(--row)}
|
||
.toolbar .title{display:flex;align-items:center;gap:10px;font:500 11px/1.7 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ember)}
|
||
.toolbar .title i{width:14px;height:14px;border:1.5px solid var(--ember);border-radius:50%;display:inline-block;position:relative}
|
||
.toolbar .title i::after{content:"";position:absolute;inset:4px;background:var(--ember);border-radius:50%}
|
||
.chip{font:400 11px/1.2 var(--f-mono);color:var(--ash);border:var(--hair);border-radius:4px;padding:5px 8px;white-space:nowrap}
|
||
.toolbar .right{margin-left:auto;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
||
.tb{background:transparent;border:1px solid transparent;color:var(--ash);font:400 13px/1.2 var(--f-sans);padding:7px 10px;border-radius:6px;cursor:pointer}
|
||
.tb:hover{color:var(--bone)}
|
||
.tb[aria-pressed="true"]{color:var(--bone);border-color:var(--line-2);background:var(--graphite)}
|
||
.tb.on{color:var(--ember-text);border-color:var(--ember-40)}
|
||
.sep{width:1px;height:18px;background:var(--line)}
|
||
.graph{display:grid;grid-template-columns:minmax(0,1fr) 295px;align-items:start}
|
||
@media (max-width:1000px){.graph{grid-template-columns:1fr}}
|
||
.gcol{padding:0;min-width:0;border-right:0;position:relative}
|
||
@media (max-width:1000px){.gcol{border-right:0;border-bottom:var(--hair)}}
|
||
.gcol .state{position:absolute;left:25px;top:14px;z-index:3;font-size:10px}
|
||
.scene{position:relative}
|
||
#dag{display:block;width:100%;background:var(--row);touch-action:pan-y}
|
||
.gtop{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;padding:10px 25px;border-top:var(--hair);font:10px/1.7 var(--mono);color:var(--ash)}
|
||
.gtop .hint{white-space:nowrap}
|
||
.gtop .lg{display:flex;flex-wrap:wrap;gap:6px 10px;flex:1 1 auto;justify-content:center}
|
||
.gtop .lg span{display:inline-flex;align-items:center;gap:6px;color:var(--ink-2);font-family:var(--f-sans);font-size:11px;white-space:nowrap}
|
||
.gtop .zoom{margin-left:4px}
|
||
.gunder{padding:8px 25px 10px;border-top:var(--hair);font:10px/1.7 var(--mono);color:var(--ash)}
|
||
@media (max-width:700px){.gtop{padding:10px 16px;gap:8px 12px}.gtop .lg{flex-basis:100%;justify-content:flex-start}.gtop .zoom{margin-left:auto}.gunder{padding:8px 16px 10px}}
|
||
.tip{position:absolute;left:0;top:0;pointer-events:none;background:var(--graphite);border:1px solid var(--line-2);border-radius:6px;padding:10px 12px;font:400 12px/1.5 var(--f-mono);color:var(--ink-2);white-space:nowrap;z-index:5}
|
||
.tip[hidden]{display:none}
|
||
.gfoot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;padding:17px 25px;border-top:var(--hair);font:10px/1.7 var(--mono);color:var(--ash)}
|
||
.zoom{display:inline-flex;align-items:center;border:var(--hair);border-radius:6px;overflow:hidden}
|
||
.zoom button{background:transparent;border:0;color:var(--ink-2);font:400 13px/1 var(--f-mono);padding:8px 12px;cursor:pointer}
|
||
.zoom button:hover{background:var(--hover)}
|
||
.zoom span{font:400 11px/1 var(--f-mono);color:var(--ash);padding:0 6px;min-width:44px;text-align:center}
|
||
.icol{padding:16px 18px;min-width:0;font-size:12px;border-left:var(--hair)}
|
||
.icol .ih{display:flex;align-items:center;gap:8px;margin-bottom:10px}.icol .ih .chip{margin-left:auto}
|
||
.icol .ih .eyebrow{margin:0}
|
||
.icol .num{font:500 22px/1.2 var(--f-sans);color:var(--bone);margin:6px 0 4px;overflow-wrap:anywhere}
|
||
.icol .hash{font:400 11px/1.5 var(--f-mono);color:var(--ash);overflow-wrap:anywhere;margin-bottom:14px}
|
||
.insp{display:grid;grid-template-columns:auto minmax(0,1fr);gap:0 10px;margin:0;border-top:var(--hair);padding-top:8px}
|
||
.insp dt{font:11px var(--mono);color:var(--ash);padding:7px 0;border-bottom:var(--hair)}
|
||
.insp dd{margin:0;font:11px var(--mono);color:var(--bone);font-weight:500;text-align:right;padding:7px 0;border-bottom:var(--hair);overflow-wrap:anywhere;min-width:0}
|
||
.insp dd.hot{color:var(--molten-text)}
|
||
.icol .note{font-size:12px;margin-top:14px;padding-top:12px;border-top:var(--hair)}
|
||
.insp-empty{color:var(--ash);font-size:13px;line-height:1.5;padding:6px 0 2px}
|
||
.mstats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-bottom:var(--hair);background:var(--row)}
|
||
.mstats>div{padding:22px 25px;border-right:var(--hair);min-width:0}
|
||
.mstats>div:last-child{border-right:0}
|
||
.mstats .mk{font:10px var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--ash)}
|
||
.mstats .mv{display:flex;align-items:baseline;gap:8px;margin:8px 0 6px}
|
||
.mstats .mv b{font:700 clamp(21px,2.2vw,29px)/1.1 var(--display);color:var(--bone);letter-spacing:-.04em}
|
||
.mstats .mv b.own{color:var(--molten-text)}.mstats .mv b.dim{color:var(--ash)}
|
||
.mstats .mv small{font:400 11px/1.4 var(--f-mono);color:var(--ash)}
|
||
.mstats .mf{font:400 11px/1.4 var(--f-mono);color:var(--ash);overflow-wrap:anywhere}
|
||
@media (max-width:900px){.mstats{grid-template-columns:repeat(2,minmax(0,1fr))}.mstats>div:nth-child(2){border-right:0}.mstats>div:nth-child(-n+2){border-bottom:var(--hair)}}
|
||
.tabs{display:inline-flex;border:var(--hair);border-radius:6px;padding:3px;gap:2px;background:var(--graphite)}
|
||
.tab{background:transparent;border:0;color:var(--ash);font:400 12px/1.2 var(--f-sans);padding:6px 10px;border-radius:4px;cursor:pointer}
|
||
.tab.on{background:var(--row);color:var(--bone)}
|
||
.ititle{font:500 22px/1.2 var(--f-sans);color:var(--bone);margin:6px 0 4px;letter-spacing:-.01em}
|
||
.proof-scene{height:170px;border:var(--hair);border-radius:6px;background:var(--row);margin:12px 0;overflow:hidden}
|
||
.proof-scene canvas{display:block;width:100%;height:100%}
|
||
.proof-head{display:flex;justify-content:space-between;align-items:baseline;font:500 13px/1.3 var(--f-sans);color:var(--bone);margin-bottom:8px}
|
||
.track{display:flex;gap:3px;height:3px;margin-bottom:10px}
|
||
.track i{flex:1 1 0;background:var(--line);border-radius:2px}
|
||
.track i.proving{background:var(--ember)}.track i.verified{background:var(--bone)}.track i.paid{background:var(--molten)}
|
||
.shards{list-style:none;margin:0 0 12px;padding:0;font:400 11px/1.6 var(--f-mono)}
|
||
.shards li{display:flex;justify-content:space-between;gap:8px;color:var(--ink-2)}
|
||
.shards li::before{content:"\25CF";font-size:7px;margin-right:6px;color:var(--line-2);vertical-align:middle}
|
||
.shards li.proving,.shards li.proving::before{color:var(--ember-text)}.shards li.verified,.shards li.verified::before{color:var(--bone)}.shards li.paid,.shards li.paid::before{color:var(--molten-text)}
|
||
.lgi{width:10px;height:10px;border-radius:3px;display:inline-block;flex:none;position:relative}
|
||
.lgi.tick::after{content:"\2713";position:absolute;left:0;top:-4px;font-size:11px;color:var(--bone)}
|
||
.motion{margin-top:25px;border:var(--hair);border-radius:16px;background:var(--row);padding:25px}
|
||
.motion h2{font:500 var(--t-h3)/1.3 var(--f-sans);margin:0 0 14px;color:var(--bone)}
|
||
.beats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4)}
|
||
@media (max-width:900px){.beats{grid-template-columns:1fr}}
|
||
.beats .num{font:400 10px/1 var(--f-mono);color:var(--ember-text)}
|
||
.beats h3{font:500 14px/1.4 var(--f-sans);margin:6px 0 4px;color:var(--bone)}
|
||
.beats p{margin:0;font-size:13px;color:var(--ink-2);line-height:1.5}
|
||
.legend-row{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 18px;padding:17px 25px;border-top:var(--hair);font:10px/1.7 var(--mono);color:var(--ash)}
|
||
.legend-row .lg{display:flex;flex-wrap:wrap;gap:8px 16px}
|
||
.legend-row .lg span{display:inline-flex;align-items:center;gap:7px;color:var(--ink-2);font-family:var(--f-sans);font-size:12px}
|
||
.sw{width:9px;height:9px;transform:rotate(45deg);display:inline-block;flex:none}
|
||
.three{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);margin-top:var(--s-4)}
|
||
.two{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:var(--s-4);margin-top:var(--s-4)}
|
||
.lb table td,.lb table th{white-space:nowrap}.lb .you td{color:var(--molten-text)}
|
||
/* the leaderboard (7 October 2026): ten rows by default in a box of fixed height, so the page below never jumps when the toggle opens; the
|
||
extra rows scroll inside; the viewer's pinned row sits under a dashed rule */
|
||
.tbl.lb{height:432px;overflow:auto}.lb .pinned td{border-top:1px dashed var(--line-2)}.lb-more{margin:8px 0 0;font-size:12px}.lb-more .linkish{color:var(--ash)}
|
||
@media (max-width:900px){.two{grid-template-columns:1fr}}
|
||
@media (max-width:1000px){.three{grid-template-columns:1fr}}
|
||
.dp{border:var(--hair);border-radius:16px;background:var(--row);padding:25px;min-width:0}
|
||
.dp .ph{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:14px}
|
||
.dp h2{font:500 11px/1.7 var(--mono);letter-spacing:.1em;text-transform:uppercase;margin:0;color:var(--ash)}
|
||
.dp .tag{font:400 10px/1.2 var(--f-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--ash)}
|
||
.big{display:flex;align-items:baseline;gap:10px;margin-bottom:8px}
|
||
.big b{font:700 29px/1 var(--display);letter-spacing:-.04em;color:var(--bone)}
|
||
.big span{font:400 12px/1.4 var(--f-sans);color:var(--ash)}
|
||
.bars{display:flex;align-items:flex-end;gap:3px;height:80px;margin-top:10px}
|
||
.bars i{flex:1 1 0;background:linear-gradient(to top,var(--ember-40),var(--molten));border-radius:2px 2px 0 0;min-height:2px;opacity:.9}
|
||
.bars i.now{background:var(--molten)}
|
||
.axis{display:flex;justify-content:space-between;font:400 10px/1.4 var(--f-mono);color:var(--ash);margin-top:8px}
|
||
.ids{display:flex;flex-direction:column;gap:12px}
|
||
.id-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 10px;font:400 12px/1.4 var(--f-mono);color:var(--ink-2);align-items:center}
|
||
.id-row .name{display:flex;align-items:center;gap:8px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.id-row .name .sw{background:var(--line-2)}
|
||
.id-row.mine .name{color:var(--ember-text)}
|
||
.id-row.mine .name .sw{background:var(--ember)}
|
||
.id-row .pct{color:var(--bone);white-space:nowrap}
|
||
.id-row .bar{grid-column:1/-1;height:3px;background:var(--line);border-radius:2px;overflow:hidden}
|
||
.id-row .bar i{display:block;height:100%;background:var(--ember);opacity:.85}
|
||
.id-row.mine .bar i{background:var(--molten)}
|
||
.evs{display:flex;flex-direction:column;max-height:330px;overflow:auto}
|
||
.evs div{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:10px;align-items:baseline;padding:9px 0;border-bottom:var(--hair);font:400 12px/1.4 var(--f-mono);color:var(--ink-2)}
|
||
.evs div:last-child{border-bottom:0}
|
||
.evs .dot{width:6px;height:6px;background:var(--molten);border-radius:50%;animation:none}
|
||
.evs .dot.lock{background:var(--ember)}.evs .dot.quiet{background:var(--ash)}
|
||
.evs .what{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.evs .what b{font-weight:500;color:var(--bone)}
|
||
.evs .t{color:var(--ash);font-size:11px;white-space:nowrap}
|
||
.evs div.new{animation:land .9s ease-out}
|
||
@keyframes land{0%{background:var(--ember-12)}100%{background:transparent}}
|
||
@media (prefers-reduced-motion:reduce){.evs div.new{animation:none}}
|
||
.tablebar{margin-top:25px;border:var(--hair);border-radius:12px;background:var(--row)}
|
||
.tablebar summary{padding:16px 21px;font:500 var(--t-md)/1.3 var(--f-sans);color:var(--bone)}
|
||
.tablebar summary::after{content:"+";font:400 14px/1 var(--f-mono);color:var(--ash)}
|
||
.tablebar[open] summary::after{content:"\2212"}
|
||
.tablebar summary small{font:400 11px/1.4 var(--f-mono);color:var(--ash);margin-left:auto;margin-right:12px}
|
||
.tablebar .tbl{border:0;border-top:var(--hair);border-radius:0}
|
||
.tablebar table{font-size:13px}
|
||
.tablebar td,.tablebar th{padding:13px 22px}
|
||
.tablebar tr[data-hash]{cursor:pointer}
|
||
.tablebar tr[data-hash]:hover td{background:var(--hover)}
|
||
.obs-foot{display:flex;flex-wrap:wrap;justify-content:space-between;gap:10px;margin-top:25px;padding-bottom:100px;font:10px/1.8 var(--mono);color:var(--ash)}
|
||
.linkish{background:none;border:0;padding:0;color:var(--ember-text);font:inherit;cursor:pointer}
|
||
.linkish:hover{text-decoration:underline}
|
||
details.tablebar{border-top:var(--hair);border-bottom:var(--hair)}
|
||
details.tablebar summary{display:flex;align-items:center}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- nav:start -->
|
||
<a class="skip" href="#main">Skip to content</a>
|
||
<nav class="nav" aria-label="Main" data-nav-version="5">
|
||
<div class="container nav-row">
|
||
<a href="/" class="logo" aria-label="Igneum home">
|
||
<svg class="brand-mark" viewBox="0 0 1024 1024" aria-hidden="true"><rect width="1024" height="1024" rx="160" fill="#0C0C0E"></rect><g transform="translate(166.95 166.95) scale(6.901)"><polygon points="50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34" fill="#F2541B"></polygon><polygon points="50,42 59,58 50,82 41,58" fill="#0C0C0E"></polygon></g></svg>
|
||
<span class="word">IGNEUM</span>
|
||
</a>
|
||
<span class="devnet" id="nav-devnet" title="Coins have no value. The chain may reset."><span class="dot off" id="foot-dot"></span><span id="foot-state">devnet</span></span>
|
||
<div class="nav-groups" id="nav-groups" role="list">
|
||
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-mine" data-group="mine" aria-expanded="false" aria-controls="nav-panel-mine" aria-haspopup="true">Mine<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
|
||
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-network" data-group="network" data-active aria-expanded="false" aria-controls="nav-panel-network" aria-haspopup="true">Network<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
|
||
<div class="nav-group" role="listitem"><button type="button" class="group-btn" id="nav-btn-learn" data-group="learn" aria-expanded="false" aria-controls="nav-panel-learn" aria-haspopup="true">Learn<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m7 10 5 5 5-5"/></svg></button></div>
|
||
</div>
|
||
<div class="nav-controls">
|
||
<button class="btn icon-btn" type="button" data-theme-toggle aria-label="Switch to light theme"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1 1m12 12 1 1M5 19l1-1M18 6l1-1"/></svg></button>
|
||
<a href="/download" class="btn primary small cta" data-nav="download">Download</a>
|
||
<button class="burger" id="nav-burger" type="button" aria-expanded="false" aria-controls="nav-sheet" aria-label="Open the menu" aria-haspopup="true"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path class="bars" d="M4 6h16M4 12h16M4 18h16"/><path class="cross" d="m6 6 12 12M6 18 18 6"/></svg></button>
|
||
</div>
|
||
</div>
|
||
<div class="panels" id="nav-panels">
|
||
<div class="panel-wrap container">
|
||
<div class="nav-panel" id="nav-panel-mine" data-group="mine" role="region" aria-labelledby="nav-btn-mine" hidden>
|
||
<div class="panel-list">
|
||
<a href="/miner" data-nav="miner"><b>Ember, the miner</b><span>One click installs the node, the miner and the prover.</span></a>
|
||
<a href="/download" data-nav="download"><b>Download</b><span>Windows, macOS, Linux and HiveOS.</span></a>
|
||
<a href="/app" data-nav="app"><b>The app</b><span>What you see while the card mines.</span></a>
|
||
<a href="/wallet" data-nav="wallet"><b>The wallet</b><span>Your coins. Final means final.</span></a>
|
||
<a href="/miners" data-nav="miners"><b>GPU bench table</b><span>Measured rates, card by card.</span></a>
|
||
<a href="/dev-fee" data-nav="dev-fee"><b>The dev fee</b><span>The optional one, in full view, off with one flag.</span></a>
|
||
<a href="/faucet" data-nav="faucet"><b>Testnet faucet</b><span>Test coin for an address, once a day.</span></a>
|
||
<a href="/metamask" data-nav="metamask"><b>Add to MetaMask</b><span>Igneum as a network in your wallet.</span></a>
|
||
</div>
|
||
</div>
|
||
<div class="nav-panel" id="nav-panel-network" data-group="network" role="region" aria-labelledby="nav-btn-network" hidden>
|
||
<div class="panel-list">
|
||
<a href="/live" data-nav="live" aria-current="page"><b>Live devnet</b><span>The chain as it grows, one lane per miner.</span></a>
|
||
<a href="/explorer" data-nav="explorer"><b>Explorer</b><span>Look a block or an address up.</span></a>
|
||
<a href="/journey" data-nav="journey"><b>The journey</b><span>Six phases, four gates, the log behind them.</span></a>
|
||
<a href="/bench" data-nav="bench"><b>Engineering log</b><span>Every measurement, with the commands that made it.</span></a>
|
||
<a href="/evidence" data-nav="evidence"><b>Evidence</b><span>Every claim and how far it is tested.</span></a>
|
||
</div>
|
||
</div>
|
||
<div class="nav-panel" id="nav-panel-learn" data-group="learn" role="region" aria-labelledby="nav-btn-learn" hidden>
|
||
<div class="panel-list">
|
||
<a href="/litepaper" data-nav="litepaper"><b>Litepaper</b><span>The design, as published.</span></a>
|
||
<a href="/ledger" data-nav="ledger"><b>Ledger</b><span>Every criticism, answered or conceded.</span></a>
|
||
<a href="/claims" data-nav="claims"><b>What Igneum does not claim</b><span>The limits, stated first.</span></a>
|
||
<a href="/randomx" data-nav="randomx"><b>Igneum vs RandomX</b><span>What was kept and what was rebuilt for GPUs.</span></a>
|
||
<a href="/provenance" data-nav="provenance"><b>Built on the shoulders</b><span>Every borrowed part, credited.</span></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="nav-sheet" id="nav-sheet" role="dialog" aria-modal="true" aria-label="Menu" hidden>
|
||
<div class="sheet-scroll">
|
||
<div class="sheet-group"><div class="sheet-head">Mine</div>
|
||
<a href="/miner" data-nav="miner"><b>Ember, the miner</b><span>One click installs the node, the miner and the prover.</span></a>
|
||
<a href="/download" data-nav="download"><b>Download</b><span>Windows, macOS, Linux and HiveOS.</span></a>
|
||
<a href="/app" data-nav="app"><b>The app</b><span>What you see while the card mines.</span></a>
|
||
<a href="/wallet" data-nav="wallet"><b>The wallet</b><span>Your coins. Final means final.</span></a>
|
||
<a href="/miners" data-nav="miners"><b>GPU bench table</b><span>Measured rates, card by card.</span></a>
|
||
<a href="/dev-fee" data-nav="dev-fee"><b>The dev fee</b><span>The optional one, in full view, off with one flag.</span></a>
|
||
<a href="/faucet" data-nav="faucet"><b>Testnet faucet</b><span>Test coin for an address, once a day.</span></a>
|
||
<a href="/metamask" data-nav="metamask"><b>Add to MetaMask</b><span>Igneum as a network in your wallet.</span></a>
|
||
</div>
|
||
<div class="sheet-group"><div class="sheet-head">Network</div>
|
||
<a href="/live" data-nav="live" aria-current="page"><b>Live devnet</b><span>The chain as it grows, one lane per miner.</span></a>
|
||
<a href="/explorer" data-nav="explorer"><b>Explorer</b><span>Look a block or an address up.</span></a>
|
||
<a href="/journey" data-nav="journey"><b>The journey</b><span>Six phases, four gates, the log behind them.</span></a>
|
||
<a href="/bench" data-nav="bench"><b>Engineering log</b><span>Every measurement, with the commands that made it.</span></a>
|
||
<a href="/evidence" data-nav="evidence"><b>Evidence</b><span>Every claim and how far it is tested.</span></a>
|
||
</div>
|
||
<div class="sheet-group"><div class="sheet-head">Learn</div>
|
||
<a href="/litepaper" data-nav="litepaper"><b>Litepaper</b><span>The design, as published.</span></a>
|
||
<a href="/ledger" data-nav="ledger"><b>Ledger</b><span>Every criticism, answered or conceded.</span></a>
|
||
<a href="/claims" data-nav="claims"><b>What Igneum does not claim</b><span>The limits, stated first.</span></a>
|
||
<a href="/randomx" data-nav="randomx"><b>Igneum vs RandomX</b><span>What was kept and what was rebuilt for GPUs.</span></a>
|
||
<a href="/provenance" data-nav="provenance"><b>Built on the shoulders</b><span>Every borrowed part, credited.</span></a>
|
||
</div>
|
||
<div class="sheet-foot">
|
||
<a href="/download" class="btn primary big" data-nav="download">Download</a>
|
||
<div class="sheet-social"><a href="https://discord.gg/igneum" target="_blank" rel="noopener">Discord</a><a href="https://github.com/igneum-network/spec" target="_blank" rel="noopener">GitHub</a><a href="https://www.reddit.com/user/Igneum_network/" target="_blank" rel="noopener">Reddit</a></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
<script>
|
||
(function(){
|
||
// the slim bar (site-ui-5, 7 Oct 2026): three group buttons open one panel each; the burger opens the sheet on phones.
|
||
// Keyboard: Enter or Space opens a group, Escape closes it and returns focus to its button, arrows move between the
|
||
// group buttons, Tab walks the open panel's links, a click outside closes. The theme toggle flips data-theme and stores it.
|
||
var n=document.querySelector('.nav');if(!n)return;
|
||
var btns=[].slice.call(n.querySelectorAll('.group-btn')),panels=[].slice.call(n.querySelectorAll('.nav-panel')),wrap=n.querySelector('.panels');
|
||
var burger=document.getElementById('nav-burger'),sheet=document.getElementById('nav-sheet');
|
||
function panelOf(g){return panels.filter(function(p){return p.getAttribute('data-group')===g;})[0];}
|
||
function closeAll(focusBack){var was=null;btns.forEach(function(b){if(b.getAttribute('aria-expanded')==='true')was=b;b.setAttribute('aria-expanded','false');});panels.forEach(function(p){p.hidden=true;});n.classList.remove('panel-open');if(focusBack&&was)was.focus();}
|
||
function open(g){closeAll(false);var b=btns.filter(function(x){return x.getAttribute('data-group')===g;})[0],p=panelOf(g);if(!b||!p)return;b.setAttribute('aria-expanded','true');p.hidden=false;n.classList.add('panel-open');}
|
||
btns.forEach(function(b,i){
|
||
b.addEventListener('click',function(){var on=b.getAttribute('aria-expanded')==='true';if(on)closeAll(false);else open(b.getAttribute('data-group'));});
|
||
b.addEventListener('keydown',function(e){
|
||
var k=e.key;
|
||
if(k==='ArrowRight'||k==='ArrowLeft'){e.preventDefault();var j=(i+(k==='ArrowRight'?1:btns.length-1))%btns.length;btns[j].focus();if(n.classList.contains('panel-open'))open(btns[j].getAttribute('data-group'));}
|
||
else if(k==='ArrowDown'){e.preventDefault();open(b.getAttribute('data-group'));var f=panelOf(b.getAttribute('data-group')).querySelector('a');if(f)f.focus();}
|
||
else if(k==='Escape'){closeAll(true);}
|
||
});
|
||
});
|
||
if(wrap)wrap.addEventListener('keydown',function(e){if(e.key==='Escape'){e.stopPropagation();closeAll(true);}});
|
||
document.addEventListener('click',function(e){if(!n.classList.contains('panel-open'))return;if(e.target.closest('.group-btn')||e.target.closest('.nav-panel'))return;closeAll(false);});
|
||
document.addEventListener('focusin',function(e){if(!n.classList.contains('panel-open'))return;if(n.contains(e.target))return;closeAll(false);});
|
||
document.addEventListener('keydown',function(e){if(e.key==='Escape'&&n.classList.contains('panel-open'))closeAll(true);});
|
||
// the sheet on phones
|
||
function setSheet(o){if(!burger||!sheet)return;n.classList.toggle('open',o);sheet.hidden=!o;burger.setAttribute('aria-expanded',o?'true':'false');burger.setAttribute('aria-label',o?'Close the menu':'Open the menu');document.documentElement.classList.toggle('nav-locked',o);if(o){var f=sheet.querySelector('a');if(f)f.focus();}}
|
||
if(burger&&sheet){
|
||
burger.addEventListener('click',function(){setSheet(!n.classList.contains('open'));});
|
||
sheet.addEventListener('click',function(e){if(e.target.closest('a'))setSheet(false);});
|
||
sheet.addEventListener('keydown',function(e){
|
||
if(e.key==='Escape'){setSheet(false);burger.focus();return;}
|
||
if(e.key!=='Tab')return;var f=sheet.querySelectorAll('a,button');if(!f.length)return;var first=f[0],last=f[f.length-1];
|
||
if(e.shiftKey&&document.activeElement===first){e.preventDefault();burger.focus();}else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();burger.focus();}
|
||
});
|
||
burger.addEventListener('keydown',function(e){if(e.key==='Tab'&&!e.shiftKey&&n.classList.contains('open')){e.preventDefault();var f=sheet.querySelector('a');if(f)f.focus();}});
|
||
var mq=window.matchMedia('(min-width:861px)');if(mq.addEventListener)mq.addEventListener('change',function(){setSheet(false);});
|
||
}
|
||
// the theme toggle
|
||
var t=n.querySelector('[data-theme-toggle]');
|
||
function paintToggle(){var dark=document.documentElement.getAttribute('data-theme')!=='light';t.setAttribute('aria-label',dark?'Switch to light theme':'Switch to dark theme');t.innerHTML=dark?'<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M2 12h2m16 0h2M5 5l1 1m12 12 1 1M5 19l1-1M18 6l1-1"/></svg>':'<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M20.7 13.3A8.5 8.5 0 0 1 10.7 3.3 8.5 8.5 0 1 0 20.7 13.3Z"/></svg>';}
|
||
if(t){t.addEventListener('click',function(){var v=document.documentElement.getAttribute('data-theme')==='light'?'dark':'light';document.documentElement.setAttribute('data-theme',v);try{localStorage.setItem('igneum-theme',v);}catch(e){}document.dispatchEvent(new CustomEvent('igneum-theme'));});paintToggle();document.addEventListener('igneum-theme',paintToggle);}
|
||
})();
|
||
</script>
|
||
<!-- nav:end -->
|
||
|
||
<main id="main" class="wrap obs">
|
||
<header class="obs-head" id="top">
|
||
<div>
|
||
<div class="breadcrumb"><a href="/">Igneum</a><span>/</span><span>Live devnet</span></div>
|
||
<div class="eyebrow"><span class="line"></span>Network observatory</div>
|
||
<h1>The work becomes<br><span class="accent">the chain.</span></h1>
|
||
<p>Every block has a story. Follow the connections, and find your own.</p>
|
||
</div>
|
||
<div class="side">
|
||
<div class="cta"><a href="/miner#get" class="btn primary">Download the miner</a><a href="/explorer" class="btn">Open the explorer</a></div>
|
||
<div class="state" id="live-state"><span class="dot off"></span>connecting to the observer</div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="tiles6" aria-live="polite">
|
||
<div><div class="k">Blocks / second <i>↗</i></div><div class="v tick" id="s-bps">pending</div><div class="d">counted over the node’s last 60 s; the target is 1</div></div>
|
||
<div><div class="k">Blue score <i>#</i></div><div class="v tick" id="s-blue">pending</div><div class="d">the newest block’s count of blue ancestors</div></div>
|
||
<div><div class="k">Network hash rate <i>∿</i></div><div class="v tick" id="s-hash">pending</div><div class="d">the node’s estimate from the last 1,000 blocks’ difficulty</div></div>
|
||
<div><div class="k">Active vote keys <i>◇</i></div><div class="v tick" id="s-keys">pending</div><div class="d">keys with a block in 10 min; a card runs several</div></div>
|
||
<div><div class="k">Connected peers <i>⇄</i></div><div class="v tick" id="s-peers">pending</div><div class="d">peers of the observer’s node</div></div>
|
||
<div><div class="k">Locked checkpoint <i>●</i></div><div class="v tick" id="s-lock">pending</div><div class="d" id="s-lock-d">signed by two thirds of all 30-day weight</div></div>
|
||
</div>
|
||
|
||
<section class="panel" aria-label="The block graph">
|
||
<div class="mstats">
|
||
<div><div class="mk">Blocks in window</div><div class="mv"><b id="m-blocks">0</b><small id="m-win">last 90 s</small></div><div class="mf" id="m-keys">waiting for the observer</div></div>
|
||
<div><div class="mk">Proven blocks</div><div class="mv"><b id="m-proven">0</b><small id="m-proven-pct">reading</small></div><div class="mf">of the last 10 minutes, every shard verified or paid</div></div>
|
||
<div><div class="mk">Latest checkpoint</div><div class="mv"><b id="m-cp">None</b><small id="m-cp-w"></small></div><div class="mf" id="m-cp-note">no checkpoint in the reply</div></div>
|
||
</div>
|
||
<div class="toolbar">
|
||
<div class="title"><i></i>The block graph</div>
|
||
<span class="chip" id="c-count">0 blocks</span>
|
||
<div class="tabs" role="tablist" aria-label="Which blocks">
|
||
<button type="button" class="tab on" data-filter="all" aria-pressed="true">All blocks</button>
|
||
<button type="button" class="tab" data-filter="chain" aria-pressed="false">Selected chain</button>
|
||
</div>
|
||
<div class="right">
|
||
<span class="chip" id="lane-caption">keys</span>
|
||
<span class="sep"></span>
|
||
<button type="button" class="tb" id="dag-pause" aria-pressed="false">Pause</button>
|
||
<button type="button" class="tb on" id="dag-follow">Follow</button>
|
||
</div>
|
||
</div>
|
||
<div class="graph">
|
||
<div class="gcol">
|
||
<div class="scene"><div class="state" id="dag-state"><span class="dot off"></span>connecting to the observer</div><canvas id="dag" aria-label="The devnet's block graph, live: time-aligned miner lanes, every parent connection, the selected chain as one path, checkpoint bands, your blocks framed"></canvas><div class="tip" id="dag-tip" hidden></div><div class="chip-zoom" id="dag-chip" hidden>scroll to zoom · Esc to release</div></div>
|
||
<div class="gtop">
|
||
<span class="hint">Click to inspect · Drag to explore</span>
|
||
<div class="lg" aria-label="Key">
|
||
<span><i class="lgi" style="border:1.5px solid var(--included)"></i>Included</span>
|
||
<span><i class="lgi" style="border:1.5px solid var(--excluded)"></i>Excluded</span>
|
||
<span><i class="lgi" style="border:1.5px solid var(--ember);background:var(--ember-12)"></i>Selected chain</span>
|
||
<span><i class="lgi tick"></i>Proven</span>
|
||
<span><i class="lgi" style="border:1.5px solid var(--ember);border-radius:50%"></i>Locked checkpoint</span>
|
||
</div>
|
||
<span class="zoom"><button type="button" id="z-out" aria-label="Wider window">−</button><span id="z-pct">60 s</span><button type="button" id="z-in" aria-label="Narrower window">+</button></span>
|
||
</div>
|
||
<div class="gunder"><span id="blue-range">blue score pending</span></div>
|
||
</div>
|
||
<aside class="icol" id="inspector" aria-live="polite">
|
||
<div class="ih"><div class="eyebrow">Block inspector</div><span class="chip" id="i-kind">select a block</span><button type="button" class="btn small" id="insp-close" hidden>Clear</button></div>
|
||
<h3 class="ititle" id="i-title">Select a block</h3>
|
||
<div class="hash" id="i-hash">Click the graph, or a row of the table below.</div>
|
||
<div class="proof-scene"><canvas id="proof" aria-label="Select a block to see its shards"></canvas></div>
|
||
<div class="proof-head"><span>Proof shards</span><span id="i-shard-count" class="mono">not set</span></div>
|
||
<div class="track" id="i-track"></div>
|
||
<ul class="shards" id="i-shards"><li class="muted">No block selected.</li></ul>
|
||
<dl class="insp">
|
||
<dt>Inclusion</dt><dd id="i-incl">not set</dd>
|
||
<dt>Miner key</dt><dd id="i-miner">not set</dd>
|
||
<dt>Blue score</dt><dd id="i-blue">not set</dd>
|
||
<dt>DAA score</dt><dd id="i-daa">not set</dd>
|
||
<dt>Parent links</dt><dd id="i-parents">not set</dd>
|
||
<dt>Header time</dt><dd id="i-time">not set</dd>
|
||
<dt>Checkpoint</dt><dd id="i-cp">not set</dd>
|
||
<dt>Finality</dt><dd id="i-lock">not set</dd>
|
||
</dl>
|
||
<p class="note">Proof, chain selection and finality are separate states. None is inferred from a block’s age; a lock is drawn only when the observer reports one.</p>
|
||
</aside>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="motion">
|
||
<h2>Motion, with meaning.</h2>
|
||
<div class="beats">
|
||
<div><span class="num">01</span><h3>A block arrives.</h3><p>A brief signal traces its real parent edges.</p></div>
|
||
<div><span class="num">02</span><h3>The proof takes shape.</h3><p>Shard tiles follow the planned, proving, verified and paid states the observer reports.</p></div>
|
||
<div><span class="num">03</span><h3>A checkpoint locks.</h3><p>A pending marker becomes a solid band only when the observer reports it locked.</p></div>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="three">
|
||
<div class="dp">
|
||
<div class="ph"><h2>Block activity</h2><span class="tag">header times / window</span></div>
|
||
<div class="big"><b id="a-count">0</b><span>blocks in this view</span></div>
|
||
<div class="bars" id="a-bars" aria-label="Blocks per minute over the last hour, newest on the right"></div>
|
||
<div class="axis"><span>one bar a minute, the last 30 min</span><span>now</span></div>
|
||
<p class="note" id="a-note" style="margin-top:12px;font-size:12px">Counted by the observer as blocks arrive.</p>
|
||
</div>
|
||
<div class="dp">
|
||
<div class="ph"><h2>Mining identities</h2><span class="tag">displayed window</span></div>
|
||
<div class="ids" id="miners"><div class="empty">No blocks in the window.</div></div>
|
||
<p class="note" style="margin-top:14px;font-size:12px" id="miners-more">Vote-key share of the displayed blocks. Several keys may belong to one GPU.</p>
|
||
</div>
|
||
<div class="dp">
|
||
<div class="ph"><h2>Event stream</h2><span class="tag" id="ev-count">live</span></div>
|
||
<div class="evs" id="events"><div class="empty">Waiting for the first read.</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="two" id="weights">
|
||
<div class="dp">
|
||
<div class="ph"><h2>Weight leaderboard</h2><span class="tag" id="w-tag">30-day weight</span></div>
|
||
<div class="tbl lb"><table>
|
||
<thead><tr><th class="num">Rank</th><th>Key</th><th class="num">Blocks in window</th><th class="num">Presence</th><th>Last block</th></tr></thead>
|
||
<tbody id="w-body"><tr><td colspan="5">Waiting for the first read.</td></tr></tbody>
|
||
</table></div>
|
||
<p class="lb-more"><button type="button" class="linkish" id="w-toggle" hidden>Show top 20</button></p>
|
||
<p class="note" style="margin-top:14px;font-size:12px" id="w-note">Weight is blue blocks over the window, never hashrate: a card that arrived today sits at the bottom. The dust line and the window are read from the node.</p>
|
||
</div>
|
||
<div class="dp">
|
||
<div class="ph"><h2>Who is mining</h2><span class="tag">10 minutes</span></div>
|
||
<div class="ids" id="census"><div class="empty">Waiting for the first read.</div></div>
|
||
<p class="note" style="margin-top:14px;font-size:12px">Counted from the observer’s reply. The card-by-card hardware census arrives with the app’s “Make my page public” switch; until then no card model is shown.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<details class="tablebar" id="table">
|
||
<summary>Explore blocks as a table <small>keyboard-accessible view</small></summary>
|
||
<div class="tbl"><table>
|
||
<thead><tr><th>Blue score</th><th>Hash</th><th>Vote key</th><th>Parents</th><th>State</th><th>Chain block</th></tr></thead>
|
||
<tbody id="tbody"><tr><td colspan="6">Waiting for the first read.</td></tr></tbody>
|
||
</table></div>
|
||
</details>
|
||
|
||
<div class="obs-foot"><span>Igneum / observatory</span><span>One node read every 2 s. Nothing here is a replay.</span></div>
|
||
</main>
|
||
|
||
<!-- footer:start -->
|
||
<footer class="site-footer">
|
||
<div class="container">
|
||
<div class="footer-grid">
|
||
<div class="footer-brand">
|
||
<a href="/" class="logo" aria-label="Igneum home"><svg class="brand-mark" viewBox="0 0 1024 1024" aria-hidden="true"><rect width="1024" height="1024" rx="160" fill="#0C0C0E"></rect><g transform="translate(166.95 166.95) scale(6.901)"><polygon points="50,4 74,34 67,58 80,54 61,96 39,96 20,54 33,58 26,34" fill="#F2541B"></polygon><polygon points="50,42 59,58 50,82 41,58" fill="#0C0C0E"></polygon></g></svg><span class="word">IGNEUM</span><span class="stop">.</span></a>
|
||
<p>Mined by GPUs. Proven by fire.</p>
|
||
<div class="social" aria-label="Igneum elsewhere">
|
||
<a href="https://github.com/igneum-network/spec" target="_blank" rel="noopener" aria-label="Igneum on GitHub: the spec, the vectors and the issues"><svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true"><path d="M12 .5C5.7.5.5 5.7.5 12c0 5.1 3.3 9.4 7.9 10.9.6.1.8-.3.8-.6v-2.1c-3.2.7-3.9-1.4-3.9-1.4-.5-1.3-1.3-1.7-1.3-1.7-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.7 1.3 3.4 1 .1-.8.4-1.3.7-1.6-2.6-.3-5.3-1.3-5.3-5.7 0-1.3.5-2.3 1.2-3.1-.1-.3-.5-1.5.1-3.1 0 0 1-.3 3.2 1.2.9-.3 1.9-.4 2.9-.4s2 .1 2.9.4c2.2-1.5 3.2-1.2 3.2-1.2.6 1.6.2 2.8.1 3.1.8.8 1.2 1.8 1.2 3.1 0 4.4-2.7 5.4-5.3 5.7.4.4.8 1.1.8 2.2v3.2c0 .3.2.7.8.6 4.6-1.5 7.9-5.8 7.9-10.9C23.5 5.7 18.3.5 12 .5z"></path></svg></a>
|
||
<a href="https://discord.gg/igneum" target="_blank" rel="noopener" aria-label="The Igneum Discord"><svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true"><path d="M19.6 5.3A17 17 0 0 0 15.4 4l-.2.4a15.6 15.6 0 0 1 3.9 1.9 13.6 13.6 0 0 0-14.2 0A15.6 15.6 0 0 1 8.8 4.4L8.6 4a17 17 0 0 0-4.2 1.3C1.8 9.2 1.1 13 1.4 16.7a17.1 17.1 0 0 0 5.2 2.6l1.1-1.8a10.8 10.8 0 0 1-1.7-.8l.4-.3a12.2 12.2 0 0 0 11.2 0l.4.3-1.7.8 1.1 1.8a17 17 0 0 0 5.2-2.6c.4-4.3-.7-8-3-11.4zM8.7 14.4c-1 0-1.8-.9-1.8-2.1s.8-2.1 1.8-2.1 1.9 1 1.8 2.1c0 1.2-.8 2.1-1.8 2.1zm6.6 0c-1 0-1.8-.9-1.8-2.1s.8-2.1 1.8-2.1 1.9 1 1.8 2.1c0 1.2-.8 2.1-1.8 2.1z"></path></svg></a>
|
||
<a data-social="reddit" href="https://www.reddit.com/user/Igneum_network/" target="_blank" rel="noopener" aria-label="Igneum on Reddit"><svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor" aria-hidden="true"><path d="M22 12.1a2.2 2.2 0 0 0-3.7-1.6 10.8 10.8 0 0 0-5.8-1.8l1-4.6 3.2.7a1.5 1.5 0 1 0 .2-.9l-3.6-.8a.5.5 0 0 0-.5.4l-1.1 5.2a10.8 10.8 0 0 0-5.9 1.8A2.2 2.2 0 1 0 3.4 14a4.3 4.3 0 0 0 0 .7c0 3.4 3.9 6.1 8.6 6.1s8.6-2.7 8.6-6.1a4.3 4.3 0 0 0 0-.7 2.2 2.2 0 0 0 1.4-1.9zM7 13.6a1.5 1.5 0 1 1 1.5 1.5A1.5 1.5 0 0 1 7 13.6zm8.6 4.1a5.7 5.7 0 0 1-3.6 1.1 5.7 5.7 0 0 1-3.6-1.1.4.4 0 0 1 .6-.6 4.9 4.9 0 0 0 3 .9 4.9 4.9 0 0 0 3-.9.4.4 0 0 1 .6.6zm-.3-2.6a1.5 1.5 0 1 1 1.5-1.5 1.5 1.5 0 0 1-1.5 1.5z"></path></svg></a>
|
||
</div>
|
||
<div class="footer-dl" aria-label="Download Ember"><a href="/download#windows"><span class="osmark mini" data-os="windows" title="Windows"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="M3 5.6l7.3-1v7.1H3zM11.4 4.4L21 3v8.7h-9.6zM3 12.3h7.3v7.1L3 18.4zM11.4 12.3H21V21l-9.6-1.4z"/></svg></span>Windows</a><a href="/download#mac"><span class="osmark mini" data-os="mac" title="macOS"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="M16.4 12.6c0-2.5 2-3.6 2.1-3.7-1.2-1.7-3-1.9-3.6-2-1.5-.2-3 .9-3.8.9-.8 0-2-.9-3.3-.8-1.7 0-3.2 1-4.1 2.5-1.8 3-.5 7.6 1.3 10.1.9 1.2 1.9 2.6 3.2 2.5 1.3 0 1.8-.8 3.3-.8 1.6 0 2 .8 3.3.8 1.4 0 2.3-1.2 3.1-2.5 1-1.4 1.4-2.8 1.4-2.9 0 0-2.7-1-2.9-4.1zM13.9 5.3c.7-.8 1.2-2 1-3.2-1 0-2.2.7-2.9 1.5-.6.7-1.2 1.9-1 3 1.1.1 2.2-.5 2.9-1.3z"/></svg></span>macOS</a><a href="/download#linux"><span class="osmark mini" data-os="linux" title="Linux"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="currentColor"><path d="M12 2c-2.4 0-4 1.9-4 4.6 0 1.2.2 2 0 2.8-.6 1.4-2.1 2.9-2.6 4.9-.3 1.1-.1 2 .3 2.6-.6.4-1.3 1-1.1 1.7.3 1 2.1 1.2 3.2 1.8.7.4 1.5.6 2.1.1.6.2 1.3.3 2.1.3s1.5-.1 2.1-.3c.6.5 1.4.3 2.1-.1 1.1-.6 2.9-.8 3.2-1.8.2-.7-.5-1.3-1.1-1.7.4-.6.6-1.5.3-2.6-.5-2-2-3.5-2.6-4.9-.2-.8 0-1.6 0-2.8C16 3.9 14.4 2 12 2zm-1.4 4.2c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zm2.8 0c.5 0 .8.5.8 1.2s-.3 1.2-.8 1.2-.8-.5-.8-1.2.3-1.2.8-1.2zM12 9.3c.9 0 1.9.5 1.9 1s-1 1.2-1.9 1.2-1.9-.7-1.9-1.2 1-1 1.9-1zm0 3.4c2.2 0 3.6 2.6 3.6 4.4 0 1.5-1.6 2.3-3.6 2.3s-3.6-.8-3.6-2.3c0-1.8 1.4-4.4 3.6-4.4z"/></svg></span>Linux</a><a href="/download#hive"><span class="osmark mini" data-os="hive" title="HiveOS"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round" stroke-linecap="round"><path d="M12 2.6 20.2 7.3v9.4L12 21.4 3.8 16.7V7.3z"/><path d="M12 7.4 16 9.7v4.6L12 16.6 8 14.3V9.7z"/><path d="M12 7.4V2.6M16 9.7l4.2-2.4M16 14.3l4.2 2.4M12 16.6v4.8M8 14.3l-4.2 2.4M8 9.7 3.8 7.3"/></svg></span>HiveOS</a></div>
|
||
<a href="https://github.com/igneum-network/spec" target="_blank" rel="noopener" class="text-link">Specification and test vectors<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 18 18 6M6 6h12v12"/></svg></a>
|
||
</div>
|
||
<div class="footer-column"><h4>Run</h4><div>
|
||
<a href="/download">Download Ember</a>
|
||
<a href="/miner">The miner</a>
|
||
<a href="/app">The app</a>
|
||
<a href="/wallet">The wallet</a>
|
||
<a href="/miners">GPU bench table</a>
|
||
<a href="/dev-fee">The dev fee</a>
|
||
<a href="/faucet">Testnet faucet</a>
|
||
<a href="/metamask">Add Igneum to MetaMask</a>
|
||
</div></div>
|
||
<div class="footer-column"><h4>Read</h4><div>
|
||
<a href="/litepaper">Litepaper</a>
|
||
<a href="/evidence">Evidence</a>
|
||
<a href="/bench">Engineering log</a>
|
||
<a href="/ledger">Ledger: every criticism</a>
|
||
<a href="/claims">What Igneum does not claim</a>
|
||
<a href="/randomx">Igneum vs RandomX</a>
|
||
<a href="/provenance">Built on the shoulders</a>
|
||
</div></div>
|
||
<div class="footer-column"><h4>Explore</h4><div>
|
||
<a href="/live">Live devnet</a>
|
||
<a href="/explorer">Explorer</a>
|
||
<a href="/journey">Journey</a>
|
||
<a href="/download">Downloads: devnet build</a>
|
||
<a href="https://discord.gg/igneum" target="_blank" rel="noopener">Community Discord</a>
|
||
<a href="mailto:hello@igneum.network">hello@igneum.network</a>
|
||
<a href="https://github.com/igneum-network/spec/issues" rel="noopener">An issue on the spec</a>
|
||
</div></div>
|
||
</div>
|
||
<div class="footer-bottom">
|
||
<p>Igneum Labs LTD · Unit IH-00-01-01-OF-01, Level 01, Innovation One, Dubai International Financial Centre. Experimental software. Nothing on this site is an offer to sell anything.<br>Report a flaw by email or by an issue on the spec. Nobody from Igneum will ask for your seed. © 2026 Igneum · not an offer to sell anything</p>
|
||
<div class="theme-group" role="group" aria-label="Theme"><button type="button" data-theme-set="system" aria-pressed="true">System</button><button type="button" data-theme-set="light" aria-pressed="false">Light</button><button type="button" data-theme-set="dark" aria-pressed="false">Dark</button></div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
|
||
<script>
|
||
(function(){
|
||
// theme control: stores light or dark under igneum-theme; system clears it and follows the OS. The head applied the value before paint.
|
||
var bs=document.querySelectorAll('[data-theme-set]');if(!bs.length)return;
|
||
var media=window.matchMedia('(prefers-color-scheme: light)');
|
||
function stored(){try{var t=localStorage.getItem('igneum-theme');return t==='light'||t==='dark'?t:'system';}catch(e){return 'system';}}
|
||
function apply(){var c=stored();document.documentElement.setAttribute('data-theme',c==='system'?(media.matches?'light':'dark'):c);bs.forEach(function(b){b.setAttribute('aria-pressed',b.getAttribute('data-theme-set')===c?'true':'false');});document.dispatchEvent(new CustomEvent('igneum-theme'));}
|
||
bs.forEach(function(b){b.addEventListener('click',function(){var v=b.getAttribute('data-theme-set');try{if(v==='system')localStorage.removeItem('igneum-theme');else localStorage.setItem('igneum-theme',v);}catch(e){}apply();});});
|
||
if(media.addEventListener)media.addEventListener('change',function(){if(stored()==='system')apply();});
|
||
document.addEventListener('igneum-theme',function(){var c=stored();bs.forEach(function(b){b.setAttribute('aria-pressed',b.getAttribute('data-theme-set')===c?'true':'false');});});
|
||
bs.forEach(function(b){b.setAttribute('aria-pressed',b.getAttribute('data-theme-set')===stored()?'true':'false');});
|
||
// the network state word in the status bar: one read of the observer per page view
|
||
var fs=document.getElementById('foot-state'),fd=document.getElementById('foot-dot');if(fs&&fd){fetch('/api/live?window=30',{cache:'no-store'}).then(function(r){return r.json();}).then(function(d){var on=d&&d.ok&&d.state&&!d.state.stale;fs.textContent=on?'devnet live':'devnet, observer stale';fd.className='dot '+(on?'live':'off');}).catch(function(){fs.textContent='devnet';});}
|
||
})();
|
||
</script>
|
||
<!-- footer:end -->
|
||
|
||
<script src="/leaderboard.js"></script>
|
||
<script src="/live-dag.js" defer></script>
|
||
<script src="/proof-core.js" defer></script>
|
||
<script>
|
||
(function(){
|
||
function $(id){return document.getElementById(id);}
|
||
var fmtN=function(v){return v===null||v===undefined?'pending':Number(v).toLocaleString('en-GB');};
|
||
function fmtHash(h){if(h===null||h===undefined||!(h>0))return 'pending';return h>=1e9?(h/1e9).toFixed(1)+' GH/s':(h/1e6).toFixed(1)+' MH/s';}
|
||
function rel(ms){var s=Math.max(0,Math.round(ms/1000));if(s<60)return s+' s ago';var m=Math.floor(s/60);if(m<60)return m+' min ago';var h=Math.floor(m/60);if(h<24)return h+' h ago';return Math.floor(h/24)+' d ago';}
|
||
function hms(ms){var d=new Date(ms);return String(d.getUTCHours()).padStart(2,'0')+':'+String(d.getUTCMinutes()).padStart(2,'0')+':'+String(d.getUTCSeconds()).padStart(2,'0');}
|
||
function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');}
|
||
// a number that changed glows for a frame: motion only from a real change
|
||
function set(id,text){var el=$(id);if(!el||el.textContent===text)return;el.textContent=text;el.classList.add('flash');setTimeout(function(){el.classList.remove('flash');},60);}
|
||
var seen={},shardState={},cpState={},evSeen={},evList=[],ready=false,sel=null,lastD=null,dag=null;
|
||
var mine='';
|
||
document.addEventListener('click',function(e){var t=e.target;
|
||
var row=t&&t.closest?t.closest('tr[data-hash]'):null;if(row&&dag){dag.select(row.getAttribute('data-hash'),'table');}});
|
||
function render(d){var s=d.state,pv=d.proving,fn=d.finality,now=new Date(d.now).getTime();lastD=d;
|
||
// the weight leaderboard (the finality weights the observer relays) and the census by client (the miners' engines)
|
||
(function(){var w=fn&&fn.weights,keys=w&&w.keys?w.keys.slice():[],p=fn&&fn.params||{};keys.sort(function(a,b){return (b.blocks||0)-(a.blocks||0);});
|
||
var seen={};(d.miners||[]).forEach(function(m){seen[m.id]=m;});
|
||
$('w-tag').textContent=keys.length?keys.length+' keys · window '+fmtN(p.weightWindow)+' DAA · dust '+fmtN(p.dust):'30-day weight';
|
||
$('w-body').innerHTML=keys.length?(function(){var LB=window.IgneumLeaderboard,r=LB?LB.rows(keys,lbShow,mine):{rows:keys.slice(0,24).map(function(k,i){return Object.assign({},k,{rank:i+1,you:!!mine&&k.id===mine});}),pinned:null,toggle:null};var tg=$('w-toggle');if(tg){tg.hidden=!r.toggle;if(r.toggle){tg.textContent=r.toggle.label;tg.dataset.next=r.toggle.next;}}return r.rows.concat(r.pinned?[Object.assign({},r.pinned,{pin:true})]:[]).map(function(k){var m=seen[k.id],last=m&&m.last_seen?Math.max(0,Math.round((now-new Date(m.last_seen).getTime())/1000))+' s ago':'not in 10 min';
|
||
return '<tr'+(k.you?(k.pin?' class="you pinned"':' class="you"'):'')+'><td class="num">'+k.rank+'</td><td class="mono">'+esc(k.id)+(k.you?' (you)':'')+'</td><td class="num">'+fmtN(k.blocks)+'</td><td class="num">'+(!k.voter?(k.stripped_until_daa?'stripped':'under dust'):k.participation===null||k.participation===undefined?'pending':Math.round(k.participation*100)+'%')+'</td><td>'+last+'</td></tr>';}).join('')+(keys.length>24?'<tr><td colspan="5">and '+(keys.length-24)+' more keys</td></tr>':''):'<tr><td colspan="5">No weights in the reply.</td></tr>';
|
||
var tot=(d.miners||[]).length,voters=keys.filter(function(k){return k.voter;}).length,signing=keys.filter(function(k){return k.voter&&k.participation>=.9;}).length,lock=null;(fn&&fn.checkpoints||[]).forEach(function(c){if(c.state==='locked'&&(!lock||c.index>lock.index))lock=c;});
|
||
var rows=[['Keys with a block in 10 min',tot,tot],['Voters above the dust line',voters,keys.length||tot],['Voters signing 90% of points or more',signing,voters],['Weight signing at the last lock',lock&&lock.fraction_total!==null&&lock.fraction_total!==undefined?Math.round(lock.fraction_total*100)+'%':'pending',null]];
|
||
$('census').innerHTML=rows.map(function(r){var pc=r[2]&&typeof r[1]==='number'?r[1]/r[2]*100:(typeof r[1]==='string'&&/%$/.test(r[1])?parseFloat(r[1]):0);return '<div class="id-row"><span class="name"><i class="sw"></i>'+r[0]+'</span><span class="pct">'+(typeof r[1]==='number'?fmtN(r[1])+(r[2]&&r[2]!==r[1]?' of '+fmtN(r[2]):''):r[1])+'</span><span class="bar"><i style="width:'+Math.min(100,pc).toFixed(1)+'%"></i></span></div>';}).join('');})();
|
||
// the six tiles
|
||
set('s-bps',s.blocks_per_second_60s!==null&&s.blocks_per_second_60s!==undefined?Number(s.blocks_per_second_60s).toFixed(2):'pending');
|
||
set('s-blue',fmtN(s.blue_score));set('s-hash',fmtHash(s.hashes_per_second_estimate));
|
||
set('s-keys',fmtN(s.miners_10m!==null&&s.miners_10m!==undefined?s.miners_10m:(d.miners||[]).length));set('s-peers',fmtN(s.peers));
|
||
var lock=null;if(fn&&fn.checkpoints)fn.checkpoints.forEach(function(c){if(c.state==='locked'&&(!lock||c.index>lock.index))lock=c;});
|
||
var le=$('s-lock');if(fn&&fn.supported&&!fn.active){set('s-lock',fn.latest_locked_index?'#'+fmtN(fn.latest_locked_index):'none');le.className='v tick';$('s-lock-d').textContent='finality paused: under two thirds of the weight is signing';}
|
||
else if(lock){set('s-lock','#'+fmtN(lock.index));le.className='v tick';var t=lock.locked_at?new Date(String(lock.locked_at).replace(' ','T')).getTime():NaN;$('s-lock-d').textContent=(isNaN(t)?'locked':'locked '+rel(now-t))+(lock.fraction_total?' with '+Math.round(lock.fraction_total*100)+'% of all 30-day weight':'');}
|
||
else{set('s-lock',fn&&fn.supported?'none yet':'no rule');le.className='v tick word';$('s-lock-d').textContent=fn&&fn.supported?'the 30-day weight window is filling':'';}
|
||
// the graph's count, the blue range, the chain-only view
|
||
var vr=dag?dag.getViewRange():null,w=dag?dag.getWindow():90,cut=vr?vr.start:now-w*1000,top0=vr?vr.end:now,on=[];(d.blocks||[]).forEach(function(b){if(b.ts>=cut&&b.ts<=top0)on.push(b);});
|
||
// block activity: the last 30 minutes, one bar a minute, from the observer's per-minute counts
|
||
var bpm=(s.blocks_per_minute||[]).slice(-30),max=Math.max(1,Math.max.apply(null,bpm.map(function(p){return p[1]||0;}).concat([1])));
|
||
$('a-count').textContent=on.length;$('a-bars').innerHTML=bpm.map(function(p,i){return '<i style="height:'+Math.max(2,Math.round((p[1]||0)/max*100))+'%" title="'+(p[1]||0)+' blocks"'+(i===bpm.length-1?' class="now"':'')+'></i>';}).join('');
|
||
var tot30=bpm.reduce(function(a,p){return a+(p[1]||0);},0);$('a-note').textContent=fmtN(tot30)+' blocks in the last '+bpm.length+' min, '+(bpm.length?(tot30/bpm.length).toFixed(1):'0')+' a minute on average; the target is 60.';
|
||
// mining identities: share of the displayed blocks, the reader's own key marked when known
|
||
var share={},tot=0;on.forEach(function(b){share[b.miner]=(share[b.miner]||0)+1;tot++;});var ids=Object.keys(share).sort(function(a,b){return share[b]-share[a];}),mel=$('miners');
|
||
if(ids.length){var top=ids.slice(0,8),rest=ids.length-top.length;mel.innerHTML=top.map(function(id){var n=share[id],pc=n/tot*100;return '<div class="id-row'+(mine&&id===mine?' mine':'')+'"><span class="name"><i class="sw"></i>'+esc(id)+(mine&&id===mine?' (you)':'')+'</span><span class="pct">'+pc.toFixed(1)+'%</span><div class="bar"><i style="width:'+Math.round(pc)+'%"></i></div></div>';}).join('');
|
||
$('miners-more').textContent=(rest>0?'and '+rest+' more. ':'')+'Vote-key share of the displayed blocks. Several keys may belong to one GPU.';}
|
||
else mel.innerHTML='<div class="empty">No blocks in the window.</div>';
|
||
// the event stream: the observer's own events plus what changed between reads
|
||
var evs=[];(d.events||[]).forEach(function(e){evs.push({ts:new Date(e.ts).getTime(),k:e.kind.replace(/_/g,' '),cls:e.kind==='checkpoint_locked'?'lock':/quiet/.test(e.kind)?'quiet':'',text:e.text});});
|
||
(d.blocks||[]).forEach(function(b){if(!seen[b.hash]){seen[b.hash]=1;if(ready)evs.push({ts:b.ts,k:'Block observed',cls:'',text:(b.number?'#'+fmtN(b.number):b.hash)+' by '+b.miner});}
|
||
(b.shards||[]).forEach(function(sh){var key=b.hash+':'+sh.i,prev=shardState[key];shardState[key]=sh.state;if(ready&&prev!==sh.state&&(sh.state==='verified'||sh.state==='paid'))evs.push({ts:now,k:sh.state==='paid'?'Shard paid':'Shard proven',cls:'',text:(sh.i+1)+' of '+sh.n+' for '+(b.number?'#'+fmtN(b.number):b.hash)+(sh.prover?' by '+sh.prover:'')});});});
|
||
if(fn&&fn.checkpoints)fn.checkpoints.forEach(function(c){var prev=cpState[c.index];cpState[c.index]=c.state;if(ready&&prev!==c.state)evs.push({ts:c.state==='locked'&&c.locked_at?new Date(String(c.locked_at).replace(' ','T')).getTime():now,k:'Checkpoint '+c.state,cls:c.state==='locked'?'lock':'',text:'#'+fmtN(c.index)+(c.fraction_total?', '+Math.round(c.fraction_total*100)+'% of weight':'')});});
|
||
evs.forEach(function(e){var id=e.k+'|'+e.text+'|'+Math.round(e.ts/1000);if(!evSeen[id]){evSeen[id]=1;evList.unshift({id:id,fresh:ready,ts:e.ts,k:e.k,cls:e.cls,text:e.text});}});
|
||
evList.sort(function(a,b){return b.ts-a.ts;});evList=evList.slice(0,14);ready=true;
|
||
var eel=$('events');if(evList.length){eel.innerHTML=evList.map(function(e){var f=e.fresh;e.fresh=false;return '<div'+(f?' class="new"':'')+'><span class="dot '+e.cls+'"></span><span class="what"><b>'+esc(e.k)+'</b> '+esc(e.text)+'</span><span class="t">'+hms(e.ts)+'</span></div>';}).join('');$('ev-count').textContent=evList.length+' recent';}
|
||
// the table: the displayed blocks, newest first
|
||
var rows=on.slice().sort(function(a,b){return b.blue_score-a.blue_score;}).slice(0,40);
|
||
$('tbody').innerHTML=rows.length?rows.map(function(b){var word=b.locked?'locked checkpoint':b.proven?'proven':b.color==='red'?'excluded':b.chain?'selected chain':b.color==='blue'?'included':'pending';return '<tr data-hash="'+esc(b.hash)+'"><td class="num">'+fmtN(b.blue_score)+'</td><td>'+esc(b.hash)+'</td><td>'+esc(b.miner)+'</td><td class="num">'+(b.parents||[]).length+'</td><td>'+word+'</td><td class="num">'+(b.number?fmtN(b.number):'')+'</td></tr>';}).join(''):'<tr><td colspan="6">No blocks in the window.</td></tr>';}).join('');})():;
|
||
}
|
||
// the inspector: the pack's selected record, kept fresh on every reply through onSelect(block, 'update'); the proof scene is IgneumProof
|
||
var proof=null;
|
||
function inspect(b){sel=b;$('insp-close').hidden=false;var mineB=mine&&b.miner===mine;$('i-kind').textContent=mineB?'your block':b.locked?'checkpoint':b.chain?'chain block':b.color==='red'?'excluded':'side block';
|
||
$('i-title').textContent=b.locked?'Checkpoint locked':b.proven?'Proof complete':(b.shards||[]).some(function(x){return x.state==='proving';})?'Proof in progress':'Block observed';
|
||
$('i-hash').textContent=b.hash+(b.number?' · #'+fmtN(b.number):'');
|
||
var sh=b.shards||[],done=sh.filter(function(x){return x.state==='verified'||x.state==='paid';}).length;
|
||
var sw=window.IgneumDag&&IgneumDag.shardWords?IgneumDag.shardWords(b,Date.now()):{summary:sh.length?'':'no shard plan',items:sh.map(function(x){return {word:x.state};})},cap=function(s){return s.replace(/^./,function(c){return c.toUpperCase();});};
|
||
$('i-shard-count').textContent=sh.length?done+' / '+sh.length+' complete':sw.summary;$('i-track').innerHTML=sh.map(function(x){return '<i class="'+esc(x.state)+'"></i>';}).join('');
|
||
$('i-shards').innerHTML=sh.length?sh.map(function(x,i){return '<li class="'+esc(x.state)+'"><span>Shard '+String(i+1).padStart(2,'0')+'</span><span>'+esc(cap(sw.items[i]?sw.items[i].word:x.state))+'</span></li>';}).join(''):'<li class="muted">'+esc(cap(sw.summary))+'.</li>';
|
||
$('i-incl').textContent=(b.color==='blue'?'Included':b.color==='red'?'Excluded':'Pending')+(b.chain?' / selected chain':'');
|
||
$('i-miner').textContent=b.miner+(mineB?' (you)':'');$('i-blue').textContent=fmtN(b.blue_score);$('i-daa').textContent=fmtN(b.daa);
|
||
$('i-parents').textContent=(b.parents||[]).length+' observed'+((b.parents||[]).length?': '+b.parents.join(', '):'');$('i-time').textContent=hms(b.ts)+' UTC';
|
||
var fn=lastD&&lastD.finality,cp=null;if(fn&&fn.checkpoints)fn.checkpoints.forEach(function(c){if(b.locked&&c.hash===b.hash)cp=c;});
|
||
$('i-cp').textContent=cp?'this block, #'+fmtN(cp.index)+(cp.fraction_total?', '+Math.round(cp.fraction_total*100)+'% of weight':''):'not a checkpoint';
|
||
$('i-lock').textContent=b.final?'Final (reported)':'Not marked final';
|
||
if(proof)proof.setBlock(b);}
|
||
function uninspect(){sel=null;$('insp-close').hidden=true;$('i-kind').textContent='select a block';$('i-title').textContent='Select a block';$('i-hash').textContent='Click the graph, or a row of the table below.';$('i-shard-count').textContent='not set';$('i-track').innerHTML='';$('i-shards').innerHTML='<li class="muted">No block selected.</li>';['i-incl','i-miner','i-blue','i-daa','i-parents','i-time','i-cp','i-lock'].forEach(function(id){$(id).textContent='not set';});if(proof)proof.setBlock(null);}
|
||
$('insp-close').addEventListener('click',function(){if(dag)dag.select(null,'clear');uninspect();});
|
||
// the four stats above the graph, from the module's own window
|
||
function miner(st){if(!dag)return;var cps=dag.getCheckpoints(),cp=cps.length?cps[cps.length-1]:null;
|
||
$('m-blocks').textContent=fmtN(st.blocks);$('m-win').textContent='last '+st.window+' s';$('m-keys').textContent=st.minerKeys+' miner keys · not a card count';$('lane-caption').textContent=st.minerKeys+' keys';
|
||
|
||
// the Proven tile reads its own 600 s window every 10 s (provenTile below): proofs land minutes after the block, so the scene's short window would read zero
|
||
$('m-cp').textContent=cp?(cp.state==='locked'?'Locked':'Pending'):'None';$('m-cp-w').textContent=cp&&cp.fraction_total!==null&&cp.fraction_total!==undefined?Math.round(cp.fraction_total*100)+'% weight':'';$('m-cp-note').textContent=cp?'#'+fmtN(cp.index)+' · blue score '+fmtN(cp.blue_score):'no checkpoint in the reply';
|
||
$('c-count').textContent=st.blocks+' blocks';var r=dag.getViewRange(),lo=null,hi=null;dag.getBlocks().forEach(function(b){if(b.ts>=r.start&&b.ts<=r.end){if(lo===null||b.blue_score<lo)lo=b.blue_score;if(hi===null||b.blue_score>hi)hi=b.blue_score;}});$('blue-range').textContent=lo===null?'blue score pending':'blue score '+fmtN(lo)+' to '+fmtN(hi);}
|
||
var lbShow=10;document.getElementById('w-toggle').addEventListener('click',function(){lbShow=parseInt(this.dataset.next,10)||10;if(lastD)render(lastD);});
|
||
function mountDag(){if(dag||!window.IgneumDag)return;
|
||
dag=IgneumDag.mount($('dag'),{poll:false,window:60,fps:60,mine:mine||undefined,tooltip:$('dag-tip'),chip:$('dag-chip'),pauseButton:$('dag-pause'),
|
||
onWindow:function(w){$('z-pct').textContent=w+' s';if(lastD)render(lastD);},
|
||
onState:function(st,reason){var el=$('dag-state');el.className='state '+(st==='live'?'live':st==='failed'?'bad':'');el.innerHTML='<span class="dot '+(st==='live'?'live':st==='failed'?'bad':'off')+'"></span>'+(st==='live'?'live devnet':esc(reason||st));if(proof)proof.setPaused(st!=='live'||dag.getStats().paused);},
|
||
onPause:function(p){$('dag-follow').classList.toggle('on',!p);if(proof)proof.setPaused(p||dag.getState().state!=='live');},
|
||
onFollow:function(f){$('dag-follow').classList.toggle('on',f);},
|
||
onStats:miner,autoHeight:true,
|
||
onSelect:function(b,why){if(b){var full=lastD&&(lastD.blocks||[]).filter(function(x){return x.hash===b.hash;})[0];inspect(Object.assign({},b,full?{number:full.number}:{}));}else uninspect();}});
|
||
if(window.IgneumProof&&!proof)proof=IgneumProof.mount($('proof'));
|
||
if(lastD)feed(lastD);}
|
||
function remount(){if(dag){dag.destroy();dag=null;}mountDag();}
|
||
function feed(d){if(!dag)return;dag.push(d);}
|
||
if(window.IgneumDag)mountDag();else{var ms=document.querySelector('script[src="/live-dag.js"]');if(ms)ms.addEventListener('load',mountDag);}
|
||
// the Proven tile: a 600 s window of its own, read every 10 s, so the number is never zero by the proof lag alone
|
||
function provenTile(){fetch('/api/live?window=600&summary=1',{cache:'no-store'}).then(function(r){return r.json();}).then(function(d){if(!d||!d.ok)return;$('m-proven').textContent=fmtN(d.proven);$('m-proven-pct').textContent=d.chain?Math.round(d.proven/d.chain*100)+'% of '+fmtN(d.chain)+' chain blocks':'no chain blocks';}).catch(function(){});}
|
||
provenTile();setInterval(provenTile,10000);
|
||
if(!window.IgneumProof){var ps=document.querySelector('script[src="/proof-core.js"]');if(ps)ps.addEventListener('load',function(){if(dag&&!proof)proof=IgneumProof.mount($('proof'));});}
|
||
document.querySelectorAll('.tab[data-filter]').forEach(function(t){t.addEventListener('click',function(){document.querySelectorAll('.tab[data-filter]').forEach(function(x){x.classList.toggle('on',x===t);x.setAttribute('aria-pressed',x===t?'true':'false');});if(dag)dag.setFilter(t.getAttribute('data-filter'));});});
|
||
$('dag-follow').addEventListener('click',function(){if(dag){dag.setPaused(false);dag.follow();}});
|
||
$('z-in').addEventListener('click',function(){if(dag)dag.setWindow(dag.getWindow()-15);});$('z-out').addEventListener('click',function(){if(dag)dag.setWindow(dag.getWindow()+15);});
|
||
window.__dbg={render:render,feed:feed,getDag:function(){return dag;}};
|
||
function setLive(st,reason){var el=$('live-state');el.className='state '+(st==='live'?'live':st==='failed'?'bad':'');el.innerHTML='<span class="dot '+(st==='live'?'live':st==='failed'?'bad':'off')+'"></span>'+(st==='live'?'live devnet · one node read every 2 s':st==='connecting'?'connecting to the observer':esc(reason||st));}
|
||
function poll(){fetch('/api/live?window=300',{cache:'no-store'}).then(function(r){if(!r.ok)throw new Error(r.status);return r.json();}).then(function(d){if(!d.ok)throw new Error(d.error);failures=0;setLive(d.state.stale?'stale':'live',d.state.stale?'observer stale':'');render(d);feed(d);}).catch(function(){failures++;if(failures>=3)setLive('failed','live feed unavailable');});}
|
||
poll();setInterval(function(){if(!document.hidden)poll();},2000);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|