aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/names.js
Commit message (Collapse)AuthorAgeFilesLines
...
* Pencil in a boxAdam Soltys2026-08-041-1/+1
| | | | Co-Authored-By: Claude Fable 5 <[email protected]>
* A proper pencilAdam Soltys2026-08-041-1/+1
| | | | Co-Authored-By: Claude Fable 5 <[email protected]>
* A quieter pen inside the address box; the header avatar stops flashingAdam Soltys2026-08-041-5/+5
| | | | | | | | The avatar img was recreated on every render — boot's render bursts made it flash; there is exactly one header avatar, so the node is reused until the profile actually changes. Co-Authored-By: Claude Fable 5 <[email protected]>
* The name is edited where the name is — a pencil by the addressAdam Soltys2026-08-041-7/+12
| | | | Co-Authored-By: Claude Fable 5 <[email protected]>
* Offer the custom-name form right on the Receive paneAdam Soltys2026-08-041-0/+6
| | | | | | | Anyone still on the npub-shaped default sees their address here, not in the collapsed corner of Settings where the claim form lived. Co-Authored-By: Claude Fable 5 <[email protected]>
* Claim with the login identity, so a migrated name can come homeAdam Soltys2026-08-041-1/+5
| | | | | | | | | | The registrar now lets a migrated coinos user's nostr identity (re)take its own name — migration could land the claim in whatever wallet ran it, stranding the name there. The claim form signs with the (re)attached login identity when there is one; the wallet key alone could never prove the takeover. Co-Authored-By: Claude Fable 5 <[email protected]>
* Drop the BOLT 12 explainer blurbAdam Soltys2026-08-041-1/+0
| | | | Co-Authored-By: Claude Fable 5 <[email protected]>
* Receive: the BOLT 12 section takes over the cardAdam Soltys2026-08-031-2/+4
| | | | | | | | | Opening it hides the payment address and its QR — two payment codes on one screen is a good way to have someone scan the wrong one. "Hide" becomes "Back", which is what it now does. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Onboarding: a step for migrating a legacy coinos.io accountAdam Soltys2026-08-031-0/+2
| | | | | | | | | | | | | | | | | | | Between "do you have a nostr account" and claiming a username, new users are asked whether they already have an account on the original coinos. Yes hands off to coinos.io/migrate with their fresh v3 payment address and a return URL — they're already signed in there, so no password or key ever travels. That page sweeps the balance over Lightning and renames the old account, releasing the username. Coming back, coinos.io returns ?migrated=<username>; v3 claims that name on the registrar (retrying for a minute, since the registrar's "is this a legacy user?" guard caches), and their lightning address now resolves to the v3 wallet. The legacy page ships in coinos-ui and is NOT deployed yet. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* BOLT 12 offers with a custom memo on the Spending receive pageAdam Soltys2026-08-031-3/+76
| | | | | | | | | | | | | | | | | | Mining pools (Ocean) and payroll pay to a reusable offer rather than a lightning address, and the memo is how the payer labels it. A disclosure under the payment address mints one: the registrar's new NIP-98'd /offer endpoint asks the ASP's CLN for an `amount: any` offer carrying the memo, keyed to the caller's name (issuer = their address, so two users' identical memos can't collapse onto one CLN offer). Up to ten each, identical memos reuse the existing offer, and GET lists them. Settled offer payments already had a home: the registrar's settle loop now resolves a custom offer id to its owner and hands it to the same forwarder the default offer uses — an instant, free arkoor send into the user's Spending balance. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* First-run onboarding: a five-step wizard and a coach-mark tourAdam Soltys2026-08-021-0/+2
| | | | | | | | | | | | | | | | | | | Fresh devices land in a full-screen flow instead of the unlock screen: welcome → "do you have a nostr account?" (sign in brings wallet, name, and profile along; No mints a wallet on the spot) → claim a username (the background npub-default only surfaces a Keep button; a custom claim — or a restored login's recovered name — advances by itself) → pick a punk or upload a photo (nostr.build), published as the kind-0 name+picture → confetti. "Enter coinos" drops into a three-stop tour: the avatar menu, the Spending/Savings toggle, and the tabs with the swipe tip — each highlighted by a measured gold ring over a dimmed page. One time only (localStorage flag), with an "I already have a wallet" escape to the classic screen. New seams: names.namesClaimForm, messages.publishProfile. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Identity polish: 12-char npub default names, no ellipsis, copyable npubAdam Soltys2026-08-021-2/+2
| | | | | | | | | The registrar's auto-claimed username and every npub-fallback display name use the npub's first 12 characters, shown whole (no truncation dots), and the profile page's npub gets a copy button. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Profiles: view pages, editable own kind 0, zap recipients in historyAdam Soltys2026-08-021-0/+2
| | | | | | | | | | | | | | | | | | | Tapping any avatar or author name (chat rooms, DM threads, the chat home) opens a profile page: avatar, name, nip05, lightning address, about, npub, with Message and Pay actions (Pay runs the npub payment cascade). Your own profile — reachable from your avatar on the chat home — gets an editor for name, about, picture, and lightning address (prefilled with your coinos address); saving merges over the newest published kind 0 so fields we don't understand survive the round trip. Zaps now remember who they went to: the ark feature keys the recipient by what the movement already records (destination address or invoice) and history rows wear a clickable avatar chip that opens the profile. The messages feature exposes showProfile/profileChip seams so any feature can do the same. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Deliver incoming Lightning without depending on an operator floatAdam Soltys2026-08-021-2/+7
| | | | | | | | | | | | | | | | A payment to an address settled on our node and then sat in a retry queue because the float wallet that forwards it was empty — the money was safe but invisible to the recipient. Delivery now has a second route: ask the recipient's wallet for an invoice (CLINK) and pay it over Lightning, which needs no float at all. The float path stays first because it works while they're offline; the queue is now the last resort rather than the only one. Existing addresses never carried the wallet's offer key, so that route was unavailable to them. The wallet now records what it published and re-registers whenever the registrar is missing the current key. Co-Authored-By: Claude Fable 5 <[email protected]>
* Payment addresses accept Lightning from LNURL-only walletsAdam Soltys2026-08-011-0/+3
| | | | | | | | | | | | | | An address only worked for wallets that speak DNS payment instructions or BOLT 12; everything else looks for /.well-known/lnurlp/<name>. The registrar now serves LUD-06/16 (with NIP-57 zap support), preferring the path that touches no funds: if the recipient's wallet published a CLINK offer key, we ask IT for the invoice over nostr and hand the result straight back — the payment never passes through us. Only when nobody answers does our node mint the invoice, and the existing settle forwarder pushes the money on to their address, signing a zap receipt when the payment was a zap. Co-Authored-By: Claude Fable 5 <[email protected]>
* Restore two helpers an earlier edit deleted, and guard the class of bugAdam Soltys2026-08-011-0/+14
| | | | | | | | | | | | | | A bulk replacement removed lookupMine() and the flag along with the block it was rewriting, so names setup threw at runtime — the kind of break every existing test happily passed over because nothing ever constructed a feature and started it. tools/features-smoke-test.js does exactly that: builds every feature against a stubbed wallet with the network cut, runs init/render/stop, and fails on undefined identifiers. It caught the second missing helper immediately. Co-Authored-By: Claude Fable 5 <[email protected]>
* Get an address immediately, without waiting on a signer promptAdam Soltys2026-08-011-25/+28
| | | | | | | | | | | | | | | The passive setup path asked the browser extension to sign the claim, so it sat behind a permission popup — 20s per attempt, retried, hence the minute-long spinner ending in the manual form. The wallet's own key now makes that claim: no signer, no prompt, no wait. Tying the address to the user's real npub happens at login instead, where the signer is already live, and nominates the wallet key to manage the record after. Failures are visible now rather than hidden: the pane shows why setup failed, the watchdog is 12s instead of 60s, internal timeouts are tighter, and the registrar logs every refusal with its reason. Co-Authored-By: Claude Fable 5 <[email protected]>
* The real cause: the CORS preflight rejected our own auth headerAdam Soltys2026-08-011-8/+21
| | | | | | | | | | | | | | | | NIP-98 puts the claim under an Authorization header, but the registrar only allowed content-type in access-control-allow-headers, so browsers blocked every claim before sending it. The failure arrived as a generic network error, which the retry logic treated as transient — hence the endless 'setting up your payment address' spinner. Bun tests never saw it because they don't preflight. Registrar now allows the header. Client-side, nothing may hang: signing, the registrar call and the ark lookup all have timeouts, retries are capped, and a one-minute watchdog always resolves the spinner into either an address or the manual form. Co-Authored-By: Claude Fable 5 <[email protected]>
* Never spin on a claim that can only failAdam Soltys2026-08-011-6/+21
| | | | | | | | | | | | After a reload the extension signer is gone, so claiming the user's real npub name was signed by the wallet key — which the anti-squatting rule rightly refuses, and the retry loop then span forever. An installed extension is now silently re-attached when possible (keeping the address tied to the real identity across reloads), refusals are treated as permanent rather than retried, and anything unresumable falls back to the wallet's own npub so an address always appears. Co-Authored-By: Claude Fable 5 <[email protected]>
* Actually assign the default payment addressAdam Soltys2026-08-011-3/+22
| | | | | | | | | | The auto-claim ran once at feature init — before Ark finishes connecting — saw an unavailable wallet and gave up for good, so users got a claim box instead of their npub address. It now retries while Ark comes up (and after a failed claim), and shows a setting-up state rather than the claim form while it works. Co-Authored-By: Claude Fable 5 <[email protected]>
* One wallet per Nostr identity, NIP-98 auth, npub payment addressesAdam Soltys2026-08-011-43/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | Consistency fix with teeth: logging in with a pasted key derived one wallet while an extension login for the SAME identity found no backup and generated a different one. Now every signer kind runs one flow — look for the published association first (that's where the money is), then derive (key in hand) or generate (signer only) — and a derived seed is published too. That costs nothing, since the derivation is public and anyone holding the key could compute it anyway, and it makes the identity open the same wallet however you log in. Registrar auth is now NIP-98 (HTTP Auth, kind 27235) instead of a homemade envelope: the signature binds the URL, method and body hash, so a captured header can't be replayed elsewhere. NIP-78 already covered the encrypted association; NIP-26 delegation is deprecated, so owner→manager nomination lives in the registrar's own model: an npub-shaped name may only be claimed by that identity, which nominates the wallet key to keep the record updated afterwards (the wallet key is the only one always available — offline, in the worker). Payment addresses therefore default to the user's REAL npub in all three login methods, falling back to the wallet's own identity when no Nostr account is linked. Co-Authored-By: Claude Fable 5 <[email protected]>
* Default usernames from the npub — no onboarding promptAdam Soltys2026-08-011-14/+23
| | | | | | | | | | | | | Every wallet silently claims the first 20 characters of its npub as its payment address the first time it opens: unique, free, and nothing to decide. The pick-a-username gate is gone (the generic onboardingView hook stays as an extension point). A custom name is an optional change tucked into the payment-address card — and swapping to one releases the old name so the registrar and DNS stay tidy. Custom names may become paid later to deter squatting; the default tier keeps working regardless. Co-Authored-By: Claude Fable 5 <[email protected]>
* Username onboarding + the payment address leads ReceiveAdam Soltys2026-08-011-23/+85
| | | | | | | | | | | | | | | New wallets must pick a username before entering the wallet: the onboarding gate renders a claim screen until a name exists. Imported seeds skip it — the registrar's new /pubkey lookup recovers the name owned by the wallet's key, so nothing is retyped. If claiming errors (registrar or ark unreachable) a do-it-later escape appears rather than locking anyone away from funds; the prompt returns next open. The Receive tab now defaults to the payment address — name QR + copy — with the on-chain address and other modes behind it, and the claim form inline for wallets that skipped onboarding. Co-Authored-By: Claude Fable 5 <[email protected]>
* Coinos v3: rebrand from Hal, payment addresses move to @coinos.ioAdam Soltys2026-08-011-8/+8
| | | | | | | | | | | | | | | The wallet is the next version of coinos, deployed at v3.coinos.io (same build as halwallet.app) ahead of an eventual migration of coinos.io itself. App name, manifest, notifications, and the NWC alias all say Coinos; the Hal Finney tribute stays. The registrar is multi-domain (per-domain Cloudflare zones; existing halwallet.app names keep working) and new claims default to @coinos.io. Names belonging to existing coinos users are reserved for them — the registrar checks the live coinos API before granting a claim — until the migration gives those users a way to claim their own. Co-Authored-By: Claude Fable 5 <[email protected]>
* Zappable offer codes and per-name Lightning offersAdam Soltys2026-08-011-1/+9
| | | | | | | | | | | | | | | | | | | | | | | | | CLINK offers (noffer): every wallet gets a static offer keypair (synced across devices, first-minted wins) answering kind-21001 invoice requests — from open tabs and from the service worker while closed, which mints against the mirrored state (the record now carries chain-4 and chain-5 key windows) and raises an open-to-receive notification. Zap requests ride along and their kind-9735 receipts publish once the payment is claimed. The code is shown in the payment-address card for pasting into a Nostr profile; the notifier watches and relays kind 21001 alongside NWC. Payment names also gain a Lightning offer: the registrar creates a BOLT 12 offer per name on the node and appends lno= to the DNS record; a settle-forwarder pushes each received payment on to the name's ark destination from a small float wallet (custody window: seconds between Lightning settle and the ark send). Name resolution now runs full client-side DNSSEC validation (src/dnssec.js): binary DoH, root-anchor chain walk, RSA + ECDSA via WebCrypto — the resolver is untrusted transport, verified against live signed zones including the canonical BIP-353 test name. Co-Authored-By: Claude Fable 5 <[email protected]>
* Payment names: ₿[email protected] via BIP-353 DNS payment instructionsAdam Soltys2026-08-011-0/+179
Receiving: a Settings card claims a username, signed with the wallet's nostr key; the new names registrar (names/server.js, deployed at names.halwallet.app) enforces first-come ownership by that key and mirrors the claim into a DNSSEC-signed TXT record at <name>.user._bitcoin-payment.halwallet.app whose BIP-21 URI carries the wallet's reusable ark address. The record re-registers itself if the ark address ever changes, and a collapsible hint shows the single CNAME a user adds to serve the same name from their own domain (BIP-353 supports delegation when both zones are DNSSEC-signed). Sending: a pasted name@domain resolves over DNS first — two independent DoH resolvers must agree and both report the DNSSEC AD flag (full client-side chain validation is the stated follow-up) — an ark= instruction pays natively, an on-chain path fills the send form, and a name with no DNS record falls back to the Lightning-address zap flow. Co-Authored-By: Claude Fable 5 <[email protected]>