feat(extensions): add LNURL-withdraw extension #6

Merged
padreug merged 8 commits from feature/withdraw into dev 2026-04-02 19:05:20 +00:00

8 commits

Author SHA1 Message Date
Patrick Mulligan
68c71599f8 fix(lnd): allow self-payments for LNURL-withdraw
Some checks failed
Docker Compose Actions Workflow / test (push) Has been cancelled
When the user's wallet (e.g. Zeus) is connected to the same LND node
that LP uses, LNURL-withdraw fails because LND rejects the payment
with "no self-payments allowed". This is safe because LP always
decrements the user's balance before paying and refunds on failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
5aaa3bcc23 feat(extensions): pay from caller's balance via PayAppUserInvoice
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>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
cb9fb78eb8 feat(withdraw): track creator pubkey on withdraw links
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>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
1273da9020 feat: route Nostr RPC to extension methods
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>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
3ee8b6b010 feat(withdraw): add HTTP API for creating withdraw links
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>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
f06d50f227 feat(server): add CORS support for extension HTTP routes
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>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
e998762ca7 feat: integrate extension system with withdraw extension support
- 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>
2026-04-02 14:48:55 -04:00
Patrick Mulligan
8de5e4fd3a feat(extensions): add LNURL-withdraw extension
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>
2026-04-02 14:48:55 -04:00