Every second-level name registration under a TLD now routes 90% of the
service fee to whoever holds that TLD's certificate on chain, with 10%
going to the platform address. That's the economic incentive for
minting a TLD: you earn from every name registered under it.
The mechanism, end to end:
1. resolver-web.js fetchTldMap now also records mintScriptHex — the
scriptPubKey of the TREG output that carries each TLD's NFT.
Exported so registrar can decode it into a cashaddr with libauth.
MVP: this is the ORIGINAL owner; NFT transfers after mint are not
traced yet (a follow-up will walk the chain of transfers).
2. registrar.js gains findTldOwnerAddress(client, tld) and
splitServiceFee(sats). The split constants live at the top of the
file (TLD_OWNER_SHARE_NUM/DEN = 90/100) so the ratio moves in one
place. Rounding: BigInt division favours the platform on odd sat
counts so the two shares always sum EXACTLY to the input.
3. quoteRegistration wraps the existing flow: it derives the TLD from
the name, looks up the TLD owner, and if the owner ≠ buyer it asks
buildRegistrationTx to add a second fee output. If the owner
couldn't be resolved (TLD not registered, decode failure) the full
fee stays on the platform address — the buyer still pays the same
amount either way.
4. register-tx.js buildRegistrationTx accepts tldFeeAddress/tldFeeSats
and, when set, emits an extra P2PKH output for the TLD owner. Sits
between the beacon dust and the platform-fee output; outputMap
records .tldOwnerFee so callers can find it. costs also carries
tldOwnerFeeSats and netCostSats includes it.
5. priceSummary in registrar-config splits the 'Service fee' row into
'Service fee — TLD owner (90%)' + 'Service fee — platform (10%)'
whenever tldOwnerFeeSats > 0, with a per-line note explaining
where the money goes.
Bundle: re-exported findTldOwnerAddress + splitServiceFee from
register-entry.js. Rebuilt bns-register.js (~34 kB) and deployed;
cache-buster bumped to ?v=20260908split on portal / admin /
register-flow.js.
Verified live: findTldOwnerAddress('.bch') returns the operator
cashaddr; quoteRegistration('tester42.bch') builds cleanly with a
9,000/1,000 split output pair on a 10,000-sat fee; priceSummary
renders both lines. No regressions on the TLD-mint flow (buyer IS
the TLD owner there — split short-circuits and it stays a single
fee output as before).
Adds the external-wallet variant of registerTldWithBuiltInWallet so
WizardConnect users can mint TLDs from the sirius.x portal without
first importing a seed. Same transaction shape (TREG payload, TLD-
beacon output, service-fee output) — the wallet approves the mint
(and, if needed, a one-time prep signature to satisfy the vout-0
non-token genesis-input rule) on the user's own device.
Bundle: re-exported from src/web/register-entry.js and rebuilt
(bns-register.js: 33.3 kB, cache-buster bumped to ?v=20260907tldext
on portal.html / register.html / admin/index.html).
Portal: TLD-register submit now dispatches on wallet.source, calling
registerTldWithExternalWallet with wallet.session when the user is
signed in via WC. Removed the WC-disable guard and updated the card
copy to say TLD mints also go through the wallet's signing prompt.
Uses the same landOnChain helper as registerWithExternalWallet, so
wallet-broadcasts (walletBroadcasts:true sessions) and duplicate/
mempool responses are handled identically.
New public API in register-tx.js:
- TLD_BEACON constant (per Decentralized.DNS/DESIGN-tld-registry.md §3);
keep in step with Argus/src/config.js:TLD_BEACON and the indexer's
BNS_TLD_BEACON_SCRIPTHASH — all three must agree, or clients disagree
about which TLDs exist.
- normalizeTld(input) — validates a bare TLD label (1–16 chars,
[a-z0-9-]), matches bns.js's normalizeTld.
- buildTldRegistrationTx({...}) — mints a per-TLD certificate onto the
TLD beacon. Same shape as buildRegistrationTx (genesis-input rule,
dust accounting, change-at-vout-0) but the payload op is "TREG", the
commitment is the TLD label, and dust flows to TLD_BEACON instead of
the name beacon.
register-entry.js re-exports registerTldWithBuiltInWallet so the
in-browser registrar can drive TLD mints alongside name mints.
gateway/public-gateway.mjs:
* GET /api/holdings/<scripthash> and POST /api/holdings {scripthashes:[…]}
— server-side wallet-holdings lookup for the portal. Bns-indexer is
beacon-only so it can't answer listunspent for arbitrary addresses; the
gateway does the electrum roundtrip and cross-joins with the cached BCNR
index. Client posts scripthashes (no libauth needed on the server) and
gets back the names owned.
* elConnect now falls through to whole-buffer JSON.parse when a Fulcrum
response lacks a trailing newline — chipnet.bch.ninja does this and
otherwise every elCall to it times out. Same tolerance pattern as
bns-indexer.test.mjs's tiny electrum client.
* verifyElectrum picks a full electrum with a 3s server.version probe so a
hung server fails over to the next in seconds instead of stalling 20.
* Skips silentmode.st/electrum and coinspectrum.duckdns.org:50011 for
/api/holdings — both are bns-indexer routes that don't do listunspent.
web/register-entry.js: export addressToScripthash so the portal can derive
the scripthash for each of its wallet's watched addresses before POSTing.
Browser bundle rebuilt.
site-sirius-x pages:
* favicon + logo hrefs made relative (./assets/… on index/portal,
../assets/… on docs/theseus). Absolute /sirius-x/… broke on the sirius.x
BCNR route where the site is served from root instead of under /sirius-x/.
* Roadmap nav link added back to portal, docs, theseus — the landing has an
anchor to a section on itself, so subpages now link to it explicitly.
* portal.html: loadNames rewritten to POST scripthashes to /api/holdings
instead of doing client-side electrum. Works on browsers whose networks
block chipnet electrum ports; same-origin HTTPS on 443.
* portal.html: bundle import ?v= bumped so Chrome's in-memory ES module
map picks up the new bundle instead of a stale cached copy.