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.
83 lines
4.5 KiB
JavaScript
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);
|