2026-09-09 01:09:05 +02:00
|
|
|
// Sirius.X pricing model — deterministic per-label cost so users can predict
|
|
|
|
|
// what a name or TLD will cost before they click Register. Public tiers only;
|
|
|
|
|
// operator-level discounts and coupon overrides land in a future revision
|
|
|
|
|
// (the plan is oracle-fed rates + coupon-code redemption at mint time).
|
|
|
|
|
//
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
// Two layers decide what a NAME costs:
|
|
|
|
|
// 1. The TLD owner's on-chain policy (`price`, `hidden`, `policy`) — read
|
|
|
|
|
// from the gateway's /api/tlds snapshot of the TLD beacon. A TLD owner
|
|
|
|
|
// who sets `price: 7` sells every name under that TLD for $7, flat.
|
|
|
|
|
// 2. Otherwise the length tiers below.
|
|
|
|
|
//
|
2026-09-09 01:09:05 +02:00
|
|
|
// Exposed as window.siriusPricing so both the register-flow modal and the
|
|
|
|
|
// inline search widgets on landing/tld.html use one source of truth.
|
|
|
|
|
|
|
|
|
|
(() => {
|
|
|
|
|
// Chipnet placeholder rate: mainnet swaps this for a real BCH/USD oracle.
|
|
|
|
|
// The numbers keep the demo transactions in the "few chipnet coins" range
|
|
|
|
|
// so a single faucet visit covers a name or a TLD.
|
|
|
|
|
const CHIPNET_SATS_PER_USD = 250_000;
|
|
|
|
|
|
|
|
|
|
const usdToSats = (usd) => BigInt(Math.max(0, Math.round(Number(usd) * CHIPNET_SATS_PER_USD)));
|
|
|
|
|
|
|
|
|
|
const cleanLabel = (s) => String(s || "").toLowerCase().replace(/[^a-z0-9-]/g, "");
|
|
|
|
|
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
// ---------- TLD owner policies ----------
|
|
|
|
|
// tld -> { price, hidden, frozen, policy, owner, records }
|
|
|
|
|
// Filled from /api/tlds (see loadTldPolicies). Unknown TLDs fall through
|
|
|
|
|
// to tier pricing and are treated as sellable, so a gateway blip never
|
|
|
|
|
// blocks a purchase; the chain is the authority at mint time anyway.
|
|
|
|
|
// include_hidden=1 so the policy map knows about switched-off (private)
|
|
|
|
|
// TLDs too — their owners register names under them from the portal, and
|
|
|
|
|
// the register flow must be able to price and gate them. The public
|
|
|
|
|
// listing (visibleTlds) still drops anything hidden.
|
|
|
|
|
const TLD_API = "https://navigate.st/api/tlds?include_hidden=1";
|
|
|
|
|
const TLD_POLICIES = new Map();
|
|
|
|
|
let tldList = null; // raw /api/tlds rows, once loaded (hidden ones excluded)
|
|
|
|
|
let tldLoad = null; // memoised in-flight fetch
|
|
|
|
|
|
|
|
|
|
function normalisePolicy(row) {
|
|
|
|
|
const rec = row && row.records && typeof row.records === "object" ? row.records : {};
|
|
|
|
|
const priceRaw = row && row.price_usd != null ? row.price_usd : rec.price;
|
|
|
|
|
const price = typeof priceRaw === "number" && Number.isFinite(priceRaw) && priceRaw >= 0 ? priceRaw : null;
|
|
|
|
|
const hidden = !!(row && row.hidden) || rec.hidden === 1 || rec.hidden === true;
|
|
|
|
|
const policy = typeof rec.policy === "string" ? rec.policy : "open";
|
|
|
|
|
return {
|
|
|
|
|
tld: row.tld,
|
|
|
|
|
price,
|
|
|
|
|
hidden,
|
|
|
|
|
hiddenBy: row && row.hidden_by ? row.hidden_by : (hidden ? "owner" : null),
|
|
|
|
|
frozen: policy === "frozen",
|
feat(bns): name marketplace and TLD-owner co-sign rule
Two gaps the owner panel left open. First, a hidden TLD was only a UI
gate: anyone could still broadcast a REG under it and every indexer
admitted it. Second, there was no way to sell a name without trusting
the other side.
Co-sign rule (consensus, applied in lockstep by bns.js and
resolver-web.js): a REG under a TLD whose records at that height say
policy "cosign" or hidden 1 is indexed only if the transaction carries
the TLD's own certificate. The certificate can only be spent by the
owner's key and is re-issued to them in the same transaction, so it is
a co-signature nobody can forge and nothing is consumed. The TLD map
now keeps the TUPD timeline so policy is evaluated at the REG height.
Owners register under their private TLDs with the certificate added
from their own wallet; third parties under a "cosign" TLD build the
full transaction, sign their inputs and queue it at /api/cosign, where
the owner approves it from the dashboard (signCosignRequest refuses to
sign unless the certificate returns to the same locking script).
Marketplace: a listing is the seller's certificate input plus a price
output signed SIGHASH_SINGLE|ANYONECANPAY, stored by the gateway as a
bulletin board (/api/market, verified against the on-chain owner and
pruned when the certificate moves). The buyer completes it in one
transaction, so the seller is paid exactly when the name moves.
Cancelling also spends the certificate once so the offer is void.
Site: market.html, Sell sub-tab and Pending approvals in the portal,
Market link in nav and footer, six dictionaries extended, cache tags
bumped. Verified on chipnet: cosigned.sc registered by a throwaway
wallet through the queue with the .sc certificate back at the owner;
aloevera.test listed and delisted through the API.
Ariadne's resolver-web.js copy and the mobile Bns.java port still need
the co-sign rule; until then they admit REGs this index rejects.
2026-09-17 04:04:22 +02:00
|
|
|
// cosign: anyone may register, but the TLD owner must co-sign the
|
|
|
|
|
// registration (indexers reject a REG under a cosign/hidden TLD that
|
|
|
|
|
// does not carry the TLD certificate). hidden implies the same rule
|
|
|
|
|
// on chain; in the UI hidden is owner-only, cosign is request-based.
|
|
|
|
|
cosign: policy === "cosign",
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
policy,
|
feat(bns): name marketplace and TLD-owner co-sign rule
Two gaps the owner panel left open. First, a hidden TLD was only a UI
gate: anyone could still broadcast a REG under it and every indexer
admitted it. Second, there was no way to sell a name without trusting
the other side.
Co-sign rule (consensus, applied in lockstep by bns.js and
resolver-web.js): a REG under a TLD whose records at that height say
policy "cosign" or hidden 1 is indexed only if the transaction carries
the TLD's own certificate. The certificate can only be spent by the
owner's key and is re-issued to them in the same transaction, so it is
a co-signature nobody can forge and nothing is consumed. The TLD map
now keeps the TUPD timeline so policy is evaluated at the REG height.
Owners register under their private TLDs with the certificate added
from their own wallet; third parties under a "cosign" TLD build the
full transaction, sign their inputs and queue it at /api/cosign, where
the owner approves it from the dashboard (signCosignRequest refuses to
sign unless the certificate returns to the same locking script).
Marketplace: a listing is the seller's certificate input plus a price
output signed SIGHASH_SINGLE|ANYONECANPAY, stored by the gateway as a
bulletin board (/api/market, verified against the on-chain owner and
pruned when the certificate moves). The buyer completes it in one
transaction, so the seller is paid exactly when the name moves.
Cancelling also spends the certificate once so the offer is void.
Site: market.html, Sell sub-tab and Pending approvals in the portal,
Market link in nav and footer, six dictionaries extended, cache tags
bumped. Verified on chipnet: cosigned.sc registered by a throwaway
wallet through the queue with the .sc certificate back at the owner;
aloevera.test listed and delisted through the API.
Ariadne's resolver-web.js copy and the mobile Bns.java port still need
the co-sign rule; until then they admit REGs this index rejects.
2026-09-17 04:04:22 +02:00
|
|
|
category: row && row.category ? row.category : null,
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
owner: row && row.owner ? row.owner : null,
|
|
|
|
|
records: rec,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setTldPolicies(rows) {
|
|
|
|
|
TLD_POLICIES.clear();
|
|
|
|
|
for (const r of rows || []) {
|
|
|
|
|
const row = typeof r === "string" ? { tld: r } : r;
|
|
|
|
|
const tld = cleanLabel(row && row.tld);
|
|
|
|
|
if (!tld) continue;
|
|
|
|
|
TLD_POLICIES.set(tld, normalisePolicy({ ...row, tld }));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fetch the TLD list once per page. Resolves to the array of visible TLD
|
|
|
|
|
// rows (or null on failure) — never rejects, callers just fall back.
|
|
|
|
|
function loadTldPolicies({ url = TLD_API, force = false } = {}) {
|
|
|
|
|
if (tldLoad && !force) return tldLoad;
|
|
|
|
|
tldLoad = (async () => {
|
|
|
|
|
try {
|
|
|
|
|
const r = await fetch(url, { cache: "no-store" });
|
|
|
|
|
if (!r.ok) throw new Error("api " + r.status);
|
|
|
|
|
const j = await r.json();
|
|
|
|
|
const rows = Array.isArray(j.tlds) ? j.tlds : [];
|
|
|
|
|
setTldPolicies(rows);
|
|
|
|
|
// Only a beacon-sourced list is a sellable list. A gateway still
|
|
|
|
|
// serving the legacy `tlds.bch`-derived union includes every suffix
|
|
|
|
|
// that ever appeared on a name (".de", ".silentmode", …), which is
|
|
|
|
|
// not what the registry sells — keep the page's own fallback then.
|
|
|
|
|
tldList = j.source === "TLD_BEACON" ? rows.filter((t) => !t.hidden) : null;
|
|
|
|
|
return tldList;
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
return tldLoad;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolves once the list is loaded, or after `ms` — search UIs await this
|
|
|
|
|
// so the first paint already shows owner prices without ever hanging.
|
|
|
|
|
function tldReady(ms = 2500) {
|
|
|
|
|
return Promise.race([
|
|
|
|
|
loadTldPolicies(),
|
|
|
|
|
new Promise((res) => setTimeout(() => res(null), ms)),
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function tldPolicy(tld) {
|
|
|
|
|
return TLD_POLICIES.get(cleanLabel(tld)) || null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Does one of `addresses` (the signed-in wallet's) hold this TLD's NFT?
|
|
|
|
|
// `owner` comes from the gateway's beacon snapshot (mint output, updated
|
|
|
|
|
// on every TUPD carrier), so a wallet that owns the TLD matches here.
|
|
|
|
|
function isTldOwner(tld, addresses) {
|
|
|
|
|
const p = tldPolicy(tld);
|
|
|
|
|
if (!p || !p.owner || !addresses) return false;
|
|
|
|
|
const list = Array.isArray(addresses) ? addresses : [addresses];
|
|
|
|
|
return list.some((a) => typeof a === "string" && a === p.owner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Can names be sold under this TLD right now?
|
|
|
|
|
// hidden → owner switched the TLD off: private TLD. The public cannot
|
|
|
|
|
// buy, but the OWNER still can — pass their wallet addresses
|
|
|
|
|
// and a hidden TLD they hold answers ok with owner: true.
|
|
|
|
|
// frozen → owner set policy "frozen" (no new registrations, owner included)
|
|
|
|
|
function tldSellable(tld, addresses) {
|
|
|
|
|
const p = tldPolicy(tld);
|
|
|
|
|
if (!p) return { ok: true, reason: null, owner: false };
|
|
|
|
|
const owner = isTldOwner(tld, addresses);
|
|
|
|
|
if (p.frozen) return { ok: false, reason: "frozen", policy: p, owner };
|
|
|
|
|
if (p.hidden && !owner) return { ok: false, reason: "hidden", policy: p, owner };
|
feat(bns): name marketplace and TLD-owner co-sign rule
Two gaps the owner panel left open. First, a hidden TLD was only a UI
gate: anyone could still broadcast a REG under it and every indexer
admitted it. Second, there was no way to sell a name without trusting
the other side.
Co-sign rule (consensus, applied in lockstep by bns.js and
resolver-web.js): a REG under a TLD whose records at that height say
policy "cosign" or hidden 1 is indexed only if the transaction carries
the TLD's own certificate. The certificate can only be spent by the
owner's key and is re-issued to them in the same transaction, so it is
a co-signature nobody can forge and nothing is consumed. The TLD map
now keeps the TUPD timeline so policy is evaluated at the REG height.
Owners register under their private TLDs with the certificate added
from their own wallet; third parties under a "cosign" TLD build the
full transaction, sign their inputs and queue it at /api/cosign, where
the owner approves it from the dashboard (signCosignRequest refuses to
sign unless the certificate returns to the same locking script).
Marketplace: a listing is the seller's certificate input plus a price
output signed SIGHASH_SINGLE|ANYONECANPAY, stored by the gateway as a
bulletin board (/api/market, verified against the on-chain owner and
pruned when the certificate moves). The buyer completes it in one
transaction, so the seller is paid exactly when the name moves.
Cancelling also spends the certificate once so the offer is void.
Site: market.html, Sell sub-tab and Pending approvals in the portal,
Market link in nav and footer, six dictionaries extended, cache tags
bumped. Verified on chipnet: cosigned.sc registered by a throwaway
wallet through the queue with the .sc certificate back at the owner;
aloevera.test listed and delisted through the API.
Ariadne's resolver-web.js copy and the mobile Bns.java port still need
the co-sign rule; until then they admit REGs this index rejects.
2026-09-17 04:04:22 +02:00
|
|
|
// Sellable, but the registration needs the owner's co-signature: the
|
|
|
|
|
// flow builds the request and parks it in the gateway's approval queue.
|
|
|
|
|
if (p.cosign && !owner) return { ok: true, reason: "cosign", policy: p, owner };
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
return { ok: true, reason: null, policy: p, owner };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Visible TLD labels in listing order, or null if no beacon-sourced list
|
|
|
|
|
// is available (callers keep their own fallback list then).
|
|
|
|
|
function visibleTlds() {
|
|
|
|
|
return tldList ? tldList.map((t) => t.tld) : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------- name pricing ----------
|
|
|
|
|
// Owner-set flat price first; else LENGTH-first tiers, then downshift for
|
|
|
|
|
// "less brandable" shapes (all-digits, hyphenated). Kept as multiplicative
|
|
|
|
|
// modifiers so tiers remain the primary story and mods just soften an
|
|
|
|
|
// edge case.
|
|
|
|
|
function priceForName(label, tld) {
|
2026-09-09 01:09:05 +02:00
|
|
|
const s = cleanLabel(label);
|
|
|
|
|
if (!s) return { usd: 0, tier: "invalid" };
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
const p = tld ? tldPolicy(tld) : null;
|
|
|
|
|
if (p && p.price != null) {
|
|
|
|
|
return { usd: p.price, tier: "tld-set", sats: usdToSats(p.price), tld: p.tld, ownerSet: true };
|
|
|
|
|
}
|
2026-09-09 01:09:05 +02:00
|
|
|
let usd, tier;
|
|
|
|
|
if (s.length === 1) { usd = 5.00; tier = "premium-1"; }
|
|
|
|
|
else if (s.length === 2) { usd = 3.00; tier = "short-2"; }
|
|
|
|
|
else if (s.length === 3) { usd = 2.00; tier = "short-3"; }
|
|
|
|
|
else if (s.length <= 5) { usd = 1.00; tier = "standard"; }
|
|
|
|
|
else if (s.length <= 7) { usd = 0.50; tier = "long"; }
|
|
|
|
|
else if (s.length <= 16) { usd = 0.25; tier = "extended"; }
|
|
|
|
|
else { usd = 0.10; tier = "very-long"; }
|
|
|
|
|
// Modifiers.
|
|
|
|
|
if (/^\d+$/.test(s)) { usd = round2(usd * 0.5); tier += "+digits"; }
|
|
|
|
|
if (s.includes("-")) { usd = round2(usd * 0.7); tier += "+hyphen"; }
|
|
|
|
|
return { usd, tier, sats: usdToSats(usd) };
|
|
|
|
|
}
|
|
|
|
|
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
// Per-label overrides — TLDs the operator wants priced outside the tiers.
|
|
|
|
|
// Cheap namespaces (`.test`, `.dev`, `.local`) exist for experimentation,
|
|
|
|
|
// school assignments and demo throwaways: length-tier pricing prices them
|
|
|
|
|
// like premium TLDs, which isn't the point. Add labels here to opt them
|
|
|
|
|
// out of the tier and (optionally) mark them renewal-free.
|
|
|
|
|
//
|
|
|
|
|
// Shape: label -> { usd, tier, noRenewal? }
|
|
|
|
|
const SPECIAL_TLDS = {
|
|
|
|
|
"test": { usd: 0.01, tier: "sandbox", noRenewal: true },
|
|
|
|
|
};
|
|
|
|
|
|
2026-09-09 01:09:05 +02:00
|
|
|
function priceForTld(label) {
|
|
|
|
|
const s = cleanLabel(label);
|
|
|
|
|
if (!s) return { usd: 0, tier: "invalid" };
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
if (Object.prototype.hasOwnProperty.call(SPECIAL_TLDS, s)) {
|
|
|
|
|
const o = SPECIAL_TLDS[s];
|
|
|
|
|
return { usd: o.usd, tier: o.tier, sats: usdToSats(o.usd), noRenewal: !!o.noRenewal };
|
|
|
|
|
}
|
2026-09-09 01:09:05 +02:00
|
|
|
let usd, tier;
|
2026-09-09 03:45:41 +02:00
|
|
|
if (s.length === 1) { usd = 500.00; tier = "premium-1"; }
|
|
|
|
|
else if (s.length === 2) { usd = 250.00; tier = "short-2"; }
|
|
|
|
|
else if (s.length === 3) { usd = 150.00; tier = "short-3"; }
|
|
|
|
|
else if (s.length <= 6) { usd = 100.00; tier = "standard"; }
|
|
|
|
|
else if (s.length <= 10) { usd = 50.00; tier = "long"; }
|
|
|
|
|
else { usd = 25.00; tier = "extended"; }
|
2026-09-09 01:09:05 +02:00
|
|
|
return { usd, tier, sats: usdToSats(usd) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rounded USD → display string. Under $1 shows cents ($0.25); $1 and up
|
|
|
|
|
// shows whole dollars ($5) unless there's a fractional part.
|
|
|
|
|
function formatUsd(usd) {
|
|
|
|
|
const n = Number(usd || 0);
|
|
|
|
|
if (n >= 1 && n === Math.floor(n)) return `$${n}`;
|
|
|
|
|
return `$${n.toFixed(2)}`;
|
|
|
|
|
}
|
|
|
|
|
function formatSats(sats) {
|
|
|
|
|
return `${BigInt(sats || 0n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} sat`;
|
|
|
|
|
}
|
|
|
|
|
function round2(n) { return Math.round(Number(n) * 100) / 100; }
|
|
|
|
|
|
|
|
|
|
window.siriusPricing = {
|
|
|
|
|
priceForName,
|
|
|
|
|
priceForTld,
|
|
|
|
|
formatUsd,
|
|
|
|
|
formatSats,
|
|
|
|
|
usdToSats,
|
|
|
|
|
CHIPNET_SATS_PER_USD,
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
// TLD owner policy layer
|
|
|
|
|
loadTldPolicies,
|
|
|
|
|
setTldPolicies,
|
|
|
|
|
tldReady,
|
|
|
|
|
tldPolicy,
|
|
|
|
|
tldSellable,
|
|
|
|
|
isTldOwner,
|
|
|
|
|
visibleTlds,
|
|
|
|
|
TLD_API,
|
2026-09-09 01:09:05 +02:00
|
|
|
};
|
feat(sirius-x): TLD owner panel — owner-set price, on/off switch, private TLDs
A TLD owner needed to run their namespace without the operator: set what
every name under the TLD sells for, take the TLD off the public registry
for a while, and still register names under it themselves.
Both settings live on chain in the TLD's TUPD records (`price`, `hidden`)
because changes are rare and every client already walks the TLD beacon.
The gateway's /api/tlds now carries records, owner, price_usd and
hidden_by per TLD; pricing.js quotes the owner price ahead of the length
tiers and only trusts a TLD_BEACON-sourced list; the register flow refuses
hidden and frozen TLDs for the public but lets the owner through at the
platform share only (the 90% owner cut would be paid to themselves). The
portal's TLDs tab loads real holdings, shows price and on/off state, and
gives each TLD a one-click switch, a price/policy editor and an inline
"register a name under .tld" form. Docs and the design table describe the
two new records.
2026-09-16 21:28:18 +02:00
|
|
|
|
|
|
|
|
// Warm the policy cache as soon as the script lands; every consumer
|
|
|
|
|
// awaits tldReady() before it paints a price.
|
|
|
|
|
loadTldPolicies();
|
2026-09-09 01:09:05 +02:00
|
|
|
})();
|