// node --test tools/observer/hash-origin.test.mjs // One known-finished day (the fixture: every share adds up, the outside block and the two pools are found, the step // fires at 2.5x) and one known-failed day (an empty window passes no gate; a key with no blue block is not a key; a // day without yesterday has no ratio), per the watcher rule of CLAUDE.md (4 October 2026). import { test } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { compute, renderText, DUST_BLOCKS_30D, OUTSIDE_POOL_DAYS } from './hash-origin.mjs'; const HERE = dirname(fileURLToPath(import.meta.url)); const fixture = () => JSON.parse(readFileSync(join(HERE, 'fixtures', 'hash-origin-day.json'), 'utf8')); const close = (a, b, eps = 1e-9) => assert.ok(Math.abs(a - b) < eps, `${a} ~ ${b}`); test('the known-finished day: counts, shares, pools, fleet, the step and the gates', () => { const r = compute(fixture()); assert.equal(r.blue_blocks, 80960); assert.equal(r.keys.with_block, 10, 'the 0-blue key is not a key with a block'); assert.equal(r.keys.new_today, 7, 'three keys mined yesterday; seven are new'); // above dust over 30 days: a (58,000), b (23,000), c, d, e, f, 1, 2, 3 (900) = 9; key 4 has 90 < 100; key 5 none assert.equal(r.keys.above_dust_30d, 9); assert.equal(r.pools.attested, 2); assert.equal(r.pools.shared_payouts, 2); const project = r.pools.rows.find(p => p.kind === 'project'), outside = r.pools.rows.find(p => p.kind === 'attested'); assert.equal(project.keys, 2); assert.equal(project.blue_blocks, 15000); assert.equal(outside.keys, 2); assert.equal(outside.blue_blocks, 15000); close(r.pools.attested_share, 30000 / 80960); close(r.pools.shared_share, 30000 / 80960); assert.equal(r.fleet.keys, 3); assert.equal(r.fleet.blue_blocks, 51000); close(r.fleet.share, 51000 / 80960); assert.equal(r.outside.keys, 7); assert.equal(r.outside.blue_blocks, 29960); close(r.fleet.share + r.outside.share, 1); close(r.keys.top10_share, 1, 1e-9); close(r.network.ratio, 2.5); assert.equal(r.network.step_flag, true); assert.equal(r.gates.first_100_keys, false); assert.equal(r.gates.first_block_outside_fleet, true); assert.equal(r.gates.outside_pool_today, true, 'the outside pool holds 18.5 percent today'); assert.equal(r.gates.outside_pool_days, 2, 'today plus yesterday; the day before breaks the streak'); assert.equal(r.gates.first_outside_pool, false); assert.equal(r.gates.first_1000_independent, false); assert.equal(r.day_of_go, 2); const t = renderText(r); assert.ok(t.includes('A STEP'), 'the step is said'); assert.ok(t.includes(`2 of ${OUTSIDE_POOL_DAYS} days`)); assert.ok(!/[0-9a-f]{32}/i.test(t), 'no 32-hex token in the posted text (discord-hooks guard)'); assert.ok(!/\b\d{1,3}(\.\d{1,3}){3}\b/.test(t), 'no IP address in the posted text'); }); test('the known-failed day: an empty window passes nothing and claims nothing', () => { const r = compute({ date: '2026-10-21', blocks: [{ vote_key_hash: 'a'.repeat(64), evm_miner: 'x', blue: 0, total: 5 }], fleetKeys: ['a'.repeat(64)] }); assert.equal(r.blue_blocks, 0); assert.equal(r.keys.with_block, 0); assert.equal(r.keys.above_dust_30d, 0); assert.equal(r.pools.attested, 0); assert.equal(r.pools.shared_payouts, 0); assert.equal(r.fleet.share, null); assert.equal(r.outside.share, null); assert.equal(r.network.hps, null); assert.equal(r.network.ratio, null); assert.equal(r.network.step_flag, false); for (const g of ['first_100_keys', 'first_block_outside_fleet', 'outside_pool_today', 'first_outside_pool', 'first_1000_independent']) assert.equal(r.gates[g], false, g); assert.equal(r.day_of_go, null); assert.ok(renderText(r).includes('not yet')); }); test('the first-100 gate and the 7-day outside pool pass only on their numbers', () => { const blocks = []; for (let i = 0; i < 100; i++) blocks.push({ vote_key_hash: i.toString(16).padStart(64, '0'), evm_miner: 'igna-outside-pool', blue: 10, total: 10 }); const prev = []; for (let i = 0; i < OUTSIDE_POOL_DAYS - 1; i++) prev.push({ gates: { outside_pool_today: true }, network: { hps: 1e9 } }); const unattested = compute({ date: '2026-11-01', blocks, networkHps: 1e9, prevReports: prev }); assert.equal(unattested.gates.first_100_keys, true); assert.equal(unattested.gates.outside_pool_today, false, 'a shared payout nobody attested is not a pool'); assert.equal(unattested.pools.shared_payouts, 1); assert.equal(unattested.pools.attested, 0); const r = compute({ date: '2026-11-01', blocks, networkHps: 1e9, prevReports: prev, knownPools: ['igna-outside-pool'] }); assert.equal(r.gates.first_100_keys, true); assert.equal(r.gates.first_outside_pool, true); assert.equal(r.network.step_flag, false, '1.0x is not a step'); const r99 = compute({ date: '2026-11-01', blocks: blocks.slice(1), prevReports: prev.slice(1), knownPools: ['igna-outside-pool'] }); assert.equal(r99.gates.first_100_keys, false); assert.equal(r99.gates.first_outside_pool, false); assert.ok(DUST_BLOCKS_30D === 100); });