aboutsummaryrefslogtreecommitdiffstats
path: root/src/i18n.js
Commit message (Collapse)AuthorAgeFilesLines
* How it works: tighten Spending & Savings to two paragraphsAdam Soltys2026-08-021-3/+2
| | | | | Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* How it works: condense the basics to three paragraphsAdam Soltys2026-08-021-5/+3
| | | | | | | | | Twelve words + what losing them means, one paragraph; no-server plus offline, one paragraph; standards/restorability, one line. Stale locale translations pruned to fall back to English. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* How it works: drop the block-explorer mentionAdam Soltys2026-08-021-1/+1
| | | | | | | | | electrum.coinos.io is the default data source now, not mempool.space, and the basics card reads better without plumbing details. Stale locale translations of the paragraph fall back to the new English. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* How it works: fold moving/housekeeping into Spending & Savings, drop SPAdam Soltys2026-08-021-7/+1
| | | | | | | | | | One card instead of three: the analogy, what runs Spending (Ark + Lightning) in plain words, and a single paragraph covering Move money, fees, automatic upkeep, and the pre-signed escape route. The silent payments section goes — no user-facing SP receive mode exists anymore. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* How it works: explain Spending vs Savings for laymenAdam Soltys2026-08-021-2/+4
| | | | | | | | | | | | | The one-paragraph section grows to three: the pocket-cash vs savings analogy, what actually runs Spending (Ark's shared pool locked to your key, plus Lightning interop) in plain words, and a rule of thumb for which balance money belongs in. Also fixes the stale housekeeping paragraph that still told users to refresh coins in Settings — that's automatic now. Stale translations of the two changed keys are pruned so locales fall back to the new English. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Ark: partial moves to Savings via an exact-amount splitAdam Soltys2026-08-021-0/+3
| | | | | | | | | | | | | | | Into Savings now has an amount field with a Max button. Max (or the full balance) keeps the existing whole-balance cooperative offboard. A partial amount first mints a vtxo of exactly that amount with a self-send — the mailbox delivers self-sends, verified on regtest — then offboards just that vtxo, so the number typed is the number that leaves Spending (fees still come off what arrives, shown on the success screen). startOffboard accepts a vtxo subset for this; an exact-match vtxo skips the split. The unilateral exit page remains reachable from a link under the field. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Chat behind a header button, full-screen; move-panel polishAdam Soltys2026-08-021-1/+0
| | | | | | | | | | | | | | | Chat leaves the tab bar (which returns to its four evenly spaced tabs) for an icon button in the header next to the wallet selector. It now takes over the whole screen — no balance card, no tabs — with a back button on the chat home view, and the logo still leads back to the wallet. The generic tabs/tabContent seams this reverts to unused are removed again. Move panel: the direction toggle stretches across the card, and the "X sats in Spending" line is gone — the balance sits right above it. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Settings: collapse the recovery phrase behind a reveal buttonAdam Soltys2026-08-021-0/+1
| | | | | | | | | | | | The masked twelve-word grid took a full screen of the Settings page just to say "there's a backup here". Collapsed card now carries one line of warning and the reveal button; the grid (always unmasked — the masked state had no job once the gate exists) appears only after an explicit reveal, and Hide collapses it again. Applies to both the main Settings tab and the per-account screen, which share the card. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Ark: automatic vtxo upkeep, and Move money inline on the balance cardAdam Soltys2026-08-021-1/+0
| | | | | | | | | | | | | | | | Refresh/consolidation is no longer a user concern: after each sync the wallet renews automatically when any spendable vtxo is within ~a week of expiry or fragmentation reaches six vtxos (a send needs one vtxo that covers the amount), throttled to one attempt per half hour and never while another round is in flight. The manual refresh button is gone. The separate Move money page is gone too — the button on the balance card now unfolds an inline panel with an Into Spending / Into Savings toggle: boarding happens right there, and Into Savings hands off to the existing exit page (cooperative offboard + unilateral exit unchanged). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Settings: surface wallet settings, add Nostr section, tuck rarities into ↵Adam Soltys2026-08-021-0/+2
| | | | | | | | | | | | | | | | | | Advanced The main Settings tab now inlines the active wallet's own cards (recovery phrase, name, public key) instead of linking to a sub-page, followed by payment address, Ark status, network, and data source. All nostr cards — address, account link, wallet connect, device sync — sit under one Nostr heading via a new nostrSettingsCards seam. Offline transfer, address rescan, and auto-logout move to an Advanced sub-page. The Ark provider picker is gone: mainnet always rides coinos (a stale stored choice no longer wins); dev networks keep their per-network defaults. The per-account screen (Accounts → ⚙) reuses the same card builders unchanged. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Chat: device sync via Community List (13302) and Invite List (13303)Adam Soltys2026-08-021-0/+2
| | | | | | | | | | | | | | | Memberships and minted invite-link keys now follow the user across devices: both lists are NIP-44 self-encrypted replaceables (CORD-02 §8, CORD-05 §4), published under the wallet key (the cross-device constant) and the login npub when a signer is live. Merging validates the self-certifying community_id before adopting keys, keeps tombstones permanent, and lets the newest of added_at/removed_at win, so a stale device can never resurrect a community you left. Leaving is a two-tap control in the room's invite panel (the built-in coinos community is exempt) and publishes a guestbook Leave alongside the tombstone. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Chat v2: DMs, invites, and multi-community — coinos is the default, not ↵Adam Soltys2026-08-021-0/+29
| | | | | | | | | | | | | | | | | | | | | | | the only - NIP-17 private DMs (src/dm.js): kind-14 rumors in sender-signed seals under ephemeral wraps; interops with other nostr DM clients. Login signers gained encryptTo/decryptFrom so extensions and bunkers can seal to a peer; the inbox listens for both the login npub and the wallet key and publishes a kind-10050 DM-relay list for the wallet key when none exists. - Concord invites (CORD-05): mint shareable links (33301 bundle on relays, keys only in the URL fragment), join by pasting a link or opening v3.coinos.io/invite/…, and direct invites giftwrapped to an npub with the k-tag index hint. Bundles self-certify the founder before anything joins. - Multi-community: home view lists DM threads and communities; found your own community in-app (owner-signed genesis). coinos stays baked in as default. - Welcome DM: the names registrar DMs every first-time registrant from Adam's npub on claim (config: welcome{sk,message}; deduped in registrar state). Every new wallet auto-claims a payment address, so every new user gets one. - relay.coinos.io write policy now allows 33301/13302/13303. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Remove the Hal Finney tributeAdam Soltys2026-08-021-1/+0
| | | | | Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Chat: Concord encrypted community messaging, with a default coinos roomAdam Soltys2026-08-021-0/+11
| | | | | | | | | | | | Implements the Concord protocol (CORD-01..04) — private streams, the control-plane fold, guestbook membership, owner-rooted authority — and ships a built-in "coinos" community founded by Adam's npub (owner/admin). Messages sign with the nostr login identity when a signer is live, else the wallet's NIP-06 key; all encryption rides derived stream keys so remote signers only ever sign seals. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Spending is the headline balance; Savings sits under itAdam Soltys2026-08-021-23/+23
| | | | | | | | | No total: the two are different kinds of money and summing them says nothing useful. Layout keys off whether the instant balance exists at all rather than off its amount — a zero Spending balance is still a Spending balance. Co-Authored-By: Claude Fable 5 <[email protected]>
* Speak about money, not rails: Spending and SavingAdam Soltys2026-08-011-57/+69
| | | | | | | | | | | | | | | | The balance card now leads with the total and names the two places money lives — Spending (instant) and Saving (on-chain) — instead of an on-chain headline with an 'Ark balance' line hanging off it. A 'Move money' button under the balance opens one screen that moves funds either way, replacing a board form buried inside the Ark receive pane. Strings throughout drop Ark and Lightning: boarding becomes 'Move to Spending', exiting becomes 'Move to Saving', the receive tabs read 'Instant' and 'Saving address', and How it works explains two balances and the escape hatch without naming a protocol. The rails keep their names in the code, where they belong. Co-Authored-By: Claude Fable 5 <[email protected]>
* Drop npub-locked gifts; collapse Nostr login behind a buttonAdam Soltys2026-08-011-18/+1
| | | | | | | | | | | | | | Gifts are plain bearer links again: the recipient-npub field, the one-time claim code, the DM delivery, the /lg/ claim route and the NIP-07 in-place decrypt are all gone, along with the crypto that only they used. Unclaimed gifts remain reclaimable by the sender, so nothing can be stranded by the removal. The unlock screen shows a single 'Sign in with Nostr' button that reveals the login options when tapped, instead of the full card competing with create/import. Co-Authored-By: Claude Fable 5 <[email protected]>
* Get an address immediately, without waiting on a signer promptAdam Soltys2026-08-011-0/+1
| | | | | | | | | | | | | | | 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]>
* Actually assign the default payment addressAdam Soltys2026-08-011-0/+1
| | | | | | | | | | 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]>
* Log in with Nostr, and link a wallet to a Nostr accountAdam Soltys2026-08-011-0/+21
| | | | | | | | | | | | | | | | | | | | | | | | | Three ways in: a NIP-07 browser extension, a NIP-46 remote signer (Amber, Amethyst — paste its bunker:// address), or a pasted nsec/hex key that lives in memory for the session and is never stored. How an account gets a wallet depends on what we can see, and the two cases are genuinely different: * We hold the key (pasted nsec): the seed is DERIVED from it — sha256("coinos:wallet-seed:v1" | privkey) as BIP-39 entropy. The same Nostr key always opens the same wallet, on any device, with nothing stored anywhere. * We only have a signer: deriving is impossible (we never see the key, and neither signatures nor NIP-44 ciphertexts reproduce), so the seed is ASSOCIATED instead — generated once and published as a replaceable event encrypted to the user's own key, which only their signer can decrypt. Later logins find and decrypt it. The second path means the Nostr key can recover the money; the UI says so before publishing anything. Linking an already-open wallet uses the same publish path and refuses to overwrite an account's existing wallet. Co-Authored-By: Claude Fable 5 <[email protected]>
* Default usernames from the npub — no onboarding promptAdam Soltys2026-08-011-3/+2
| | | | | | | | | | | | | 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-0/+4
| | | | | | | | | | | | | | | 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]>
* The coinos mark in the headerAdam Soltys2026-08-011-1/+1
| | | | | | | Inline single-color SVG of the brand symbol (ring + half-moon) that inherits the ink color, next to the lowercase wordmark. Co-Authored-By: Claude Fable 5 <[email protected]>
* Coinos v3: rebrand from Hal, payment addresses move to @coinos.ioAdam Soltys2026-08-011-5/+5
| | | | | | | | | | | | | | | 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-4/+7
| | | | | | | | | | | | | | | | | | | | | | | | | 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/+13
| | | | | | | | | | | | | | | | | | | | 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]>
* Simplify: one Lightning path, one balance, fewer featuresAdam Soltys2026-08-011-31/+1
| | | | | | | | | | | | | | | | | | | | | | | | | Dropped: silent payments (feature, wallet chains, scan worker, indexer config), Boltz submarine/reverse swaps (feature + swap.js + tools), the third-party ark swap bridge (config, client flows, settings card — the ASP's own Lightning send is the one path now), and the Consolidate coins settings action. The NWC pouch is gone with them: background answering now spends the WHOLE ark balance. The IndexedDB record mirrors the real manager state plus the chain-3 keys for its live coins and a change-index window; the worker pays through the ASP exactly like the open app, and the app folds the worker's spends, change, and key allocations back in on connect (additive merge + reconcile against the server). A leftover chain-6 pouch from the short-lived pouch era is swept home automatically using the keys stored in its own record. The stated tradeoff: same-origin script access now reaches the ark balance, not a carve-out — the ark balance is walking-around money, the on-chain wallet's keys are never mirrored, and per-connection NWC budgets remain the enforced ceiling. Bundle: 726KB -> 602KB. Co-Authored-By: Claude Fable 5 <[email protected]>
* Background NWC: the worker now answers — and pays — from the pouchAdam Soltys2026-08-011-3/+10
| | | | | | | | | | | | | | | | | | | | | | | The no-tap half of background wallet-connect. The push payload carries the (encrypted, client-signed) request event; a bundled service-worker responder (src/sw-nwc.js -> nwc-respond.js) finds the matching pouch in IndexedDB, decrypts with the connection's service key, and answers get_info/get_balance/list_transactions from pouch state. pay_invoice pays through the swap bridge with an ArkManager running over the pouch's chain-6 key window (one HTLC lock, one HTTP swap), enforcing per-payment and daily budgets from the pouch's own spend log, checking the notifier's /answered endpoint so it never double-pays or shouts over an open device, and persisting the swap before handing it off so the app can refund a crashed flight. Anything it can't handle falls back to the wake-the-user notification. The notifier grows /publish (verified 23195s only, rate-limited) as the worker's reply pipe and /answered for race avoidance. The app gains pouch funding (mailbox-less arkoor self-send whose recipient bytes we keep), emptying, spend/budget reconciliation on open, and refund recovery with the pouch's own keys. Co-Authored-By: Claude Fable 5 <[email protected]>
* Wake hal for wallet-connect requests while it is closedAdam Soltys2026-08-011-0/+5
| | | | | | | | | | | | | | | | | | | Step 3, first half. Android Chrome freezes backgrounded PWAs and closes their relay sockets, so a phone with hal "open" answers nothing — which is what made Amethyst spin. Push is the only way to reach a frozen app. - service worker gains a `push` handler. It deliberately does NOT spend: if a window is open it nudges it to re-listen, otherwise it raises a notification that opens hal on tap. Putting a spend path in the worker is the remaining half and wants its own testing. - hal-side: request permission, subscribe with the notifier's VAPID key, and register its service pubkeys with nwcpush.coinos.io. Turning it off deregisters, unsubscribes, and clears the pouch — no reason to leave spendable keys where a worker can read them if nothing will. - a Settings toggle, and the ark feature exposes the ASP context the pouch record needs. Co-Authored-By: Claude Fable 5 <[email protected]>
* Add Nostr Wallet Connect (NIP-47) — hal as a wallet serviceAdam Soltys2026-08-011-0/+13
| | | | | | | | | | | | | | | | | | | | | | | | | Other apps can connect over nostr and pay from this wallet without touching its keys, within a per-payment and daily budget the user sets, revocable at any time. hal holds no native Lightning balance, so every operation runs over Ark: pay_invoice takes the swap bridge when configured and falls back to the ASP's lightning-send, make_invoice mints on the ASP. NWC availability therefore tracks Ark availability. - kinds 13194/23194/23195, nip44_v2 and nip04, replying in whichever scheme the request used; every request gets a reply so clients never hang - each connection gets its own service keypair, so revoking one can't affect the others and none is tied to the user's nostr identity - budgets are checked BEFORE spending, not reconciled after - requests are ignored unless signed by that connection's client key, and replayed/stale events (>120s) can't re-trigger a payment - Settings card to create, show (URI + QR) and revoke connections, and it says plainly that this only works while a tab is open tools/nwc-test.js drives it as a real client: both encryption schemes, budget refusal with a genuine over-limit invoice, unsupported-method errors, and a request from an unauthorized key being ignored. Co-Authored-By: Claude Fable 5 <[email protected]>
* Settings: coinos ASP presets + swap-bridge providerAdam Soltys2026-07-311-0/+7
| | | | | | | | | | | | | | | - ark presets gain coinos entries (ark.coinos.io on mainnet, ark-staging.coinos.io on mutinynet) alongside Second's - new per-network swap-bridge setting (preset/custom URL + access token) with its own Settings card When a bridge is configured, a bolt11 quote asks it first and shows its fee; paying locks an HTLC only the bridge can claim, and only by revealing the invoice preimage. Any failure — unreachable bridge, refused swap, unpayable invoice — refunds and falls back to the ASP's own lightning-send, so the payment never dead-ends. Hanging swaps are refunded on reconnect. Co-Authored-By: Claude Fable 5 <[email protected]>
* Fix send-form UX around lightning pays; harden ln state machinesAdam Soltys2026-07-311-0/+2
| | | | | | | | | | | | | | | | | | | - a rejected cosign (gRPC INVALID_ARGUMENT) returns the input vtxo to spendable and fails the action instead of leaving it pending forever — the stuck-pending state that pushed small zaps onto Boltz's 25k minimum - ark ln-pay now takes over when funds are settling (retrying quote) rather than falling through to Boltz - typing a destination clears stale send errors (also cleared on tab switch); paste path likewise - typed lightning addresses no longer auto-advance mid-keystroke (the matcher fired at `[email protected]` before `.com`, yanking the form away): the send form offers an explicit "Zap <addr>" button; pasted/scanned addresses still advance immediately - ln-recv: HTLC vtxos anchored to a not-yet-confirmed pool round park and retry instead of throwing; the requested HTLC expiry is anchored on first prepare so retries can't inflate it past the server's grant Co-Authored-By: Claude Fable 5 <[email protected]>
* Add Ark <-> Lightning via the ASP (captaind-native submarine swaps)Adam Soltys2026-07-311-0/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | The ASP is the HTLC counterparty (second.tech's protocol), so no external swap provider is needed: paying a bolt11 converts pubkey vtxos into ServerHtlcSend vtxos the server can only claim by revealing the invoice preimage; receiving grants ServerHtlcRecv vtxos claimed by revealing ours. Failure paths cosign the HTLC back (revocation) — proven end-to-end against regtest captaind, which independently derives the HTLC taproots. - ark/lightning.js: bolt11 decode, lightning fee schedules, all pay/receive gRPC-web wrappers (cosign, initiate, status, revocation, hold-invoice receive flow, anti-DoS attestation) - ark/send.js: arkoor builder generalized to policy outputs (pubkey / serverHtlcSend / serverHtlcRecv), two-leaf taproot trees, HTLC clause scripts, reusable per-part cosign helpers for package RPCs - ark/manager.js: ln-pay and ln-recv crash-safe action state machines (deterministic receive preimages from the seed, chain 5), mailbox lightning notifications, unpayable-invoice -> instant revocation - proto.js: lightning ArkInfo fields + mailbox lightning message decode - validate/refresh: policy-aware vtxo validation and reconstruction - features: bolt11 routes via ark when the balance covers it (Boltz stays the fallback), lightning-invoice receive on the Ark pane - tools/ark/ln-test.js: harness proving HTLC cosign + revocation against captaind; manager-test.js updated for the consolidated bc-container chain Co-Authored-By: Claude Fable 5 <[email protected]>
* Add NIP-57 Lightning zaps (npub / lightning address / lnurl)Adam Soltys2026-07-301-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | Send a Lightning zap to a nostr npub, a lightning address (name@domain), or an lnurl. New src/lnurl.js does the resolution half — target → LNURL-pay params → signed kind-9734 zap request → callback → bolt11 — and the new zaps feature (src/features/zaps.js) drives the amount/comment UI, then hands the invoice to the existing Boltz submarine-swap flow via a new swaps.startLnPay hook, so there's one tested pay/review/confirm/success path. Routing: a bolt11 is still caught by swaps; an npub still prefers an instant free Ark zap when Ark can serve it, and only falls through to a Lightning zap otherwise — ark's "no Ark address" screen also offers an explicit "Zap over Lightning" fallback (gated on the zaps feature's canLnZap). A real zap receipt is attributed only when the server advertises allowsNostr and we know the recipient's pubkey; otherwise it degrades to a plain LNURL-pay. Nostr seam gains nostrSign (finalize without publishing), nostrProfile (kind-0 with lud16/lud06), and nostrRelays. Lightning addresses are debounced in matchSendText since their regex matches mid-typing. Verified: unit tests for parse/encode/zap-request; a live resolve→signed 9734→payable mainnet bolt11 against coinos; and an in-browser DOM smoke (zap form + LNURL params over CORS + allowsNostr hint + handoff). Co-Authored-By: Claude Opus 4.8 <[email protected]>
* Consolidate ark exit into one page: cooperative + unilateralAdam Soltys2026-07-061-0/+8
| | | | | | | | | | | | | The cooperative offboard was buried under the receive-tab board form and the unilateral exit lived in Settings — both unintuitive. Now a small 'Exit' link next to the Ark balance opens a dedicated page that explains and offers both: cooperative (server co-signs, fast, no on-chain funds needed, small server fee) and unilateral (trustless, timelocked, pays mining fees). In-flight exit progress (hop counter, timelock countdown, cancel) moved here from Settings; the receive pane loses the offboard button and Settings loses the exit button. Co-Authored-By: Claude Fable 5 <[email protected]>
* Ark icon: Second's logo instead of the crossed-swords placeholderAdam Soltys2026-07-061-1/+1
| | | | | | | | | | | | | | The ⚔ was a U+2694 emoji stand-in. Swap in Second's actual mark (second.tech logo: a triangle with an evenodd inner cutout) as two format.js helpers — ARK_ICON (dark rounded-square app badge + white mark, for card/section headers) and ARK_MARK (bare currentColor glyph, for the history-row circle). Wired into the Ark settings card, the boarding/withdrawal/exit history rows + detail section, and the How-it-works Ark section; the gift source toggle drops the emoji for plain 'Ark'. Verified the badge renders (18px, #00090C square, white evenodd mark). Co-Authored-By: Claude Fable 5 <[email protected]>
* Ark zaps PoC — a NIP-61-shaped zap protocol over arkoorAdam Soltys2026-07-061-0/+7
| | | | | | | | | | | | | | | | | | | | | Lightning zaps are welded to LNURL+bolt11; nutzaps (NIP-61) proved the alternative shape, and ark fits it better than Cashu because delivery already exists (the mailbox). Draft protocol, kinds provisional: kind 10037 (replaceable) announces the wallet's ark address+network; the zap itself is a plain instant arkoor send; kind 9737 is the sender-signed receipt tagging recipient, amount, comment, and the delivered vtxo id — so the receipt is checkable against the actual payment, unlike a bare attestation. UX: paste an npub into Send and hal offers the zap (needs both the ark and sync features; npub decoding is inline bech32 so ark-only builds stay lean). The nostr layer gains generic publishEvent/fetchEvents, exposed through the sync seam as wallet.nostrPublish/nostrFetch. Proven on regtest against a mini NIP-01 relay: announce, resolve, zap 1,000 sats with a comment, instant receipt+delivery, vtxo match. Co-Authored-By: Claude Fable 5 <[email protected]>
* Docs: How-it-works covers Lightning/Ark/SP/gifts; README rewriteAdam Soltys2026-07-051-0/+10
| | | | | | | | | | | The in-app page grows plain-language cards for Lightning swaps, Ark (instant off-chain, the unilateral escape hatch, expiry housekeeping, fees), silent payments, and gift links. The README catches up with reality: the native-JS Ark client headlines the feature list, and the modular HAL_FEATURES build system gets its own section — every feature is a plugin behind a build seam, and excluded code never ships. Co-Authored-By: Claude Fable 5 <[email protected]>
* Exit status: real progress, blocks-left countdown, honest failuresAdam Soltys2026-07-051-2/+3
| | | | | | | | | | | | | submitpackage answers HTTP 200 even when it rejects the package — the verdict hides in package_msg/tx-results — so a mainnet no-fee-coin exit sat at 'publishing on-chain…' forever believing its bare hop had relayed. Rejections now surface (and become the actionable needs-a-fee- coin message on the bumpless path). The status line shows hop progress (step 2 of 9), the timelock wait counts down in blocks with a rough wall-clock estimate, and a stuck exit that never published anything gets a 'Cancel this exit' link that returns the vtxo to spendable. Co-Authored-By: Claude Fable 5 <[email protected]>
* Show the ark board fee before boardingAdam Soltys2026-07-051-0/+2
| | | | | | | | | | 100,000 in, 99,670 out was a surprise: the ASP's board fee (min/base/ ppm from its published schedule; it funds the exit tx's P2A fee anchor) was only visible after the fact. The board form now shows the fee and the net amount live as you type, and the funding tx's detail view gets an 'Ark server fee' line. Co-Authored-By: Claude Fable 5 <[email protected]>
* Exit works on plain-esplora regtest; human-readable ark status linesAdam Soltys2026-07-051-3/+8
| | | | | | | | | | | | submitPackage falls back to sequential /tx posts when the esplora lacks POST /txs/package (regtest electrs) — works wherever the node relays zero-fee v3 parents. The ark card stops speaking developer: in-flight operations summarize as '{n} deposit(s) confirming' instead of 'board:funded, exit:chain, …', exit lines read 'Exiting N sats — publishing on-chain…', and transient errors show 'hit a snag — retrying automatically' instead of raw gRPC/HTTP text. Co-Authored-By: Claude Fable 5 <[email protected]>
* Unilateral exit: put vtxos on-chain without the serverAdam Soltys2026-07-051-0/+8
| | | | | | | | | | | | | | | | | | | | | | The trustless backstop behind the Ark card's promise. The vtxo's genesis chain reconstructs to fully-signed txs (keyspend sigs for cosigned/arkoor transitions, preimage script-path for hark leaves); they are zero-fee v3 with P2A anchors, so each hop broadcasts as a [parent, CPFP child] package via esplora POST /txs/package, one confirmed hop at a time (TRUC allows a single unconfirmed parent). After the vtxo tx confirms and the CSV exit delta passes, the claim spends the delayed_sign leaf with only the user key into the wallet's own receive address. Settings gains 'Exit on-chain without the server' with live per-exit status lines; the claim tx is labeled 'Ark exit' in History. Probing uses /tx/:txid (definitive 404), never /tx/:txid/status, which answers confirmed:false for unknown txids. Also: a fresh visitor opening an ark gift link now adopts the gift's network automatically instead of being sent to Settings. Co-Authored-By: Claude Fable 5 <[email protected]>
* Ark gifts: instant off-chain bearer gifts inside the gift flowAdam Soltys2026-07-051-0/+7
| | | | | | | | | | | | | | | | | | | | | | Ark can't presign a bearer spend, so an ark gift is a vtxo sent to an ephemeral ark identity whose seed IS the link (/ag/<code>: net, amount, 32-byte secret). The claimer rebuilds the identity, reads its mailbox, and sweeps to their own ark address — instant, free, and it works for a brand-new empty wallet with zero on-chain footprint. The sender keeps the secret, which is what makes revoke possible (first cosign wins). The gift form gains an On-chain/Ark source toggle when ark balance exists; ark gifts skip the lock/split logic entirely. Claim, choose- wallet, already-claimed, and nostr-locked (/lg/) flows all branch by code kind; unclaimed ark gifts list with one-tap revoke and lazily mark themselves claimed via GetVtxoStatus. Features stay decoupled: gifts asks for ark support via the new ctx.hook seam, so either feature builds alone. Also restores goHome in the feature ctx — lost in the plugin-seam extraction, it made the already-claimed screen throw on render. Co-Authored-By: Claude Fable 5 <[email protected]>
* Collaborative offboard: move the ark balance back on-chainAdam Soltys2026-07-051-0/+5
| | | | | | | | | | | | | | | | | | | | PrepareOffboard/FinishOffboard against captaind — per-input ownership attestations, connector-based musig forfeits (with the deterministic fanout tx when there is more than one input), and fee math that mirrors the server bit-for-bit (weight fee rounds up, ppm-by-expiry rounds down) since it rejects any other net amount. The receive pane gains a 'Move back on-chain' button that withdraws everything to the wallet's own fresh address; the incoming tx is labeled 'Ark withdrawal' in History and the ark side records the movement. Crash-safe: the txid persists before FinishOffboard and resume asks GetVtxoStatus whether the forfeits landed (the server broadcasts the tx itself). Also fixes boarding to applySentTx after broadcasting the funding tx — without it the spent coin lingered in the utxo set (a second board double-spent it), and the post-board scan() could resurrect it by racing the explorer's indexing. Co-Authored-By: Claude Fable 5 <[email protected]>
* Boarding UX: label the funding tx and show an in-flight ark balanceAdam Soltys2026-07-051-0/+2
| | | | | | | | | | The board's on-chain send showed as a generic 'Sent' and the sats vanished from the balance until the vtxo registered. The funding tx now reads 'Ark board' in History (with a detail section showing the net credit), and an 'Ark (boarding…)' line carries the pending amount from broadcast until the board completes. Co-Authored-By: Claude Fable 5 <[email protected]>
* History: gifts are timeline entries, not a separate sectionAdam Soltys2026-07-041-0/+1
| | | | | | | | | | | | | | | Gift links now sort into the send/receive timeline like any entry: a clickable row (🎁, status tag, age, amount) opening a detail page that carries the date/status plus the actions that used to crowd the list row (view gift link, cancel/reclaim with the existing confirm flow). A claimed gift merges into its claim transaction's row — labeled as the gift, clickable to the tx detail, which gains a "This transaction delivered your gift" section (claim txid resolved via outspend and cached on the gift record). The old pinned gifts header and the paginated all-gifts view are gone. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Gift claim: name the real failure when the funding tx isn't visibleAdam Soltys2026-07-041-0/+1
| | | | | | | | | | | | | | Claiming a gift whose funding tx is unknown to the claimer's data source (different network/chain, or not yet propagated) used to fail with the misleading "already been claimed". Now: - the claim screen probes the funding tx up front (esplora's status/ outspend endpoints don't 404 for unknown txids, so outspend alone can't detect this) and shows a network/data-source notice, and - a missing-inputs broadcast rejection maps to the same explanation instead of the generic already-claimed message. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Gift claim: correct copy when claiming into an existing walletAdam Soltys2026-07-041-0/+1
| | | | | | | | | "Claim it into a brand-new wallet that only you control." only fits the new-wallet path; claiming into an existing wallet now says which wallet it lands in ("Claim it into your wallet "Wallet 1"."). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Gift claim: make the wallet chooser read as a choiceAdam Soltys2026-07-041-0/+2
| | | | | | | | | | | | The existing-wallet buttons looked like inert inputs. Now: a "Receive into one of your wallets:" label, a chevron on each wallet row so it reads as tappable, and an "or" divider before the new-wallet button. (tools/ark/gift-shot.js: screenshot harness that mints a real regtest gift and opens its link.) Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Ark: history rows open a detail viewAdam Soltys2026-07-041-0/+3
| | | | | | | | | | | Ark movements are clickable like on-chain txs. The detail view shows amount, date, status, the destination address (sends, copyable), the vtxo id, and for boards the funding txid with copy + explorer link. Movements now record those fields at completion time; older records without them still render (amount/date/status only). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy