Skip to content
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

Payment Method Refactor #201

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 92 additions & 69 deletions 04.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,82 @@
# NUT-04: Mint tokens
# NUT-04: Minting tokens

`mandatory`

---

Minting tokens is a two-step process: requesting a mint quote and minting new tokens. Here, we describe both steps.
Minting tokens is a two-step process: requesting a mint quote and minting new tokens.

In the first request the wallet asks the mint for a quote for a specific `amount` and `unit` to mint, and the payment `method` to pay. The mint responds with a quote that includes a `quote` id and a payment `request`. The user pays the `request` and, if successful, requests minting of new tokens with the mint in a second request. The wallet includes the `quote` id and new `outputs` in the second request.
1. The wallet **MUST** first request a mint quote by specifying the `amount`, `unit`, and payment `method`.
- The mint **MUST** respond with a `quote` ID and a payment `request` for valid requests.
2. After payment, the wallet **MUST** initiate the minting process by sending the `quote` ID and `outputs` in a second request.

We limit this document to mint quotes of `unit="sat"` and `method="bolt11"` which requests a bolt11 Lightning invoice (typically generated by the mint to add Bitcoin to its reserves) to mint ecash denominated in Satoshis.
---

## Mint Quote

# Mint quote
To request a mint quote, the wallet **MUST** send a `POST /v1/mint/quote/{method}` request. The `method` specifies the payment method (e.g., `bolt11`).

To request a mint quote, the wallet of `Alice` makes a `POST /v1/mint/quote/{method}` request where `method` is the payment method requested (here `bolt11`).
### Request Endpoint

```http
POST https://mint.host:3338/v1/mint/quote/bolt11
POST https://mint.host:3338/v1/mint/quote/{method}
```

The wallet of `Alice` includes the following `PostMintQuoteBolt11Request` data in its request:
### Request Body

The request body **MUST** include the following fields:

```json
{
"amount": <int>,
"unit": <str_enum["sat"]>,
"description": <str|null>
"unit": <str>,
"opts": <obj|null>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am in favor of the change, but strictly speaking it is a breaking change.

}
```

with the requested `amount` and the `unit`. An optional `description` can be passed if the mint signals support for it in `MintMethodSetting`.
- `amount`: The requested amount to mint.
- `unit`: The unit of the amount.
- `opts`: Options specific to the payment method.

### Response

The mint `Bob` then responds with a `PostMintQuoteBolt11Response`:
The mint **MUST** respond with a `PostMintQuoteResponse`:

```json
{
"quote": <str>,
"request": <str>,
"state": <str_enum[STATE]>,
"expiry": <int>
"expiry": <int|null>
}
```

Where `quote` is the quote ID and `request` is the payment request to fulfill. `expiry` is the Unix timestamp until which the mint quote is valid.
- `quote`: A unique ID for the quote.
- `request`: The payment request.
- `state`: The current state of the quote (`UNPAID`, `PAID`, or `ISSUED`).
- `expiry`: The expiration timestamp for the quote (or `null` for quotes without expiration).

`state` is an enum string field with possible values `"UNPAID"`, `"PAID"`, `"ISSUED"`:
The wallet **MUST** store the `amount` and `quote` ID in its database for use during token minting after payment.

- `"UNPAID"` means that the quote's request has not been paid yet.
- `"PAID"` means that the request has been paid.
- `"ISSUED"` means that the quote has already been issued.
---

### Security Note

Note: `quote` is a **unique and random** id generated by the mint to internally look up the payment state. `quote` **MUST** remain a secret between user and mint and **MUST NOT** be derivable from the payment request. A third party who knows the `quote` ID can front-run and steal the tokens that this operation mints.
The `quote` ID **MUST** be unique and secret. It **MUST NOT** be derivable from the payment request. Leaking this ID allows third parties to steal tokens.

---

## Example
### Example: Requesting a Quote

Request of `Alice` with curl:
**Request:**

```bash
curl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{"amount": 10, "unit": "sat"}' -H "Content-Type: application/json"
curl -X POST https://mint.host:3338/v1/mint/quote/{method} \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, using bolt11 should be preferred over {method}, because it is an example and other variables have concrete values too (10 and sat).

-d '{"amount": 10, "unit": "sat"}' \
-H "Content-Type: application/json"
```

Response of `Bob`:
**Response:**

```json
{
Expand All @@ -70,33 +87,46 @@ Response of `Bob`:
}
```

The wallet **MUST** store the `amount` in the request and the `quote` id in the response in its database so it can later request the tokens after paying the request. After payment, the wallet continues with the next section.
---

## Check mint quote state
## Checking Mint Quote State

To check whether a mint quote has been paid, `Alice` makes a `GET /v1/mint/quote/bolt11/{quote_id}`.
To check whether a mint quote has been paid, the wallet **MUST** send a `GET /v1/mint/quote/{method}/{quote_id}` request.

```http
GET https://mint.host:3338/v1/mint/quote/bolt11/{quote_id}
```
### Example: Checking Quote State

Like before, the mint `Bob` responds with a `PostMintQuoteBolt11Response`.

Example request of `Alice` with curl:
**Request:**

```bash
curl -X GET http://localhost:3338/v1/mint/quote/bolt11/DSGLX9kevM...
curl -X GET https://mint.host:3338/v1/mint/quote/{method}/{quote_id}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, use concrete values in an example.

```

# Minting tokens
**Response:**

After requesting a mint quote and paying the request, the wallet proceeds with minting new tokens by calling the `POST /v1/mint/{method}` endpoint where `method` is the payment method requested (here `bolt11`).
```json
{
"quote": "DSGLX9kevM...",
"request": "lnbc100n1pj4apw9...",
"state": "UNPAID",
"expiry": 1701704757
}
```

---

## Minting Tokens

After completing the payment, the wallet **MUST** send a `POST /v1/mint/{method}` request to mint tokens.

### Request Endpoint

```http
POST https://mint.host:3338/v1/mint/bolt11
POST https://mint.host:3338/v1/mint/{method}
```

The wallet `Alice` includes the following `PostMintBolt11Request` data in its request
### Request Body

The request body **MUST** include:

```json
{
Expand All @@ -105,25 +135,31 @@ The wallet `Alice` includes the following `PostMintBolt11Request` data in its re
}
```

with the `quote` being the quote ID from the previous step and `outputs` being `BlindedMessages` (see [NUT-00][00]) that the wallet requests signatures on whose sum is `amount` as requested in the quote.
- `quote`: The quote ID.
- `outputs`: Blinded messages (see [NUT-00](00.md)) for the requested amount.

The mint `Bob` then responds with a `PostMintBolt11Response`:
### Response

The mint **MUST** respond with a `PostMintResponse`:

```json
{
"signatures": <Array[BlindSignature]>
}
```

where `signatures` is an array of blind signatures on the outputs.
- `signatures`: Blind signatures for the outputs.

---

## Example
### Example: Minting Tokens

Request of `Alice` with curl:
**Request:**

```bash
curl -X POST https://mint.host:3338/v1/mint/bolt11 -H "Content-Type: application/json" -d \
'{
curl -X POST https://mint.host:3338/v1/mint/{method} \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too.

-H "Content-Type: application/json" \
-d '{
"quote": "DSGLX9kevM...",
"outputs": [
{
Expand All @@ -140,7 +176,7 @@ curl -X POST https://mint.host:3338/v1/mint/bolt11 -H "Content-Type: application
}'
```

Response of `Bob`:
**Response:**

```json
{
Expand All @@ -159,11 +195,15 @@ Response of `Bob`:
}
```

If the invoice was not paid yet, `Bob` responds with an error. In that case, `Alice` **CAN** repeat the same request until the Lightning invoice is settled.
If the payment is incomplete, the mint **MUST** return an error. The wallet **SHOULD** retry until the payment is completed.

---

### Unblinding Signatures

## Unblinding signatures
After receiving blind signatures, the wallet **MUST** unblind them to generate `Proofs`. This involves the blinding factor `r` and the mint's public key `K` (see BDHKE in [NUT-00](00.md)).

Upon receiving the `BlindSignatures` from the mint `Bob`, the wallet of `Alice` unblinds them to generate `Proofs` (using the blinding factor `r` and the mint's public key `K`, see BDHKE [NUT-00][00]). The wallet then stores these `Proofs` in its database:
The wallet **MUST** store the `Proofs` in its database:

```json
[
Expand All @@ -184,7 +224,7 @@ Upon receiving the `BlindSignatures` from the mint `Bob`, the wallet of `Alice`

## Settings

The settings for this nut indicate the supported method-unit pairs for minting and whether minting is disabled or not. They are part of the info response of the mint ([NUT-06][06]) which in this case reads
The mint's [NUT-06](06.md) settings **MUST** indicate supported method-unit pairs for minting. It **MUST** also specify whether minting is disabled.

```json
{
Expand All @@ -198,22 +238,17 @@ The settings for this nut indicate the supported method-unit pairs for minting a
}
```

`MintMethodSetting` indicates supported `method` and `unit` pairs and additional settings of the mint. `disabled` indicates whether this minting is disabled.

`MintMethodSetting` is of the form:
`MintMethodSetting` indicates supported `method` and `unit` pairs. The `disabled` field indicates whether this minting is disabled. The `min_amount` and `max_amount` fields indicate the minimum and maximum amount for an operation of this method-unit pair.

```json
{
"method": <str>,
"unit": <str>,
"min_amount": <int|null>,
"max_amount": <int|null>,
"description": <bool|null>
}
```

`min_amount` and `max_amount` indicate the minimum and maximum amount for an operation of this method-unit pair.

Example `MintMethodSetting`:

```json
Expand All @@ -222,20 +257,8 @@ Example `MintMethodSetting`:
"unit": "sat",
"min_amount": 0,
"max_amount": 10000,
"description": true
}
```

[00]: 00.md
[01]: 01.md
[02]: 02.md
[03]: 03.md
[04]: 04.md
[05]: 05.md
[06]: 06.md
[07]: 07.md
[08]: 08.md
[09]: 09.md
[10]: 10.md
[11]: 11.md
[12]: 12.md
# Well-Known Payment Methods
- [bolt11](20.md)
Loading