argus/src/cdn-name-index.mjs
Local Dev eaf4956f55 Ariadne for Android 0.20: every live TLD claimed; CDN name snapshot refreshed by the gateway
The app read its TLD set from /api/tlds `advertised` — the legacy nine —
so a name under a newer registry TLD was intercepted only once the local
index already carried it. It now reads `routable` (falling back to
`advertised` for an older gateway) and ships a bootstrap list matching
today's routed set for cold start.

The cold-start snapshot it pulls from dl.silentmode.st was produced by
publish-name-mirror.mjs, which needs the operator wallet and ran by hand:
the CDN copy was sixteen days and seven names behind. cdn-name-index.mjs
now reshapes the gateway's own /api/registry into the snapshot format on
the VPS every ten minutes (systemd timer in VPS/SilentMode), so no wallet
and no hand step are involved.
2026-09-28 02:01:55 +02:00

48 lines
2.5 KiB
JavaScript

// Keep the CDN's interpreted name index fresh from the gateway's own index.
//
// Ariadne for Android (and Theseus, via NETWORKS.cdnIndexUrl) pull
// https://dl.silentmode.st/bns-name-index.json on cold start: a snapshot of
// every registered name with its records, so the first page loads before
// the electrum walk finishes. It was produced by publish-name-mirror.mjs,
// which needs the operator wallet and ran by hand — the CDN copy went stale
// for weeks (seven names behind on 2026-09-28). The gateway already holds
// the same index in memory and serves it as /api/registry, so this script
// simply reshapes that into the snapshot format and writes the CDN file.
// Runs on the VPS from a systemd timer (VPS/SilentMode/cdn-name-index.*).
//
// node cdn-name-index.mjs [--gateway http://127.0.0.1:8700] [--out /opt/silent-mode/dl/bns-name-index.json]
//
// Snapshot shape (what Bns.java's loadDisk / pullSiaIndex parse):
// [{ name, category, records, txid, height, updatedTxid }, …]
import { readFileSync, writeFileSync, renameSync, existsSync } from "node:fs";
const args = process.argv.slice(2);
const opt = (k, d) => { const i = args.indexOf(k); return i >= 0 && args[i + 1] ? args[i + 1] : d; };
const GATEWAY = opt("--gateway", "http://127.0.0.1:8700");
const OUT = opt("--out", "/opt/silent-mode/dl/bns-name-index.json");
const MIN_NAMES = 10; // a shorter answer is a gateway still warming up, not the registry
const r = await fetch(`${GATEWAY}/api/registry`, { signal: AbortSignal.timeout(20_000) });
if (!r.ok) throw new Error(`gateway ${r.status}`);
const reg = await r.json();
const names = Array.isArray(reg.names) ? reg.names : [];
if (names.length < MIN_NAMES) throw new Error(`only ${names.length} names — not writing`);
const snapshot = names
.filter((e) => e && typeof e.name === "string" && e.records && typeof e.records === "object")
.map((e) => ({
name: e.name,
category: e.category || "",
records: e.records,
txid: e.txid || "",
height: Number(e.height) || 0,
updatedTxid: e.updated_txid ?? e.updatedTxid ?? null,
}))
.sort((a, b) => (a.height || 0) - (b.height || 0) || a.name.localeCompare(b.name));
const next = JSON.stringify(snapshot);
const prev = existsSync(OUT) ? readFileSync(OUT, "utf8") : "";
if (prev === next) { console.log(`unchanged (${snapshot.length} names)`); process.exit(0); }
writeFileSync(OUT + ".tmp", next);
renameSync(OUT + ".tmp", OUT);
console.log(`wrote ${OUT}: ${snapshot.length} names, height hint ${reg.height_hint ?? "?"}`);