From ebed5baab0467cd000dfa2cfad28a3cf7a944972 Mon Sep 17 00:00:00 2001 From: Egge <80262989+Egge21M@users.noreply.github.com> Date: Fri, 18 Oct 2024 19:30:13 +0200 Subject: [PATCH] NUT-18: Payment Requests (#124) * 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 <106775972+ok300@users.noreply.github.com> * remove wrong line * add example * prettier --------- Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com> Co-authored-by: gudnuf Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com> --- 18.md | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 6 ++- 2 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 18.md diff --git a/18.md b/18.md new file mode 100644 index 0000000..7b2b3e9 --- /dev/null +++ b/18.md @@ -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 , + "a": int , + "u": str , + "r": bool , + "m": Array[str] , + "d": str , + "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]] +} +``` + +- `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: `` +- 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: `` + +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 , + "memo": str , + "mint": str, + "unit": , + "proofs": Array +} +``` + +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 diff --git a/README.md b/README.md index e0ca519..f0b745f 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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: @@ -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