<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinos-server.git/lib/nwc.ts, branch regtest-fulcrum</title>
<subtitle>coinos server — legacy coinos.io backend (Lightning, on-chain, Liquid)</subtitle>
<id>https://git.coinos.io/coinos-server.git/atom?h=regtest-fulcrum</id>
<link rel='self' href='https://git.coinos.io/coinos-server.git/atom?h=regtest-fulcrum'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/'/>
<updated>2026-06-06T16:10:16Z</updated>
<entry>
<title>nwc: fix pay_invoice reply reliability, rate-limit drops, notifications</title>
<updated>2026-06-06T16:10:16Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-06-06T16:10:16Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=8cb1882111c079cfac9870054d9917fa5f94de76'/>
<id>urn:sha1:8cb1882111c079cfac9870054d9917fa5f94de76</id>
<content type='text'>
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 -&gt; 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) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>nwc: pay_invoice honors request amount for amountless bolt11</title>
<updated>2026-06-05T01:40:42Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-06-05T01:40:42Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=ce9616f62d0ac682c1e92956ef4cb48f053df27d'/>
<id>urn:sha1:ce9616f62d0ac682c1e92956ef4cb48f053df27d</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>nwc: fix make_invoice timestamps (ms -&gt; seconds) breaking NWC clients</title>
<updated>2026-06-05T01:19:25Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-06-05T01:19:25Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=0154bb060fad7650cd8b825a30a5d88e7018bf8d'/>
<id>urn:sha1:0154bb060fad7650cd8b825a30a5d88e7018bf8d</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>nwc: publish 13194 info event only when missing, recheck hourly</title>
<updated>2026-06-03T04:23:27Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-06-03T04:23:27Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=6372d9185021aeb379e8c67386ba72f7b0aa4bdd'/>
<id>urn:sha1:6372d9185021aeb379e8c67386ba72f7b0aa4bdd</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>nwc: handle stale client state cleanly and skip reverted-duplicate records</title>
<updated>2026-05-18T06:21:39Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-05-18T06:19:25Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=3b7a1efaa1040de29d97640b371f24b41a6562a0'/>
<id>urn:sha1:3b7a1efaa1040de29d97640b371f24b41a6562a0</id>
<content type='text'>
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) &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>nwc heartbeat</title>
<updated>2026-03-30T06:40:15Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-03-30T06:40:15Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=51428790ea558f8e34c3034e75d2e49a076261b8'/>
<id>urn:sha1:51428790ea558f8e34c3034e75d2e49a076261b8</id>
<content type='text'>
</content>
</entry>
<entry>
<title>stop republishing primal events</title>
<updated>2026-03-18T08:34:41Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-03-18T08:34:41Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=f677540cf8548a03fb354536ec70b6186e812eae'/>
<id>urn:sha1:f677540cf8548a03fb354536ec70b6186e812eae</id>
<content type='text'>
</content>
</entry>
<entry>
<title>adjust ln minfee</title>
<updated>2026-03-15T22:49:17Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-03-15T22:49:17Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=74af7b1d0922e740c0358dfd131776fd7c877767'/>
<id>urn:sha1:74af7b1d0922e740c0358dfd131776fd7c877767</id>
<content type='text'>
</content>
</entry>
<entry>
<title>consult archive for older payments</title>
<updated>2026-01-30T20:31:59Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-01-30T20:31:59Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=edd76a99a90d56ab641c48b95dd5891558baa133'/>
<id>urn:sha1:edd76a99a90d56ab641c48b95dd5891558baa133</id>
<content type='text'>
</content>
</entry>
<entry>
<title>relay reconnect logic</title>
<updated>2026-01-30T17:18:39Z</updated>
<author>
<name>Adam Soltys</name>
<email>asoltys@gmail.com</email>
</author>
<published>2026-01-30T17:18:39Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinos-server.git/commit/?id=3e2b756e5b97db690b9a707049060805ca88c9de'/>
<id>urn:sha1:3e2b756e5b97db690b9a707049060805ca88c9de</id>
<content type='text'>
</content>
</entry>
</feed>
