When userPubkey is provided, resolve the ApplicationUser and call
applicationManager.PayAppUserInvoice instead of paymentManager.PayInvoice
directly. This ensures notifyAppUserPayment fires, sending
LiveUserOperation events via Nostr for real-time balance updates.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Store the Nostr pubkey of the user who creates a withdraw link so the
LNURL callback debits the correct user's balance instead of the app
owner's. Pass userPubkey through from RPC handler to WithdrawManager.
- Add creator_pubkey column (migration v4)
- Store creatorPubkey on link creation
- Pass creator_pubkey to payInvoice on LNURL callback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Initialize extension system before nostrMiddleware so registered
RPC methods are available. Extension methods (e.g. withdraw.createLink)
are intercepted and routed to the extension loader before falling
through to the standard nostrTransport.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add POST /api/v1/withdraw/create endpoint to allow external apps (ATM,
web clients) to create LNURL-withdraw links via HTTP instead of RPC.
Changes:
- Add handleCreateWithdrawLink HTTP handler
- Fix route ordering: callback routes before wildcard :unique_hash
- Extract app_id from Authorization header (Bearer app_<id>)
- Use is_unique=false for simple single-use ATM links
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enable CORS on the extension HTTP server to allow cross-origin requests
from ATM apps and other web-based clients.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add extension loader initialization to startup
- Create mainHandlerAdapter to bridge mainHandler with extension context
- Mount extension HTTP routes on separate port (main port + 1)
- Configure EXTENSION_SERVICE_URL for LNURL link generation
The withdraw extension provides LUD-03 LNURL-withdraw support for
creating withdraw links that allow users to pull funds.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements LUD-03 (LNURL-withdraw) for creating withdraw links
that allow anyone to pull funds from a Lightning wallet.
Features:
- Create withdraw links with min/max amounts
- Quick vouchers: batch creation of single-use codes
- Multi-use links with wait time between uses
- Unique QR codes per use (prevents sharing exploits)
- Webhook notifications on successful withdrawals
- Full LNURL protocol compliance for wallet compatibility
Use cases:
- Faucets
- Gift cards / prepaid cards
- Tips / donations
- User onboarding
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- 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>
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>
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>
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>
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
1 changed files with 17 additions and 13 deletions