argus/test/bns-indexer.test.mjs
Local Dev f9a5eb367f Theseus navigator UI overhaul, BNS-only indexer, site restructure
Theseus Navigator:
- Firefox-style toolbar: SVG back/fwd/reload/home buttons
- security padlock badge in the address bar opens a floating site-info
  overlay VIEW (on top of the page, never pushes content down)
- Edge-style favorites bar (shown only on the new-tab/home page)
- search-engine picker (DuckDuckGo/Google/Bing/Brave/Startpage)
- Theseus logo moved right, opens Settings; native menu removed
- address bar doubles as search; bottom resolver status line

Argus:
- BNS-only indexer: an electrum endpoint over a bare BCHN node
  (watches just the beacon, caches txs so no txindex needed) + test
- registry lifecycle / portfolio / name-index modules

Site restructure (nav/apps/store/hermes/choose) + runbook notes.
2026-07-30 08:16:55 +02:00

83 lines
4.5 KiB
JavaScript

// Proves the BNS-only indexer serves the electrum protocol correctly, using REAL
// chipnet data (no BCHN needed): pull the beacon history + txs from a public
// electrum, seed the indexer, serve it locally, and confirm resolver-web resolves
// a name through OUR indexer identically to the public server. Also unit-tests
// scripthashOf + processTx against a real beacon transaction.
import WebSocket from "ws";
import { resolveName, BEACON_SCRIPTHASH } from "../src/lib/resolver-web.js";
import { BeaconIndex, RpcSource, startElectrumWS, scripthashOf } from "../src/indexer/bns-indexer.js";
// Dial by IP + SNI (this machine's resolver daemon breaks Node getaddrinfo).
const PUBLIC = { url: "wss://chipnet.bch.ninja:50004", ip: "135.148.236.244" };
const PUBLIC_IPURL = "wss://135.148.236.244:50004";
const PUBLIC_SNI = "chipnet.bch.ninja";
const NAME = "hello.bch";
const PORT = 50099;
let failures = 0;
const ok = (c, m) => { console.log((c ? " ✅ " : " ❌ ") + m); if (!c) failures++; };
// tiny electrum client
function elClient(url, opts) {
return new Promise((resolve, reject) => {
const ws = new WebSocket(url, opts);
let id = 0, buf = ""; const pending = new Map();
ws.on("open", () => resolve({
call(method, params = []) {
return new Promise((res, rej) => {
const i = ++id; pending.set(i, { res, rej });
ws.send(JSON.stringify({ id: i, method, params }) + "\n");
setTimeout(() => { if (pending.has(i)) { pending.delete(i); rej(new Error("timeout " + method)); } }, 20000);
});
},
close() { ws.close(); },
}));
ws.on("error", reject);
const settle = (line) => { try { const m = JSON.parse(line); const p = pending.get(m.id); if (p) { pending.delete(m.id); m.error ? p.rej(new Error(JSON.stringify(m.error))) : p.res(m.result); } } catch {} };
ws.on("message", (d) => {
buf += d.toString(); let nl;
while ((nl = buf.indexOf("\n")) >= 0) { const line = buf.slice(0, nl).trim(); buf = buf.slice(nl + 1); if (line) settle(line); }
const rest = buf.trim(); // some servers omit the trailing newline
if (rest) { try { JSON.parse(rest); settle(rest); buf = ""; } catch {} }
});
});
}
console.log("1) pulling REAL beacon data from", PUBLIC.url, "(via IP", PUBLIC.ip + ") …");
const pub = await elClient(PUBLIC_IPURL, { servername: PUBLIC_SNI });
const history = await pub.call("blockchain.scripthash.get_history", [BEACON_SCRIPTHASH]);
ok(Array.isArray(history) && history.length > 0, `beacon history fetched (${history.length} txs)`);
const txMap = {};
for (const { tx_hash } of history) txMap[tx_hash] = await pub.call("blockchain.transaction.get", [tx_hash, true]);
ok(Object.keys(txMap).length === history.length, `fetched all ${history.length} verbose txs`);
// resolve the reference answer via the PUBLIC server (directIP → uses pinned ip)
const reference = await resolveName(NAME, { WebSocket, electrum: [PUBLIC], directIP: true });
pub.close();
ok(!!reference, `${NAME} resolves on the public server (records: ${reference ? Object.keys(reference.records) : "—"})`);
console.log("2) unit-testing scripthashOf + processTx on a real beacon tx …");
// find a real output that pays the beacon and check our scripthash math
let matched = null;
for (const tx of Object.values(txMap)) {
for (const v of tx.vout || []) {
if (v.scriptPubKey && v.scriptPubKey.hex && scripthashOf(v.scriptPubKey.hex) === BEACON_SCRIPTHASH) { matched = tx; break; }
}
if (matched) break;
}
ok(!!matched, "scripthashOf() reproduces the beacon scripthash from a real output");
const probe = new BeaconIndex(BEACON_SCRIPTHASH);
ok(matched && probe.processTx(matched, 100) === true, "processTx() flags a real beacon tx as touching");
console.log("3) serving the SAME data through our indexer and resolving through it …");
const index = new BeaconIndex(BEACON_SCRIPTHASH);
index.seed(history, txMap);
const wss = startElectrumWS(index, { bind: "127.0.0.1", port: PORT }, null); // rpc=null: cache-only
const mine = await resolveName(NAME, { WebSocket, electrum: [{ url: `ws://127.0.0.1:${PORT}` }] });
ok(!!mine, `${NAME} resolves through OUR indexer`);
ok(mine && reference && JSON.stringify(mine.records) === JSON.stringify(reference.records),
"records IDENTICAL to the public server");
ok(mine && reference && mine.category === reference.category, "token category matches");
wss.close();
console.log(failures === 0 ? "\n🎉 ALL PASSED — indexer is protocol-correct" : `\n💥 ${failures} check(s) failed`);
process.exit(failures === 0 ? 0 : 1);