-
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
Changes from 6 commits
b7b0781
b12b4ee
9021c09
0e9b53d
80e6d6f
50fc922
1632d88
0c57a0d
183d2bb
3349e24
ec0cb4e
64dc463
5734943
40ec76b
0f4ddc2
28e6f9f
459d66f
4989f52
ec3bfa3
0663344
a2c6172
1c1050d
211864c
4ec6ec7
8002b5b
09d70ec
c09e45f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# NUT-XX: Payment Requests | ||
|
||
`optional` | ||
|
||
--- | ||
|
||
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 | ||
|
||
1. Receiver creates a payment request, encodes it and displays it to the sender | ||
2. Sender scans the request and constructs a matching token | ||
3. Sender sends the token according to the transport specified in the payment request | ||
4. Receiver receives the token and finalises the transaction | ||
|
||
## Payment Request | ||
|
||
A Payment Request is defined as follows | ||
|
||
```json | ||
{ | ||
"a": int <optional>, | ||
"u": str, | ||
"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 commentThe 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 commentThe 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 commentThe 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? |
||
"t": Transport | ||
} | ||
thesimplekid marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
while Transport is defined as | ||
|
||
- a: The amount of the requested token (payment amount) | ||
- u: The unit of the requested token (e.g. sats) | ||
- r: The mint to use to mint the token | ||
- 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 commentThe 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]> |
||
|
||
The sending wallet MUST honor all parts of a payment request that are specified | ||
|
||
## Transport | ||
|
||
Transport is an important part of Cashu Payment Requests. Receivers can choose what kind of transport they want to support and where they want to receive the token. By making this clear in the payment requests, wallets can handle payment requests accordingly (or decline them if they do not support the transport layer). A transport consists of a type and a target. | ||
|
||
```json | ||
{ | ||
"t": str, | ||
"a": Target | ||
} | ||
``` | ||
|
||
- 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 commentThe 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 commentThe 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. |
||
|
||
- nostr | ||
- type: "nostr" | ||
- target: "<nprofile...>" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the nostr transport follow NIP-61? |
||
- post | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
- type: "post" | ||
- target: "<endpoint url>" | ||
- type: "email" | ||
- target: "<email address>" | ||
- sms | ||
- type: "sms" | ||
- target: "<phone number>" | ||
|
||
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 commentThe 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 commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better to use a structured object because:
|
||
``` | ||
|
||
## Encoded Request | ||
|
||
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 commentThe 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. |
||
|
||
_Example_ | ||
|
||
```sh | ||
creqAaVhQRVhVWNzYXRhTXgiaHR0cHM6Ly9taW50Lm1pbmliaXRzLmNhc2gvQml0Y29pbmFEeCNQbGVzYXNlIHBheSB0aGUgdmVyeSBmaXJzdCBjYXNodSBwcmFUgaJhVGVub3N0cmJUYXhGbnByb2ZpbGUxcXFzZG11cDZlMno2bWNwZXVlNno2a2wwOGhlNDloY2VuNXhucmMzdG5wdncwbWRndGplbWgwc3V4YTBrag | ||
``` |
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?