igneum/docs/api/public-stats.md
igneum-labs 50363a64f8 Base unit (O-2.6): the design, the proposed Decided sentence and the ledger row for 18 decimals
docs/design/base-unit.md: where every amount lives (UTXO value, entry, mass view, coinbase and its payload, fees, script introspection, p2p, gRPC, RPC model, JSON and wasm, wallet, UTXO index, the exec bridge, pool accounting, pool software, app display, observer and public stats, the manifest), the u128 Amount type, the serialisation and versioning table (tx version 2 for the 16-byte value, a store schema version with the u64 legacy decode, two uint64 varints on the wire with the low word on the existing field number), the EVM side (1 IGN = 10^18 wei, the bridge the identity), the devnet unchanged at 8 with its digest unmoved, the display rule (8 visible digits), the hostile review (the u64 pool share overflow, the ramp, the 66-period table, the floor at the finer unit, the storage mass constant at 10^22, dust and the relay floor, MAX_SOMPI, KIP-10 script numbers, JavaScript precision, the wrong-unit peer, the half-widened binary, Postgres bigint), the measurement (+8 B per UTXO on disk, +17 B in memory, +6.4 B per output on the wire) with the consequences by tier, and phase B in ten commits with hours (26). Spec 2.5 carries the proposed Decided sentence and the 18-decimal rate; 06-open-items O-2.6 proposed decided with its gate B10; fud-ledger E22; fork-divergence row for the fork commits (3158571c, fa61e035, fcd6b6e9, 6d5f2488 on the box mirror, branch decimals); bench-log "Base unit widening cost"; public-stats unit note; ledger-decisions row 5 lane state.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 22:15:09 +00:00

11 KiB

Public stats API

5 October 2026. Two JSON endpoints on the site for profitability sites, pool software and anyone who wants the network numbers without running a node: /api/stats and /api/supply. WhatToMine's listing form asks for an explorer or pool with an API, the reward halving schedule and a source to fetch total coins from; this is that source. A third endpoint, /api/explorer, feeds the explorer pages (docs/plans/explorer.md).

Both are served by Vercel functions (site/api/stats.mjs, site/api/supply.mjs) that read what the devnet observer (tools/observer/observer.mjs) wrote to Neon; no secret is involved beyond the database connection the site already holds. Cached 10 s at the edge (Cache-Control: public, max-age=10, s-maxage=10), CORS open (Access-Control-Allow-Origin: *), GET only. A failed read answers 500 with {ok: false, error} and Cache-Control: no-store.

The contract is the FIELDS list exported by each handler. site/api/public-stats.test.mjs checks a fixture against it without a database, and tools/ci/public-api-check.mjs <url> checks a deployment (CI runs it against https://igneum.network on master).

/api/stats

Field Meaning Source
network, chain_id, node_version Network name, EVM chain id (4461 mainnet, 4462 testnet, 4463 devnet, design 8.1), the node's version observer live_state
algorithm The lottery hash, named fixed text
stale, age_s, observer_updated_at stale when the observer has not written for 30 s; treat every number as last known then observer
height The chain block number (the EVM block number): the number of the newest chain block the observer has a shard plan for live_blocks.number
block_count, header_count Every DAG block the node holds getBlockDagInfo
daa, blue_score DAA score and blue score of the newest block live_blocks, getSinkBlueScore
difficulty The node's difficulty (target per block) getBlockDagInfo
hashrate, hashrate_unit, hashrate_source H/s: the node's estimateNetworkHashesPerSecond over 1,000 blocks, else blue work added per second over 10 min observer
block_time_target_s, block_time_measured_s 1 s by design (spec 2.1); 60 / DAG blocks in the last 60 s observer
blocks_per_day_target, blocks_per_day_measured 86,400; the last hour's DAG blocks x 24 (null until the observer has an hour) observer
block_reward E(daa) of spec 2.5 at the newest DAA score: sompi (8 decimals), ign, the 80% miner_ign and 20% proving_pool_ign, ramp_factor, halving_period, next_halving_daa, next_halving_in_s site/lib/emission.mjs
last_block Hash, time, age, blue score, DAA, coinbase address, vote key id, EVM transaction count, whether it is a chain block live_blocks
finality Finality v2: active, the latest locked checkpoint index and blue score observer
peers, mempool, miners_10m Connected peers, mempool size, distinct vote keys in 10 min (a card runs several) observer

Note for a profitability calculator: block_reward is per blue block merged; at the 1 block per second target that is also the reward per DAA second. The 20% proving-pool part is paid to provers, not to the miner of the block, so a miner's expected income per block is miner_ign. During the 30-day launch ramp the reward climbs from 10% to 100% of the schedule (ramp_factor); /api/supply shows where the ramp stands.

Example, the devnet on 5 October 2026 (through the local preview against a test observer, so block_time_measured_s reflects a one-minute window):

{
  "ok": true,
  "now": "2026-10-05T19:32:09.321Z",
  "network": "igneum-devnet",
  "chain_id": 4463,
  "node_version": "2.1.0",
  "algorithm": "Igneum lottery hash: random-program GPU hash, new program every hour, generator v2 (docs/spec/01-lottery-hash.md)",
  "stale": false,
  "age_s": 0.9,
  "height": 82145,
  "block_count": 126358,
  "header_count": 126358,
  "daa": 126357,
  "blue_score": 123504,
  "difficulty": 125543017.00697394,
  "hashrate": 258756880,
  "hashrate_unit": "H/s",
  "hashrate_source": "the node's estimateNetworkHashesPerSecond over a 1,000-block window; blue work added per second over 10 min when the node refuses the window",
  "block_time_target_s": 1,
  "block_time_measured_s": 0.952,
  "blocks_per_day_target": 86400,
  "blocks_per_day_measured": 14040,
  "block_reward": {
    "sompi": "455909062",
    "ign": "4.55909062",
    "miner_ign": "3.6472725",
    "proving_pool_ign": "0.91181812",
    "split": "80% block producer, 20% proving pool",
    "daa_used": 126357,
    "ramp_factor": 0.143874,
    "halving_period": 0,
    "next_halving_daa": 63115200,
    "next_halving_in_s": 62988843
  },
  "last_block": {
    "hash": "bbec3139d3f38e3517716374707998e77f536a67813edfb619c5bed93a5779ab",
    "time": "2026-10-05T19:32:06.157Z",
    "ts_ms": 1791228726157,
    "age_s": 3.2,
    "blue_score": 123504,
    "daa": 126357,
    "miner": "igneumdev:qrt8nzgrghr2a2xuc7lstzclcnt3n632d2chhc946rphkc6flcyswvkrym8s4",
    "miner_id": "7b8ef6fd",
    "tx_count": 0,
    "chain": true
  },
  "finality": {
    "active": true,
    "latest_locked_index": 4116,
    "latest_locked_blue_score": 123480,
    "chain_id": "igneum-devnet"
  },
  "peers": 4,
  "mempool": 0,
  "miners_10m": 21,
  "observer_updated_at": "2026-10-05T19:32:08.394726+00:00",
  "source": "tools/observer reading one node every 2 s; reward from docs/spec/02-consensus.md 2.5 at the node's DAA score"
}

/api/supply

Field Meaning
unit IGN; the devnet's coinbase pays in 8-decimal units and the EVM shows 18; the testnet and mainnet unit is 18 on both sides (O-2.6, proposed Decided 6 October 2026, docs/design/base-unit.md), so decimals_consensus reads the network's genesis parameter
daa The newest DAA score the observer stored
max_supply_ign 4,000,000,000, the hard cap (spec 2.5, no tail emission: spec 5.10)
circulating_ign, circulating_sompi Minted so far by the rule: E(t) summed over every DAA second from 0 to daa, exact (floor sum, mintedByRule)
minted_at_end_ign, never_minted_ign What the schedule reaches when the per-second rate hits 0 (period 32), and the part of the cap the ramp and the floors never mint
emission_per_second_ign, block_reward_ign E(daa) now
halving Interval 63,115,200 DAA s (two years), current period, the next halving's DAA score, seconds to it, a date estimate at one DAA second per second
ramp 10% at genesis to 100% at DAA 2,592,000 (30 days), the factor now, whether it is complete
schedule 33 rows: period, start and end DAA, years from genesis, IGN per second, IGN per block at 1 BPS, minted by the end of the period, share of the cap
check The observer's hourly comparison of the chain against the rule over its newest 500 blocks: rule_match counts blocks whose coinbase payload declares exactly E(daa); sum_match counts blocks whose coinbase outputs equal the declared subsidies of the blocks they merge; examples names mismatches
rule, source, note The formula, where it lives, and the caveat: the chain pays per block merged, so a block rate above target mints above the schedule for as long as it lasts

Example (schedule cut to five rows here):

{
  "ok": true,
  "now": "2026-10-05T19:32:09.374Z",
  "network": "igneum-devnet",
  "chain_id": 4463,
  "unit": {
    "symbol": "IGN",
    "decimals_consensus": 8,
    "decimals_evm": 18,
    "note": "the coinbase pays in 8-decimal units (open item O-2.6 keeps Kaspa's SOMPI_PER_KASPA); the EVM shows the same amount at 18 decimals"
  },
  "daa": 126357,
  "max_supply_ign": "4000000000",
  "circulating_ign": "488236.39686436",
  "circulating_sompi": "48823639686436",
  "minted_at_end_ign": "3963038988.86765648",
  "never_minted_ign": "36961011.13234352",
  "emission_per_second_ign": "4.55909062",
  "block_reward_ign": "4.55909062",
  "halving": {
    "interval_daa_s": 63115200,
    "interval_years": 2,
    "period": 0,
    "next_halving_daa": 63115200,
    "next_halving_in_s": 62988843,
    "next_halving_estimate": "2028-10-03T20:26:12.374Z",
    "estimate_note": "the estimate assumes one DAA second per wall-clock second from now"
  },
  "ramp": {
    "start_percent": 10,
    "length_daa_s": 2592000,
    "length_days": 30,
    "factor_now": 0.143874,
    "complete": false,
    "remaining_s": 2465643,
    "withheld_ign": "36961011.13234352",
    "withheld_note": "the ramp withholds about 37 million IGN that are never minted; integer floors withhold the rest (spec 2.5)"
  },
  "schedule": [
    {
      "period": 0,
      "start_daa": 0,
      "end_daa": 63115200,
      "years_from_genesis": "0 to 2",
      "per_second_ign": "31.68808781",
      "per_block_ign_at_1bps": "31.68808781",
      "minted_by_end_ign": "1963038999.85152848",
      "share_of_cap_by_end": 49.0759
    },
    {
      "period": 1,
      "start_daa": 63115200,
      "end_daa": 126230400,
      "years_from_genesis": "2 to 4",
      "per_second_ign": "15.8440439",
      "per_block_ign_at_1bps": "15.8440439",
      "minted_by_end_ign": "2963038999.40880848",
      "share_of_cap_by_end": 74.0759
    },
    {
      "period": 2,
      "start_daa": 126230400,
      "end_daa": 189345600,
      "years_from_genesis": "4 to 6",
      "per_second_ign": "7.92202195",
      "per_block_ign_at_1bps": "7.92202195",
      "minted_by_end_ign": "3463038999.18744848",
      "share_of_cap_by_end": 86.5759
    },
    "... 29 more rows ...",
    {
      "period": 32,
      "start_daa": 2019686400,
      "end_daa": 2082801600,
      "years_from_genesis": "64 to 66",
      "per_second_ign": "0",
      "per_block_ign_at_1bps": "0",
      "minted_by_end_ign": "3963038988.86765648",
      "share_of_cap_by_end": 99.0759
    }
  ],
  "check": {
    "bps": 1,
    "sampled": 470,
    "examples": [],
    "sum_match": 466,
    "checked_at": "2026-10-05T19:30:28.385Z",
    "rule_match": 470,
    "sum_skipped": 4,
    "sum_mismatch": 0,
    "rule_mismatch": 0
  },
  "rule": "E(t) = ramp(t) * floor(10^9 * UNIT / 31,557,600) >> floor(t / 63,115,200); ramp(t) = min(1, 1/10 + 9/10 * t / 2,592,000); t = DAA score / bps, bps = 1",
  "source": "docs/spec/02-consensus.md 2.5; vendor/igneum-node consensus/core/src/igneum.rs block_subsidy and launch_ramp; circulating = the rule summed over every DAA second from 0 to the node's DAA score (site/lib/emission.mjs mintedByRule, exact)",
  "note": "circulating is the schedule at this DAA score. The chain pays E per blue block it merges and per red inside the DAA window, which tracks the schedule one block per DAA step; the devnet of 3 October 2026 ran 4.7x the schedule for eight minutes during a retarget lag (spec 2.5). check reports what the observer measured on the newest blocks."
}

/api/explorer

The explorer's own feed, cached 5 s: ?blocks=N[&before=ms] (latest blocks), ?block=hash, ?height=N, ?address=0x..|igneumdev:.., ?search=q. Shapes are in site/api/explorer.mjs; the pages are the reference client. Balances need EXPLORER_EVM_RPC on the deployment (a public EVM JSON-RPC); without it balance.available is false with the reason.