aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/sp-wallet.js
Commit message (Collapse)AuthorAgeFilesLines
* Simplify: one Lightning path, one balance, fewer featuresAdam Soltys2026-08-011-544/+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]>
* Sync silent-payment scan across devices so the catch-up runs onceAdam Soltys2026-07-311-1/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | SP state (lastSpScan watermark + found spUtxos) was in the nostr snapshot but, unlike Ark/gifts, its cache extension wasn't mergeAlways — so it only applied via the newest full snapshot at load time, last-writer-wins. The watermark could regress (a device behind on SP, or mid-rescan, publishing a newer snapshot would reset another device's watermark), so every device tended to re-grind the ~1M-tweak backlog independently. Make it a commutative merge like Ark: - mergeAlways: true, so it merges live and from older snapshots too. - lastSpScan takes the MAX (monotonic high-water mark, never regresses) — this is what makes the block catch-up run once across all devices. - spUtxos is an additive union by outpoint; a coin we already track is never mutated, and spend detection stays each device's own job (_refreshSpUtxos drops backend-spent coins), so stale merged-in coins self-heal on refresh. - Anti-entropy: republish our superset when we know more, guarded so it stops once devices converge. A manual rescan still works — it forces from=1 synchronously (no await before capturing it), so a concurrent max-merge can't sabotage the re-scan. Verified with a merge unit test driving the real extension (max/union/converge). Co-Authored-By: Claude Opus 4.8 <[email protected]>
* Fix silent-payment catch-up pegging the CPU (both threads)Adam Soltys2026-07-301-12/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | A wallet a few thousand blocks behind gets the whole scan window from the indexer at once (~1M tweaks over ~3900 mainnet blocks). The catch-up loop chunked by 100 BLOCKS, but the cost is one EC point-multiply per TWEAK and mainnet blocks are wildly uneven (up to 2565 tweaks each) — so a 100-block chunk could be ~25k tweaks, seconds of work that blew the worker's 30s timeout. On timeout the caller ran the SAME chunk inline on the main thread while the orphaned worker kept grinding it, pegging both threads and freezing the visible tab for the whole ~20min catch-up. Two fixes: - Chunk by tweak count (budget 2000, always ≥1 block) instead of block count, so every worker call stays sub-second regardless of block density. Verified against live mainnet data: max chunk drops from ~25k tweaks to ~2.8k (~850ms, <3% of the timeout). - On a worker-call timeout, TERMINATE the worker instead of leaving it grinding the orphaned request behind the caller's inline fallback — that double-grind was the both-threads-pegged symptom. _ensureSpWorker respawns a fresh worker on the next call. Diagnosed via CDP CPU profiling of the live tab (95% self-time in _spHitBlocks -> _spCandidate -> secp256k1 wNAF/precompute). Co-Authored-By: Claude Opus 4.8 <[email protected]>
* Stop pointless SP catch-up scansAdam Soltys2026-07-051-0/+10
| | | | | | | | | | | | | A gift-claimed wallet is a brand-new seed but the claim flow never passed generated:true, so every gift wallet ground through the indexer's full history (~336k tweaks) hunting silent payments it could not have received — the CPU burn seen with a fresh gift wallet open. Fresh claim wallets now fast-forward their scan watermark to the tip like any other generated wallet. And two tabs on the same wallet no longer duplicate a catch-up: a localStorage lease, refreshed per chunk, lets the second tab yield. Co-Authored-By: Claude Fable 5 <[email protected]>
* Chunk the silent-payment catch-up scanAdam Soltys2026-07-051-10/+26
| | | | | | | | | | | | | | | An imported mainnet wallet's first scan pulled the indexer's whole window (~336k tweaks, 25MB) and posted it to the worker as ONE message: it blew the 30s worker timeout, fell back to the inline main-thread loop (minutes of jank) while the worker kept grinding the orphaned request — the runaway CPU/memory users saw. The catch-up now processes 100-block chunks: each worker call is seconds, the scan watermark checkpoints after every chunk (an interrupted catch-up resumes instead of restarting from zero), buffers free as it goes, and the UI yields between chunks. Verified against the live indexer: full catch-up in ~5min of background work, main heap bounded (~80MB peak), no timeouts. Co-Authored-By: Claude Fable 5 <[email protected]>
* Features phase 2b: silent payments + nostr sync leave the core walletAdam Soltys2026-07-041-0/+467
wallet.js drops from 2,374 to ~1,970 lines, holding only BIP84 on-chain logic plus generic feature seams. New seams added this pass: registerBalanceExtra extra confirmed/pending buckets registerInputProvider extra spendable inputs for buildTx registerSendPreparer destinations needing post-selection derivation registerInputSigner non-BIP84 input signing registerHistoryProvider / registerScanHook / registerRealtimeHook / registerLoadHook / registerCacheExtension / registerCacheSavedHook src/features/sp-wallet.js: the whole BIP-352 engine — key derivation, worker-accelerated indexer scanning, the live indexer WebSocket, SP outputs as spendable inputs, sp1 send preparation, and per-output-key signing — installs via those seams (installSpWallet). src/features/sync.js: nostr identity + encrypted cross-device state sync plus its Settings card, installed via load/cache-saved/realtime hooks. profileChip/nostrProfile move here-adjacent (into gifts, the only other nostr consumer), so core app.js no longer imports nostr at all. buildTx/sign are now feature-agnostic (input providers + preparers + signers); _recomputeBalance* use the balance-extra registry, so a core build with no SP no longer calls a missing spBalance() (that regression dropped the minimal build into offline mode — caught by the smoke test). New coverage: tools/sp-test.js drives two browser "devices" through an SP send, indexer discovery, and an SP-input spend on the ark regtest chain (needs tools/sp-indexer.js pointed at bitcoind:18543). Minimal smoke now also asserts no SP/nostr code ships. Minimal profile: 314KB, down from 412KB (full: 580KB). All suites green: minimal smoke, sp-test, ark UI, gift lifecycle. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy