Skip to content

Conversation

@dolcalmi
Copy link

@dolcalmi dolcalmi commented Jul 11, 2025

@openoms
Copy link

openoms commented Jul 15, 2025

One main question:
Shall the https://example.com/verify/894e7f7e... link be implemented for the completeness of LUD21 support?

Have run the pull request review through Augment, here is the answer:


Pull Request Review: LUD-21 Support for Verifying LNURL-pay Payments
Overview
This PR implements LUD-21 (Lightning Network URL Protocol 21) which allows verification of LNURL-pay payments by providing payment preimages when invoices are paid. This is a significant enhancement that enables payment verification for LNURL-pay flows.

What LUD-21 Does
LUD-21 extends the existing LNURL-pay payment status endpoints to include the payment preimage (paymentPreimage) in the response when a payment has been successfully completed. This allows clients to cryptographically verify that a payment was actually made by checking the preimage against the payment hash.

Key Changes

  1. Core Implementation
    New functionality: Added getPreImage() method to PaymentStatusChecker that retrieves preimages using getInvoicePreImageByHash
    GraphQL Schema Updates: Added paymentPreimage field to LnInvoicePaymentStatus and LnInvoicePaymentStatusPayload types
    Query/Subscription Updates: Modified all payment status queries and subscriptions to include preimage when payment is completed
  2. API Endpoints Enhanced
    The following endpoints now return payment preimages for paid invoices:

lnInvoicePaymentStatusByHash (query)
lnInvoicePaymentStatusByPaymentRequest (query)
lnInvoicePaymentStatus (query)
All corresponding subscription endpoints
3. Testing
Added comprehensive test coverage in bats/tests/public-ln-receive.bats
Tests verify that preimage is null for pending payments and non-null for paid payments
Updated helper functions to validate preimage presence
Technical Implementation Review
✅ Strengths
Proper Error Handling: The implementation correctly handles errors when retrieving preimages and propagates them appropriately through the GraphQL error system.
Consistent API Design: The paymentPreimage field is consistently added across all relevant GraphQL types and endpoints.
Backward Compatibility: The changes are additive - existing clients will continue to work, and the new field is optional.
Comprehensive Testing: Good test coverage including both positive and negative test cases.
Security Considerations: Preimages are only returned for paid invoices, which is the correct behavior.
⚠️ Areas of Concern
Missing LNURL-pay Integration: While the PR adds preimage support to payment status endpoints, I don't see the actual LNURL-pay callback endpoint (/lnurlp/[username]/callback) being modified to support the LUD-21 verify flow. LUD-21 typically requires a separate verify endpoint or parameter.
No Verify Endpoint: LUD-21 usually specifies a dedicated verify endpoint (e.g., /lnurlp/[username]/verify) that clients can call to verify payments. This doesn't appear to be implemented.

✅ Previously Missed Implementation Details
Verify Endpoint: The verify URL is properly constructed and included in LNURL-pay callback responses
Payment Hash Integration: The verify URL includes the payment hash as required by LUD-21
Complete Flow: Clients can now use the verify URL to check payment status and retrieve preimages

Specification Compliance: Without seeing the actual LUD-21 specification implementation in the LNURL-pay flow, it's unclear if this fully implements the standard.
🔍 Questions for Clarification
LNURL-pay Integration: How does this integrate with the actual LNURL-pay flow? Does the callback response now include verify information?
Verify Endpoint: Is there a separate verify endpoint being added, or is verification handled through the existing payment status endpoints?
Client Usage: How would a client use this to verify an LNURL-pay payment in practice?
Code Quality Assessment
The code quality is generally good:

Clean separation of concerns
Proper TypeScript typing
Consistent error handling patterns
Good test coverage
Recommendations
Documentation: Add documentation explaining how clients should use this for LUD-21 verification.
LNURL-pay Integration: Ensure the LNURL-pay callback properly advertises verification capabilities according to LUD-21.
Specification Reference: Include a link to the LUD-21 specification in the PR description for context.
Conclusion
This is a solid implementation of the payment preimage functionality needed for LUD-21. The code is well-structured and properly tested. However, the review would benefit from seeing how this integrates with the actual LNURL-pay flow to ensure full LUD-21 compliance.

Recommendation: Approve with minor suggestions for documentation and clarification on the complete LNURL-pay integration.

@john-zaprite
Copy link

[Augment] I don't see the actual LNURL-pay callback endpoint (/lnurlp/[username]/callback) being modified to support the LUD-21 verify flow. LUD-21 typically requires a separate verify endpoint or parameter.
No Verify Endpoint: LUD-21 usually specifies a dedicated verify endpoint (e.g., /lnurlp/[username]/verify) that clients can call to verify payments. This doesn't appear to be implemented.

Looks like it's constructed here…

const verifyUrl = `${protocol}://${hostname}${portString}/lnurlp/${username}/verify/${invoice.paymentHash}`

And included in the response…

@john-zaprite
Copy link

Also, one thing to check is that the preimage is returned in hex and not base64?

@openoms
Copy link

openoms commented Jul 15, 2025

Also, one thing to check is that the preimage is returned in hex and not base64?

the preimage is referenced as the hex-encoded preimage (32 byte) in LND: https://lightning.engineering/api-docs/api/lnd/invoices/settle-invoice/#code-samples
and also mentioned as that in the LNURL specs in: https://github.com/lnurl/luds/blob/227f850b701e9ba893c080103c683273e2feb521/10.md?plain=1#L57
So I think it is correct to return it as hex, would you expect it in base64 for some reason?

Copy link

@openoms openoms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected that the verify link is also implemented so LUD21 is fully covered

@john-zaprite
Copy link

So I think it is correct to return it as hex, would you expect it in base54 for some reason?

Sorry, my comment was confusing. I was just making sure it was in hex, so that's perfect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants