aboutsummaryrefslogtreecommitdiffstats
path: root/names
Commit message (Collapse)AuthorAgeFilesLines
* Translation: into the phone's language, and DeepL with your own key. ↵Adam Soltys5 days2-3/+46
| | | | | | | isolabellart saw the Translate button but nothing became Italian: the target was the app's language, coinos has no Italian UI (so it ran in English), and the language guess didn't know Italian. Posts now translate into the reader's choice (Settings → Nostr → Translation, any of 31 languages), else the phone's language when the app has no UI for it, else the app's; the guess knows Italian, Dutch and Polish. And, as Jumble offers: a DeepL API key of your own, kept on the device and sent per request as x-deepl-key — the registrar passes it to DeepL (api-free for ":fx" keys; DeepL refuses browsers) and never stores or logs it; a refused key or used-up quota says so once. names: translateDeepl (prose only, links/tags kept, detected source back, 401/402/422 statuses), CORS allows the header. Deployed to cs names. tools/translate-italian-test.js, tools/deepl-translate.test.js. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
* Names: letters and numbers only, 2–24 — coinos v2's rule. The registrar ↵Adam Soltys5 days1-2/+11
| | | | | | | took a-z, 0-9 and . _ - (1–30), so bitcoin-education and a dozen others got through. A NEW claim must now match /^[a-z0-9]{2,24}$/ (v2's /^[\p{L}\p{N}]{2,24}$/u, held to ASCII since a name is a DNS label); a name already held (19 with . _ -, plus "f" and "g") is grandfathered — its owner can still update it — as are v2 migrations carrying their own name and npub-shaped defaults. /name/<n> answers invalid: true for a free name that breaks the rule; the claim form says "Letters and numbers only" as it's typed, and the suggested name from a nostr profile is stripped to letters and digits. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
* Translation: a hashtag in a script the reader can't read gets its ↵Adam Soltys5 days1-5/+5
| | | | | | | translation in brackets after it — "#総合部絵チャ (…)" — the tag itself kept as the link it is. A post that is only such hashtags now counts as foreign (it was judged by its prose alone, of which it has none, so nothing ever offered to translate it), and ⋯ → Translate on a post with no words says so instead of "already in your language". The registrar's language detection reads the glossed tags too; lang-guess's scriptOf takes a minimum (a two-character tag has a script too). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
* Translation: posts in another language are shown in yours — "Translated ↵Adam Soltys5 days3-0/+125
| | | | | | | from Spanish · Show original" under the words, automatic by default for posts the language guess calls foreign (Settings → Nostr → Translation switches it off and leaves a Translate link instead), and ⋯ → Translate for any post. The browser's on-device Translator does it when the language pair is already installed (desktop Chrome); otherwise the registrar's new POST /translate (names/translate.js): a cached, 4-at-a-time front for a LibreTranslate container on cs (names/compose-libretranslate.yml, v1.9.6, 32 languages; none for sw/mr/ta/te, so those readers get no offer). Links, nostr: mentions, :emoji:, #tags and long codes are never sent to the model — only the prose between them, batched in one call (src/translate-split.js, shared). Translations are remembered (coinos-translations, 300). tools/translate-test.js Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
* POS terminals ring up in the owner's currency: the app sends its currency ↵Adam Soltys6 days1-1/+6
| | | | | | when minting a terminal token (it sent none, so every terminal priced sales in USD and a $0.03 sale paid out as $0.04 CAD), and a new token retunes the terminals already paired to that name Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Registrar: rateExempt IPs in names-config.json skip the per-minute limits ↵Adam Soltys6 days1-0/+4
| | | | | | (the operator's own IP while testing sign-ups) Co-Authored-By: Claude Opus 5.5 <[email protected]>
* names: a welcome DM counts as sent only when a relay acknowledges it — ↵Adam Soltys7 days1-2/+24
| | | | | | dead sockets are dropped and it retries on fresh ones (four welcomes on 2026-10-07 vanished after the uplink dropped while the log said sent) Co-Authored-By: Claude Opus 5.5 <[email protected]>
* names: /name says whether the holder is where a migration grant sent the nameAdam Soltys10 days1-1/+9
| | | | | | | | | | coinos.io's v3 bridge forwards a migrated legacy account's incoming payments to the v3 wallet only on proof: the holder is the legacy account's own key, or the wallet its session named via /migrate-grant (granted: true). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_011bvzKaZosXGHkigcGcSzAR
* Link previews: the common named entities decode too (an &ndash; showed raw ↵Adam Soltys2026-09-271-3/+5
| | | | | | | in a card). Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Links in posts show as the cards their pages describe.Adam Soltys2026-09-272-0/+154
| | | | | | | | | | | | A plain link becomes an Open Graph card: picture, title, a line, the site. The registrar fetches the page on the reader's behalf (names/preview.js, GET /preview?url=): only public hosts, at most half a megabyte of HTML, cached a day. The client warms the card with the rest of the post so the row arrives whole, keeps a few hundred cards across sessions, and leaves a page with nothing to say as a bare link. Pictures and YouTube keep their boxes. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Registrar: an invoice the wallet hands back must have a minute left; ask ↵Adam Soltys2026-09-221-6/+24
| | | | | | | once more before minting our own. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* Accounts from the header, snapshot-first Spending restore, name ownership ↵Adam Soltys2026-09-182-4/+12
| | | | | | | | | | | | | | | | grants. Header buttons always leave the current feature screen; an account with no remembered nostr identity opens Accounts instead of nothing. Logout confirms in place. A scan finishing after logout or an account switch no longer drops the new session into offline mode (stateGeneration guards in sync + ark). Spending restores from the snapshot first. A migration grant names the identity that owns an address; its manager may register it without becoming that identity (names/ownership.js). Browser tests for account access, profile retry, spending restore, thread reply focus, custom-emoji reactions and registry ownership. Co-Authored-By: Claude Fable 5.1 <[email protected]>
* A gift made for one head can be put straight on it.Adam Soltys2026-09-141-2/+4
| | | | | Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
* A knight's helm, for one small knight.Adam Soltys2026-09-141-1/+2
| | | | | | | | | | A gifted hat that covers the whole face — its own square drawing over the avatar rather than perched on it: steel great helm, cross slit, breathing holes, a red plume. Never sold; the registrar's gift endpoint knows it beside the beta hard hat. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
* names: a migration grant unlocks a reserved legacy name.Adam Soltys2026-09-101-7/+10
| | | | | | | | | | | | | Migrating the coinos.io house account `coinos` swept its balance fine, then every claim bounced with "name is reserved": the reserved-word check ran before the migration grant was consulted. A reserved word that is also a real coinos.io account can only reach the registrar through a migration, whose grant is the old account's authenticated say-so — so the grant now clears the reserved check too. Reserved names without a grant stay reserved. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
* Payment push notifications are scoped to their network, so a mainnet payment ↵Adam Soltys2026-09-051-1/+3
| | | | | | | stops opening the staging PWA. The same seed derives the same nostr pubkey on mainnet and staging, so both PWAs registered push under one pubkey and the notifier — matching only by pubkey — fanned every mainnet payment out to the staging subscription too; tapping it opened staging.coinos.io. Now the client stamps its network on the push registration (pushWatch net: getNetwork()), the registrar declares its own network on the /notify call (CFG.forwarder.network), and nwcpush delivers a payment only to registrations whose net matches — with a rollout-safe fallback: a device that hasn't re-registered yet (net=null) still gets the push, and a caller that omits net still reaches everyone, so nobody goes dark mid-deploy. Deployed names + nwcpush on cs Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
* Point of sale: a coinos-pos terminal works against a nameAdam Soltys2026-09-051-2/+209
| | | | | | | | | | | | | | | | | | Registrar: the owner mints a bearer POS token from Settings (NIP-98 POST /pos/token, DELETE revokes; /admin/pos/token for operators). With it the terminal gets /pos/me, rings up sales at /pos/invoice (fiat via coinos.io rates, or sats), reads /pos/payments, and holds a websocket at /pos/ws that gets a payment message when the sale settles. Sales are always minted on our node so the settle loop sees them and the ordinary forward path delivers the sats to the name's ark address. The name's lnurlp pins the newest unpaid sale under five minutes old — coinos.io's /p/<name> rule — so an NFC tap or a scan pays exactly that invoice. Wallet: a "Point of sale" section on the names card creates, copies and revokes tokens. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y
* Lightning receives to a [email protected] address now wear the ⚡ instead of ↵Adam Soltys2026-09-041-4/+39
| | | | | | | the Ark mark: a faucet paying the LN address settles on the registrar's CLN and arrives as an anonymous arkoor from the float (the mailbox protocol carries no memo), so the wallet genuinely couldn't tell the rail. The registrar now records a receipt {sat, hash, ts} per LN settlement it forwards via the float (7-day ring per name) and serves them at GET /lnreceipts (NIP-98, owner/manager only — it's a feed of incoming amounts); the wallet fetches them through the names feature (which holds the signer) and fuzzy-matches receive movements by exact amount + delivery within ±3 min, stamping viaLn + the payment hash so a receipt can never claim a second row. History row and detail view show ⚡ for viaLn receives; the tag rides the sync snapshot to other devices via merge enrichment. viaClink deliveries need none of this — the wallet's own LN-receive flow already tags itself. Best-effort by design: an amount+time collision only mislabels an icon Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
* The registrar grows a webhook API — the coinos.io-style merchant notify, ↵Adam Soltys2026-09-031-0/+166
| | | | | | | self-custodial edition: a name's owner registers an https URL (NIP-98, owner or manager key) and every Lightning settlement for that name POSTs {type, address, amount, hash, preimage, memo, secret} there, firing on settlement independent of the ark delivery. URLs are vetted hard (https only, no credentials, every resolved address must be public unicast — RFC1918/CGNAT/loopback/link-local refused, re-checked before every delivery), retries back off 30s/5m/30m from a persisted queue, and GET /webhook shows the config plus the last delivery's outcome. Proven live: a throwaway name, a 21-sat Lightning payment, one webhook delivered Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The tester with 233 sats gets to spend them: invoice coverage judges the SUM ↵Adam Soltys2026-09-021-0/+33
| | | | | | | of spendable coins (the single-coin gate silently declined anything over the largest coin, though multi-input pays gather 24), an uncoverable invoice now owns its paste — board the shortfall from Savings, or say what's short — instead of dropping the bolt11 into the address field like a dead click, and chain calls gain a last-resort relay through the registrar (/esplora passthrough, tip cached) for the network that blackholes every public esplora Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* A hard hat for the crew that builds this with us: an operator-giftable ↵Adam Soltys2026-08-311-3/+28
| | | | | | | construction hat joins the catalog (never listed for sale — like the crown it appears only in a rack that holds it), the registrar grows POST /hats/grant behind the admin token (hex or npub, crown excluded), and a gifted hat settles into the rack instead of knocking a paid hat off a bare-headed recipient wears it at once Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Google accounts can speak: the DM seal signs with the present for remote ↵Adam Soltys2026-08-301-4/+10
| | | | | | | signers (the pomegranate FROST operators refuse backdated events, and NIP-59's tweak on the seal protects nothing — only the recipient ever sees that layer; the public-facing wrap keeps its tweak under our own ephemeral key), and the registrar welcomes each PERSON once instead of once per key — the Google flow's two claims (wallet key, then real npub with the wallet as manager) were earning the same inbox two identical greetings Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The registrar learns who a migrated name belongs to: coinos.io's migrate ↵Adam Soltys2026-08-301-1/+38
| | | | | | | action — running with the old account's authenticated session, which IS the ownership proof — posts a migrate-grant (Bearer migrateToken) naming the v3 destination, and the claim guard honors that grant where the identity-only check (old account's npub must sign the claim) could never pass for a v3 wallet key; without it every migrated claim 409'd forever and the wizard spun on 'Claiming…' Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Staging gets the mainnet fee model end to end: /lnquote?network=mutinynet ↵Adam Soltys2026-08-291-12/+16
| | | | | | | quotes from the staging ASP's own CLN (helpers take their backend), the client asks it by default on mutinynet, and the quote URL concat survives a query string Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* The wallet learns to read BOLT 12 for itself: offers and invoices decode ↵Adam Soltys2026-08-291-8/+49
| | | | | | | client-side, and every invoice the ASP fetches over onion messages is verified here — payment hash read from the raw TLVs, offer terms mirrored byte-for-byte, the issuer's schnorr signature checked against LDK's exact merkle construction (proven against a live CLN-signed fixture) — so no server can hand back an invoice whose preimage it already holds. Paste an lno1 or resolve a name whose record carries one and the existing HTLC pay flow carries it (captaind's Invoice enum takes lni strings natively); a name's owner may now publish their OWN node's offer in their DNS record, retiring the registrar's stand-in — senders fetch invoices straight from their node and no coinos service ever touches the money. The /lnquote fallback prices blinded paths by entry node + advertised payinfo Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* An address can point home: a name's owner may register their own CLINK offer ↵Adam Soltys2026-08-291-25/+79
| | | | | | | code and the registrar asks THEIR node for invoices — delivered there first, float as fallback, and no invoice is relayed or paid unless it demands exactly the sats owed on the right network. hal learns to pay pasted noffer1 codes through the zap flow (fixed, variable and payer-chosen pricing, amount verified before the HTLC locks). The depth advisory slims to one line — an uncooperative exit's price and a Manage link — and the new coins screen shows each vtxo's amount, expiry and arkoor depth beside what renewal costs and buys Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* A name the registrar no longer grants is a costume: the wallet verifies its ↵Adam Soltys2026-08-281-1/+1
| | | | | | | cached name against the record's owner and manager keys each refresh, shedding stale ones (an evicted squat once lingered in the squatter's UI) — the /name endpoint now names the manager too Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* A name's proof is its key, not a flag: takenByCoinosUser stops trusting ↵Adam Soltys2026-08-281-5/+8
| | | | | | | `migrated` (which let poppy get squatted) — an existing coinos.io name yields only to a claim signed by that account's own nostr key; the squatted record, its DNS entry and its offer are evicted Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The chosen name outranks the placeholder everywhere: a claim can no longer ↵Adam Soltys2026-08-271-1/+7
| | | | | | | release a custom name to make room for an npub default (the race that deleted passkeyguy), sign-in asks the registrar about the login identity before reaching for a placeholder, and the registrar answers /pubkey with the name the user picked rather than whichever record is younger Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* Dead coins stop travelling: an expired vtxo leaves the balance and the coin ↵Adam Soltys2026-08-241-0/+26
| | | | | | | picker (sub-dust IOUs excepted), a shortfall names the dead weight it can't spend, and the names float renews any coin a day ahead of the reaper — a 100k forward left home on an expired coin and the recipient rightly refused it at the door Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The float sips instead of gulping: top-ups arrive in pool-sized chunks that ↵Adam Soltys2026-08-181-2/+5
| | | | | | | accumulate to the target, sparing the ask that dies whole on a thin vtxo pool Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
* The float keeps itself fed: below low water it loops sats off the CLN ↵Adam Soltys2026-08-181-4/+106
| | | | | | | through a neighbourly circular route all by itself, the sync heartbeat drives whatever's mid-flight every minute, and an operator can board on-chain reserves in through two admin calls Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
* The party hat leaves the party: gone from catalog and price list alike — ↵Adam Soltys2026-08-181-1/+1
| | | | | | | heads that bought one on staging simply go bare Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* A wallet keeps one name per domain, not one name total: staging and mainnet ↵Adam Soltys2026-08-181-1/+4
| | | | | | | claims stop clobbering each other, the registrar answers who-am-I per domain, and a custom name claimed on one device replaces the npub placeholder on every other Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Staging LNURL declines what it cannot deliver: only the recipient wallet ↵Adam Soltys2026-08-171-0/+5
| | | | | | | mints for @staging names — our mainnet node will not take real sats it can only strand Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Staging gets a hat economy of its own: mutinynet mints on its own CLN into ↵Adam Soltys2026-08-171-25/+39
| | | | | | | its own registry, play sats never buy mainnet flex — plus the toque earns its Canadian name, the wizard takes the throne at 2.1M, the crown leaves the menu, and every hat sits a little higher and straighter Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Hats: put your money where your head is — supporter hats perch above the ↵Adam Soltys2026-08-161-0/+136
| | | | | | | avatar everywhere it appears, from 21-sat beanie to 2.1M-sat top hat; the crown stays on the founder Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Every name learns to vouch for its keeper: the registrar answers nostr.json, ↵Adam Soltys2026-08-151-0/+11
| | | | | | | so [email protected] is a NIP-05 too Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* Welcome DMs stop echoing: sent-copies thread under their recipient whichever ↵Adam Soltys2026-08-151-3/+4
| | | | | | | identity authored them, the registrar keeps no sender copy at all, and the old self-thread residue sweeps itself Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A claim with an ark address that doesn't decode is refused at the door — a ↵Adam Soltys2026-08-151-0/+9
| | | | | | | corrupt one recorded is a payment black hole Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A failed forward retry says why — the goyslop 190k spent a day failing in ↵Adam Soltys2026-08-151-1/+2
| | | | | | | a bare catch Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* An invoice's name mapping lives as long as the invoice can settle, and a ↵Adam Soltys2026-08-151-2/+13
| | | | | | | nameless settle leaves a trace — one paid 1000 sats vanished into a silent continue behind a 1-hour sweep Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* Sub-sat routes round back up: a zero quote just fails its first attempt and ↵Adam Soltys2026-08-141-5/+7
| | | | | | | pays 1 sat on retry anyway — true free needs the ASP to bring the msats Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A route that costs less than a sat quotes as free — the ASP eats the ↵Adam Soltys2026-08-141-2/+8
| | | | | | | msats, which mostly land back on our own node Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* The network fee gets asked, not assumed: /lnquote prices a lightning payment ↵Adam Soltys2026-08-131-0/+77
| | | | | | | through askrene before anything locks — zero to ourselves and direct peers Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* The float reads its mail: sync at startup and before each retry round, so a ↵Adam Soltys2026-08-091-0/+6
| | | | | | | top-up is seen without a restart Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01DbA53PJA8fgSvMcEzfuw22
* A stuck forward now holds its tongue: retries back off to an hour, and an ↵Adam Soltys2026-08-091-2/+11
| | | | | | | offer knock reads as money arriving, not leaving Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01DbA53PJA8fgSvMcEzfuw22
* Registrar: a migrated legacy name is claimableAdam Soltys2026-08-031-1/+5
| | | | | | | | | takenByCoinosUser now reads the account it finds: a live one still blocks the name, but one flagged migrated has handed receiving over, so v3 may claim it. 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-0/+41
| | | | | | | | | | | | | | | | | | 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
* Push notifications for payments and messages; offline Spending noticeAdam Soltys2026-08-021-0/+7
| | | | | | | | | | | | | | | | | | | | | | | The nwcpush notifier grows a second registration kind alongside NWC: a notify watch of what it can see without keys — kind-1059 wraps p-tagged at the user (DMs, direct invites), zap receipts (9735/9737), and wraps authored by the user's community channel keys (chat). It pushes a typed nudge, throttled per device (chat bursts collapse); the service worker shows a generic notification unless a window is visible, and tapping opens the app. The names registrar reports settled lightning-address receives server-to-server (token-gated /notify), so the common payment path notifies even with no nostr event in sight. The app registers silently whenever permission is already granted and keeps the watch current as communities change; a dismissible card on the chat home offers to enable it otherwise. Ark zap receipts (9737) join the relay whitelist so the payment watch can see them. Also: the offline Spending receive pane now says you're offline and offers a one-tap switch to Savings instead of spinning forever. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi