aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
Commit message (Collapse)AuthorAgeFilesLines
...
* A hat swapped on one device reaches the others in minutes, not by ↵Adam Soltys2026-08-301-4/+16
| | | | | | | dinnertime: the worn-hat cache revalidates after two minutes instead of six hours (still painted from cache instantly — the refresh rides behind), and learning a hat came OFF now repaints too, where the old check only redrew for fresh hats Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Hat fitting, final millimetres: everything settles three pixels lower and ↵Adam Soltys2026-08-301-10/+10
| | | | | | | one further left Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Hat fitting, round two: the six whose art carries less bottom padding come ↵Adam Soltys2026-08-301-7/+9
| | | | | | | down ten points (crown and wizard stay perched), and the whole rack rides five percent left of center — dead-center read as drifting off the head Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Hats return to perching: the banner overlap now moves the row's direct child ↵Adam Soltys2026-08-301-8/+8
| | | | | | | (pulling the avatar up inside its hat-wrap left the crown planted on the face), and the whole catalog rises 20 points — hats covered a quarter of every avatar and now kiss the top few pixels Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* A migrated coinos.io account keeps its face and its cover: the claim fetches ↵Adam Soltys2026-08-301-1/+55
| | | | | | | the legacy avatar and banner and fills the kind 0's empty slots (fill, never overwrite — an existing nostr identity keeps its own look), the wizard's punk picker steps aside for a profile that already has a picture, and v3 finally wears cover photos — nostr's standard kind-0 banner renders full-bleed across the top of every profile card with the avatar overlapping it, settable by URL or upload in the profile editor Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The username claim field forgets its draft when a wallet opens: a name typed ↵Adam Soltys2026-08-301-1/+7
| | | | | | | before logout used to greet whichever account opened next on the device (the field lives in global UI state and nothing ever reset it) Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The header dot stops arriving fashionably late on a brand-new account: the ↵Adam Soltys2026-08-301-4/+9
| | | | | | | first-frame optimism keyed on 'no rooms yet', but init() creates the coinos room before the first paint, so the guard never fired and the dot waited for real messages to decrypt — it now keys on no messages having landed, which is what it meant all along Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The migration round trip stops eating its own homework: the ?migrated= ↵Adam Soltys2026-08-302-7/+13
| | | | | | | return is stashed synchronously at boot and claimed whenever the wallet actually opens (the old 1.5s one-shot silently dropped it), the wizard's 'I'm done, continue' state survives the trip to coinos.io as a persisted step, the legacy page shows the claim in progress instead of re-asking, and a finished claim advances the wizard by itself. Fresh-seed polish riding along: the spending-setup ask stops waiting out registrar round trips that only exist for restored wallets, and the header punk paints synchronously instead of after an async identity fetch Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* A board that never funded stops masquerading as work in progress: the tx ↵Adam Soltys2026-08-301-0/+23
| | | | | | | build failing now marks the action failed on the spot, and connect sweeps any unfunded board stub older than an hour — a lingering 'created' stub silently blocked auto-renewal on that wallet for good (cooney had one from the Max shortfall, another wallet a 50k one) Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The boarded screen tells the truth about the wait: 'Ready to spend after N ↵Adam Soltys2026-08-301-2/+9
| | | | | | | confirmations' comes from the ASP's requiredBoardConfirmations instead of a hardcoded 1 that contradicted the 0/3 counter under the balance Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The Max sweep's stand-in taproot program takes the x-only 32 bytes — the ↵Adam Soltys2026-08-301-1/+2
| | | | | | | compressed point's parity byte made an invalid witness program and Max fell to zero Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Max on the board form stops promising sats the funding transaction can't ↵Adam Soltys2026-08-301-3/+10
| | | | | | | carry: the sweep draft now prices against a taproot output (the board funding address's real shape) instead of the wallet's 12-vbytes-smaller P2WPKH change — tapping Max then Move earned 'insufficient funds for amount + fee' by exactly that margin Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Pasting your own coinos name (or ark address) opens the boarding panel at ↵Adam Soltys2026-08-302-15/+42
| | | | | | | paste time, not at review: the names resolver asks the ark feature before filling the send form, a raw address paste runs the same check, and the review path still carries a typed amount into the panel — one boardOwnAddress helper serves all three doors Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The cooney ghost spend gets laid to rest on every device: the ark-state ↵Adam Soltys2026-08-301-1/+19
| | | | | | | merge now lets a movement's late-learned fields through — inputIds, unlockHash, and a fee that upgrades a recorded zero — where the by-id union used to keep each device's first copy forever, so the rescue's post-hoc enrichment never propagated and other devices painted the renewal's 16 consumed inputs as a fresh red 'Spent on another device −29,014' Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* A lone coin reads as one: the coins page intro gets a singular form instead ↵Adam Soltys2026-08-301-1/+3
| | | | | | | of '1 coins totalling' Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Two dust coins stop dying unrenewed at the door: the automatic renewal's ↵Adam Soltys2026-08-301-15/+40
| | | | | | | coin subset must clear the server's 330-sat output floor by itself, so it now pulls in the smallest healthy coins when the expiring ones alone can't mint an output (128+5 sats retried a doomed round silently every 30 minutes). The coins page also breathes: .coin rows with hairlines and the big accent checkboxes, the amount full-size with its renewal price on the right, the meta line down to 'expires in 26d · depth 6 · exit fee 3,688', and a coin past its height says 'expired' instead of 'expires 0h' Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The coins table stops wrapping into confetti on a phone: each coin is now a ↵Adam Soltys2026-08-301-12/+15
| | | | | | | two-line row — the amount, then 'expires 26d · depth 6 · exit fee 1,844 · renew 117' riding inline — so there is no header row and no five-column horizontal budget to blow; the column-header strings retire Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The DM drain wakes the signer itself: boot's single resume attempt losing to ↵Adam Soltys2026-08-301-3/+10
| | | | | | | cold-start churn left the phone holding every wrap with nothing ever asking the bunker again — now a drain that finds its decryptor set incomplete calls resume (single-flight, rate-limited) before deciding anything, and the bunker resume deadline stretches to 15s Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* A signer dying mid-drain stops burning retry budget: the pass breaks off and ↵Adam Soltys2026-08-301-0/+4
| | | | | | | leaves the untried wraps pending for the next full-strength attempt, instead of counting them as failures against a decryptor set that was no longer there Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The Amethyst signer stops dying every time a stranger's wrap fails to ↵Adam Soltys2026-08-302-46/+100
| | | | | | | decrypt: only connection-shaped failures (with a real per-op deadline now — a backgrounded signer app used to just hang the call) drop the live bunker, the reconnect surfaces offer only the door the account actually came through (a recorded 'via', so an Amethyst-linked npub no longer stares at Google and passkey buttons), the settings card quietly reattaches from the stored session instead of waiting for a tap, and the DM retry drain eases to three full-strength passes per wrap Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* DMs stop losing the race with the signer, and your own address stops paying ↵Adam Soltys2026-08-303-10/+121
| | | | | | | yourself: undecrypted wraps are kept and retried when a signer comes live (the backfill used to be consumed and dropped whenever the login signer hadn't resumed yet — each device kept a different random subset of history), the inbox also reads the relays our kind-10050 actually advertises, and pasting your own ark address or coinos name into Send now opens the board panel from Savings instead of a silent Spending→Spending self-send; a foreign ark address while Savings is selected says to switch instead of quietly spending the other balance Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The renewal forecast joins the new style: one terse line — 'Coins renew in ↵Adam Soltys2026-08-291-5/+10
| | | | | | | ~29 days for 150 sats. Manage' — that yields entirely when the depth advisory is on screen, and the day(s) shrug is gone Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* The coins table tightens up: an Exit fee column prices pulling each coin ↵Adam Soltys2026-08-291-4/+22
| | | | | | | on-chain by itself, expiry reads as a countdown (14d, 13h) instead of a date, and depth is just the number Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* The exit-cost line stops arriving late: the last computed answer is ↵Adam Soltys2026-08-291-9/+21
| | | | | | | remembered per wallet and painted on the very first render, then the live figure replaces it in place — no more layout lurch while ark connects Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* Read is read everywhere: the messages home gains a Mark-all-read link (every ↵Adam Soltys2026-08-291-1/+53
| | | | | | | DM and channel watermark jumps to its newest foreign message), and read state now rides its own sync domain — watermarks only ever grow, so a per-key max merges cleanly across devices and a thread read on the phone stops glowing on the desk Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* Renewal by the coin: each row on the coins screen gets a checkbox (all ↵Adam Soltys2026-08-291-7/+31
| | | | | | | ticked by default, so one tap still renews everything), the header ticks or clears the lot, and the button quotes the selection's exact fee — renew the expensive stragglers now, let the nearly-free ones ripen Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* The coins screen answers the question it was built for: each vtxo shows what ↵Adam Soltys2026-08-291-5/+36
| | | | | | | renewing it TODAY costs beside its expiry and depth, the renewal card lays out the server's whole bracket schedule (read live from ArkInfo, never hardcoded) — dearer the more lifetime a coin still carries, free in the final stretch where the wallet renews on its own — and says plainly that renewing sooner only buys the cheaper exit sooner Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* The composer learns the second dimension: a textarea that grows with the ↵Adam Soltys2026-08-291-4/+22
| | | | | | | text (capped at five lines), Enter still sends, and a newline is one Shift+Enter or Ctrl+J away — bubbles already knew how to show them Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* A half-typed message waits where you left it: drafts live per conversation ↵Adam Soltys2026-08-291-12/+34
| | | | | | | (each DM and each channel its own), survive navigation and reloads through feature state on a typing debounce, and clear only when the message actually sends Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* A round's output can no longer strand: every refresh asks the server to drop ↵Adam Soltys2026-08-292-11/+74
| | | | | | | its unlock hash in the mailbox, and any device that finds such a breadcrumb with no matching action adopts the claim itself (input ids now read from the status response — the rescue needs no operator). History learns to tell the whole truth and nothing more: coins the server saw spent elsewhere get a folded row (skipping coins a known renewal consumed), renewals fold across devices on their unlock hash and appear only when they cost something, and a rescue records the fee the round actually took. The account page keeps its header icons when reached from an open wallet; the messages page folds the control/guestbook replay once per burst instead of painting every intermediate state — no more blinking messages from superseded ban lists or member counts crawling to their total, which now paints from last session's settled figure Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* A door where people will look for it: 'Deliver to your own node' gets its ↵Adam Soltys2026-08-291-4/+11
| | | | | | | own entry in the address's more-options menu and a section in the Settings names card — it no longer hides as an appendix behind the CLINK zap code, which returns to being just that 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-293-44/+126
| | | | | | | 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-293-17/+177
| | | | | | | 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
* The mailbox checkpoint was a timestamp all along: receives are dated by when ↵Adam Soltys2026-08-291-2/+31
| | | | | | | the server actually delivered them (verified to the millisecond), so an import shows hours-old payments as hours old — no celebration for news that isn't; a wallet whose Savings holds nothing opens onto the Spending that holds everything; and same-payment duplicates fold at display time on every device, however the state arrived Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* One payment, one line: the settle path is idempotent (the mailbox push and ↵Adam Soltys2026-08-281-1/+13
| | | | | | | the status poll raced past each other's step checks — a toque got two history entries), movements carry their payment hash, and the sync merge folds same-preimage lightning records into the earliest telling Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The profile editor learns to take a photo, not just a URL: an Upload button ↵Adam Soltys2026-08-281-0/+18
| | | | | | | feeds the same signed nostr.build path the onboarding picker uses and fills the picture field with the result Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* A name the registrar no longer grants is a costume: the wallet verifies its ↵Adam Soltys2026-08-281-0/+15
| | | | | | | 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
* Max learns the ark rail: an ark address gets its own Max button filling the ↵Adam Soltys2026-08-281-0/+8
| | | | | | | whole spendable Spending balance — free sends mean the maximum really is the balance Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* Renewals earn a line in the ledger: "Renewed ↻" rows in history showing ↵Adam Soltys2026-08-281-7/+24
| | | | | | | what the round cost (or "free"), with the in-and-out detail behind them — and the toast is simply "Renewal requested" Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The advisory names both prices: "renew for 2 sats to bring that down to ↵Adam Soltys2026-08-281-1/+6
| | | | | | | about 1,060" — and stays silent when renewing wouldn't actually help; the toast learns to speak in one plain breath Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The exit-cost advisory moves to where eyes already are: a quiet line under ↵Adam Soltys2026-08-281-7/+8
| | | | | | | the Spending balance — current trustless-exit price, the renewal that shrinks it, one inline Renew now — instead of a settings card nobody would know to dig for Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The tradeoff gets a quiet advanced card, not a quiz: when coins run four or ↵Adam Soltys2026-08-281-1/+28
| | | | | | | more hops deep, Settings grows an "exit cost" card naming today's trustless-exit price and offering a one-tap renewal that flattens the history — invisible to everyone whose coins are shallow Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* An exit dearer than its cargo is not an option: when the trustless road ↵Adam Soltys2026-08-281-0/+8
| | | | | | | would cost more than it moves, the fallback says so plainly and points at Lightning — the road with no mining fees — instead of offering an 8,486-sat ticket for 928 sats of passenger Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* No exit leaves without fare money: starting one now requires Savings to ↵Adam Soltys2026-08-281-1/+8
| | | | | | | cover the estimated hop fees (named in the refusal), and a mid-flight stall says exactly how many sats the next step needs and that it resumes on its own Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The explorer link stops blinking with the retry loop — it shows only for ↵Adam Soltys2026-08-281-10/+14
| | | | | | | transactions genuinely broadcast — and the ETA drops its tilde: "about 25 hours" says approximate once, in words Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The send flow chooses the road itself: cooperative always goes first, and ↵Adam Soltys2026-08-281-12/+39
| | | | | | | only when the server actually refuses does the trustless fallback appear — stating up front that the whole balance exits to Savings, how long it takes, and the mining-fee reserve Savings will pay, with the button disabled until Savings can cover it Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The send page sends and history remembers: an in-flight exit is a pending ↵Adam Soltys2026-08-281-13/+79
| | | | | | | history record with its own detail card (ETA, explorer link, cancel while it's real) — pasting an address with everything mid-exit now stays on the send form with a plain no-spendable-balance error and a link to that record, and the exit page drops its double balance Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The exit page stops arguing with itself: the header names how much is ↵Adam Soltys2026-08-281-2/+10
| | | | | | | mid-exit, and the cooperative card explains that the balance is held by the exit below — and that cancelling it (while nothing has broadcast) frees the coins for the cooperative road Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* A claimed gift shows you the pocket it landed in: an ark gift claim latches ↵Adam Soltys2026-08-281-3/+15
| | | | | | | the Spending side and selects it on every path into the wallet — backup, verify, skip, or straight in — instead of opening onto an empty Savings face Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* A send can't quietly change accounts: pasting an on-chain address in ↵Adam Soltys2026-08-281-6/+19
| | | | | | | Spending while every coin is mid-exit now opens the exit's own status page — before, it fell through to the Savings send form, whose fee-trimmed Max read as the spending balance shrinking by half Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi