feat(api): unified POST /pay endpoint for any lightning destination#13
Merged
martinsaposnic merged 2 commits intomasterfrom May 6, 2026
Merged
feat(api): unified POST /pay endpoint for any lightning destination#13martinsaposnic merged 2 commits intomasterfrom
martinsaposnic merged 2 commits intomasterfrom
Conversation
Adds POST /pay alongside the existing /payinvoice. Accepts BOLT11,
BOLT12 offers, LNURL, and lightning addresses; resolves them via
bitcoin-payment-instructions; dispatches through ldk-node.
Behavior:
- Blocks by default (30s, hard-capped at 50s for ALB/CloudFront idle).
- waitForPaymentSecs=0 short-circuits (fire-and-return PENDING).
- Reads PaymentDetails after wake-up so paymentHash/preimage/feeSat/status
match GET /payments/outgoing/{paymentId}.
- Subscribes to MdkClient events BEFORE dispatch to avoid losing fast
failures. Lagged receivers retry; closed sender treated as PENDING.
- Pre-dispatch and resolver errors return ApiError; PayResponse{failed}
is reserved for payments LDK accepted then later failed.
- Mirrors lightning-js's malicious-LNURL amount check.
- payerNote/quantity rejected on BOLT11 destinations.
bitcoin-payment-instructions pinned to the same git rev that ldk-node
already pulls transitively, so no duplicate compilation.
Tests cover input validation, LNURL transport failure, malicious LNURL
amount mismatch (wiremock), dispatch failure, blocked-until-succeeded,
and wait=0 short-circuit.
/payinvoice is unchanged.
amackillop
approved these changes
May 6, 2026
Contributor
|
Need to do a followup to start porting the core logic into the library to prepare for lightning-js transition |
Contributor
Author
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
POST /payalongside the existing/payinvoice. Accepts BOLT11, BOLT12 offers, LNURL, and lightning addresses (resolved viabitcoin-payment-instructions).waitForPaymentSecs=0short-circuits to fire-and-returnPENDING.PaymentDetails, not events — fields stay 1:1 consistent withGET /payments/outgoing/{paymentId}(preimage, feeSat, status). Pre-dispatch and resolver errors returnApiError;PayResponse{failed}is reserved for payments LDK accepted then later failed.payerNote/quantityon BOLT11 destinations.bitcoin-payment-instructionspinned to the same git revldk-nodealready pulls transitively to avoid duplicate compilation./payinvoiceis unchanged.Test plan
nix run .#integration-test(CI) — runs newtest_pay_*block alongside existing tests:curl -u :PASSWORD -d "destination=lnbcrt..." -d "amountSat=1000" http://localhost:.../payDeferred to vNext
https://, needs HTTPS test server)Notes
bitcoin-payment-instructions's HTTP resolver reports both connect-time errors and JSON parse errors with the same"Failed to fetch ..."string, so unparseable LNURL responses currently surface as 500 (not 400 as the original spec contemplated). Library patch needed to differentiate.vss-server, so I couldn't run the integration tests locally. Relying on CI.🤖 Generated with Claude Code