gl-sdk: Add LNURL pay, withdraw, and address resolution#701
Draft
gl-sdk: Add LNURL pay, withdraw, and address resolution#701
Conversation
Build out gl-client's lnurl module as a complete LNURL protocol library. This lays the foundation for exposing LNURL support through gl-sdk in subsequent commits. Changes: - Make lnurl sub-modules public so gl-sdk can access the types - Add lnurl_encode() for bech32 LNURL encoding (LUD-01) - Add SuccessAction enum with Message/Url/Aes variants (LUD-09/10) - Add ProcessedSuccessAction and SuccessAction::process() for AES decryption using the payment preimage - Add LnUrlResponse enum and LNURL::resolve() for tag-based dispatch - Add comment_allowed to PayRequestResponse (LUD-12 prep) - Add success_action to PayRequestCallbackResponse - Refactor pay/withdraw to method-based API on the response types: PayRequestResponse::validate(), .description(), .get_invoice() WithdrawRequestResponse::build_callback_url() - Add extract_description_from_metadata() utility - Add get_json() to LnUrlHttpClient trait for generic resolution - Add aes/cbc dependencies for LUD-10 AES-256-CBC decryption - 29 tests (up from 12) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thin binding layer that wraps gl-client's LNURL protocol types with UniFFI annotations for cross-language export. No protocol logic here, only type definitions and From conversions. New types: ResolvedLnUrl, LnUrlPayRequestData, LnUrlPayRequest, LnUrlPayResult, LnUrlPaySuccessData, LnUrlWithdrawRequestData, LnUrlWithdrawRequest, LnUrlWithdrawResult, LnUrlWithdrawSuccessData, LnUrlErrorData, SuccessActionProcessed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add LnUrl and LnUrlAddress variants to InputType. parse_input() now recognizes bech32 LNURL strings (lnurl1...) and Lightning Addresses (user@domain.com) in addition to BOLT11 invoices and node IDs. Detection is offline only -- no HTTP calls. The caller should use Node::resolve_lnurl() to resolve LnUrl/LnUrlAddress inputs to their typed endpoint data (pay or withdraw). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire up the LNURL flows as methods on Node, following the two-phase pattern: resolve first to inspect metadata, then pay or withdraw. - resolve_lnurl(): accepts LNURL bech32, lightning address, or raw URL. Single HTTP GET with tag-based dispatch via gl-client. - lnurl_pay(): validates, fetches invoice, pays it, processes any success action (message/url/aes decryption). - lnurl_withdraw(): creates invoice via receive(), submits it to the service's callback URL. All three are pure orchestration -- protocol logic is in gl-client. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add TypeScript/Node.js wrappers for the LNURL functionality: - resolve_lnurl(), lnurl_pay(), lnurl_withdraw() on Node - All LNURL types: ResolvedLnUrl, LnUrlPayRequest, LnUrlPayResult, LnUrlWithdrawRequest, LnUrlWithdrawResult, SuccessActionProcessed - Enums represented as discriminated unions with string `type` field - Millisatoshi amounts as i64 for JS number compatibility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a test LNURL server backed by a real CLN node, implementing LUD-01/03/06/09/16. The server issues real BOLT11 invoices and pays real invoices for withdraw, enabling full end-to-end testing. New files: - gltesting/lnurl_server.py: LnurlServer class with pay, withdraw, and lightning address endpoints - tests/test_lnurl_server.py: 6 tests for the server itself (HTTP responses, invoice generation, k1 management) - tests/test_lnurl.py: 5 integration tests using the full Greenlight stack (scheduler, signer, SDK node, channels) against the LNURL server. Includes end-to-end LNURL-pay with actual Lightning payments and success action verification. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ignore glsdk.py, libglsdk.so, __pycache__, and bindings/ since these are regenerated by uniffi-bindgen from the compiled Rust library. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The SDK's lnurl_pay() was reconstructing a PayRequestResponse struct (a server response type) on the client side just to call its get_invoice() method. Fix by extracting the logic into a public fetch_invoice() free function that takes callback/amount/metadata directly. The method on PayRequestResponse now delegates to it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same fix as the previous commit but for the withdraw side: the SDK was reconstructing a WithdrawRequestResponse just to call build_callback_url(). Extract a free function that takes callback, k1, and invoice directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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
Adds LNURL support to
gl-sdk(and the underlyinggl-client), exposed through UniFFI and NAPI bindings. The change is purely additive — no existing APIs were removed or had their signatures changed.New top-level types (11 classes)
ResolvedLnUrl— result of resolving a bare LNURL / Lightning AddressLnUrlPayRequest,LnUrlPayRequestData,LnUrlPayResult,LnUrlPaySuccessDataLnUrlWithdrawRequest,LnUrlWithdrawRequestData,LnUrlWithdrawResult,LnUrlWithdrawSuccessDataLnUrlErrorData,SuccessActionProcessedNew methods on
Noderesolve_lnurl(input: str) -> ResolvedLnUrllnurl_pay(request: LnUrlPayRequest) -> LnUrlPayResultlnurl_withdraw(request: LnUrlWithdrawRequest) -> LnUrlWithdrawResultInputTypeextensionsparse_input()now also recognizes bare LNURLs and Lightning Addresses;InputTypegainedis_ln_url()/is_ln_url_address()variant checks alongside the existingbolt11/node_idones.Supporting work
gl-client: LNURL protocol primitives covering LUD-01/03/06/09/10/16gl-sdk-napi: matching TypeScript/Node bindings for the new types and methodsgl-testing: CLN-backed LNURL server fixture plus integration tests for pay/withdraw flowsfetch_invoice()andbuild_withdraw_callback_url()extracted as free functions ingl-clientfor reuse across callersTest plan
task sdk:testpasses (UniFFI Python bindings + integration tests)cargo test -p gl-clientpasses (LNURL protocol unit tests)cargo test -p gl-sdkpasseslibs/gl-sdk-napi)task testing:checkpasses (LNURL server fixture +test_lnurl.py,test_lnurl_server.py)🤖 Generated with Claude Code