Chipnet, TREG on TLD_BEACON:
.cash txid 83822310a7d7d3762fb36690f4d20911177cc3f2c9b7598c593f8a8dc7e06c23
Follow-up name mints (operator wallet, chipnet):
REG bitcoin.cash txid 4a684964cc067599fdbb58d6b174bfe97a5f92046586d2f2dc9660cd4ce5d12f
UPD bitcoin.cash txid 326d0490a90d50c4c19369e6ec18db732a58ea4a1ee110d6609aae07fdefe174
(records.h = 126-byte on-chain whitepaper-style page)
Gateway /opt/bns-gateway/public-gateway.mjs updated in-place on the VPS
to build /api/tlds from a fresh buildTldSnapshot(TLD_BEACON) walk instead
of the legacy `tlds.bch` root record — so newly-minted TLDs (.cash, .coin
and the rest of the seed set) now surface in the sirius.x TLD list. That
gateway edit isn't in this repo; the change is documented here for the
audit trail.
106 lines
4.8 KiB
JavaScript
106 lines
4.8 KiB
JavaScript
// One-off (idempotent): seed the chipnet TLD-certificate beacon with the
|
|
// operator-confirmed initial TLD set. Reads what's already there via the wallet's
|
|
// provider (so re-runs skip anything present), then mints a TREG for each
|
|
// missing TLD. Verifies at the end by rebuilding the snapshot from beacon
|
|
// history — the same code path the /tld-list.json endpoint uses.
|
|
//
|
|
// node src/seed-tld-beacon.mjs
|
|
//
|
|
// Design context: Decentralized.DNS/DESIGN-tld-registry.md §9 item 1. Chipnet
|
|
// only — mainnet is a separate switch and needs the TLD covenant first.
|
|
|
|
import { loadWallet } from "./lib/wallet.js";
|
|
import { registerTld, parseOpReturn } from "./lib/bns.js";
|
|
import { buildTldSnapshot } from "./lib/tld-index.js";
|
|
import { TLD_BEACON } from "./config.js";
|
|
|
|
// Operator-confirmed seed set (2026-08-20): shipped defaults minus
|
|
// deviant/bcnr/silentmode, plus x for the coinspectrum.x work already in flight.
|
|
// Extended 2026-08-29: asm, neo, gt, sc, sia, com; then dex, cex, nt; then dea.
|
|
// The operator holds the countersignature key that would otherwise gate
|
|
// ICANN-adjacent TLDs (.com, .sc, .gt, .neo) on mainnet; on chipnet no covenant
|
|
// enforces the gate, so these are seeded directly under operator authority.
|
|
// `.com` is HELD by the operator (excluded from the public registrar UI) so
|
|
// nobody else can claim names under it — the TLD cert stays on-chain, but no
|
|
// second-level registrations are offered. Future TUPD may set policy:"frozen"
|
|
// once the TLD covenant lands and enforces it.
|
|
const SEED_TLDS = [
|
|
"bch", "p2p", "bit", "nav", "test", "x",
|
|
"asm", "neo", "gt", "sc", "sia", "com",
|
|
"dex", "cex", "nt", "dea",
|
|
"hub", "os", "vpn",
|
|
"cash",
|
|
];
|
|
|
|
// Empty records for the seed — the TLD covenant work will populate
|
|
// policy/fee_bps/reserved later. Empty means "defaults apply everywhere",
|
|
// which per the design doc §3 is {policy:"open", fee_bps:500, min_len:1}.
|
|
const SEED_RECORDS = {};
|
|
|
|
const wallet = await loadWallet("main");
|
|
console.log(`from wallet : ${wallet.cashaddr}`);
|
|
console.log(`TLD beacon : ${TLD_BEACON}`);
|
|
console.log(`target TLD set : ${SEED_TLDS.join(" ")}`);
|
|
|
|
// Fetch what's already on the beacon so re-runs skip it.
|
|
console.log("\nfetching current TLD-beacon state …");
|
|
const history = await wallet.provider.getHistory(TLD_BEACON);
|
|
const txs = new Map();
|
|
for (const { tx_hash } of history) {
|
|
try { txs.set(tx_hash, await wallet.provider.getRawTransactionObject(tx_hash)); }
|
|
catch { /* unreadable — skip */ }
|
|
}
|
|
const before = buildTldSnapshot({ history, txs });
|
|
console.log(`present : ${before.tlds.length ? before.tlds.map((t) => t.tld).join(" ") : "(none)"}`);
|
|
|
|
const existing = new Set(before.tlds.map((t) => t.tld));
|
|
const toMint = SEED_TLDS.filter((t) => !existing.has(t));
|
|
if (!toMint.length) {
|
|
console.log("\nnothing to do — all target TLDs already registered.");
|
|
process.exit(0);
|
|
}
|
|
console.log(`will register : ${toMint.join(" ")} (${toMint.length} tx)`);
|
|
|
|
const bal = await wallet.getBalance("sat");
|
|
console.log(`wallet balance : ${bal} sat`);
|
|
|
|
const results = [];
|
|
for (const tld of toMint) {
|
|
process.stdout.write(` TREG ${tld} … `);
|
|
try {
|
|
const res = await registerTld(wallet, tld, SEED_RECORDS);
|
|
results.push({ tld, ok: true, ...res });
|
|
console.log(`ok txid=${res.txid} category=${res.category?.slice(0, 16)}…`);
|
|
} catch (e) {
|
|
results.push({ tld, ok: false, error: String(e && e.message || e) });
|
|
console.log(`FAIL ${e && e.message || e}`);
|
|
}
|
|
// A short pause so a chain query between two REGs sees the previous tx.
|
|
await new Promise((r) => setTimeout(r, 500));
|
|
}
|
|
|
|
const failed = results.filter((r) => !r.ok);
|
|
console.log(`\n${results.length - failed.length}/${results.length} TREG(s) broadcast${failed.length ? ` (${failed.length} failed)` : ""}`);
|
|
|
|
// Verify by rebuilding the snapshot from the beacon.
|
|
console.log("\nverifying via TLD-beacon snapshot rebuild …");
|
|
await new Promise((r) => setTimeout(r, 2000)); // mempool propagation
|
|
const historyAfter = await wallet.provider.getHistory(TLD_BEACON);
|
|
const txsAfter = new Map();
|
|
for (const { tx_hash } of historyAfter) {
|
|
try { txsAfter.set(tx_hash, await wallet.provider.getRawTransactionObject(tx_hash)); }
|
|
catch { /* skip */ }
|
|
}
|
|
const after = buildTldSnapshot({ history: historyAfter, txs: txsAfter });
|
|
console.log(`snapshot root : ${after.root}`);
|
|
console.log(`snapshot tlds :`);
|
|
for (const t of after.tlds) {
|
|
console.log(` - ${t.tld.padEnd(6)} cat=${t.category.slice(0, 16)}… regHeight=${t.regHeight ?? "(mempool)"} txid=${t.regTxid.slice(0, 16)}…`);
|
|
}
|
|
const missing = SEED_TLDS.filter((t) => !after.tlds.some((s) => s.tld === t));
|
|
if (missing.length) {
|
|
console.log(`\nWARNING: still missing after broadcast: ${missing.join(" ")}`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`\ndone — all ${SEED_TLDS.length} target TLDs present on the TLD beacon.`);
|
|
process.exit(0);
|