2026-08-29 21:57:33 +02:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
< title > Portal — your names on Sirius.X< / title >
2026-08-29 21:57:33 +02:00
< meta name = "description" content = "Sign in with your Bitcoin Cash seed phrase to see every BCNR name your wallet holds and manage records. Your keys never leave the browser." >
2026-08-31 05:40:47 +02:00
< link rel = "icon" href = "./assets/favicon.svg" type = "image/svg+xml" >
< link rel = "mask-icon" href = "./assets/favicon.svg" color = "#d6ff3d" >
2026-08-31 04:30:53 +02:00
< meta property = "og:type" content = "website" >
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
< meta property = "og:site_name" content = "Sirius.X" >
< meta property = "og:title" content = "Sirius.X portal — your BCNR names" >
2026-08-31 04:30:53 +02:00
< meta property = "og:description" content = "Sign in with your seed phrase to see every name your wallet holds and manage records. Keys never leave the browser." >
< meta property = "og:url" content = "https://silentmode.st/sirius-x/portal.html" >
sirius.x: /brand/ kit — logo, mono, avatar, banner, favicon, palette
brand/ ships every reusable mark plus a browseable kit page:
* logo.svg — full colour wordmark (star + sirius.x, .x in acid green)
* logo-mono.svg — currentColor version for print / one-colour merch
* favicon.svg — 64×64 rounded square, scales cleanly to 16×16
* avatar.svg — 512×512 square, hard corners (platforms round-mask)
* banner.svg — 1200×630 OG / Twitter Card canvas, crop-tolerant layout
* index.html — brand-kit page: asset previews + download links, full
colour palette with names/hex, typography sample, do/don't guidance,
MIT-attribution notice.
Nav: added 🎨 Brand link to every sirius.x page (landing, portal, docs,
theseus). og:image on every page updated to point at /brand/banner.svg
instead of the wordmark logo — social crawlers get a proper 1200×630
banner with title, tagline, and mark instead of a thin logo strip.
Kept /assets/favicon.svg and /assets/logo.svg in place so existing
external references (Nostr metadata, third-party embeds) don't break.
2026-08-31 05:44:25 +02:00
< meta property = "og:image" content = "https://silentmode.st/sirius-x/brand/banner.svg" >
2026-08-31 04:30:53 +02:00
< meta name = "twitter:card" content = "summary" >
2026-08-29 21:57:33 +02:00
< style >
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
}
*{box-sizing:border-box}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:820px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px}
.topnav .brand .g{color:var(--acid)}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
2026-08-29 22:22:37 +02:00
.topnav a.portal{margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500}
.topnav a.portal:hover{background:rgba(214,255,61,.18)}
2026-08-29 21:57:33 +02:00
header.hero{text-align:center;padding:3rem 1.2rem 1rem}
.mark{font-size:44px;line-height:1}
h1{font-size:clamp(1.6rem,4.5vw,2.2rem);margin:.3rem 0 .3rem}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1rem;max-width:580px;margin:0 auto}
h2{font-size:1.25rem;margin:0 0 .4rem}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:2rem}
section:first-of-type{border-top:none;margin-top:1rem}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px;margin-top:1rem}
label{display:block;font-size:13px;color:var(--mut);margin:14px 0 5px}
textarea,input[type=password],input[type=text]{
width:100%;padding:11px 13px;border-radius:10px;border:1px solid #ffffff22;background:#0e131b;
color:var(--ink);font-size:14px;font-family:inherit;outline:none
}
textarea{min-height:74px;resize:vertical;font-family:ui-monospace,monospace;font-size:13px}
textarea:focus,input:focus{border-color:#4b7bec}
.btn{display:inline-block;text-decoration:none;padding:10px 18px;border-radius:10px;background:#4b7bec;color:#fff;font-size:14px;border:none;cursor:pointer;font-family:inherit}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn.small{padding:6px 12px;font-size:12.5px}
.btn:hover{filter:brightness(1.12)}
.btn:disabled{opacity:.45;cursor:not-allowed;filter:none}
.row{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px;align-items:center}
.muted{color:var(--mut);font-size:13px}
.dim{color:var(--dim);font-size:12.5px}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px;word-break:break-all}
.badge{display:inline-block;font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600}
.b-x{background:rgba(214,255,61,.14);color:var(--acid)}
.b-warn{background:rgba(255,199,95,.14);color:var(--warn)}
.err{color:var(--taken);font-size:13.5px;margin-top:10px}
.status{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;color:var(--mut);margin-top:12px}
.status.ok{border-left:3px solid var(--ok)}
.status.err{border-left:3px solid var(--taken);color:var(--taken)}
.hidden{display:none}
.authbox{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.authbox .card{margin:0}
.authbox h3{margin:0 0 .3rem;font-size:1rem}
.authbox p{margin:0;color:var(--mut);font-size:13px}
.authbox .card > .cta{margin-top:14px}
2026-08-31 21:44:20 +02:00
.name-row{display:grid;grid-template-columns:1fr auto auto auto;gap:10px;align-items:center;
2026-08-29 21:57:33 +02:00
padding:14px 16px;background:var(--panel2);border:1px solid var(--line);border-radius:12px;margin-top:8px}
.name-row .n{font-family:ui-monospace,monospace;font-size:15px}
.name-row .rec{color:var(--mut);font-family:ui-monospace,monospace;font-size:12px;grid-column:1/-1;margin-top:6px;word-break:break-all}
.name-row .rec .k{color:var(--dim)}
2026-08-31 21:44:20 +02:00
/* record editor modal */
.modal{position:fixed;inset:0;background:rgba(6,9,14,.82);backdrop-filter:blur(3px);
display:none;align-items:flex-start;justify-content:center;padding:3vh 1rem;overflow-y:auto;z-index:50}
.modal.open{display:flex}
.sheet{background:var(--panel);border:1px solid var(--line);border-radius:16px;max-width:620px;width:100%;
padding:24px 26px;position:relative}
.sheet h3{margin:0 0 .3rem;font-size:1.15rem;font-family:ui-monospace,monospace}
.sheet .sub{color:var(--mut);font-size:13px;margin:0 0 1.2rem}
.sheet .x{position:absolute;top:14px;right:16px;background:none;border:none;color:var(--dim);font-size:22px;cursor:pointer;line-height:1}
.sheet label{display:block;font-size:12px;color:var(--mut);margin:12px 0 4px;text-transform:uppercase;letter-spacing:.4px}
.sheet .field-hint{color:var(--dim);font-size:11.5px;margin-left:8px;text-transform:none;letter-spacing:0}
.sheet input[type=text],.sheet textarea{
width:100%;padding:9px 12px;border-radius:8px;border:1px solid #ffffff22;background:#0e131b;
color:var(--ink);font-size:13px;font-family:ui-monospace,monospace;outline:none
}
.sheet textarea{min-height:60px;resize:vertical}
.sheet input:focus,.sheet textarea:focus{border-color:#4b7bec}
.sheet .budget{display:flex;justify-content:space-between;align-items:center;font-size:12px;color:var(--mut);margin-top:14px;padding:8px 12px;background:var(--panel2);border-radius:8px}
.sheet .budget.over{background:rgba(246,118,138,.15);color:var(--taken)}
.sheet .actions{display:flex;gap:10px;justify-content:flex-end;margin-top:16px}
.sheet .steps-log{margin-top:12px;font-family:ui-monospace,monospace;font-size:12px;color:var(--mut);background:#0e131b;border:1px solid var(--line);border-radius:8px;padding:10px 12px;max-height:120px;overflow-y:auto;display:none}
.sheet .steps-log.on{display:block}
.sheet .steps-log div::before{content:"› ";color:var(--acid)}
.sheet .msg{font-size:13px;margin-top:12px}
.sheet .msg.err{color:var(--taken)} .sheet .msg.ok{color:var(--ok)}
2026-08-29 21:57:33 +02:00
footer{border-top:1px solid var(--line);padding:2rem 0 3rem;color:var(--dim);font-size:13px;text-align:center;margin-top:2.5rem}
@media (max-width:520px){
.name-row{grid-template-columns:1fr auto}
}
< / style >
< / head >
< body >
< nav class = "topnav" >
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
< a class = "brand" href = "./" > ⭐ < span class = "g" > Sirius.X< / span > < / a >
2026-08-29 21:57:33 +02:00
< a href = "./#try" > Try it< / a >
2026-08-29 22:00:37 +02:00
< a href = "./docs/" > 📚 Docs< / a >
2026-08-29 21:57:33 +02:00
< a href = "./theseus/" > 🧭 Theseus< / a >
2026-09-06 22:32:23 +02:00
< a href = "./register.html" > 🪪 Register< / a >
feat(sirius-x): public tld.html — search + mint a TLD end-to-end
Missing user-facing surface: minting a TLD required either the portal
(sign in first, register second, tucked under 'Signed in') or the
operator-only admin panel. New tld.html is a public, single-purpose
page that lets anyone go straight from label to certificate.
Flow: type a label → live check against /api/tlds → 'Register .foo →'
appears → sign-in cards (New / Import / WizardConnect) revealed inline
→ mint section shows label, address, price → submit walks through
'connected → checking-availability → loading-coins → building →
signing → broadcasting → registered'.
Wire is proven end-to-end (search returns a registerable card for
free labels, wallet flow generates a valid seed, address, submit
reaches 'wallet is empty' with a friendly faucet hint for the
signed-in address). Downstream of loading-coins is the same build/
sign/broadcast path exercised by every name registration.
Dispatch on wallet.source uses registerTldWithExternalWallet when
signed in via WC, else registerTldWithBuiltInWallet. Live TLD table
under the search shows every currently registered TLD with its
category; refreshes on successful mint.
Nav: '🌐 TLD' added to all 7 pages between Register and Brand.
Landing's 'Register a TLD' card now points here (previously linked
to the operator admin, which locked out anyone who isn't operator).
2026-09-07 20:39:11 +02:00
< a href = "./tld.html" > 🌐 TLD< / a >
2026-08-31 05:40:47 +02:00
< a href = "./#roadmap" > Roadmap< / a >
sirius.x: /brand/ kit — logo, mono, avatar, banner, favicon, palette
brand/ ships every reusable mark plus a browseable kit page:
* logo.svg — full colour wordmark (star + sirius.x, .x in acid green)
* logo-mono.svg — currentColor version for print / one-colour merch
* favicon.svg — 64×64 rounded square, scales cleanly to 16×16
* avatar.svg — 512×512 square, hard corners (platforms round-mask)
* banner.svg — 1200×630 OG / Twitter Card canvas, crop-tolerant layout
* index.html — brand-kit page: asset previews + download links, full
colour palette with names/hex, typography sample, do/don't guidance,
MIT-attribution notice.
Nav: added 🎨 Brand link to every sirius.x page (landing, portal, docs,
theseus). og:image on every page updated to point at /brand/banner.svg
instead of the wordmark logo — social crawlers get a proper 1200×630
banner with title, tagline, and mark instead of a thin logo strip.
Kept /assets/favicon.svg and /assets/logo.svg in place so existing
external references (Nostr metadata, third-party embeds) don't break.
2026-08-31 05:44:25 +02:00
< a href = "./brand/" > 🎨 Brand< / a >
2026-08-29 21:57:33 +02:00
< a href = "https://silentmode.st/" rel = "noopener" > Silent Mode ↗< / a >
2026-08-29 22:22:37 +02:00
< a href = "./portal.html" class = "portal here" > 🔑 Sign in< / a >
2026-08-29 21:57:33 +02:00
< / nav >
< header class = "hero" >
< div class = "mark" > 🔑< / div >
< h1 > Your < span class = "g" > names< / span > portal< / h1 >
< p class = "tag" > Sign in with your Bitcoin Cash seed phrase or connect an external wallet to see
every BCNR name your wallet holds. Your keys never leave this browser tab.< / p >
< / header >
< div class = "wrap" >
< section id = "signin" >
< h2 > Sign in< / h2 >
< p class = "muted" > Pick one. Nothing is transmitted — resolution is a read-only chain query,
and signing (for record edits) happens locally in the browser or in your external wallet.< / p >
< div class = "authbox" style = "margin-top:14px" >
2026-09-07 00:15:43 +02:00
< div class = "card" id = "card-new" >
< h3 > 🆕 New wallet< / h3 >
< p > Generate a fresh 12-word BIP-39 phrase in your browser. Write it down before continuing —
it never leaves this page and there is nothing to reset if you lose it.< / p >
< div class = "row" >
< button class = "btn acid" id = "new-btn" > Generate a phrase< / button >
< / div >
< div id = "new-phrase" class = "hidden" style = "margin-top:14px" >
< label > Your new recovery phrase< / label >
< textarea id = "new-seed" readonly style = "font-family:ui-monospace,monospace;font-size:14px" > < / textarea >
< label style = "margin-top:10px;display:flex;gap:9px;align-items:flex-start;font-size:13.5px" >
< input type = "checkbox" id = "new-ack" style = "margin-top:3px" >
< span > I have written this phrase down somewhere safe. I understand it is the only way
to recover this wallet and cannot be reset.< / span >
< / label >
< div class = "row" >
< button class = "btn acid" id = "new-signin-btn" disabled > Sign in with new wallet →< / button >
< button class = "btn ghost" id = "new-copy-btn" > Copy phrase< / button >
< / div >
< / div >
< div id = "new-err" class = "err hidden" > < / div >
< / div >
< div class = "card" id = "card-import" >
< h3 > 📥 Import a seed phrase< / h3 >
2026-08-29 21:57:33 +02:00
< p > Paste your 12- or 24-word BIP-39 recovery phrase. It stays in memory only, wiped when you
close the tab or sign out.< / p >
< label for = "seed" > Recovery phrase< / label >
< textarea id = "seed" placeholder = "word1 word2 … word12" spellcheck = "false" autocomplete = "off" > < / textarea >
< div class = "row" >
< button class = "btn acid" id = "signin-btn" > Sign in →< / button >
< span class = "dim" > Chipnet only for now.< / span >
< / div >
< div id = "signin-err" class = "err hidden" > < / div >
< / div >
2026-09-07 00:15:43 +02:00
< div class = "card" id = "card-wc" >
< h3 > 🔗 Connect an external wallet< / h3 >
2026-08-29 21:57:33 +02:00
< p > Use Cashonize 0.9+ or Paytaca via WizardConnect. The wallet signs record edits — the seed
never touches this page.< / p >
< div class = "row" >
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
< button class = "btn acid" id = "wc-btn" > Connect wallet< / button >
2026-08-29 21:57:33 +02:00
< / div >
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
< div id = "wc-uri-box" class = "hidden" style = "margin-top:14px" >
< label > Open your wallet, scan or paste this URI, then approve the connection:< / label >
< div style = "display:flex;gap:8px;align-items:center;margin-top:6px" >
< code id = "wc-uri" style = "flex:1;word-break:break-all;background:#0e131b;border:1px solid var(--line);border-radius:8px;padding:9px 11px;font-family:ui-monospace,monospace;font-size:12.5px;color:var(--ink)" > < / code >
< button class = "btn ghost" id = "wc-copy" type = "button" > Copy< / button >
< / div >
< p class = "dim" style = "margin-top:8px" > Waiting for your wallet…< / p >
< div class = "row" > < button class = "btn ghost" id = "wc-cancel" type = "button" > Cancel< / button > < / div >
< / div >
< div id = "wc-err" class = "err hidden" > < / div >
2026-09-07 01:39:16 +02:00
< p class = "dim" style = "margin-top:8px" > Record edits and TLD mints are approved on your device
via the wallet's signing prompt — the seed never touches this page.< / p >
2026-08-29 21:57:33 +02:00
< / div >
< / div >
< div class = "status" style = "margin-top:14px" >
Don't have a wallet? Create one during
2026-09-06 22:32:23 +02:00
< a href = "./register.html" > name registration< / a > — the recovery phrase
2026-08-29 21:57:33 +02:00
is generated in your browser and encrypted with your password.
< / div >
< / section >
< section id = "me" class = "hidden" >
< h2 > Signed in< / h2 >
sirius.x/portal: register a TLD in-browser (M1.5 — chipnet, USD-priced)
Sign-in view grows a "Register a new TLD" card. User picks a label (validated
against [a-z0-9-]{1,16} and normalised as they type), sees live sats price
computed from a USD field via a static chipnet oracle rate (250,000 sats/USD
≈ $400/BCH), can check availability against navigate.st/api/tlds, then submit
a TREG signed with the built-in wallet — same code path seed-tld-beacon.mjs
uses server-side, but via the browser-exported registerTldWithBuiltInWallet.
* Live price display recalculates on USD-input change; service fee is
paid to REGISTRAR.serviceFee.address (same fee address name registrations
use — no per-TLD split yet since that's mainnet covenant territory).
* Check-availability polls the live /api/tlds endpoint before the user
commits sats to a doomed TREG.
* Progress log streams the shared onProgress steps
("checking-availability", "signing", "broadcast: <txid>") so users can
tell whether the transaction actually left the browser.
* Chipnet rate + form default of $5 make full-flow tests possible from
the operator wallet (~1.25M sats each); users can override the USD to
$0.01 for cheap iteration during testing.
UI verified end-to-end (label sanitisation, price recalc, availability
check against real API, buttons gate correctly on wallet state). Full
sign+broadcast requires a funded wallet — operator can verify.
Next: real oracle (CoinGecko / Kraken feed) + tiered pricing by label
length + admin panel for changing the rate config.
2026-09-06 18:18:41 +02:00
< div class = "card" id = "tld-register-card" >
< h3 style = "margin:0 0 .3rem;font-size:1.05rem" > Register a new TLD< / h3 >
< p class = "muted" style = "margin:0 0 .8rem" > TLDs are per-registry NFTs on the chipnet TLD beacon.
Public mints go through a service-fee output to fund the registry. Chipnet uses a placeholder
rate; mainnet will price by label length via a real oracle.< / p >
< label > Label < span class = "dim" style = "margin-left:6px" > 1– 16 chars, [a-z0-9-]< / span > < / label >
< input type = "text" id = "tld-label" placeholder = "myregistry" autocomplete = "off" spellcheck = "false" maxlength = "16" >
< label style = "margin-top:12px" > Service fee (USD) < span class = "dim" style = "margin-left:6px" > chipnet test rate< / span > < / label >
< input type = "text" id = "tld-usd" value = "5" >
< div class = "status" id = "tld-price" > = < b > 0< / b > sats · rate < b > 0< / b > sats/USD< / div >
< div class = "row" >
< button class = "btn acid small" id = "tld-check" disabled > Check availability< / button >
< button class = "btn small" id = "tld-submit" disabled > Register (~0 sats)< / button >
< / div >
< div id = "tld-log" class = "status" style = "display:none;font-family:ui-monospace,monospace;font-size:12.5px;margin-top:12px" > < / div >
< div id = "tld-msg" style = "margin-top:10px;font-size:13.5px" > < / div >
< / div >
< h2 style = "margin-top:2rem" > Wallet< / h2 >
2026-08-29 21:57:33 +02:00
< div class = "card" >
< label > Receive address< / label >
< div > < code id = "me-addr" > —< / code > < / div >
< label style = "margin-top:14px" > Token address (holds your name certificates)< / label >
< div > < code id = "me-taddr" > —< / code > < / div >
< div class = "row" >
< button class = "btn ghost small" id = "signout-btn" > Sign out< / button >
< span class = "dim" id = "me-info" > —< / span >
< / div >
< / div >
< h2 style = "margin-top:2rem" > Names you hold< / h2 >
< div class = "status" id = "names-status" > Loading names from the chain…< / div >
< div id = "names-list" > < / div >
< / section >
< / div >
2026-08-31 21:44:20 +02:00
<!-- record - editor modal — populated by JS when a name's Edit button fires -->
< div class = "modal" id = "editor" >
< div class = "sheet" >
< button class = "x" id = "ed-close" title = "close" > × < / button >
< h3 id = "ed-name" > —< / h3 >
< p class = "sub" > Edit records. Only your key can sign this UPD; the transaction fee is a few
cents in chain fees plus the beacon dust. Leave a field blank to omit that record.< / p >
< label > h < span class = "field-hint" > inline HTML — served as-is at the site root< / span > < / label >
< textarea id = "ed-h" placeholder = "<h1>My site</h1>" > < / textarea >
< label > s3 < span class = "field-hint" > Sia bucket key, trailing slash for directories< / span > < / label >
< input type = "text" id = "ed-s3" placeholder = "bns/myname/" >
< label > ip < span class = "field-hint" > IPv4 that serves this name over Host header< / span > < / label >
< input type = "text" id = "ed-ip" placeholder = "1.2.3.4" >
< label > tls < span class = "field-hint" > SHA-256 of your leaf cert — chain-pinned TLS trust< / span > < / label >
< input type = "text" id = "ed-tls" placeholder = "hex — 64 chars, no separators" >
< label > u < span class = "field-hint" > redirect target< / span > < / label >
< input type = "text" id = "ed-u" placeholder = "https://…" >
< div class = "budget" id = "ed-budget" > payload: < b > < span id = "ed-budget-used" > 0< / span > < / b > / < span id = "ed-budget-max" > ?< / span > bytes< / div >
< div class = "steps-log" id = "ed-log" > < / div >
< div class = "msg" id = "ed-msg" > < / div >
< div class = "actions" >
< button class = "btn ghost" id = "ed-cancel" > Cancel< / button >
< button class = "btn acid" id = "ed-save" > Save records →< / button >
< / div >
< / div >
< / div >
2026-08-29 21:57:33 +02:00
< footer >
Your keys, your names, your browser. ·
< a href = "./" > back to sirius.x< / a > ·
2026-09-06 22:32:23 +02:00
< a href = "./register.html" > register a new name< / a >
2026-08-29 21:57:33 +02:00
< / footer >
< script type = "importmap" >
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
< / script >
< script type = "module" >
// The registrar bundle exports everything we need: BuiltInWallet for local
// wallet unlock, resolveName/buildIndex for chain queries, getUtxosForAddresses
// for holdings. This portal is a read-first surface; record edits (UPD) will
// come next and will piggyback on the same signing path the registrar uses.
2026-08-31 03:35:39 +02:00
// Cache-buster bumped whenever the bundle changes. Chrome's in-memory ES
// module map ignores Cache-Control on the .js URL for the lifetime of a tab,
// so a plain "/js/bns-register.js" import can return a stale instance days
// after deploy. A query string forces the module loader to treat this as a
// new URL and fetch fresh bytes.
2026-09-07 01:39:16 +02:00
import * as BNS from "https://silentmode.st/js/bns-register.js?v=20260907tldext";
2026-08-29 21:57:33 +02:00
const $ = (id) => document.getElementById(id);
const esc = (s) => String(s).replace(/[& < >"']/g, (c) => ({"&":"& ","< ":"< ",">":"> ",'"':"" ","'":"' "}[c]));
let wallet = null;
2026-09-07 00:15:43 +02:00
// Persist signed-in state so the profile dropdown (profile-menu.js) can flip
// from "onboarding" to "signed in" and any tab on the same origin (sirius.x)
// reflects the current session. The wallet keys themselves never leave this
// page — localStorage only holds a small address-only breadcrumb, no seed.
function writeProfile(w) {
try {
localStorage.setItem("siriusProfile", JSON.stringify({
address: w.address,
tokenAddress: w.tokenAddress,
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
source: w.source ?? "seed", // "seed" | "wc"
2026-09-07 00:15:43 +02:00
signedInAt: Date.now(),
}));
} catch {}
// profile-menu.js listens for this to re-render the nav dropdown in the
// same tab (the "storage" event only fires in *other* tabs).
window.dispatchEvent(new Event("siriusProfileChanged"));
}
function clearProfile() {
try { localStorage.removeItem("siriusProfile"); } catch {}
window.dispatchEvent(new Event("siriusProfileChanged"));
}
2026-08-29 21:57:33 +02:00
// ---------- sign in ----------
$("signin-btn").addEventListener("click", async () => {
const btn = $("signin-btn");
const errBox = $("signin-err");
errBox.classList.add("hidden");
const raw = $("seed").value.trim();
if (!raw) { errBox.textContent = "Enter your seed phrase to sign in."; errBox.classList.remove("hidden"); return; }
btn.disabled = true; btn.textContent = "Unlocking…";
try {
wallet = await BNS.BuiltInWallet.fromMnemonic(raw);
} catch (e) {
errBox.textContent = "Could not unlock: " + (e.message || e);
errBox.classList.remove("hidden");
btn.disabled = false; btn.textContent = "Sign in →";
return;
}
$("seed").value = "";
btn.disabled = false; btn.textContent = "Sign in →";
2026-09-07 00:15:43 +02:00
writeProfile(wallet);
await enterPortal();
});
// ---------- new wallet ----------
// Generates a fresh BIP-39 phrase in the browser via BuiltInWallet.create().
// The phrase is shown once for the user to write down; sign-in only unlocks
// after they acknowledge they have saved it. From that point on the flow is
// identical to import (BuiltInWallet in memory, no persistence of the seed).
$("new-btn").addEventListener("click", async () => {
const btn = $("new-btn");
const errBox = $("new-err");
errBox.classList.add("hidden");
btn.disabled = true; btn.textContent = "Generating…";
let fresh;
try { fresh = await BNS.BuiltInWallet.create(); }
catch (e) {
errBox.textContent = "Could not generate a phrase: " + (e.message || e);
errBox.classList.remove("hidden");
btn.disabled = false; btn.textContent = "Generate a phrase";
return;
}
wallet = fresh;
$("new-seed").value = fresh.mnemonic;
$("new-phrase").classList.remove("hidden");
btn.disabled = true; btn.textContent = "Phrase generated";
});
$("new-ack").addEventListener("change", (e) => {
$("new-signin-btn").disabled = !e.target.checked;
});
$("new-copy-btn").addEventListener("click", () => {
navigator.clipboard?.writeText($("new-seed").value);
});
$("new-signin-btn").addEventListener("click", async () => {
if (!wallet) return;
// Wipe the visible phrase immediately — it's in the wallet object now.
$("new-seed").value = "";
$("new-phrase").classList.add("hidden");
writeProfile(wallet);
2026-08-29 21:57:33 +02:00
await enterPortal();
});
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
// ---------- WizardConnect ----------
// Ports the WC flow from register.html into a sign-in surface. The portal
// doesn't need to mint — it only reads holdings and signs UPDs — so this is
// simpler than the register flow: open a session, show the URI/QR, wait for
// approval, wrap the returned addresses in a wallet-shaped object with a
// `source: "wc"` flag so downstream code (record editor, sign-out) can
// dispatch to the external-wallet path.
$("wc-btn").addEventListener("click", async () => {
const btn = $("wc-btn");
const errBox = $("wc-err");
const uriBox = $("wc-uri-box");
errBox.classList.add("hidden");
btn.disabled = true; btn.textContent = "Starting…";
let session;
try {
const mod = await import("https://silentmode.st/js/wizardconnect.js");
session = await mod.openWizardSession({
dappName: BNS.REGISTRAR.wizardConnect.dappName,
dappIcon: BNS.REGISTRAR.wizardConnect.dappIcon,
prefix: BNS.REGISTRAR.addressPrefix,
// libauth is only bundled once (in the main bundle); wizardconnect.js
// needs these pubkey/hash helpers passed through.
crypto: {
pubkeyToAddress: BNS.pubkeyToAddress,
pubkeyToLockingBytecode: BNS.pubkeyToLockingBytecode,
binToHex: BNS.binToHex,
txidOfHex: BNS.txidOfHex,
},
});
} catch (e) {
errBox.textContent = "Could not start WizardConnect: " + (e.message || e);
errBox.classList.remove("hidden");
btn.disabled = false; btn.textContent = "Connect wallet";
return;
}
const uri = session.qrUri ?? session.uri;
$("wc-uri").textContent = uri;
uriBox.classList.remove("hidden");
btn.textContent = "Waiting for wallet…";
try {
await session.ready;
} catch (e) {
errBox.textContent = "Wallet did not approve: " + (e.message || e);
errBox.classList.remove("hidden");
uriBox.classList.add("hidden");
btn.disabled = false; btn.textContent = "Connect wallet";
try { await session.disconnect(); } catch {}
return;
}
let addresses;
try { addresses = await session.getAddresses(); }
catch (e) {
errBox.textContent = "Wallet returned no addresses: " + (e.message || e);
errBox.classList.remove("hidden");
uriBox.classList.add("hidden");
btn.disabled = false; btn.textContent = "Connect wallet";
try { await session.disconnect(); } catch {}
return;
}
if (!addresses?.length) {
errBox.textContent = "The connected wallet exposed no addresses.";
errBox.classList.remove("hidden");
uriBox.classList.add("hidden");
btn.disabled = false; btn.textContent = "Connect wallet";
try { await session.disconnect(); } catch {}
return;
}
// Wallet-shaped wrapper — enough for holdings lookup and dispatching the
// WC path in the record editor. External wallets don't expose keyFor(),
// so any codepath that needs it (TLD mint via built-in path) is guarded
// by `wallet.source !== "wc"`.
wallet = {
source: "wc",
address: addresses[0],
tokenAddress: BNS.toTokenAddress(addresses[0]),
watchedAddresses: addresses,
session,
};
writeProfile(wallet);
uriBox.classList.add("hidden");
btn.disabled = false; btn.textContent = "Connect wallet";
await enterPortal();
});
$("wc-cancel").addEventListener("click", async () => {
if (wallet?.session) { try { await wallet.session.disconnect(); } catch {} }
$("wc-uri-box").classList.add("hidden");
$("wc-btn").disabled = false;
$("wc-btn").textContent = "Connect wallet";
});
$("wc-copy").addEventListener("click", () => {
navigator.clipboard?.writeText($("wc-uri").textContent);
});
$("signout-btn").addEventListener("click", async () => {
// Close any live WC session before dropping the reference.
if (wallet?.source === "wc" & & wallet.session) {
try { await wallet.session.disconnect(); } catch {}
}
2026-08-29 21:57:33 +02:00
wallet = null;
2026-09-07 00:15:43 +02:00
clearProfile();
2026-08-29 21:57:33 +02:00
$("me").classList.add("hidden");
$("signin").classList.remove("hidden");
$("names-list").innerHTML = "";
$("names-status").textContent = "Loading names from the chain…";
2026-09-07 00:15:43 +02:00
// Reset the new-wallet card so a subsequent sign-in starts clean.
$("new-btn").disabled = false; $("new-btn").textContent = "Generate a phrase";
$("new-phrase").classList.add("hidden");
$("new-ack").checked = false;
$("new-signin-btn").disabled = true;
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
// Reset the WC card too.
$("wc-btn").disabled = false; $("wc-btn").textContent = "Connect wallet";
$("wc-uri-box").classList.add("hidden");
2026-08-29 21:57:33 +02:00
});
2026-09-07 00:15:43 +02:00
// ---------- ?mode= deep-link ----------
// The profile dropdown links to portal.html?mode=new|import|wc — bring the
// matching card into view and highlight its border briefly so the user knows
// which one they were sent to.
(function handleMode() {
const mode = new URLSearchParams(location.search).get("mode");
if (!mode) return;
const id = { new: "card-new", import: "card-import", wc: "card-wc" }[mode];
const el = id & & document.getElementById(id);
if (!el) return;
el.style.borderColor = "var(--acid)";
el.style.boxShadow = "0 0 0 3px rgba(214,255,61,.15)";
setTimeout(() => el.scrollIntoView({ behavior: "smooth", block: "center" }), 50);
setTimeout(() => { el.style.borderColor = ""; el.style.boxShadow = ""; }, 3000);
})();
2026-08-29 21:57:33 +02:00
async function enterPortal() {
$("signin").classList.add("hidden");
$("me").classList.remove("hidden");
$("me-addr").textContent = wallet.address;
$("me-taddr").textContent = wallet.tokenAddress;
$("me-info").textContent = "watched addresses: " + wallet.watchedAddresses.length;
sirius.x/portal: register a TLD in-browser (M1.5 — chipnet, USD-priced)
Sign-in view grows a "Register a new TLD" card. User picks a label (validated
against [a-z0-9-]{1,16} and normalised as they type), sees live sats price
computed from a USD field via a static chipnet oracle rate (250,000 sats/USD
≈ $400/BCH), can check availability against navigate.st/api/tlds, then submit
a TREG signed with the built-in wallet — same code path seed-tld-beacon.mjs
uses server-side, but via the browser-exported registerTldWithBuiltInWallet.
* Live price display recalculates on USD-input change; service fee is
paid to REGISTRAR.serviceFee.address (same fee address name registrations
use — no per-TLD split yet since that's mainnet covenant territory).
* Check-availability polls the live /api/tlds endpoint before the user
commits sats to a doomed TREG.
* Progress log streams the shared onProgress steps
("checking-availability", "signing", "broadcast: <txid>") so users can
tell whether the transaction actually left the browser.
* Chipnet rate + form default of $5 make full-flow tests possible from
the operator wallet (~1.25M sats each); users can override the USD to
$0.01 for cheap iteration during testing.
UI verified end-to-end (label sanitisation, price recalc, availability
check against real API, buttons gate correctly on wallet state). Full
sign+broadcast requires a funded wallet — operator can verify.
Next: real oracle (CoinGecko / Kraken feed) + tiered pricing by label
length + admin panel for changing the rate config.
2026-09-06 18:18:41 +02:00
// Initialise the TLD-register card now that the wallet is available.
if (typeof updateTldPrice === "function") { updateTldPrice(); updateTldButtons(); }
2026-08-29 21:57:33 +02:00
await loadNames();
}
// ---------- load names ----------
2026-08-31 05:40:47 +02:00
// Approach: derive the scripthash for each watched address locally (the
// wallet code already knows how), send them in one POST to
// /api/holdings, and render whatever the gateway returns. Doing the
// wallet-holdings query server-side is what makes this work on browsers
// stuck behind firewalls that block chipnet electrum ports (50004,
// 50011, 62002) — the API is same-origin HTTPS on port 443, and the
// gateway can reach the full electrums the browser can't.
2026-08-29 21:57:33 +02:00
async function loadNames() {
const status = $("names-status");
const list = $("names-list");
list.innerHTML = "";
status.className = "status";
2026-08-31 05:40:47 +02:00
status.textContent = "Preparing your addresses…";
2026-08-29 21:57:33 +02:00
try {
const addresses = wallet.watchedAddresses;
2026-08-31 05:40:47 +02:00
const scripthashes = addresses.map((a) => BNS.addressToScripthash(a));
status.textContent = `Asking the gateway about ${addresses.length} addresses…`;
const r = await fetch("https://silentmode.st/api/holdings", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ scripthashes }),
});
if (!r.ok) {
const detail = await r.text().catch(() => "");
throw new Error(`API ${r.status}: ${detail.slice(0, 200)}`);
}
const { count, names: mine } = await r.json();
if (!count) {
2026-08-29 21:57:33 +02:00
status.className = "status";
Sweep: mobile Ariadne updates, Deviant brand + sites, Hephaestus bootstrap, snappymail
Broad-scope commit sweeping in work from parallel sessions plus this session's
dev-only utilities. No single unifying theme — this is the "commit everything
that's ready" pass. Grouped by area below.
AriadneResolver / mobile
* Small updates to BchFetcher, Bns, MainActivity, AriadneVpnService, and the
Android manifest — from a parallel mobile-resolver session.
* AriadneResolver/mobile/webpreview/ — new local dev webview (index.html +
server.mjs) for iterating on the mobile UI without a device.
Email / SnappyMail
* Email/snappymail-plugin/silentmode-addresses — new SnappyMail plugin
(README, CSS, PHP entry, JS) for surfacing @silentmode.st address
management inside the webmail UI.
Hephaestus (Forgejo + auth-proxy)
* auth-proxy/src/oidc.ts + docker-compose.yml updates.
* scripts/bootstrap-auth.sh — idempotent script that registers the wallet
auth-proxy as Forgejo's OIDC provider after `docker compose up -d`. All
secrets read from .env — no literals in the script.
TheseusNavigator / dev tools
* dev/list-tlds.mjs — enumerate every registered BNS name grouped by TLD via
our own indexer.
* dev/show-tlds-bch.mjs — dump the full records payload of the legacy
tlds.bch name (kept as a diagnostic for the list-in-one-NFT era).
Deviant sites + brand
* site/deviant/ — new microsites (anthemus, potidaea, brand, mindmap, main
index) plus the full brand kit under site/deviant/brand/ (logos, icons,
palette, social exports as SVG source + PNG renders).
* site-sirius-x/portal.html — updates.
Coordination
* _coordination/sessions/mobile-resolver.md — parallel-session notes.
Deliberately excluded from this commit:
* scratchpad/ — this session's temp drafts (Sia doc mockups, tlds UPD payloads).
* TheseusNavigator/_prev/ — ~372 MB of prior release binaries; belongs in
a separate artefacts store, not the git tree. Add to .gitignore next pass.
2026-08-30 10:38:49 +02:00
status.textContent = "No BCNR names found for this wallet. If you just registered, wait a minute for confirmation and reload.";
2026-08-29 21:57:33 +02:00
return;
}
status.className = "status ok";
2026-08-31 05:40:47 +02:00
status.textContent = `You own ${count} name${count === 1 ? "" : "s"}.`;
for (const e of mine) {
2026-08-29 21:57:33 +02:00
const div = document.createElement("div");
div.className = "name-row";
const records = e.records & & Object.keys(e.records).length
? Object.entries(e.records).map(([k, v]) => `< span class = "k" > ${esc(k)}=< / span > ${esc(String(v).slice(0, 80))}`).join(" · ")
Sweep: mobile Ariadne updates, Deviant brand + sites, Hephaestus bootstrap, snappymail
Broad-scope commit sweeping in work from parallel sessions plus this session's
dev-only utilities. No single unifying theme — this is the "commit everything
that's ready" pass. Grouped by area below.
AriadneResolver / mobile
* Small updates to BchFetcher, Bns, MainActivity, AriadneVpnService, and the
Android manifest — from a parallel mobile-resolver session.
* AriadneResolver/mobile/webpreview/ — new local dev webview (index.html +
server.mjs) for iterating on the mobile UI without a device.
Email / SnappyMail
* Email/snappymail-plugin/silentmode-addresses — new SnappyMail plugin
(README, CSS, PHP entry, JS) for surfacing @silentmode.st address
management inside the webmail UI.
Hephaestus (Forgejo + auth-proxy)
* auth-proxy/src/oidc.ts + docker-compose.yml updates.
* scripts/bootstrap-auth.sh — idempotent script that registers the wallet
auth-proxy as Forgejo's OIDC provider after `docker compose up -d`. All
secrets read from .env — no literals in the script.
TheseusNavigator / dev tools
* dev/list-tlds.mjs — enumerate every registered BNS name grouped by TLD via
our own indexer.
* dev/show-tlds-bch.mjs — dump the full records payload of the legacy
tlds.bch name (kept as a diagnostic for the list-in-one-NFT era).
Deviant sites + brand
* site/deviant/ — new microsites (anthemus, potidaea, brand, mindmap, main
index) plus the full brand kit under site/deviant/brand/ (logos, icons,
palette, social exports as SVG source + PNG renders).
* site-sirius-x/portal.html — updates.
Coordination
* _coordination/sessions/mobile-resolver.md — parallel-session notes.
Deliberately excluded from this commit:
* scratchpad/ — this session's temp drafts (Sia doc mockups, tlds UPD payloads).
* TheseusNavigator/_prev/ — ~372 MB of prior release binaries; belongs in
a separate artefacts store, not the git tree. Add to .gitignore next pass.
2026-08-30 10:38:49 +02:00
: '< span class = "k" > (no records set)< / span > ';
2026-08-31 21:44:20 +02:00
const recJson = esc(JSON.stringify(e.records || {}));
2026-08-29 21:57:33 +02:00
div.innerHTML =
`< div class = "n" > ${esc(e.name)}< / div > ` +
Sweep: mobile Ariadne updates, Deviant brand + sites, Hephaestus bootstrap, snappymail
Broad-scope commit sweeping in work from parallel sessions plus this session's
dev-only utilities. No single unifying theme — this is the "commit everything
that's ready" pass. Grouped by area below.
AriadneResolver / mobile
* Small updates to BchFetcher, Bns, MainActivity, AriadneVpnService, and the
Android manifest — from a parallel mobile-resolver session.
* AriadneResolver/mobile/webpreview/ — new local dev webview (index.html +
server.mjs) for iterating on the mobile UI without a device.
Email / SnappyMail
* Email/snappymail-plugin/silentmode-addresses — new SnappyMail plugin
(README, CSS, PHP entry, JS) for surfacing @silentmode.st address
management inside the webmail UI.
Hephaestus (Forgejo + auth-proxy)
* auth-proxy/src/oidc.ts + docker-compose.yml updates.
* scripts/bootstrap-auth.sh — idempotent script that registers the wallet
auth-proxy as Forgejo's OIDC provider after `docker compose up -d`. All
secrets read from .env — no literals in the script.
TheseusNavigator / dev tools
* dev/list-tlds.mjs — enumerate every registered BNS name grouped by TLD via
our own indexer.
* dev/show-tlds-bch.mjs — dump the full records payload of the legacy
tlds.bch name (kept as a diagnostic for the list-in-one-NFT era).
Deviant sites + brand
* site/deviant/ — new microsites (anthemus, potidaea, brand, mindmap, main
index) plus the full brand kit under site/deviant/brand/ (logos, icons,
palette, social exports as SVG source + PNG renders).
* site-sirius-x/portal.html — updates.
Coordination
* _coordination/sessions/mobile-resolver.md — parallel-session notes.
Deliberately excluded from this commit:
* scratchpad/ — this session's temp drafts (Sia doc mockups, tlds UPD payloads).
* TheseusNavigator/_prev/ — ~372 MB of prior release binaries; belongs in
a separate artefacts store, not the git tree. Add to .gitignore next pass.
2026-08-30 10:38:49 +02:00
'< span class = "badge b-x" > on chain< / span > ' +
2026-08-29 21:57:33 +02:00
`< a class = "btn small ghost" href = "https://silentmode.st/bns/${encodeURIComponent(e.name)}/" target = "_blank" rel = "noopener" > view →< / a > ` +
2026-08-31 21:44:20 +02:00
`< button class = "btn small acid" data-edit = "${esc(e.name)}" data-records = '${recJson}' > Edit< / button > ` +
2026-08-29 21:57:33 +02:00
`< div class = "rec" > ${records}< / div > `;
list.appendChild(div);
}
2026-08-31 21:44:20 +02:00
// Wire Edit buttons after render.
list.querySelectorAll("[data-edit]").forEach((btn) => {
btn.onclick = () => openEditor(btn.getAttribute("data-edit"), JSON.parse(btn.getAttribute("data-records") || "{}"));
});
2026-08-29 21:57:33 +02:00
} catch (e) {
status.className = "status err";
2026-08-31 05:40:47 +02:00
status.textContent = "Could not load names: " + (e.message || e);
2026-08-29 21:57:33 +02:00
}
}
2026-08-31 21:44:20 +02:00
// ---------- record editor ----------
// Modal that composes a UPD payload from a small form and signs+broadcasts
// with the same code path register.html uses (BNS.setRecordsWithBuiltInWallet).
// External-wallet (WizardConnect) support piggybacks the same adapter and is a
// follow-up — the built-in path is the one this session's wallet flow can already
// sign with.
const EDITABLE_KEYS = ["h", "s3", "ip", "tls", "u"];
let editorName = null;
function openEditor(name, records) {
editorName = name;
$("ed-name").textContent = name;
for (const k of EDITABLE_KEYS) $("ed-" + k).value = records[k] || "";
$("ed-msg").textContent = "";
$("ed-msg").className = "msg";
$("ed-log").className = "steps-log";
$("ed-log").innerHTML = "";
$("ed-save").disabled = false;
$("ed-save").textContent = "Save records →";
updateBudget();
$("editor").classList.add("open");
}
function closeEditor() {
$("editor").classList.remove("open");
editorName = null;
}
$("ed-close").addEventListener("click", closeEditor);
$("ed-cancel").addEventListener("click", closeEditor);
$("editor").addEventListener("click", (e) => { if (e.target === $("editor")) closeEditor(); });
// Bytes budget: BNS payload is capped at 200 bytes total, of which the envelope
// (op + name) uses some. Show the user how many bytes their records take vs the
// remaining budget, and disable Save if they've gone over.
function collectRecords() {
const r = {};
for (const k of EDITABLE_KEYS) {
const v = $("ed-" + k).value.trim();
if (v) r[k] = v;
}
return r;
}
function updateBudget() {
if (!editorName) return;
try {
const max = BNS.payloadBudget(editorName, "UPD");
// The records object encodes to JSON inside the payload. Rough size:
// JSON.stringify(records).length gives a close-enough client-side estimate
// (the actual envelope is composed by the bundle at send time).
const used = new TextEncoder().encode(JSON.stringify(collectRecords())).length;
$("ed-budget-max").textContent = max;
$("ed-budget-used").textContent = used;
const over = used > max;
$("ed-budget").classList.toggle("over", over);
$("ed-save").disabled = over;
} catch { /* budget helper not available yet — ignore */ }
}
for (const k of EDITABLE_KEYS) $("ed-" + k).addEventListener("input", updateBudget);
$("ed-save").addEventListener("click", async () => {
if (!editorName || !wallet) return;
const records = collectRecords();
const msg = $("ed-msg");
const log = $("ed-log");
log.className = "steps-log on";
log.innerHTML = "";
const push = (t) => { const d = document.createElement("div"); d.textContent = t; log.appendChild(d); log.scrollTop = log.scrollHeight; };
msg.textContent = ""; msg.className = "msg";
$("ed-save").disabled = true;
$("ed-save").textContent = "Signing…";
let el = null;
try {
el = await BNS.connect();
push("connected to chipnet");
feat(sirius-x): Sirius.X brand rebrand, banner star-divider, WC on portal
Three things from one review pass:
1. Rebrand text 'sirius.x' -> 'Sirius.X' as the brand style across all
sirius.x pages (titles, meta, nav wordmark, headings, prose, footer).
Also flipped the pantheon headings to Title.X form: Silentmode.X,
Sirius.X, Theseus.X, Hephaestus.X, Prometheus.X, Helios.X, Hermes.X.
Domain literals, URLs, and code samples stay lowercase (sirius.x is
the actual on-chain name; only prose changes). Logo/avatar SVG
wordmarks and aria-labels updated to match.
2. Banner (brand/banner.svg) redesigned around a centered layout:
'Sirius.X' wordmark above, the star's horizontal arm extended
edge-to-edge as a divider line, tagline lines below. Left tip at
(0,315), right tip at (1200,315) so the arm crosses the full 1200px
banner width; vertical body compact around center. Old layout had
the star crammed into the right half and the wordmark on the left.
3. WizardConnect wired up on portal.html:
- The 'Connect wallet' button now opens a real WC session via
wizardconnect.js, shows the WIZ:// URI (copyable) and waits for
the wallet to approve.
- Successful connection builds a wallet-shaped wrapper with
source: 'wc' and a WC session for signing; siriusProfile now
carries the source so the nav dropdown can differentiate.
- Record editor dispatches to setRecordsWithExternalWallet when
source === 'wc' (bundle already ships the adapter), else stays
on setRecordsWithBuiltInWallet.
- TLD Register submit is gated off for WC users with a tooltip —
no external-wallet variant of registerTld is exported yet, so
TLD mint still needs a built-in wallet.
- Sign-out disconnects the WC session before dropping the wallet.
- toTokenAddress used to derive the tokenAddress for WC users so
the 'Signed in' card shows both forms.
2026-09-07 01:35:35 +02:00
const res = wallet.source === "wc"
? await BNS.setRecordsWithExternalWallet(el, {
session: wallet.session, name: editorName, records,
onProgress: (step) => push(step),
})
: await BNS.setRecordsWithBuiltInWallet(el, {
wallet, name: editorName, records,
onProgress: (step) => push(step),
});
2026-08-31 21:44:20 +02:00
push("broadcast: " + (res.txid || res.txId || "(no txid)"));
msg.className = "msg ok";
msg.textContent = "Saved. Records will refresh on the chain within a block.";
$("ed-save").textContent = "Saved ✓";
// Refresh the names list in the background so the user sees the new
// records once they land (may take a few seconds via cache/mempool).
setTimeout(() => loadNames(), 2500);
} catch (e) {
msg.className = "msg err";
msg.textContent = "Failed: " + (e.message || e);
push("error: " + (e.message || e));
$("ed-save").disabled = false;
$("ed-save").textContent = "Save records →";
} finally {
try { el?.close?.(); } catch {}
}
});
sirius.x/portal: register a TLD in-browser (M1.5 — chipnet, USD-priced)
Sign-in view grows a "Register a new TLD" card. User picks a label (validated
against [a-z0-9-]{1,16} and normalised as they type), sees live sats price
computed from a USD field via a static chipnet oracle rate (250,000 sats/USD
≈ $400/BCH), can check availability against navigate.st/api/tlds, then submit
a TREG signed with the built-in wallet — same code path seed-tld-beacon.mjs
uses server-side, but via the browser-exported registerTldWithBuiltInWallet.
* Live price display recalculates on USD-input change; service fee is
paid to REGISTRAR.serviceFee.address (same fee address name registrations
use — no per-TLD split yet since that's mainnet covenant territory).
* Check-availability polls the live /api/tlds endpoint before the user
commits sats to a doomed TREG.
* Progress log streams the shared onProgress steps
("checking-availability", "signing", "broadcast: <txid>") so users can
tell whether the transaction actually left the browser.
* Chipnet rate + form default of $5 make full-flow tests possible from
the operator wallet (~1.25M sats each); users can override the USD to
$0.01 for cheap iteration during testing.
UI verified end-to-end (label sanitisation, price recalc, availability
check against real API, buttons gate correctly on wallet state). Full
sign+broadcast requires a funded wallet — operator can verify.
Next: real oracle (CoinGecko / Kraken feed) + tiered pricing by label
length + admin panel for changing the rate config.
2026-09-06 18:18:41 +02:00
// ---------- TLD register (chipnet MVP) ----------
// Simple oracle: static chipnet rate for testing. Replace with a live feed
// (CoinGecko, Kraken, or a Chainlink adapter) before mainnet. The `sats` output
// is what actually gets locked into a service-fee output on the TREG transaction.
const CHIPNET_SATS_PER_USD = 250_000; // 1 BCH ≈ $400 test rate
function usdToSats(usd) {
const n = Number(String(usd).replace(/[^\d.]/g, "")) || 0;
return Math.max(0, Math.round(n * CHIPNET_SATS_PER_USD));
}
function updateTldPrice() {
const usd = $("tld-usd").value.trim() || "0";
const sats = usdToSats(usd);
$("tld-price").innerHTML = `= < b > ${sats.toLocaleString()}< / b > sats · rate < b > ${CHIPNET_SATS_PER_USD.toLocaleString()}< / b > sats/USD (chipnet)`;
$("tld-submit").textContent = `Register (~${sats.toLocaleString()} sats)`;
}
function validateTldLabel(label) {
return /^[a-z0-9-]{1,16}$/.test(label);
}
function updateTldButtons() {
const label = $("tld-label").value.trim().toLowerCase();
const valid = validateTldLabel(label);
$("tld-check").disabled = !valid || !wallet;
2026-09-07 01:39:16 +02:00
$("tld-submit").disabled = !valid || !wallet;
sirius.x/portal: register a TLD in-browser (M1.5 — chipnet, USD-priced)
Sign-in view grows a "Register a new TLD" card. User picks a label (validated
against [a-z0-9-]{1,16} and normalised as they type), sees live sats price
computed from a USD field via a static chipnet oracle rate (250,000 sats/USD
≈ $400/BCH), can check availability against navigate.st/api/tlds, then submit
a TREG signed with the built-in wallet — same code path seed-tld-beacon.mjs
uses server-side, but via the browser-exported registerTldWithBuiltInWallet.
* Live price display recalculates on USD-input change; service fee is
paid to REGISTRAR.serviceFee.address (same fee address name registrations
use — no per-TLD split yet since that's mainnet covenant territory).
* Check-availability polls the live /api/tlds endpoint before the user
commits sats to a doomed TREG.
* Progress log streams the shared onProgress steps
("checking-availability", "signing", "broadcast: <txid>") so users can
tell whether the transaction actually left the browser.
* Chipnet rate + form default of $5 make full-flow tests possible from
the operator wallet (~1.25M sats each); users can override the USD to
$0.01 for cheap iteration during testing.
UI verified end-to-end (label sanitisation, price recalc, availability
check against real API, buttons gate correctly on wallet state). Full
sign+broadcast requires a funded wallet — operator can verify.
Next: real oracle (CoinGecko / Kraken feed) + tiered pricing by label
length + admin panel for changing the rate config.
2026-09-06 18:18:41 +02:00
}
$("tld-label").addEventListener("input", () => {
// normalise as user types
$("tld-label").value = $("tld-label").value.toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 16);
updateTldButtons();
});
$("tld-usd").addEventListener("input", updateTldPrice);
$("tld-check").addEventListener("click", async () => {
const label = $("tld-label").value.trim();
const msg = $("tld-msg"); msg.textContent = ""; msg.className = "";
try {
const r = await fetch("https://navigate.st/api/tlds");
if (!r.ok) throw new Error("api " + r.status);
const j = await r.json();
const taken = (j.tlds || []).some((t) => (t.tld || t) === label);
msg.className = taken ? "err" : "ok";
msg.textContent = taken ? `❌ .${label} is already registered` : `✅ .${label} is available`;
msg.style.color = taken ? "var(--taken)" : "var(--ok)";
} catch (e) {
msg.textContent = "could not check: " + (e.message || e);
msg.style.color = "var(--warn)";
}
});
$("tld-submit").addEventListener("click", async () => {
if (!wallet) return;
const label = $("tld-label").value.trim();
if (!validateTldLabel(label)) return;
const sats = BigInt(usdToSats($("tld-usd").value.trim() || "0"));
const msg = $("tld-msg"); msg.textContent = ""; msg.className = "";
const log = $("tld-log"); log.style.display = "block"; log.innerHTML = "";
const push = (t) => { const d = document.createElement("div"); d.textContent = "› " + t; log.appendChild(d); log.scrollTop = log.scrollHeight; };
$("tld-submit").disabled = true;
$("tld-submit").textContent = "Signing…";
let el = null;
try {
el = await BNS.connect();
push("connected to chipnet");
2026-09-07 01:39:16 +02:00
const serviceFee = {
address: BNS.REGISTRAR?.serviceFee?.address ?? null,
sats,
};
const res = wallet.source === "wc"
? await BNS.registerTldWithExternalWallet(el, {
session: wallet.session,
tld: label,
records: {},
serviceFee,
tldListUrl: "https://navigate.st/api/tlds",
onProgress: (step) => push(step),
})
: await BNS.registerTldWithBuiltInWallet(el, {
wallet,
tld: label,
records: {},
serviceFee,
tldListUrl: "https://navigate.st/api/tlds",
onProgress: (step) => push(step),
});
sirius.x/portal: register a TLD in-browser (M1.5 — chipnet, USD-priced)
Sign-in view grows a "Register a new TLD" card. User picks a label (validated
against [a-z0-9-]{1,16} and normalised as they type), sees live sats price
computed from a USD field via a static chipnet oracle rate (250,000 sats/USD
≈ $400/BCH), can check availability against navigate.st/api/tlds, then submit
a TREG signed with the built-in wallet — same code path seed-tld-beacon.mjs
uses server-side, but via the browser-exported registerTldWithBuiltInWallet.
* Live price display recalculates on USD-input change; service fee is
paid to REGISTRAR.serviceFee.address (same fee address name registrations
use — no per-TLD split yet since that's mainnet covenant territory).
* Check-availability polls the live /api/tlds endpoint before the user
commits sats to a doomed TREG.
* Progress log streams the shared onProgress steps
("checking-availability", "signing", "broadcast: <txid>") so users can
tell whether the transaction actually left the browser.
* Chipnet rate + form default of $5 make full-flow tests possible from
the operator wallet (~1.25M sats each); users can override the USD to
$0.01 for cheap iteration during testing.
UI verified end-to-end (label sanitisation, price recalc, availability
check against real API, buttons gate correctly on wallet state). Full
sign+broadcast requires a funded wallet — operator can verify.
Next: real oracle (CoinGecko / Kraken feed) + tiered pricing by label
length + admin panel for changing the rate config.
2026-09-06 18:18:41 +02:00
push("broadcast: " + (res.txid || res.txId || "(no txid)"));
msg.style.color = "var(--ok)";
msg.textContent = `✅ .${label} minted. Category ${(res.category || "").slice(0, 16)}…`;
$("tld-submit").textContent = "Registered ✓";
// Trigger a name-list refresh — new TLD cert is an NFT held by this wallet.
setTimeout(() => loadNames(), 2500);
} catch (e) {
msg.style.color = "var(--taken)";
fix(sirius-x): profile-menu URLs, landing search, empty-wallet hint, drop Pantheon
Five UX fixes from a review pass:
1. profile-menu.js: dropdown links (New/Add/WC wallet, Admin) were
absolute /sirius-x/portal.html paths. That's fine on silentmode.st
but under the BCNR route (sirius.x/) the origin is different, so
the gateway forwarded to Sia which returned 'NoSuchKey' XML. Now
derive the base URL from the nav's own .portal anchor href — which
is already set per page with the right relative path — so it works
from the root, from subdirs, and under any BCNR gateway. Admin URL
is derived from the same base.
2. Landing hero got a search input. Submitting it normalises the
label ([a-z0-9-], 63 chars) and redirects to register.html?q=<label>.
register.html now honours ?q= on load: prefills the input, triggers
the parallel multi-TLD lookup, and scrolls into view. Single source
of truth stays in register.html; the landing just hands it a query.
3. Portal TLD-mint error path now special-cases 'wallet is empty' and
shows a friendlier message with the wallet's address and links to
two chipnet faucets, so the fix is one click away instead of a
guess.
4. Removed 'Pantheon' from every page's top nav — it's a section on
the landing that anyone scrolling will discover, and keeping it in
the nav crowded the bar.
5. Cache-buster ?v=20260907rel on the profile-menu.js script include
across all 7 pages so browsers that cached the pre-fix version
pick up the new one on next load.
2026-09-07 20:32:14 +02:00
const raw = String(e.message || e);
// The most common failure by far: wallet has no chipnet coins. Turn the
// opaque error into a nudge toward a faucet.
if (/wallet is empty/i.test(raw)) {
msg.innerHTML = `Failed: wallet is empty. Fund < code style = "font-size:11.5px" > ${esc(wallet.address)}< / code >
with chipnet coins first — free from
< a href = "https://tbch.googol.cash/" target = "_blank" rel = "noopener" > tbch.googol.cash< / a > or
< a href = "https://chipnet.bch.ninja/faucet" target = "_blank" rel = "noopener" > chipnet.bch.ninja/faucet< / a > .`;
} else {
msg.textContent = "Failed: " + raw;
}
push("error: " + raw);
sirius.x/portal: register a TLD in-browser (M1.5 — chipnet, USD-priced)
Sign-in view grows a "Register a new TLD" card. User picks a label (validated
against [a-z0-9-]{1,16} and normalised as they type), sees live sats price
computed from a USD field via a static chipnet oracle rate (250,000 sats/USD
≈ $400/BCH), can check availability against navigate.st/api/tlds, then submit
a TREG signed with the built-in wallet — same code path seed-tld-beacon.mjs
uses server-side, but via the browser-exported registerTldWithBuiltInWallet.
* Live price display recalculates on USD-input change; service fee is
paid to REGISTRAR.serviceFee.address (same fee address name registrations
use — no per-TLD split yet since that's mainnet covenant territory).
* Check-availability polls the live /api/tlds endpoint before the user
commits sats to a doomed TREG.
* Progress log streams the shared onProgress steps
("checking-availability", "signing", "broadcast: <txid>") so users can
tell whether the transaction actually left the browser.
* Chipnet rate + form default of $5 make full-flow tests possible from
the operator wallet (~1.25M sats each); users can override the USD to
$0.01 for cheap iteration during testing.
UI verified end-to-end (label sanitisation, price recalc, availability
check against real API, buttons gate correctly on wallet state). Full
sign+broadcast requires a funded wallet — operator can verify.
Next: real oracle (CoinGecko / Kraken feed) + tiered pricing by label
length + admin panel for changing the rate config.
2026-09-06 18:18:41 +02:00
$("tld-submit").disabled = false;
updateTldPrice(); // reset button label
} finally {
try { el?.close?.(); } catch {}
}
});
// Initial paint on page load so the card shows the price even before sign-in.
updateTldPrice();
2026-08-29 21:57:33 +02:00
< / script >
fix(sirius-x): profile-menu URLs, landing search, empty-wallet hint, drop Pantheon
Five UX fixes from a review pass:
1. profile-menu.js: dropdown links (New/Add/WC wallet, Admin) were
absolute /sirius-x/portal.html paths. That's fine on silentmode.st
but under the BCNR route (sirius.x/) the origin is different, so
the gateway forwarded to Sia which returned 'NoSuchKey' XML. Now
derive the base URL from the nav's own .portal anchor href — which
is already set per page with the right relative path — so it works
from the root, from subdirs, and under any BCNR gateway. Admin URL
is derived from the same base.
2. Landing hero got a search input. Submitting it normalises the
label ([a-z0-9-], 63 chars) and redirects to register.html?q=<label>.
register.html now honours ?q= on load: prefills the input, triggers
the parallel multi-TLD lookup, and scrolls into view. Single source
of truth stays in register.html; the landing just hands it a query.
3. Portal TLD-mint error path now special-cases 'wallet is empty' and
shows a friendlier message with the wallet's address and links to
two chipnet faucets, so the fix is one click away instead of a
guess.
4. Removed 'Pantheon' from every page's top nav — it's a section on
the landing that anyone scrolling will discover, and keeping it in
the nav crowded the bar.
5. Cache-buster ?v=20260907rel on the profile-menu.js script include
across all 7 pages so browsers that cached the pre-fix version
pick up the new one on next load.
2026-09-07 20:32:14 +02:00
< script defer src = "./js/profile-menu.js?v=20260907rel" > < / script >
2026-08-29 21:57:33 +02:00
< / body >
< / html >