| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
wallet.js drops from 2,762 to 2,374 lines and now exposes two generic
seams instead of feature code:
- registerCoinLock()/lockedCoinIds(): features contribute coin ids that
spending and the balance treat as unavailable (gift reservations).
- loadFeatureState()/saveFeatureState(): namespaced per-wallet persisted
state.
src/features/gifts-wallet.js takes the whole gift engine — reservation
sets, gift records, coin selection, the SIGHASH_SINGLE/NONE PSBT
builder, the compact codec, claim building, nostr-locked gifts — as an
installGiftWallet(wallet) instance install plus standalone exports.
Swap storage/key helpers (loadSwaps/saveSwaps/swapNode/nextSwapIndex)
install from swap.js; ark state storage installs from the ark feature.
The silent-payment scan worker only embeds when the sp feature ships
(wallet.js already tolerated its absence).
Minimal profile: 412KB, down from 476KB (full: 578KB). All suites pass:
ark UI e2e, ArkManager crash-resume, gift lifecycle, minimal smoke.
SP's engine (scanning, BIP-352 signing) stays in wallet.js — extracting
it safely wants an SP e2e harness on this stack first.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
|
| |
A reverse-swap claim is an on-chain receive, so instead of a separate LN
'Received!' card (which stacked with the generic celebration and needed
suppression), credit the claimed coin to the wallet the instant we broadcast the
claim — new wallet.creditReceive() mirrors the instant-payment watcher path
(adds the utxo + pending row, advances the receive index, emits). The generic
'Payment received!' then fires immediately with the right amount, one screen, one
tap. Dropped the LN success card + the suppression logic.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A reverse swap's preimage is sha256(swapNode(idx).privateKey) — deterministic per
index. nextSwapIndex was derived only from *saved* swaps, so an attempt that
created the swap at Boltz but threw before saving (e.g. the lockup-address-mismatch
bug) never advanced the index; the next try reused the same preimage and Boltz
rejected it ('a swap with this preimage hash exists already').
Make nextSwapIndex a persisted, monotonic counter (reserves the index on every
call, seeded from saved swaps), and have startReverse retry with the next index
when Boltz reports the preimage already exists — which also recovers wallets
already stuck on a burned index.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
swapP2TR resolves the network via netFor(name) → NETS[name] || btc.NETWORK, but
NETS had no mutinynet entry, so it fell back to MAINNET — Hal computed a bc1p…
swap address while Boltz (bitcoinSignet) returns tb1p…, tripping 'lockup address
mismatch — not paying'. Add mutinynet: btc.TEST_NETWORK (signet/testnet params,
matching the wallet's own netCfg).
Verified: swapP2TR now derives tb1p… for mutinynet (was bc1p…).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Send: show only the destination input ('Address or Lightning invoice') until a
valid on-chain/SP address is entered, then reveal amount + fee rate + coin
selection + Review. A pasted bolt11 still auto-advances to its own confirmation,
so those controls never appear for it. New wallet.isOnchainAddress() validator +
a destReady() gate; recipient onInput/paste re-render only when validity flips.
- History: stop listing swaps at the top. Instead, a send/receive that was part of
a swap shows its Lightning context (invoice, swap fee, status, refund) on the tx
detail screen via swaps.findByTxid(). Removed the dead swapListView.
- Lightning receive: drop the '50000' amount placeholder — a bare number looked
like a value was already entered; the min/max hint below covers it.
Verified in-browser: controls hidden until a valid address, then revealed; LN
receive placeholder empty; no errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Paste a bolt11 into the normal Send recipient field and Review now detects it and
routes through a Boltz submarine swap — no 'swap' concept surfaced. Split
startSubmarine into quoteSubmarine (POST + build-but-don't-broadcast the funding
tx) and fundQuotedSubmarine, so the review shows an itemized cost before
committing: Amount + Boltz fee + on-chain network fee = Total. Pay funds the
lockup; Boltz pays the invoice once it confirms.
Verified on regtest: a 60,000-sat invoice quotes to Amount 60,000 / Boltz 362 /
network 442 / Total 60,804, with a Pay button.
Lightning-address (LNURL) input + removing the standalone Swap tab are the
remaining pieces.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
A submarine swap's success is invoice.paid — Boltz has paid the Lightning invoice,
which is the whole point and irreversible. Boltz then claims its on-chain lockup
(transaction.claim.pending → claimed), often deferred to a later batch, so the old
done-set ({transaction.claimed, invoice.settled}) left Hal stuck showing
'paying / waiting for Boltz to pay' indefinitely after the payment had already
gone through. Add invoice.paid + transaction.claim.pending to the done set.
Verified: a live swap stuck at transaction.claim.pending flips to 'success ·
Invoice paid ✓' after the fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
hardcoded 50k
doReverse rejected anything under a hardcoded 50,000 sats — which happens to be
the regtest provider's minimum, but mainnet boltz's real minimum is 25,000 (and
providers/networks differ), so valid 25k-50k mainnet swaps were refused and the
max was unchecked client-side.
Add SwapManager.reverseLimits() (GET /v2/swap/reverse, cached per API) and use it
in the swap UI: show the real min/max range under the amount field and validate
against it. Reset the cached limits when the network or provider changes.
Verified: regtest min/max 50,000/40,294,967; mainnet 25,000/25,000,000.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
|
|
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]>
|