aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lightning.ts
Commit message (Collapse)AuthorAgeFilesLines
* lightning: don't wedge the listener on an already-credited preimageAdam Soltys2026-09-231-2/+8
| | | | | | | | Skip settlements whose preimage was already credited instead of retrying until the process exits, and reject previously used preimages when they are queued. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
* ln listener: skip a settlement whose account is gone before creditingAdam Soltys2026-09-051-0/+9
| | | | | | | | | | credit() now returns without writing for a missing user, but the listener's persistence check after credit() then threw and kept the cursor stuck. Check the account up front and skip like an unknown invoice, recording the preimage in `missing`. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y
* ln: bound receive-listener wait, phase-aware watchdog, re-enable health checkAdam Soltys2026-08-221-38/+104
| | | | | | | | | | | | | | | | Give waitanyinvoice an explicit 30s server-side timeout so a dead/half-open socket can no longer hold the listener indefinitely; CLN's 904 timeout during a quiet period is treated as a clean re-arm without counting as a failure. Split the listener into waiting vs processing phases so the watchdog never resets a healthy socket merely because a ledger write is slow, and never starts a second concurrent processor — a stalled processing phase is surfaced loudly instead. Process the settlement and confirm the durable payment pointer BEFORE advancing pay_index, so a store load/restart between the cursor write and credit() cannot drop a received payment. Expose listener status and add a backlog probe to the health check, and re-enable startHealthCheck(). Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01XiwgmQKwKnRxUmVDd4xSf7
* ln: tear down dead cl clients fully + recover invoice listener on socket deathAdam Soltys2026-08-151-0/+28
| | | | | | | | | | | | | | | | | Replace bare `client = null` with dropClient(): stop the clightning-client library's internal reconnect loop (clear reconnectTimeout, neuter reconnect, destroy the socket, drop listeners). A dead client was otherwise orphaned and spun forever retrying `connect ENOENT`, spamming logs and leaking a socket+timer on every cl restart. Guard the error handler on `c === client` so a stale client's late error can't drop a newer, healthy one. Add lnListen.onDrop so the invoice listener recycles immediately when its long-poll socket dies (bump epoch, re-arm) instead of waiting up to 5 minutes for the stall watchdog. Stop counting LightningUnavailableError toward the listener's process.exit escalation, so a cl restart no longer makes the app self-exit — it retries until cl returns. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* zaps: stop spurious "failed to handle zap" warnings on non-zap invoicesAdam Soltys2026-07-301-10/+21
| | | | | | | | | | | The zap dispatch parsed the invoice description and, when it wasn't JSON, suppressed the error only if the message contained "Unexpected" — V8's parse- error wording. On Bun the message is "Unable to parse JSON string", so every paid invoice with a non-JSON memo logged a warning. Parse-then-check instead: a non-JSON description is simply not a zap and is skipped silently; warn only when an actual kind-9734 zap request fails to process. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* mint/lightning: refuse caller-supplied invoices, tiered fees, log hygieneAdam Soltys2026-07-301-0/+10
| | | | | | | | | | | | | | | - invoices: reject caller-supplied bolt11/bolt12; the server always mints its own. Closes the invoice-registration path behind the shared-node credit and payment-hijack vectors. - lightning: skip mint-owned invoices (lbl* label) in the paid-invoice listener. - payments: lightning free-tier fee credit, withheld for flagged high-throughput (ln:nofree) accounts which pay an elevated rate; the failed-send reversal restores credit at the same rate. freezeCheck made crash-resilient. Lightning and bolt12 sends stay pending until the preimage settles. - payments (route): validate payment-request / invoice input types. - logging: collapse repeated xpay failure lines into one. Co-Authored-By: Claude Opus 4.8 <[email protected]>
* bolt12 zaps: pay offers, NWC pay/receive, per-user offers, NIP-44Adam Soltys2026-07-301-2/+6
| | | | | | | | | | | | | | | | - sendLightning fetches an invoice from lno1 offers (payer_note passthrough for NIP-177 zap intents) and pays it through the existing bolt12 path - NWC: new nwc#2 pay/receive methods (BIP-321 URIs, payer proofs stubbed until CLN 26.06 createproof), nip44_v2 alongside nip04 with per-request scheme detection, dual 23196/23197 notifications, 13194 refreshed when its content or encryption tag goes stale - standing per-user bolt12 offer via GET /offer; incoming bolt12 payments record invreq_payer_note as memo - parse/fetchinvoice routes handle offers; zap display parses kind 9736 receipts (amount tag + embedded intent) and drops a call to a sync() helper that never existed Co-Authored-By: Claude Fable 5 <[email protected]>
* lightning: watchdog only recycles on real backlog, not normal idleAdam Soltys2026-06-061-17/+24
| | | | | | | | | | | | | | | | | The zombie-listener watchdog (bd1ece38) treated "waitanyinvoice blocked > 5min while cl is alive" as a stall — but that's NORMAL during quiet periods, so it false-fired and needlessly recycled the cl listen socket every few minutes (~26x in 6h on 2026-06-07). Receives still worked, but it was churn + noise and would mask a genuine zombie. Fix: a blocked long-poll is only a zombie if cl actually has a paid invoice the listener isn't picking up. When blocked past the threshold, probe cl on the MAIN socket with waitanyinvoice(pay_index, 2s server-side timeout): if it returns an invoice there's a real backlog the wedged listener missed -> recycle; if it times out (CLN code 904 = nothing waiting) the listener is just idle and healthy -> leave it alone. Only recycle on a confirmed backlog. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* ln/lightning: watchdog recycles zombie receive-listener socketAdam Soltys2026-06-041-1/+65
| | | | | | | | | | | | | | | | | | | | | On 2026-06-04 cl restarted (autoheal, after its 15s healthcheck timed out), and the app's waitanyinvoice long-poll hung on the now-dead listen socket. listenerActive stayed true forever, so ensureListenerAlive never restarted it, and incoming lightning payments stopped crediting for ~2h until a manual app restart. The per-call RPC timeout in ln.ts can't catch this: waitanyinvoice is intentionally in NO_TIMEOUT (it's meant to block). Fix: ensureListenerAlive (runs every 120s) now also detects a stalled listener — active but blocked in waitanyinvoice for >5min. It probes cl via the main ln socket (getinfo); only if cl is actually alive does it treat the listen socket as a zombie, call lnListen.reset() (new: drops the proxy's socket so the next call reconnects), and re-arm. A listenerEpoch guard makes the wedged invocation bow out when its waitanyinvoice finally rejects, so we never run two listeners concurrently and never double-credit. Verified with a state-machine test covering normal receive, quiet-but-healthy (left alone), stall+cl-alive (recycled), stall+cl-down (left alone), and the no-double-listener race. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* lnurl proxyAdam Soltys2026-03-271-0/+2
|
* ensure lightning payments get processedAdam Soltys2026-03-191-0/+9
|
* listener logsAdam Soltys2026-03-181-1/+1
|
* remove logsAdam Soltys2026-03-171-2/+0
|
* health checkAdam Soltys2026-02-061-42/+103
|
* sendinvoice supportAdam Soltys2025-09-181-4/+6
|
* fix invoice lookupAdam Soltys2025-03-071-8/+2
|
* use getInvoice helperAdam Soltys2025-03-051-5/+9
|
* record payment_hashAdam Soltys2025-03-051-0/+2
|
* payment typesAdam Soltys2025-02-261-3/+4
|
* check if bolt11Adam Soltys2025-01-231-4/+2
|
* notes and stuffAdam Soltys2025-01-211-3/+9
|
* prettierAdam Soltys2025-01-141-8/+6
|
* handle zaps asynchronouslyAdam Soltys2025-01-061-2/+2
|
* fix bolt12Adam Soltys2024-12-261-3/+22
|
* bolt12 replayAdam Soltys2024-12-261-18/+15
|
* replay functionAdam Soltys2024-12-231-0/+53
|
* check for offersAdam Soltys2024-12-221-1/+1
|
* handle offersAdam Soltys2024-12-191-4/+6
|
* biome lintAdam Soltys2024-10-311-8/+14
|
* getpayment helperAdam Soltys2024-10-011-3/+2
|
* unused varsAdam Soltys2024-09-251-6/+2
|
* refactor rpc helper, accounts endpointsAdam Soltys2024-09-081-1/+1
|
* typescriptAdam Soltys2024-08-261-0/+52