Compare commits

..

7 commits

Author SHA1 Message Date
Patrick Mulligan
eb0278a82c fix: use fresh balance in PayAppUserInvoice notification
Some checks failed
Docker Compose Actions Workflow / test (push) Has been cancelled
notifyAppUserPayment was sending the stale cached balance from the
entity loaded before PayInvoice decremented it. Update the entity's
balance_sats from the PayInvoice response so LiveUserOperation events
contain the correct post-payment balance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:53:39 -05:00
Patrick Mulligan
fe4046a439 chore: update Docker build and dependencies
- Add .dockerignore for runtime state files (sqlite, logs, secrets)
- Bump Node.js base image from 18 to 20
- Add @types/better-sqlite3 dev dependency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:53:39 -05:00
Patrick Mulligan
1f4157b00f fix: correct nip44v1 secp256k1 getSharedSecret argument types
The @noble/curves secp256k1.getSharedSecret expects Uint8Array arguments,
not hex strings. Use hex.decode() to convert the private and public keys.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-28 07:53:39 -05:00
Patrick Mulligan
66b1ceedef feat(extensions): add getLnurlPayInfo to ExtensionContext
Enables extensions to get LNURL-pay info for users by pubkey,
supporting Lightning Address (LUD-16) and zap (NIP-57) functionality.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-28 07:53:39 -05:00
Patrick Mulligan
e6a4994213 docs(extensions): add comprehensive extension loader documentation
Covers architecture, API reference, lifecycle, database isolation,
RPC methods, HTTP routes, event handling, and complete examples.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-28 07:53:39 -05:00
Patrick Mulligan
86baf10041 feat(extensions): add extension loader infrastructure
Adds a modular extension system for Lightning.Pub that allows
third-party functionality to be added without modifying core code.

Features:
- ExtensionLoader: discovers and loads extensions from directory
- ExtensionContext: provides extensions with access to Lightning.Pub APIs
- ExtensionDatabase: isolated SQLite database per extension
- Lifecycle management: initialize, shutdown, health checks
- RPC method registration: extensions can add new RPC methods
- Event dispatching: routes payments and Nostr events to extensions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-28 07:53:39 -05:00
Patrick Mulligan
7973fa83cb fix(nostr): close SimplePool after publishing to prevent connection leak
Some checks failed
Docker Compose Actions Workflow / test (push) Has been cancelled
Each sendEvent() call created a new SimplePool() but never closed it,
causing relay WebSocket connections to accumulate indefinitely (~20/min).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:53:09 -05:00

View file

@ -205,6 +205,7 @@ export class NostrPool {
const log = getLogger({ appName: keys.name }) const log = getLogger({ appName: keys.name })
this.log(`📤 Publishing Kind ${event.kind} event to ${relays.length} relay(s): ${relays.join(', ')}`) this.log(`📤 Publishing Kind ${event.kind} event to ${relays.length} relay(s): ${relays.join(', ')}`)
const pool = new SimplePool() const pool = new SimplePool()
try {
await Promise.all(pool.publish(relays, signed).map(async p => { await Promise.all(pool.publish(relays, signed).map(async p => {
try { try {
await p await p
@ -220,6 +221,9 @@ export class NostrPool {
} else { } else {
this.log(`✅ Kind ${event.kind} event published successfully (id: ${signed.id.slice(0, 16)}...)`) this.log(`✅ Kind ${event.kind} event published successfully (id: ${signed.id.slice(0, 16)}...)`)
} }
} finally {
pool.close(relays)
}
} }
private getRelays(initiator: SendInitiator, requestRelays?: string[]) { private getRelays(initiator: SendInitiator, requestRelays?: string[]) {