Skip to content

lightning: implement lnurl-withdraw (LUD-03) #9993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

f321x
Copy link
Member

@f321x f321x commented Jun 27, 2025

lnurl-withdraw is used by lightning bitcoin atms, vouchers (e.g. azteco), and web services use it to allow users to withdraw funds without having to copy-paste invoices (esp. between desktop <-> smartphone).
https://github.com/lnurl/luds/blob/227f850b701e9ba893c080103c683273e2feb521/03.md

Can be tested with https://demo.lnbits.com and the Withdraw Links (LNURLW) and Pay Links (LNURLP) extensions.

@f321x f321x force-pushed the lnurl_withdraw branch 2 times, most recently from 0d1e6b5 to ca7a2b9 Compare July 1, 2025 08:40
@f321x f321x marked this pull request as ready for review July 1, 2025 08:40
@f321x f321x force-pushed the lnurl_withdraw branch 4 times, most recently from 33780d9 to 07e71df Compare July 2, 2025 07:35
@accumulator
Copy link
Member

It feels somewhat out of place to integrate this in the Send flow UI for payments, and not the Receive flow UI. Also, (QE)Invoice(Parser) is used instead of (QE)Request(Details)

@f321x
Copy link
Member Author

f321x commented Jul 14, 2025

I agree seems a bit unintuitive to paste a string to receive money into the send tab, i implemented it like this because it seems to be the "standard", i don't know of any other wallet which handles it differently, e.g. Phoenix and Blink also require to paste LNURLWs into the send field.
It would also be confusing to have a separate 'paste' button in the receive tab to paste (or scan) an 'address'/voucher to receive from, or do you see more natural way how this could be integrated without adding more buttons/fields the user has to understand? I think showing the popup when pasting the lnurlw is the clearest way to separate it from "sending" ui.

Technically, besides doing opposite things, lnurlw and lnurlp have a quite similar flow which also makes a point for handling them closely together. Its not even clear if a given lnurl string is a payRequest or a withdrawRequest until we call the encoded url and got the response from the lnurl server. Otherwise logic for handling lnurls (resolving etc.) would have to be duplicated in the (QE)Request(Details) code.

@accumulator
Copy link
Member

I agree seems a bit unintuitive to paste a string to receive money into the send tab, i implemented it like this because it seems to be the "standard", i don't know of any other wallet which handles it differently, e.g. Phoenix and Blink also require to paste LNURLWs into the send field. It would also be confusing to have a separate 'paste' button in the receive tab to paste (or scan) an 'address'/voucher to receive from, or do you see more natural way how this could be integrated without adding more buttons/fields the user has to understand? I think showing the popup when pasting the lnurlw is the clearest way to separate it from "sending" ui.

Yeah, I understand this is probably the least invasive way of doing it. I do think some people will try the Receive button for this use case. The only thing I can think of UI-wise is having an small extra button 'Scan voucher' or something in the receive tab/view, which then also presents the QR scanner.

Technically, besides doing opposite things, lnurlw and lnurlp have a quite similar flow which also makes a point for handling them closely together. Its not even clear if a given lnurl string is a payRequest or a withdrawRequest until we call the encoded url and got the response from the lnurl server. Otherwise logic for handling lnurls (resolving etc.) would have to be duplicated in the (QE)Request(Details) code.

The main issue with having this code in QEInvoice(Parser) is that most of the code there assumes outgoing payments. This might trip us over in the future. I think the potential duplication of code is limited, most of the work is done in PaymentIdentifier.

f321x added 2 commits July 16, 2025 12:07
adds handling of lnurl-withdraw payment identifiers which allow users to
withdraw bitcoin from a service by scanning a qr code or pasting the
lnurl-w code as "sending" address.
adds some more detailed tests to `test_payment_identifier.py` to test
lnurlp and lnurlw separately and mock their resolve.
separates the resolving step from the QEInvoiceParser so the 'recipient'
can be resolved first and then either an QEInvoiceParser can be used if
it is a sending request that has been resolved (invoice, address,
lnurlp, ...), or RequestDetails can be used if the resolved 'recipient'
turns out to be a voucher/LNURLW string.
@f321x
Copy link
Member Author

f321x commented Jul 16, 2025

Ok in abf0059 i removed the resolving of the 'recipient' into a separate class QEPIResolver, so it can first resolve the user input so its clear if it is a Invoice or a Request/Voucher (lnurlw) type. The lnurlw logic is now in QERequestDetails so its clearly separated from the QEInvoiceParser.
Do you think this is preferable to the implementation in ae310ad @accumulator ?

Yeah, I understand this is probably the least invasive way of doing it. I do think some people will try the Receive button for this use case. The only thing I can think of UI-wise is having an small extra button 'Scan voucher' or something in the receive tab/view, which then also presents the QR scanner.

I think its better to have a simpler UI instead of adding an extra button to the receive ui which is then used only used by a small subset of all users. I think those that want to scan a lnurlw qr code will naturally figure out to click on send as its the only view that presents a camera to scan things.

@accumulator
Copy link
Member

Do you think this is preferable to the implementation in ae310ad @accumulator ?

I will have a look after the weekend

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.

2 participants