aboutsummaryrefslogtreecommitdiffstats
path: root/src/ark
Commit message (Collapse)AuthorAgeFilesLines
...
* Dead coins stop travelling: an expired vtxo leaves the balance and the coin ↵Adam Soltys2026-08-241-8/+35
| | | | | | | 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 claim sorts its coins the way the server counts them: HTLC vtxos line up ↵Adam Soltys2026-08-181-4/+13
| | | | | | | by outpoint in internal byte order — the display-hex sort read the txid backwards and nine-coin receives bounced off the positional check Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
* A many-coined receive keeps the server's own order: the claim step stops ↵Adam Soltys2026-08-181-3/+6
| | | | | | | alphabetizing HTLC vtxos the ASP matches positionally, and the expiry guard reads the true earliest deadline instead of whoever sorted first Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
* A refresh learns to let go: a participation rejected for unusable inputs ↵Adam Soltys2026-08-181-4/+96
| | | | | | | asks the server which coins died and rebuilds around the survivors instead of resubmitting the doomed set every sync forever; the balance reconciles on a ten-minute cadence so ghosts can't pose as sats; and arkRescue() reclaims a round output whose action a device lost Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_012u4oe1KPx9faCsDBLfZYqi
* Money stops arriving without a story: the mailbox checkpoint stays local ↵Adam Soltys2026-08-181-1/+10
| | | | | | | reading progress (a merged one skipped every unprocessed message), vtxos that beat their message here get a backfilled receive, and the commit stamp takes its own footer line Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* The HTLC expiry stops trusting a cached clock: tip fetches bypass the CDN, ↵Adam Soltys2026-08-181-1/+15
| | | | | | | and when the server names its own tip the payment adopts it and retries instead of dying Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* The board drive gets a second witness: the wallet's own chain view vouches ↵Adam Soltys2026-08-181-4/+21
| | | | | | | for confirmations when the ark esplora is rate-limited or walled off, and chain errors finally surface instead of masquerading as unconfirmed Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* A confirmed board stops waiting on a flaky tip: confirmation itself counts ↵Adam Soltys2026-08-181-4/+9
| | | | | | | for one, and a failed mailbox read no longer starves the drives that only need the chain Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Zaps too gather what they need: several coins each lock an HTLC under one ↵Adam Soltys2026-08-141-50/+88
| | | | | | | payment hash and the server sums them — the fragmented-balance error is gone from Lightning as well Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A send covers itself from as many coins as it needs: one atomic package ↵Adam Soltys2026-08-142-39/+102
| | | | | | | cosign spends them all, the recipient receives several vtxos, and "consolidate with refresh() first" retires from the vocabulary Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A mailbox backlog claimed at sign-in reads as the old payments they are, not ↵Adam Soltys2026-08-141-1/+27
| | | | | | | a wall of seconds-ago windfalls; a gift send knows itself in history — status shown, link recopyable, revoke at hand Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* Pay what the route costs: sends quote the network fee up front (zero between ↵Adam Soltys2026-08-142-6/+37
| | | | | | | coinos wallets), lock exactly that, and a refunded miss retries with one more sat Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A waiting board says what it waits for: the Moving line counts ↵Adam Soltys2026-08-091-6/+12
| | | | | | | confirmations, a snag shows itself, and one stuck action no longer starves the queue behind it Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01DbA53PJA8fgSvMcEzfuw22
* Boards show the server their funding tx, as mainnet now insistsAdam Soltys2026-08-052-1/+8
| | | | | Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01M5kFodm9azZJVTQxnkDdKe
* hal speaks pver 5: preimages prove their size, and fees round up as oneAdam Soltys2026-08-057-54/+84
| | | | | | | | | | 0.6.0 servers require the new hashlock clauses (OP_SIZE 32 guard) for Lightning and rounds. New policies/transitions carry the v1 scripts and type bytes; _v0 variants keep old vtxos reconstructing and exiting. The retired third-party HTLC policy is dropped (upstream took 0x08). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01M5kFodm9azZJVTQxnkDdKe
* A wallet too small to renew warns before its coins expire; dust never diesAdam Soltys2026-08-041-1/+7
| | | | | | | | | | | | | | | | | | The warning: when the Spending balance minus round fee is under the 330-sat round minimum AND a vtxo enters the renewal window, auto-refresh can't save the coins — a wallet-screen notice (and a daily local notification, when permitted) says to receive any amount or spend before the deadline. New walletNotices feature hook renders under the balance card. The amnesty: sub-dust vtxos have no unilateral exit to protect, and regtest proves captaind keeps cosigning their spends past expiryHeight — even after the watchman claims the backing on-chain (tools/ark/expired-dust-test.js). Only hal's own receive validation stood in the way; it now exempts sub-330 vtxos from the expiry check. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
* Ark gifts go down to 1 sat; negative amounts can't OOM the encoderAdam Soltys2026-08-042-0/+8
| | | | | | | | | | | | | | | | | | Regtest-proven (tools/ark/dust-gift-test.js): the ASP cosigns all-dust arkoor sends, so a sub-dust bearer vtxo sweeps to its claimer fine, and dust folds into rounds alongside bigger siblings. The 330-sat gift floor guarded a failure that can't happen — dropped to 1 sat. The experiment also caught a live bug: refresh() of a balance smaller than the round fee computed a negative output amount, and pbWriter's varint sign-extends negatives into an infinite loop — auto-refresh would OOM the tab of any wallet too small to renew. varint now throws on negatives and refresh() refuses cleanly, before marking coins pending, when balance minus fee is under the server's 330-sat output minimum. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
* A freshly imported wallet shows history, not a celebrationAdam Soltys2026-08-031-1/+15
| | | | | | | | | | | | | | | | Importing a seed on a second device replayed "Payment received!" for a payment that had arrived on the first one. The two-hour recency guard couldn't catch it: a movement is stamped with the moment THIS device discovered it, so on a fresh device the entire history looks like it just landed — a week-old payment would have celebrated too. A wallet whose ark state didn't exist on this device now treats its first catch-up as history and acknowledges it, so only what turns up afterwards is news. Reopening an existing wallet is unaffected, and a payment that lands while you're watching still celebrates. 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-3/+9
| | | | | | | | | | | | | | | 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
* Rebrand: hal → coinos v3Adam Soltys2026-08-021-4/+4
| | | | | | | | | | | | The app already presents as Coinos; this finishes the job in the repo: package name, README, GitHub link, code comments, and the stale locale lines that still explained the old "Hal Wallet" name (they fall back to the English tribute line). Kept: the hal-nwc-pouch IndexedDB name (an upgrade-compat identifier), the halwallet.app domain in the BIP-353 names feature (live infrastructure), and the Hal Finney tribute itself. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
* Simplify: one Lightning path, one balance, fewer featuresAdam Soltys2026-08-011-26/+0
| | | | | | | | | | | | | | | | | | | | | | | | | 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-2/+32
| | | | | | | | | | | | | | | | | | | | | | | 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]>
* Stop the nostr sync snapshot from importing another ASP's coinsAdam Soltys2026-08-011-1/+9
| | | | | | | | | | | | | | | | | | | | | The phantom balance came back through the sync path. Snapshots published by older builds carry no ASP tag, so the tag check passed them, and with the local namespace empty the merge returned the snapshot wholesale — writing second.tech's vtxos straight into the coinos namespace, where the manager then stamped them as coinos'. Two fixes, both grounded in the fact that a vtxo names its own cosigner: - the sync path derives the snapshot's true owner from its vtxos and parks it under that owner instead of merging when it isn't provably ours - ArkManager.init drops any state whose coins were cosigned by a different server, whatever the stamp claims. Stamps are something we wrote; the vtxo bytes are evidence. Found by tracing localStorage reads in the live tab: the namespaced key was being *created* during load, which pointed at the merge rather than at storage keying. Co-Authored-By: Claude Fable 5 <[email protected]>
* Never render another ASP's Ark state before connectingAdam Soltys2026-08-011-0/+7
| | | | | | | | | | | | | | | | The previous fix still let a phantom balance through: loadArkState fell back to the pre-namespacing key when a namespace was empty, and the UI renders from that before any server is contacted — so the guard, which runs on connect, never got a say. loadArkState now returns only the namespaced state. Legacy state is claimed through adoptArkState(serverPubkey), which proves ownership first: from the state's own stamp, or failing that by decoding a vtxo, whose wire format names its cosigner. No network call, and it cannot guess wrong. On a match the state moves into the namespace and the legacy key is retired; on a mismatch it is left untouched for its real owner. Co-Authored-By: Claude Fable 5 <[email protected]>
* Keep Ark state per ASP, not just per walletAdam Soltys2026-08-011-0/+14
| | | | | | | | | | | | | | | | | | | | | Switching providers showed the previous server's balance and tried to resume its in-flight board ("1 deposit confirming" against a server that had never heard of it). A vtxo is only meaningful against the ASP that cosigned it, so state must be scoped to both the wallet and the server. - ark state keys gain a namespace derived from the ASP endpoint, so switching providers switches state and switching back restores it - state is stamped with the server pubkey; on connect a mismatch is discarded rather than displayed. This also self-corrects the one-time adoption of pre-namespacing state, which can only guess which ASP it belonged to - mergeArkStates refuses to fuse two servers' states, and the nostr sync snapshot carries (and filters on) the ASP it came from, so a device on a different provider can't inject foreign vtxos Nothing is deleted: each ASP's state lives under its own key, and the legacy key is left in place for whichever server rightfully claims it. Co-Authored-By: Claude Fable 5 <[email protected]>
* Client support for third-party HTLC vtxos (trustless swap bridges)Adam Soltys2026-07-314-5/+187
| | | | | | | | | | | | | | | | | | Speaks the proposed VtxoPolicy::Htlc (type byte 0x08): policy encode/decode, two-leaf taproot (claimer-with-preimage / refunder-after-expiry), preimage field on the arkoor cosign request, and GetHtlcPreimage. ArkManager gains the swap primitives: htlcLock (lock funds claimable only against a payment hash, refundable by us after expiry), htlcClaim (reveal the preimage), htlcCosignRefund (hand an unclaimable HTLC back — the server constrains the outputs to the refunder, so this is safe to expose publicly) and acceptHtlcRefund. tools/ark/htlc-bridge-test.js drives a full submarine swap between two independent wallets against a patched captaind, and asserts the ASP rejects both a wrong-preimage claim and a preimage-less spend to the bridge itself. Co-Authored-By: Claude Fable 5 <[email protected]>
* Fix send-form UX around lightning pays; harden ln state machinesAdam Soltys2026-07-311-7/+33
| | | | | | | | | | | | | | | | | | | - 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]>
* Dust-isolate arkoor outputs; prove lightning E2E on regtestAdam Soltys2026-07-312-93/+199
| | | | | | | | | | | | | | | | | The server rejects an arkoor mixing dust and non-dust outputs, which broke small Lightning payments (a 45-sat HTLC next to change) and tiny plain sends. Mirror bark's isolation: dust outputs route through a combined isolation output spent by a fanout tx, splitting a non-dust output to pad the dust below-threshold. Outputs can therefore split across two vtxos, so the manager now classifies results by policy instead of index (legacy single-field actions still resume). Regtest now runs the full stack: dedicated cln-ark node (secondark/cln-hold, hold plugin + xpay) wired into captaind with a channel to the coinos dev clc node. tools/ark/ln-e2e-test.js proves pay (5000 sat and a 25-sat dust zap), hold-invoice receive with claim, and spending the claimed vtxos. Co-Authored-By: Claude Fable 5 <[email protected]>
* Add Ark <-> Lightning via the ASP (captaind-native submarine swaps)Adam Soltys2026-07-316-40/+822
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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]>
* Exit status: real progress, blocks-left countdown, honest failuresAdam Soltys2026-07-051-1/+15
| | | | | | | | | | | | | 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]>
* Exit works on plain-esplora regtest; human-readable ark status linesAdam Soltys2026-07-051-3/+14
| | | | | | | | | | | | 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]>
* Dedupe ark receive movementsAdam Soltys2026-07-051-1/+13
| | | | | | | | | | The mailbox poll and live stream can process the same message concurrently (validation awaits in between): the vtxo itself deduped but both copies pushed a receive movement, so a claimed gift showed twice in History. The movement now only records when _addVtxo actually added the vtxo, and init() prunes duplicates the old race left behind. Co-Authored-By: Claude Fable 5 <[email protected]>
* Unilateral exit: put vtxos on-chain without the serverAdam Soltys2026-07-054-8/+197
| | | | | | | | | | | | | | | | | | | | | | 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]>
* Collaborative offboard: move the ark balance back on-chainAdam Soltys2026-07-053-1/+328
| | | | | | | | | | | | | | | | | | | | 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-1/+7
| | | | | | | | | | 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]>
* Ark: recover from stale vtxo stateAdam Soltys2026-07-043-4/+47
| | | | | | | | | | Match captaind's actual 'not spendable' error so a crashed or foreign spend fails the action instead of retrying forever, and reconcile locally-spendable vtxos against the server (GetVtxoStatus + ownership attestation) when an ark address lands in the send form. boardFee now treats absent proto3 fee fields as zero (Second's signet boards free). Co-Authored-By: Claude Fable 5 <[email protected]>
* Ark: real-time receives over the SubscribeMailbox gRPC streamAdam Soltys2026-07-042-38/+130
| | | | | | | | | | | | grpcStream() parses gRPC-web frames incrementally off fetch's body stream; the manager keeps a long-lived SubscribeMailbox subscription (auto-reconnect, 3s backoff) whose messages flow through the same duplicate-safe processing as the poll. Receives now land the moment the sender delivers (~sub-second) instead of on the next poll; the poll stays as fallback and to drive in-flight boards/refreshes. 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-4/+7
| | | | | | | | | | | 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
* Ark: 'Payment received!' celebration for Ark receivesAdam Soltys2026-07-031-0/+14
| | | | | | | | | Same card and tap-to-acknowledge flow as on-chain receives; the ack persists in the ark state (shows exactly once) and a 2h recency guard keeps old payments from celebrating when a wallet is opened later. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Ark: native-JS protocol client + persistent ArkManagerAdam Soltys2026-07-036-0/+1830
Speaks Second's bark/captaind Ark protocol directly from the browser — gRPC-web over fetch with hand-rolled protobuf, no wasm, no new deps (crypto via the existing @scure/@noble stack incl. btc-signer's BIP-327 musig2 module). src/ark: - proto.js transport, ark address codec, mailbox blinding/auth, VTXO ProtocolEncoding v2 decode - send.js arkoor send: checkpoint+arkoor txs, BIP-341 sighashes, MuSig2 cosign ceremony, signed-VTXO assembly - board.js onchain -> ark: funding taproot, exit-tx cosign - refresh.js delegated round (hArk): participation, tx-chain reconstruction, hash-locked leaf cosign, forfeit swap - validate.js receive-side verification: chain must land on the vtxo point, anchor checked onchain, every transition sig verified - manager.js persistent wallet layer: storage-checkpointed step-machine actions (send/board/refresh) that survive crashes, mailbox sync with validation, multi-input consolidation refresh tools/ark: end-to-end regtest tests (receive, send, board, refresh, manager incl. crash-mid-send + resume), all passing against captaind with the bark CLI as counterparty. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy