// Registrar configuration — the only place prices, the fee address and the // network live. Everything here is public information; no secrets (SECURITY.md // rule 0). This file is bundled into the public register page as-is. import { ELECTRUM } from "./lib/electrum.js"; import { NETWORK } from "./lib/resolver-web.js"; export const REGISTRAR = { // ---- network ----------------------------------------------------------- // Everything chain-specific is read from the network table in // lib/resolver-web.js (selected by BNS_NETWORK; chipnet unless set). Mainnet // stays a deliberate switch: its beacons are unpinned until // ROADMAP-MAINNET.md §6 is done, and requireBeacons() refuses before that. network: NETWORK.id, addressPrefix: NETWORK.prefix, explorerTx: NETWORK.explorerTx, // ---- chain connectivity ------------------------------------------------- // Order matters: the pool connects in parallel but prefers earlier entries, // and takes the UNION of beacon history across everything that answers. // // PUT YOUR OWN FULCRUM FIRST, ON 443. Every public server below listens on a // non-standard port (50004 / 62002), so a single firewall or VPN rule blocks // all of them at once — observed 2026-07-27, when all three went TCP-closed // while :443 stayed reachable. A self-hosted server on 443 is worth more than // three more public ones, and it is not a centralisation trade: the public // servers stay in the list as cross-checks, and the union means your own // server cannot hide a registration from you either. // // selfHosted: "wss://bns.example.st:443", // // See OPERATIONS-electrum.md for running one. selfHosted: null, get electrum() { return this.selfHosted ? [this.selfHosted, ...ELECTRUM] : ELECTRUM; }, // ---- discovery --------------------------------------------------------- beacon: NETWORK.beacon, tldBeacon: NETWORK.tldBeacon, // ---- price ------------------------------------------------------------- // The service fee is a plain output inside the buyer's own minting // transaction — the registrar model, like ENS. We never take custody: the // certificate is minted straight to the buyer's key in the same transaction // that pays us. If `sats` is 0n the output is omitted entirely. serviceFee: { address: NETWORK.operatorAddress, sats: 10_000n, // chipnet placeholder price — set real pricing at mainnet }, // Miner fee rate, satoshis per byte. 1 sat/byte confirms fine on BCH. feeRate: 1, // ---- external wallets --------------------------------------------------- // WizardConnect only. WalletConnect v2 was removed deliberately (2026-07-27): // it needs a Reown project ID and a relay we do not control, and WizardConnect // already covers the same wallets (Cashonize 0.9+, Paytaca) over an // end-to-end-encrypted Nostr transport with no third-party project registration. // // CashConnect is NOT here on purpose either — see the note in // Decentralized.DNS/REGISTRATION-STATUS.md. Its V0 model has the wallet build // the transaction and auto-select its own inputs, which cannot mint a name // certificate: a CashTokens genesis is defined by one specific outpoint the // dApp must choose, and the category ID is that outpoint's txid. wizardConnect: { dappName: "Silent Mode", dappIcon: "https://silentmode.st/icon.png", }, // Faucets shown to a buyer whose new wallet is empty (empty on mainnet). faucets: NETWORK.faucets, }; /** Human-readable price breakdown for the confirmation screen. */ export function priceSummary(costs) { const bch = (sats) => (Number(sats) / 1e8).toFixed(8).replace(/0+$/, "").replace(/\.$/, ""); const rows = []; // Split fee: show TLD-owner + platform lines when the TLD-owner cut is // non-zero (i.e. buyer is registering under a TLD they don't own). const tldOwner = BigInt(costs.tldOwnerFeeSats ?? 0n); const platform = BigInt(costs.serviceFeeSats ?? 0n); if (tldOwner > 0n) { rows.push({ label: "Service fee — TLD owner (90%)", sats: tldOwner, bch: bch(tldOwner), note: "goes to whoever holds this TLD's certificate on chain", }); rows.push({ label: "Service fee — platform (10%)", sats: platform, bch: bch(platform), note: "covers the resolver + gateway + indexer", }); } else { rows.push({ label: "Service fee", sats: platform, bch: bch(platform) }); } rows.push({ label: "Network fee", sats: costs.chainFeeSats, bch: bch(costs.chainFeeSats) }); rows.push({ label: "Discovery beacon", sats: costs.beaconDustSats, bch: bch(costs.beaconDustSats) }); rows.push({ label: "Held in the certificate", sats: costs.certificateDustSats, bch: bch(costs.certificateDustSats), note: "stays yours — it lives in the certificate you now own", }); rows.push({ label: "Total", sats: costs.netCostSats, bch: bch(costs.netCostSats), total: true }); return rows; }