aboutsummaryrefslogtreecommitdiffstats
path: root/tools
Commit message (Collapse)AuthorAgeFilesLines
* Gift claim: instant 'Payment received!' after claimingAdam Soltys2026-07-041-0/+7
| | | | | | | | | | | | Claiming into an existing wallet used to drop onto the Receive tab (address/QR visibly rotating) until the background scan noticed the credit and fired the celebration. The claim already knows it succeeded and for how much, so the celebration now shows immediately; the scan runs behind it and its receive-index advance is acknowledged so the generic celebration doesn't fire a second time. 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/+6
| | | | | | | | | "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/+82
| | | | | | | | | | | | 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: 'Sent!' screen matches the receive celebrationAdam Soltys2026-07-041-0/+2
| | | | | | | | Tap anywhere to proceed instead of a Done button, and the sent amount shows in red (amount-neg) rather than green. 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/+8
| | | | | | | | | | | 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: hide fee-rate, coin control, Max, and add-recipient for Ark sendsAdam Soltys2026-07-041-0/+5
| | | | | | | | | An arkoor send has no mining fee and no coin selection, so pasting an Ark address now shows just the amount field plus a hint line; the irrelevant on-chain controls stay hidden. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Ark: boarding success screen with txid link instead of a toastAdam Soltys2026-07-041-1/+5
| | | | | | | | | | Broadcasting a board now lands on a checkmark screen showing the amount that will arrive (after the board fee), a note about the confirmation, and the funding txid with copy + explorer link; Done returns to the Receive tab. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Ark: boarding lives on the Receive tab's Ark viewAdam Soltys2026-07-031-3/+10
| | | | | | | | | | | Selecting Ark on Receive now shows the address plus an inline "move on-chain funds into Ark" form (with available balance / minimum hints). The Settings card slims down to server choice, coin count, in-progress operations, and refresh/consolidate; the balance already shows on the balance card. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Ark: connect lazily — only dial the server once the wallet uses ArkAdam Soltys2026-07-031-2/+9
| | | | | | | | | | | Opening a wallet no longer contacts the ASP unless it already holds vtxos / history / unfinished operations. Fresh wallets connect on first use instead: selecting Ark on the Receive tab, confirming an Ark send, or the Connect button on the Settings card. connectArk() is idempotent and generation-guarded against wallet switches mid-dial. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
* Ark: show Ark movements in the History tabAdam Soltys2026-07-031-0/+7
| | | | | | | | | Receives, sends, and boards interleave with on-chain transactions in one time-sorted, paginated timeline, each tagged 'Ark'. Refreshes are internal churn and stay in the Settings activity list 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/+4
| | | | | | | | | 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: wire into the wallet UIAdam Soltys2026-07-032-0/+233
| | | | | | | | | | | | | | | | | | | | - Settings: Ark server card (off by default, per-network presets incl. Second mainnet + local regtest, custom URLs) with balance, coin count, board form (on-chain -> Ark; funding output pinned to vout 0 via the new buildTx noSort option), refresh/consolidate, and recent activity. - Receive: Ark option in the address-type dropdown (QR + copy). - Send: t?ark1 addresses are recognized in the normal send form and route to an Ark confirmation (no mining fee) with a success view. - Balance card: Ark balance line under the on-chain figure. - ArkManager lifecycle: per-wallet instance created on account activation, background sync every 5s (regtest) / 30s, state persisted under the wallet cache key. Verified end-to-end in a real browser (tools/ark/ui-test.js, puppeteer against the regtest stack): receive, send, board, and refresh all green. 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-035-0/+607
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* Merge branch 'master' into boltz-swapsAdam Soltys2026-06-281-0/+314
|\ | | | | | | | | | | # Conflicts: # src/api.js # src/app.js
| * Skip the mempool backlog on startup for large (mainnet) mempoolsAdam Soltys2026-06-271-0/+8
| | | | | | | | | | | | | | | | First mempool pass over a >200-tx mempool would fire thousands of getrawtransaction calls at the node in a burst. Mark the existing backlog seen and scan only new arrivals instead; small (regtest) mempools still scan fully. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Catch-up scaling: dust filter + per-block Bloom filtersAdam Soltys2026-06-271-7/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | silentpay.js: silentPaymentCandidate() (our P_0 for a tweak) + buildBloom/bloomHas (double-hashed sha256, ~0.8% FP). Validated: candidate == P_0 on all no-label vectors. Indexer /scan now returns, per block, the tweaks + a Bloom over that block's taproot output keys (no outputs), with an optional dustLimit. The wallet derives a candidate per tweak, tests the filter, and only fetches /block on a hit — so a big historical scan costs candidate math + a handful of fetches instead of downloading and scanning every block. Live WS pushes still carry full items. SP_DUST_LIMIT defaults to 0 (receive everything; the indexer honors any value). Verified end-to-end on regtest: the filter flow finds the output. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Gate mempool discovery behind SP_MEMPOOL (default on; off spares a busy node)Adam Soltys2026-06-271-2/+6
| | | | | | | | Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Mempool (unconfirmed) silent-payment discoveryAdam Soltys2026-06-271-9/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Indexer: scan the mempool (getrawmempool + getrawtransaction; prevouts fetched explicitly since verbosity-2 omits them for mempool txs), track SP-eligible unconfirmed txs, serve /mempool, and push {type:'mempool'} on change. Switched Core RPC to node:http (no keep-alive) + serialized calls — Bun's fetch was dropping sockets under the added mempool load. Wallet: handle the mempool push and /mempool catch-up (_scanSpMempool) — pending SP receipts rebuild on each update (also drops RBF'd/vanished ones); block pushes promote a pending entry to confirmed. So a silent payment shows the instant it's broadcast, like a normal receive, with no mining. Verified on regtest: an unconfirmed SP is detected and served; clean logs. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Indexer: SQLite persistence + instant ZMQ hashblock detectionAdam Soltys2026-06-271-26/+92
| | | | | | | | | | | | | | | | | | | | | | | | - Persist blocks/items to SQLite (SP_DB; defaults to in-memory) so the indexer resumes instead of re-walking the chain on restart — verified resume-from the stored height. - Subscribe to Core's hashblock ZMQ (SP_ZMQ) via a tiny pure-JS ZMTP/3.0 SUB client (no native dep, bundle stays self-contained) to trigger a sync the instant a block lands — measured ~200ms end-to-end vs the poll interval. Poll remains a backstop. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Push silent payments over WebSocket instead of pollingAdam Soltys2026-06-271-1/+18
| | | | | | | | | | | | | | | | | | | | | | | | The indexer now serves a /ws endpoint and publishes each newly-indexed block's SP items to subscribers. The wallet subscribes (_spConnect) and scans pushed items on arrival (_scanSpItems) — folding receipts into the balance instantly — catching up via /scan on connect/reconnect. Polling for SP is now only a fallback for when the socket isn't live. Verified on regtest: connect, mine a block, wallet receives the push. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Wire silent-payment receiving into the wallet (scan + balance + UI)Adam Soltys2026-06-271-0/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | wallet.js: scanSilentPayments() pulls the indexer's /scan range, matches outputs on-device, and verifies each is unspent via the chain backend; spUtxos + balance are tracked in their own bucket (one-time taproot keys), persisted in the cache. silentPaymentsAvailable()/spBalance() expose state. app.js: the Receive tab shows the reusable sp address (QR + copy), a 'Scan for silent payments' button, and the found amount; Settings gains a per-network SP indexer picker (under Data source) with custom/self-host support. sp-indexer.js: added /scan/{from} so a client fetches a whole range in one request instead of one fetch per block. Receiving verified end-to-end on regtest (scan finds the output, 49,999,800 sat confirmed). Spending SP outputs is the remaining piece. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| * Add regtest SP tweak indexer; accept Core's array-witness in inputPubKeyAdam Soltys2026-06-271-0/+118
| | | | | | | | | | | | | | | | | | | | | | | | | | | | tools/sp-indexer.js: a minimal BIP-352 oracle (Bun) that walks Core and serves, per block, one entry per eligible tx — the tweak (input_hash*A) plus that tx's taproot outputs — for the wallet to scan on-device. Shares src/silentpay.js so the tweak math is the vector-validated code. Added to the regtest compose as the 'sp' service (oven/bun, pointed at bc:18443). inputPubKey now accepts a witness as either serialized hex (vectors) or an array of stack items (Core getblock RPC). Verified end-to-end on regtest: a real SP payment is indexed and the scan recovers the output, value, and spend tweak. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* | Merge branch 'master' into boltz-swapsAdam Soltys2026-06-271-0/+44
|\| | | | | | | | | # Conflicts: # src/app.js
| * Regtest realtime via a local Electrum-over-WebSocket bridgeAdam Soltys2026-06-271-0/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | On regtest there's no realtime push (coinos watcher is mainnet-only), so the UI only updated on the 5–10s poll — a funded tx took a while to appear and a just-mined block stayed "pending" until the next reconcile. electrs speaks the Electrum protocol the watcher already understands, but only over TCP; route it through a small WS<->TCP bridge (see coinos-server/electrum-ws) so the wallet subscribes scripthashes and reconciles instantly on each notification. Data still comes from esplora; this only adds the push channel. Configurable in Settings (default ws://localhost:50003); falls back to polling if unreachable. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* | Add Boltz submarine + reverse swaps (Lightning <-> on-chain)Adam Soltys2026-06-275-0/+276
|/ | | | | | | | | | | | | | | | | | | | Non-custodial swaps via Boltz, fully client-side: hal holds the swap key + preimage and claims (reverse) / refunds (submarine) on-chain via the taproot script path, so Boltz can never strand funds. - src/swap.js: tapleaf/tree construction (byte-exact vs boltz-core vectors), swap P2TR address derivation (MuSig2 internal key + taptweak), script-path claim/refund tx builder, bolt11 decode, Boltz api-v2 client, and a polling SwapManager (reverse auto-claim; submarine fund + status + refund). - wallet.js: deterministic swap-key derivation (dedicated chain) + persistence. - api.js: configurable Boltz REST/WS endpoints. - app.js: ⚡ Swap tab — Receive over LN (reverse) + Pay an invoice (submarine). - tools/swap-*.test.js: vectors, live-address, and end-to-end regtest tests. Verified end-to-end on regtest against a local Boltz wired to coinos's bc + a dedicated CLN/hold node. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* Confirm transactions via the WebSocket push, not RESTAdam Soltys2026-06-251-4/+6
| | | | | | | | | | The watcher's block (rawblock) push now carries confirmed=true + the block time, and _applyTxNotification flips the matching history row and coins from pending to confirmed directly — for incoming and outgoing txs (flag-only, so no overcount). Confirmations no longer wait on a mempool.space reconcile; the 30s backstop poll just fills in block height / fee afterward. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* Credit payments instantly from the watcher push (no REST on critical path)Adam Soltys2026-06-251-14/+26
| | | | | | | | | | | | | | | | | | The watcher push now carries the tx data (matched outputs + confirmed flag), so the app credits an incoming payment the moment the push arrives — no mempool.space round-trip. This removes the rate-limited REST reconcile from the path a user actually waits on, and lets us back the frontier poll way off when the socket is live (30s backstop vs the old 3s receive-tab hammer), cutting the 429s to a trickle. - watcher: notification includes { txid, confirmed, outputs:[{vout,value}] }. - wallet: _applyTxNotification credits the receive coin + a pending history row optimistically (receives only; change reconciles in the background), advances the frontier, updates the balance, and schedules a background reconcile for full accuracy off the critical path. - poll intervals relaxed now that the WS does the real work instantly. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* Realtime via self-hosted ZMQ watcher (Electrum-over-WS)Adam Soltys2026-06-251-0/+257
Replace the unreliable public WebSocket push (mempool/blockchain.info address subscriptions never reliably fire) with a private notification service: - tools/zmq-watcher.js: a standalone Bun service (reusing coinos lib/zmq.ts's ZMTP subscriber) that reads Bitcoin Core's ZMQ rawtx/rawblock, computes the scripthash of each output, and pushes a blockchain.scripthash.subscribe notification to subscribed clients. No historical index (~24MB RAM) — just the live tx stream. Runs on the coinos box reading its Core's ZMQ. - wallet.js: realtime client now speaks the Electrum protocol (server.version, scripthash.subscribe, server.ping) over the WS; any scripthash notification triggers the existing refreshLive() (REST stays the source of truth). - api.js: wsUrl -> wss://coinos.io/electrum. Verified end-to-end: live mempool txs to subscribed addresses notify instantly. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>