| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
publishInfo sent the kind-13194 info event over the long-lived NWC socket
fire-and-forget. The nostr lib Relay.send is async (await wait_connected; ws.send)
but was called without await, and success was logged immediately. A send that
rejected (e.g. ws in CLOSING state during a strfry reconnect) was silently
dropped while the log claimed success, leaving NWC clients with "no info event"
until a manual republish.
Publish over a fresh short-lived socket and wait for the relay OK, retrying up to
3x with honest logging (warn on unconfirmed, err on give-up). ensureInfos
receive-based detection is unchanged. Verified on prod: deleted both info events,
restarted, both republished within seconds.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Three issues reported by an NWC client integrator (refs #80):
(a) pay_invoice sync reply: the handler polled listpays for ~20s then returned
a misleading "Payment timed out" error on slow routes even though the payment
settled — client never got the preimage. sendLightning already runs xpay to
completion and finalize() sets p.ref = preimage, so return that directly; keep
a longer listpays loop only as a fallback, and on still-in-flight return an
explicit "check with lookup_invoice" rather than implying failure.
(b) rate limiting: raised per-pubkey cap 5/min -> 60/min (normal usage — a
balance check + payment + a few lookup_invoice reconciles — trivially exceeded
5), and over-limit requests now get a NIP-47 RATE_LIMITED error reply instead
of a silent drop that looked exactly like a lost reply. Also: every request
path now always sends a 23195 reply (success, error, or handler-returned-
nothing) so a client never hangs waiting.
(c) notifications: payment_received/payment_sent are advertised in the info
event but app.notify defaulted to false unless the client sent notify:"true"
(only ~1% of apps had it on), so they never fired. Default notify ON; only
disable when explicitly "false". (Existing apps still false — backfill TBD.)
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
pay_invoice derived the amount solely from the decoded invoice, so an
amountless bolt11 yielded amount = round(undefined/1000) = NaN and
sendLightning rejected it with "Invalid amount". NIP-47 allows the client
to specify the amount (msat) in the request for exactly this case (AlbyHub
supports it; Alby Go and others hit the error). Fall back to the request's
`amount` field when the invoice carries none; invoice amount still takes
precedence when present, and a still-missing amount returns a clear error
instead of NaN. sendLightning/sendInternal already handle amountless
invoices given a valid amount — the bug was only the handler dropping it.
Fixes #83
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
generate() stores `created` in milliseconds (Date.now()), but the NWC
make_invoice response returned it directly as created_at and computed
expires_at = created_at + expiry. NWC timestamps are Unix SECONDS (NIP-47),
so clients parsed a ~1.78e12 expires_at that overflowed their date types —
e.g. ptcpay's .NET DateTimeOffset, whose max is 253402300799 (issue #84:
"creating lightning invoices via NWC fails ... Valid values are between
-62135596800 and 253402300799"). Convert created to seconds before use.
The other NWC handlers were already correct (lookup_invoice reads seconds
straight from cln; list_transactions divides p.created by 1000). Only
make_invoice leaked milliseconds.
Fixes #84
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
NWC clients (Alby Go, Lightning Piggies) fetch the kind 13194 info event
(capability advertisement) before they'll talk to the wallet; without it
they report "no info event" and show an unknown balance. The events went
missing after strfry restarted on 2026-05-29 and stayed gone for days,
because the app only published them once in the relay's on-open handler
and nothing re-asserted them.
13194 is a replaceable event meant to persist, so instead of blindly
republishing, query the relay on connect and publish only the server
pubkeys whose info event is actually missing (ensureInfo). Re-check
hourly so a relay restart that leaves our socket intact also self-heals.
Interval is cleared on close/reconnect alongside the heartbeat to avoid
leaks.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Three small NWC robustness fixes that surfaced from the Apr 29
double-credit cleanup:
- fail loudly when an NWC request references a pubkey whose user record
no longer exists (migrated/deleted account); previously crashed inside
handle() on `user.id`
- swallow `pubkey not found` and `user not found` in the per-event catch
so deleted-app/migrated-user spam doesn't fill the error log — these
are client-side staleness, not server faults
- use gf() instead of g() when fetching payment records (consistent with
the rest of the codebase: arc fallback for wiped main-db pointers)
- filter `revertedDuplicate` payments out of list_transactions so
clients never see the doubled records that were later reverted
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|