Skip to content

Commit

Permalink
NUT-18: Payment Requests (#124)
Browse files Browse the repository at this point in the history
* added v1 draft

* updated reference implementation

* updated referece Impl. + began formatting

* formatting

* fixed typo & removed ref impl

* changed transport + token

* suggestions

* fix

* remove TokenV4 JSON, instead use mint unit proofs

* add to readme

* fix transport and change tag

* change tags to support multiple values

* remove NIP-04

* remove TokenV4 JSON, instead use mint unit proofs

* add to readme

* fix transport and change tag

* change tags to support multiple values

* remove NIP-04

* readd nutix

* prettier

* Update 18.md

Co-authored-by: ok300 <[email protected]>

* remove wrong line

* add example

* prettier

---------

Co-authored-by: callebtc <[email protected]>
Co-authored-by: gudnuf <[email protected]>
Co-authored-by: ok300 <[email protected]>
  • Loading branch information
4 people authored Oct 18, 2024
1 parent 25885cd commit ebed5ba
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 2 deletions.
129 changes: 129 additions & 0 deletions 18.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# NUT-18: 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
{
"i": str <optional>,
"a": int <optional>,
"u": str <optional>,
"r": bool <optional>,
"m": Array[str] <optional>,
"d": str <optional>,
"t": Array[Transport]
}
```

Here, the fields are

- `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
- `m`: A set of mints from which the payment is requested
- `d`: A human readable description that the sending wallet will display after scanning the request
- `t`: The method of `Transport` chosen to transmit the payment (can be multiple, sorted by preference)

## Transport

`Transport` specifies methods for sending the ecash to the receiver. A transport consists of a type and a target.

```json
{
"t": str,
"a": str,
"g": Array[Array[str, str]] <optional>
}
```

- `t`: type of Transport
- `a`: target of Transport
- `g`: optional tags for the Transport

### Tags

Tags are an optional array of `[tag, value, value, ...]` tuples that can be used to specify additional features about the transport. A single tag can have multiple values.

### Transport types

The supported transport types are described below.

#### Nostr

- type: `nostr`
- target: `<nprofile>`
- tags: `[["n", "17"]]`

The `n` tag specifies the NIPs the receiver supports. At least one tag value MUST be specified. For [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) direct messages, the sender sends a `PaymentRequestPayload` as the message content.

#### HTTP POST

- type: `post`
- target: `<endpoint url>`

The execute the payment, the sender makes a `POST` request to the specified endpoint URL with the `PaymentRequestPayload` as the body.

## Payment payload

If not specified otherwise, the payload sent to the receiver is a `PaymentRequestPayload` JSON serialized object as follows:

```json
{
"id": str <optional>,
"memo": str <optional>,
"mint": str,
"unit": <str_enum>,
"proofs": Array<Proof>
}
```

Here, `id` is the payment id (corresponding to `i` in request), `memo` is an optional memo to be sent to the receiver with the payment, `mint` is the mint URL from which the ecash is from, `unit` is the unit of the payment, and `proofs` is an array of proofs (see [NUT-00][00], can also include DLEQ proofs).

## Encoded Request

The payment request is serialized using CBOR, encoded in `base64_urlsafe`, together with a prefix `creq` and a version `A`:

`"creq" + "A" + base64(CBOR(PaymentRequest))`

### Example

This is an example payment request expressed as JSON:

```json
{
"i": "b7a90176",
"a": 10,
"u": "sat",
"m": ["https://nofees.testnut.cashu.space"],
"t": [
{
"t": "nostr",
"a": "nprofile1qy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsz9mhwden5te0wfjkccte9curxven9eehqctrv5hszrthwden5te0dehhxtnvdakqqgydaqy7curk439ykptkysv7udhdhu68sucm295akqefdehkf0d495cwunl5",
"g": [["n", "17"]]
}
]
}
```

This payment request serializes to (see [here](https://cbor.nemo157.com/#type=hex&value=a3617482a261694800ffd48b8f5ecf80617081a36161016173784061636331323433356537623834383463336366313835303134393231386166393066373136613532626634613565643334376534386563633133663737333838616358210244538319de485d55bed3b29a642bee5879375ab9e7a620e11e48ba482421f3cfa261694800ad268c4d1f5826617082a3616102617378403133323364336434373037613538616432653233616461346539663166343966356135623461633762373038656230643631663733386634383330376538656561635821023456aa110d84b4ac747aebd82c3b005aca50bf457ebd5737a4414fac3ae7d94da36161016173784035366263626362623763633634303662336661356435376432313734663465666638623434303262313736393236643361353764336333646362623539643537616358210273129c5719e599379a974a626363c333c56cafc0e6d01abe46d5808280789c63616d75687474703a2f2f6c6f63616c686f73743a33333338617563736174)):

```sh
creqApWF0gaNhdGVub3N0cmFheKlucHJvZmlsZTFxeTI4d3VtbjhnaGo3dW45ZDNzaGp0bnl2OWtoMnVld2Q5aHN6OW1od2RlbjV0ZTB3ZmprY2N0ZTljdXJ4dmVuOWVlaHFjdHJ2NWhzenJ0aHdkZW41dGUwZGVoaHh0bnZkYWtxcWd5ZGFxeTdjdXJrNDM5eWtwdGt5c3Y3dWRoZGh1NjhzdWNtMjk1YWtxZWZkZWhrZjBkNDk1Y3d1bmw1YWeBgmFuYjE3YWloYjdhOTAxNzZhYQphdWNzYXRhbYF4Imh0dHBzOi8vbm9mZWVzLnRlc3RudXQuY2FzaHUuc3BhY2U=
```

[00]: 00.md
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio
| [12][12] | DLEQ proofs | [Nutshell][py], [cdk-cli] | [Nutshell][py], [cdk-mintd], [nutmix] |
| [13][13] | Deterministic secrets | [Nutshell][py], [Moksha][moksha], [cashu-ts][ts], [cdk-cli], [gonuts] | - |
| [14][14] | Hashed Timelock Contracts (HTLCs) | [Nutshell][py], [cdk-cli] | [Nutshell][py], [cdk-mintd], [nutmix] |
| [15][15] | Partial multi-path payments (MPP) | [Nutshell][py] | [Nutshell][py], [nutmix] |
| [15][15] | Partial multi-path payments (MPP) | [Nutshell][py] | [Nutshell][py] |
| [16][16] | Animated QR codes | [Cashu.me][cashume] | - |
| [17][17] | WebSocket subscriptions | [Nutshell][py] | [Nutshell][py] |
| [18][18] | Payment requests | [Cashu.me][cashume], [Boardwalk][bwc] | - |

#### Wallets:

Expand All @@ -45,7 +46,7 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio
- [Nutstash][ns]
- [Cashu.me][cashume]
- [Gonuts][gonuts]
- [Boardwalk Cash][bwc]
- [Boardwalk][bwc]

#### Mints:

Expand Down Expand Up @@ -87,3 +88,4 @@ Wallets and mints `MUST` implement all mandatory specs and `CAN` implement optio
[15]: 15.md
[16]: 16.md
[17]: 17.md
[18]: 18.md

0 comments on commit ebed5ba

Please sign in to comment.