-
Notifications
You must be signed in to change notification settings - Fork 52
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
NUT-18: Payment Requests #124
Conversation
xx.md
Outdated
```go | ||
type PaymentRequest struct { | ||
A int `amount (optional)` | ||
U string `unit` |
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.
Can the unit also be optional and default to sats?
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.
I was thinking that as well, however I can receivers run into compatibility issues quickly if they let users choose the unit.
xx.md
Outdated
- unit: The unit of the requested token (e.g. sats) | ||
- mint: The mint to use to mint the token | ||
- description: A human readable discription that the sending wallet will display after scanning the request | ||
- transport: The method of transport chosen to transmit the created token to the sender (can be multiple, sorted by preference) |
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.
Is there a use case where transport is empty? Or should there be a minimum of one element in the list?
What do you think of an optional condition that could specify spending conditions. For example if the receiver wants it locked using P2PK? |
Yes, this should be included. I will add it later doday |
Very cool. The receiver could specify the Edit: maybe even better: Edit 2: Problem: it would require one |
I added |
xx.md
Outdated
"r": str <optional>, | ||
"d": str <optional>, | ||
"m": str <optional>, | ||
"l": str <optional>, |
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.
What is the format of the lock script?
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.
I was thinking to just make it the well known secret format. Basically what will become Proof.secret.
However thinking about it, that will not work because of the nonce. Do you have something in mind? Otherwise we just have to come up with another Type
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.
Maybe just the well known secret without a nonce and the sender can add the nonce?
xx.md
Outdated
_Example_ | ||
|
||
```sh | ||
cashrqAaVhQRVhVWNzYXRhTXgiaHR0cHM6Ly9taW50Lm1pbmliaXRzLmNhc2gvQml0Y29pbmFEeCNQbGVzYXNlIHBheSB0aGUgdmVyeSBmaXJzdCBjYXNodSBwcmFUgaJhVGVub3N0cmJUYXhGbnByb2ZpbGUxcXFzZG11cDZlMno2bWNwZXVlNno2a2wwOGhlNDloY2VuNXhucmMzdG5wdncwbWRndGplbWgwc3V4YTBrag |
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.
should this be a cashureq
prefix?
can we add a version byte like with keysets? It would be good to add a paragraph explaining the payment request serialization like with tokenv3:
cashureq[version][request object]
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.
Maybe it'd be better to use a prefix that doesn't look so visually similar to a token: creq
?
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.
Yes, good point. The first byte after the prefix is indeed a version byte. I'll update the text to be more clear about that
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.
I have added a slightly different notation that makes it clear what exactly is concatianated and encoded when. Let me know what you think
xx.md
Outdated
- d: A human readable description that the sending wallet will display after scanning the request | ||
- m: The memo of the requested token (can be used for accounting purposes) | ||
- l: The lock script of the requested token | ||
- t: The method of transport chosen to transmit the created token to the sender (can be multiple, sorted by preference) |
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.
Having multiple transports and letting the user choose which one they prefer makes sense to me. The json example you provided does not allow providing multiple transports. I think it should be an array of Transport
"t": <Array[Transport]>
xx.md
Outdated
- t: type of Transport | ||
- a: target of Transport | ||
|
||
There can be many transport layers, but here are some recommendations: |
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.
I think it would be better to have a specific list of transport-types cashu supports in general instead of allowing everything. This list can be upgraded in the future without breaking the api. Otherwise a receiver could just add a new transport-type the wallet does not know how to handle.
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.
That wouldn't be an issue though. If the PR does not include a transport that the wallet can handle, the wallet can not pay it and will let the user know.
I think we should curate a list of recommended / common transports though.
xx.md
Outdated
- nostr | ||
- type: "nostr" | ||
- target: "<nprofile...>" | ||
- post |
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.
What is the transport-type post? Do you mean http with the method post? If so I would prefer the term http as the transport-type. Post could be misinterpreted as snailmail
Does this nut provide any information through the info-endpoint other than the supported-flag? |
xx.md
Outdated
Regardless of the transport layer the payload should always (unless specified differently) be a JSON serialised object as follows: | ||
|
||
```json | ||
{ "token": "cashuAy..." } |
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.
Why not just the plaintext?
Sending JSON makes sense only for HTTP but for all other transports (e.g. SMS or E-mail) it is awkward.
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.
I agree. I thought it would be good to define a reasonable standard that could work in any transport.
I an definitely open for suggestions
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.
I favor removing this requirement and allowing the plaintext encoded token to be used.
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.
I think it's better to use a structured object because:
- We will break things once we decide to add stuff later
- There is a new payment
id
field that the requester can ask for in the payment payload.
xx.md
Outdated
{ | ||
"a": int <optional>, | ||
"u": str, | ||
"r": str <optional>, |
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.
Should more than 1 mint be allowed?
xx.md
Outdated
|
||
- nostr | ||
- type: "nostr" | ||
- target: "<nprofile...>" |
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.
Should the nostr transport follow NIP-61?
xx.md
Outdated
Regardless of the transport layer the payload should always (unless specified differently) be a JSON serialised object as follows: | ||
|
||
```json | ||
{ "token": "cashuAy..." } |
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.
I favor removing this requirement and allowing the plaintext encoded token to be used.
xx.md
Outdated
|
||
Cashu Payment Requests can be encoded and displayed/sent as string or qr code. They underlying object is serialised using CBOR and finally base64 encoded and prefixed with a version byte and standard prefix. | ||
|
||
`"creq" + base64(versionByte + cbor(PaymentRequest))` |
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.
I don't have a strong opinion, but should we consider keeping the cashu prefix and using the version byte to differentiate a token and a payment request?
Also, NUT-00 doesn't encode the version byte in the base64; it is included in the prefix. We should keep the spec consistent with this treatment.
@callebtc thanks for adding the suggestions. This does indeed LGTM! |
xx.md
Outdated
- `i`: Payment id to be included in the payment payload | ||
- `a`: The amount of the requested payment | ||
- `u`: The unit of the requested payment (MUST be set if `a` is set) | ||
- `s`: Whether the payment request is for single use |
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.
Should be r
to match above
xx.md
Outdated
|
||
## Payment payload | ||
|
||
Regardless of the transport layer, the payload sent to the receiver is a JSON serialized object as follows: |
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.
How would this work with NIP-61, where the nostr event is the payment, which has its own format and should be signed by the sender?
Are we ready to remove NIP-04, because the support for NIP-17 might be too limited still. Afaik nostr-tools does not have it yet. But I agree that we probably should be looking forward and not carry stuff around that's already considered harmful |
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.
LGTM
|
||
This NUT introduces a standardised format for payment requests, that supply a sending wallet with all information necessary to complete the transaction. This enables many use-cases where a transaction is better initiated by the receiver (e.g. point of sale). | ||
|
||
## Flow |
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.
IMO it would be helpful to indicate in the Flow at which point user interaction or confirmation is needed (from the payer side), and if there is anything the app must / should show to the user before confirmation, similar to LNURL-pay / LNURL-withdraw.
18.md
Outdated
|
||
### Transport types | ||
|
||
The supported transport types are: |
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.
Which are the transport types? Looks like a list was intended here, but missing.
Co-authored-by: ok300 <[email protected]>
typo fix in #178 |
Cashu transactions are initiated by the sender and can be pushed to the receiver without any additional help. However for many use cases requesting a payment may be more desirable (e.g. point-of-sales). This proposal introduces a standardised format for payment requests, that supply a sending wallet with all information necessary to complete the transaction.