Skip to content
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

Link wallet LUD #256

Open
wants to merge 8 commits into
base: luds
Choose a base branch
from
Open

Link wallet LUD #256

wants to merge 8 commits into from

Conversation

rav3r
Copy link

@rav3r rav3r commented Feb 8, 2024

Hey,

We (THNDR Games) have one major UX issue when it comes to withdrawing sats from our games via Lightning Address, let me show you how it works right now:

IMG_0635

  1. Our user selects to which wallet they want to withdraw their prize (in my example ZBD)
  2. They must enter their lightning address for the first time setup.
  3. To get the lightning address our user must close the game, find the ZBD wallet on his phone, and somehow find it there.
  4. They must remember their address and find our game again on the phone
  5. Then they enter it manually

After interviewing users we found users had the following pain points with the manual process:

  • Inputting their email address
    • Some users did not know what the lightning address was
  • Entering the wrong Lightning Address
  • Nervous emotions when entering a Lightning Address, because it concerns money.
  • If the user did know what a Lightning Address was, they did not know which of their wallets supported it
    • “Oh, ok, I will get my Lightning Address from Phoenix”
  • If the user knew which wallet had a Lightning address, they did not know where to look for it and would give up looking.

I propose to use LNURL to create a “One Click” solution to allow the user to auto-send their lightning address directly to the service from the wallet.

This way we can prevent human errors and jumping between apps = significantly improve UX of paying apps.

@shocknet-justin
Copy link
Contributor

why not just use lnurl-withdraw here?

@rav3r
Copy link
Author

rav3r commented Feb 8, 2024

@capitalistdog

lnurl-withdraw won't work for this use case - we don't want the receiver to manually confirm every incoming payment.

@shocknet-justin
Copy link
Contributor

lnurl-withdraw won't work for this use case - we don't want the receiver to manually confirm every incoming payment.

gotchya... perhaps though the lnurl-p/address endpoint may be better simply as an extra parameter on the existing withdraw tag (similar to balanceNotify)

Where most wallets will already support withdraw, users will still be able to get funds out now, as opposed to an unsupported wallet not knowing the new tag at all

I think that would also be easier to implement wallet-side

@rav3r
Copy link
Author

rav3r commented Feb 8, 2024

lnurl-withdraw won't work for this use case - we don't want the receiver to manually confirm every incoming payment.

gotchya... perhaps though the lnurl-p/address endpoint may be better simply as an extra parameter on the existing withdraw tag (similar to balanceNotify)

Where most wallets will already support withdraw, users will still be able to get funds out now, as opposed to an unsupported wallet not knowing the new tag at all

I think that would also be easier to implement wallet-side

Thanks this is very interesting, seems like it could be a much better solution (it would work even if someone changes his lightning address). I'll think and revise my LUD soon!

@ok300
Copy link

ok300 commented Feb 8, 2024

I may be missing something, but the full flow is not clear to me:

First, the LN Wallet interacts with Service to associate a LN Address with a k1 value.

What does the other app (ZBD) do then to get or lookup the LN Address? It would need to call Service with k1 as arg, no? And if so, how does it get k1?

@rav3r
Copy link
Author

rav3r commented Feb 8, 2024

What does the other app (ZBD) do then to get or lookup the LN Address? It would need to call Service with k1 as arg, no? And if so, how does it get k1?

There are two requests:

  1. LNURL
  2. Callback

The wallet calls LNURL and gets k1 and callback url, then calls the callback with k1 and the lightning address.

EDIT: Oh wait, I see what is the problem here - the service pays to the wallet, not the other way around!

@arbadacarbaYK
Copy link
Contributor

lnurl-withdraw won't work for this use case - we don't want the receiver to manually confirm every incoming payment.

gotchya... perhaps though the lnurl-p/address endpoint may be better simply as an extra parameter on the existing withdraw tag (similar to balanceNotify)

Where most wallets will already support withdraw, users will still be able to get funds out now, as opposed to an unsupported wallet not knowing the new tag at all

I think that would also be easier to implement wallet-side

Smth similar to LUD19 (paylink discoverable from withdraw link) - but reverse.
Also maybe nice within LNURLauth (lnaddress/lnurlp discoverable from lnurlauth) for login and recovery processes to be build upon.

@rav3r
Copy link
Author

rav3r commented Feb 9, 2024

@capitalistdog @arbadacarbaYK

A fine-grained scheme for this use case would work better on iOS (as pointed out in LUD 17), for us this is a huge problem because people have multiple wallets and we never know which wallet will handle the link.

Now I believe the optimal solution is to combine two elements: a new lnurl scheme that enables requesting the wallet to send lnurl-withdraw to the service. Advantages of this strategy:

  1. Wallets that don't support Lightning Addresses can implement this
  2. Only wallets that support this feature will handle that scheme
  3. If the user changes their lightning address, the lnurl-withdraw can stay the same
  4. The wallet might use different lnurl-withdraws for various services, so in the future, wallets can impose distinct limits for different services.

What do you think?

@shocknet-justin
Copy link
Contributor

I'm not clear on what the LUD17 conventions help with here, you're not using a QR so size isn't a concern, I'd think all this does it make it work with less wallets vs. LUD03

Are there any particularly popular iOS wallets that you're concerned with supporting lightning: but not LUD03? It might be easier just to get them supporting LUD03 then getting a bunch more wallets to support LUD17

Another thing to consider is that LNURL is probably not the future given it's pre-disposition to custodial solutions and only a handful of LUD's being used broadly. It's good for making things work with what exists today- not so much for getting wallets to incorporate new things.

I wont talk my stack in depth here, but mentioned to Jack that I'll reach out once I have a production demo of what we're doing for LightningVideo withdrawals since we're on the subject of new specs.

@JssDWt
Copy link

JssDWt commented Feb 9, 2024

In general I like the idea of being able to share your address for automatic payouts this way.

About this spec:
I think the k1 is not really necessary, because the initial link already has to uniquely identify the user. (if you share the same link with two users, how would you know which lightning address belongs to which user?)

In this scheme you could even put serviceName in the querystring of the initial link, so only one http request has to be made.
lnurlp://...?s=my%20service. LN WALLET extracts the service name from the querystring, shows the message and then does a GET on the url with the lightning address attached.

Other idea:
I also fancy the idea of the initial app giving an lnurl withdraw link. Then adding the lightning address to a newly defined query parameter to the lnurl withdraw callback for automatic handling of subsequent withdraws. The withdrawal link will work with existing wallets as well, but only those implementing the additional query parameter would be able to get the automatic payouts.

@kaloudis
Copy link

kaloudis commented Feb 9, 2024

It would be really cool to be able to sign and prove you have control ownership of an LN address, to prevent user error, but AFAIK it's not possible - you can only prove ownership of your node pubkey

@rav3r
Copy link
Author

rav3r commented Feb 9, 2024

@capitalistdog

I'm not clear on what the LUD17 conventions help with here, you're not using a QR so size isn't a concern, I'd think all this does it make it work with less wallets vs. LUD03

I meant fine-grained url schemes, not bech32 encoding.

Are there any particularly popular iOS wallets that you're concerned with supporting lightning: but not LUD03? It might be easier just to get them supporting LUD03 then getting a bunch more wallets to support LUD17

Assuming your approach (new tag with a callback to send lnurl in lnurl-withdraw) I am concerned about wallets that implement lightning: but not the new tag, so wallet A could "consume" the link even if wallet B is supporting all the features.

@JssDWt

About this spec: I think the k1 is not really necessary, because the initial link already has to uniquely identify the user. (if you share the same link with two users, how would you know which lightning address belongs to which user?)

Yes, you are right - this could work exactly like a fast withdraw.

@kaloudis

It would be really cool to be able to sign and prove you have control ownership of an LN address, to prevent user error, but AFAIK it's not possible - you can only prove ownership of your node pubkey

What is your top use case for this? Maybe we can somehow add such verification

@positiveblue
Copy link

Let me know if the constrains assumed here are correct:

Problem:

  • Wallet W IS Custodial and it has different balances for many users/accounts
  • Application A needs to send a payment to a given user/account in wallet W, but does not know the user's identifier in wallet W

Current solution:

  • The Wallet W has a way to credit a given account (lightning address)
  • The user needs to introduce their "id" (lightning address) manually so Application A can get an invoice from the Wallet

Proposed solution:

  • Wallet W implements this LUD. Wallet will read a QR created by application A that will encode what the application needs and a callback where the wallet can send the information that it's being requested for the user (in this case a lightning address)

My 2 cents:

There is already a protocol that would allow this and many other use cases widely used in the industry: OAuth2. If Wallet providers implemented it (some already did, like Alby)

I think that is the road that we should follow as the industry matures: OAuth2 with a "standard" set of actions/permissions that the app can perform in the wallet (not only get the LN address's but things like load your app credit by spending from that wallet, etc..)

However, if we want something specific (simpler?) in LNURL we could copy a small part of the OAuth 2 flow.

  • The wallet A has an endpoint to request info about a user account (lnaddress, a bolt 12 invoice...)
  • The endpoint gets what the app is requesting and the callback URL
    • Case A) If the user IS logged in: it shows what app this is, what permissions is asking for and a button to accept/reject
    • Case B) If the user IS NOT logged in: registry/login flow with an end step redirecting to Case A

I would keep it simple and only return "read only info". No token that can be used with the wallet api or anything like that.

The application A encoding the info in a QR may be useful if we want the user to use ANY wallet, not only the ones "approved" by the app.

Also notice that in this proposal, I can set serviceName to whatever I want to ("HI, I am Cash APP, trust me!") and the wallet will show exactly in the permissions request page. OAuth 2 solve this with a client_id/client_secret. But that means that apps need to register to be able to use the protocol with that OAuth provider. I think we need something to prevent this "attack". From well known public keys linked to well known apps to apps registering with the wallet.

@jackeveritt
Copy link

Data point from THNDR, in Jan '24, 84.5% of our payments went to Lightning Address enabled wallets. A one click solution to link a Lightning Address during onboarding for new users would be a great improvement!

@hsjoberg hsjoberg self-requested a review February 10, 2024 06:36
@rav3r
Copy link
Author

rav3r commented Feb 12, 2024

Let me know if the constrains assumed here are correct...

Yes, in our case we use deeplinks instead of QR codes, but the flow is exactly like you described.

  • The wallet A has an endpoint to request info about a user account (lnaddress, a bolt 12 invoice...)

  • The endpoint gets what the app is requesting and the callback URL

    • Case A) If the user IS logged in: it shows what app this is, what permissions is asking for and a button to accept/reject
    • Case B) If the user IS NOT logged in: registry/login flow with an end step redirecting to Case A

I need a small clarification here - how does the app know what is the user id? I think it must be somehow passed from the wallet to the app.

Also notice that in this proposal, I can set serviceName to whatever I want to ("HI, I am Cash APP, trust me!")...

This sounds like additional protection, I believe the whole lnurl spec needs something like this - imagine someone paying for stuff from Amazon using lnurlp, it would be cool if wallets could display a "verified" merchant badge on the invoice.

@positiveblue
Copy link

I need a small clarification here - how does the app know what is the user id? I think it must be somehow passed from the wallet to the app.

  • The app does not know the user id for that wallet.
  • The app redirects to the wallet service and gives it information on where to redirect if the user approves the permissions that the app is asking [this is how the app will know what user of the app needs to be linked]
  • The user needs to log in the wallet (then is when the wallet knows what user is trying to be linked) if there is a user already logged in, that is the user.
  • The user need to approve the permisions
  • The wallet calls back the app with the data that has been asked for (usually a token that allows them to ask for more data/interact with the wallet)

There is no need for the app to know what user is being linked a priory. It will basically be whoever logs in in the wallet (or is already logged in)

This sounds like additional protection

This is the first thing that pop out into my mind when I was reading the proposal. It's ok to not fix this proposal is ok, but it is good to keep in mind that this may be a security concern.

@jackeveritt
Copy link

jackeveritt commented May 9, 2024

We have implemented the service side of this LUD in our game "Club Bitcoin: Solitaire". Download on Apple or Google.

Here is an example of how the flow works.

Example flow

If you want to test this with your wallet or app as the withdrawal wallet, you will need to contact me so I can enable this feature on your THNDR account, as it is not available publicly.

@andrerfneves
Copy link

Ack

@jackeveritt
Copy link

Based on feedback in the telegram group. We updated the proposal to include an optional 'redirect' such that the Wallet can offer to send the user back to the Service.

We have updated our implementation to support this, if you wish to test.

Reminder: In our games, this is a hidden feature and you will need to contact me to get it activated for testing.

@freeberty
Copy link

freeberty commented Aug 2, 2024

ZBD released wallet side of this proposal google play
photo_2024-08-02_18-14-34

it's available for everyone. we handle lnurll:// and zebedee:lnurll:// links at the moment

@bumi
Copy link

bumi commented Sep 15, 2024

Is NWC an alternative option for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.