sirius/js/pricing.js
Local Dev ce9248a327 feat(sirius-x): tier-based label pricing; badges on search cards + TLD list
Single source of truth (js/pricing.js) mirrored on landing, tld.html
and the mint flow — same label always shows the same price everywhere.

Name tiers (label part):
  1 char           $5.00  premium-1
  2 chars          $3.00  short-2
  3 chars          $2.00  short-3
  4–5 chars        $1.00  standard
  6–7 chars        $0.50  long
  8–16 chars       $0.25  extended
  17+ chars        $0.10  very-long
  all-digits       ×0.5   (less brandable)
  contains hyphen  ×0.7

TLD tiers (label part):
  1 char           $10.00  premium-1
  2 chars          $8.00   short-2
  3 chars          $6.00   short-3
  4–8 chars        $5.00   standard
  9+ chars         $4.00   long

Rendering:
  - Landing #search-results: acid-tinted price badge on each available
    row; grid grew a fourth column so name + badge + price + button
    all sit on one line
  - tld.html search result-card: same price badge next to the Register
    button on available TLDs
  - tld.html registered-TLDs table: new 'Mint price' column showing the
    tier price for every registered TLD, so buyers see the pricing
    ladder next to concrete examples

Mint pipe:
  - startFlow(name)/startTldFlow(label) resolve the label price via
    window.siriusPricing (default) but honour opts.serviceFeeSats when
    the caller passes one — leaves the door open for coupons /
    operator discounts / oracle overrides in a future revision without
    reshuffling call sites
  - The overridden service fee is threaded through quoteRegistration
    AND registerWithBuiltInWallet/registerWithExternalWallet so the
    confirm screen and the on-chain output agree

Chipnet placeholder rate (250,000 sat/USD) stays in pricing.js;
mainnet will swap in a live BCH/USD oracle. Operator-side discounts
and coupon codes are the next iteration — deliberately not disclosed
in this shipping copy.
2026-09-09 01:09:05 +02:00

71 lines
3 KiB
JavaScript

// 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).
//
// 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, "");
// Tier picker — LENGTH-first, 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) {
const s = cleanLabel(label);
if (!s) return { usd: 0, tier: "invalid" };
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) };
}
function priceForTld(label) {
const s = cleanLabel(label);
if (!s) return { usd: 0, tier: "invalid" };
let usd, tier;
if (s.length === 1) { usd = 10.00; tier = "premium-1"; }
else if (s.length === 2) { usd = 8.00; tier = "short-2"; }
else if (s.length === 3) { usd = 6.00; tier = "short-3"; }
else if (s.length <= 8) { usd = 5.00; tier = "standard"; }
else { usd = 4.00; tier = "long"; }
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,
};
})();