-
Notifications
You must be signed in to change notification settings - Fork 143
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
Add proposal for currencies on payRequest #251
base: luds
Are you sure you want to change the base?
Conversation
6fceacf
to
35ceb75
Compare
Nice :-D. As discussed on telegram, it would be great to align this with the existing LUD-21 proposal (and UMA) where possible. UMA actually already extended that proposal in a few of the ways you've done here:
A few super simple changes to make these more consistent:
Also a very minor spelling nit - convertable -> convertible. |
35ceb75
to
7b19a21
Compare
@jklein24 Some comments on your
I have no problems making this change, but would you explain to me why it's better? It feels to me like
Changed!
This is really interesting. Thinking about a little, how would you say the preference is BTC if BTC is not listed in the currencies? Moreover, maybe this could be achieved with a separate preferredCurrency field or something like that? I really like this idea, just thinking of the best way to achieve it.
I thought about that as well, but thought that maybe it could be an extension of the proposal, since the max/min already present kind of fulfills this role? What do you think? I'd love to hear what @ethanrose thinks as well.
Not very minor, cmon, I'd hate to merge a spelling mistake into this repo haha thanks! fixed |
7b19a21
to
56bbdd8
Compare
The order of currencies in the array dictates order of preferences between currencies. So if I prefer BRL, but can also get BTC, you'd have your currencies array contain BRL first and then BTC. You can check out the UMA protocol to see the full structure, but essentially it would look like:
|
Would love @ethanrose's take on this too. Tbh I wasn't thinking it was better for some technical reason, but more just because so many entities are already live with the |
@jklein24 Maybe I am the one missing something! Let me try to explain. First exampleThe user inputs that it wants to send 1 BRL to the other side. If the This is the use-case supported by @ethanrose PR and it looks nicer having the multiplier in this case. Second exampleThe user inputs that it wants to send 500 sats as BRL to the other side. If the ConclusionIn the second case you use the multiplier as the denominator, which I think can be confusing this it's called "multiplier". Does these examples help in any way clear up the confusion? |
Thanks for the writeup - that makes things much more clear and concrete. I guess the thing is that in your two scenarios, you're asking 2 different questions:
To me, it makes sense that these different questions would require some different math. In fact for the first scenario, the easiest thing to do would just be to decode the invoice you get back in the |
408c732
to
801f196
Compare
801f196
to
2d37cec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code: string, // Code of the currency, used as an ID for it. E.g.: BRL | ||
name: string, // Name of the currency. E.g.: Reais | ||
symbol: string, // Symbol of the currency. E.g.: R$ | ||
decimals: number, // Integer; Number of decimal places. E.g.: 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It might be good to include a longer description about this field. With UMA, a bunch of folks integrating have been a bit confused by the mechanics around decimals/multiplier. Might be good to lay out some examples and show why decimals is important for clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI @lsunsi I added some examples and notes on small currency units in the uma spec that might be helpful here too - https://github.com/uma-universal-money-address/protocol/blob/main/umad-04-lnurlp-response.md#currency-examples
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes a lot of sense, I tried complementing the spec with this info and copied your example kind of . What do you think of (6a5b6e0)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, that captures the gist of it! I think the main difference is that UMA has an explicit max of 8 decimals, but keeping it open is fine too. LGTM
21.md
Outdated
{ | ||
"pr": "lnbc1230n1pjknkl...ju36m3lyytlwv42fee8gpt6vd2v", | ||
"routes": [], | ||
+ "converted": 123 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funny enough, in UMA, I chose not to include the target amount, but did include the multiplier and some other stuff:
"paymentInfo": {
// The currency code of the receiving currency (eg. "USD"). This should match the requested currency in the payreq
// request.
"currencyCode": string,
// Millisats per "unit" of the receiving currency (eg. 1 cent in USD). A double-precision floating point number.
// In this context, this is just for convenience. The conversion rate is also baked into the invoice amount itself.
// `invoice amount = amount * multiplier + exchangeFeesMillisatoshi`
"multiplier": number,
// Number of digits after the decimal point for the receiving currency. For example, in USD, by convention, there are
// 2 digits for cents - $5.95. In this case, `decimals` would be 2. This should align with the currency's `decimals`
// field in the LNURLP response. It is included here for convenience. See [UMAD-04](/uma-04-local-currency.md) for
// details, edge cases, and examples.
"decimals": number,
// The fees charged (in millisats) by the receiving VASP to convert to the target currency.
// This is separate from the multiplier rate.
"exchangeFeesMillisatoshi": number
},
The fees are useful for a full visual cost breakdown on the sender side. The multiplier and decimals help infer the converted amount from the invoice amount. I do like having the wrapping struct to keep related fields grouped and allow for extension in the future without polluting the top-level structure. Just some food for thought :-).
UMA spec link: https://github.com/uma-universal-money-address/protocol/blob/main/umad-06-payreq-response.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting. The reason I chose to keep just the int is to keep the protocol smaller.
The only property in this structure that is not already included is the fee, right?
The reason I didn't included it is that there's multiple ways of taking the fee, right? It could be billed in sats, or in currency (althought it's kind of the same). But the fee could be in the price (spread) or separate. Etc.
What do you think about these possibilities?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's fair. I just delimit the fee in mSats always because my assumption is that it's based into the cost of the invoice: invoice amount = amount * multiplier + exchangeFeesMillisatoshi
. I like having a top-level structure to wrap payment details since I could imagine more fields being added there in the future for scenarios you're describing. With the wrapper, we wouldn't need to pollute the top level more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 8c312b4
8c312b4
to
7275242
Compare
@jklein24 @lorenzolfm @jaonoctus I hacked this webapp to showcase the LUD. It's using just the API described in this PR. https://lnurlp-live.vercel.app/lorenzolfm@bipa.app |
7275242
to
b5cf042
Compare
f670c07
to
f70a0d6
Compare
@lsunsi noice! I wrote a similar interface ¹ to do the samething 😂 that I showed to @lorenzolfm |
Yeah my theory is that he is incepting us with his ideas at the same time! |
FYI this is now live in UMA v1 and VASPs are rolling it out. Xapo, Ripio, and Bitnob are upgraded and several more are on the way. |
This will help serve use cases like e-cash wallets, bolt-12 offers which allow for other currency denominations, and [LUD-21](lnurl/luds#251 wallet providers like UMA VASPs.
Abstract
This PR proposes an extension to the payRequest specification to allow for denomination of amount in different currencies and negotiating a conversion to this currency. It aims to be backwards compatible while taking a further step on providing lightning wallets and services a common language about exchanges and remittances on foreign currencies.
The PR includes what I expect to be a detailed description with some examples of the proposed extension. It also includes some references to related works that can be competing or complementary proposals to this one. This proposal is inspired by those references.
Implementations
I've been discussing this proposal inside @bipa-app currently and I aim to implement the most recent version of it and testing with partners before merging this PR.
EDIT:
Current proposal implemented at
lsunsi@bipa.app
if anyone wants to check it out.