Skip to content
Open
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
5 changes: 3 additions & 2 deletions 04.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ Depending on the payment method, the request structure may vary, but all methods
"unit": <str_enum[UNIT]>,
"amount": <int>, // Optional
"description": <str>, // Optional
"pubkey": <str> // Optional, NUT-20
"pubkey": <str>, // Optional, NUT-20
"expiry_seconds": <int> // Optional
// Additional method-specific fields may be required
}
```

`amount`, `description` and `pubkey` are common optional fields; method-specific NUTs make them required or ignore them as needed (e.g. NUT-23 requires `amount`, NUT-20 defines `pubkey`).
`amount`, `description`, `pubkey`, and `expiry_seconds` are common optional fields. Method-specific NUTs define their use.

The mint `Bob` responds with a quote that includes some common fields for all methods:

Expand Down
5 changes: 3 additions & 2 deletions 20.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ The wallet of `Alice` includes the following `PostMintQuoteBolt11Request` data i
"amount": <int>,
"unit": <str_enum["sat"]>,
"description": <str|null>, // Optional
"pubkey": <str|null> // Optional <-- New
"pubkey": <str|null>, // Optional <-- New
"expiry_seconds": <int> // Optional, NUT-23
}
```

Expand Down Expand Up @@ -82,7 +83,7 @@ The response is the same as the `bolt11` mint quote response in [NUT-23][23] exc
Request of `Alice` with curl:

```bash
curl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{"amount": 10, "unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac"}' -H "Content-Type: application/json"
curl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{"amount": 10, "unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac", "expiry_seconds": 100}' -H "Content-Type: application/json"
```

Response of `Bob`:
Expand Down
18 changes: 13 additions & 5 deletions 23.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ For the `bolt11` method, the wallet includes the following specific `PostMintQuo
{
"amount": <int>,
"unit": <str_enum[UNIT]>,
"description": <str> // Optional
"description": <str>, // Optional
"expiry_seconds": <int> // Optional
}
```

`expiry_seconds` is the requested quote lifetime in seconds from quote creation. If omitted, the mint uses its default lifetime.

Mints **MUST** return error `11018` if `expiry_seconds` is not positive, exceeds their maximum, or cannot be honored exactly. Mints **MUST NOT** silently clamp it.

The mint responds with a `PostMintQuoteBolt11Response`:

```json
Expand All @@ -33,7 +38,7 @@ The mint responds with a `PostMintQuoteBolt11Response`:
"amount_issued": <int>,
"updated_at": <int>,
"state": <str_enum[STATE]>, // Deprecated, optional
"expiry": <int|null>
"expiry": <int>
}
```

Expand All @@ -47,14 +52,14 @@ The mint responds with a `PostMintQuoteBolt11Response`:

Wallets **SHOULD** use `amount_paid` and `amount_issued` instead of `state` whenever these fields are present.

`expiry` is the Unix timestamp until which the `request` can be paid (i.e. the bolt11 invoice expiry).
`expiry` is the invoice timestamp plus its BOLT11 expiry duration, expressed as a Unix timestamp. If `expiry_seconds` was set, it **MUST** be used as the invoice expiry duration.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should the default include a buffer for the HTLC timeouts too? If a payment is made close to LN invoice expiry, it may arrive after the expiry time and not be credited.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Mints should honor payments even expiry is reached. Wallets should do their best to check quotes that are technically expired but might have received a payment.


### Example

Request with curl:

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

Response:
Expand Down Expand Up @@ -124,6 +129,8 @@ Response:

A `description` option **MUST** be set to indicate whether the `bolt11` payment method backend supports providing an invoice description.

`max_expiry_seconds` is the maximum `expiry_seconds` accepted by the mint. If omitted, the maximum is unknown.

### Example `MintMethodSetting`

```json
Expand All @@ -133,7 +140,8 @@ A `description` option **MUST** be set to indicate whether the `bolt11` payment
"min_amount": 0,
"max_amount": 10000,
"options": {
"description": true
"description": true,
"max_expiry_seconds": 86400
}
}
```
Expand Down
16 changes: 12 additions & 4 deletions 25.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@ For the `bolt12` method, the wallet includes the following specific `PostMintQuo
"amount": <int|null>,
"unit": <str_enum[UNIT]>,
"description": <str|null>,
"pubkey": <str>
"pubkey": <str>,
"expiry_seconds": <int> // Optional
}
```

> **Note:** While a pubkey is optional as per [NUT-20][20] for [NUT-04][04] it is required in this NUT and the mint **MUST NOT** issue a mint quote if one is not included.

> **Privacy:** To prevent linking multiple mint quotes together, wallets **SHOULD** generate a unique public key for each mint quote request.

`expiry_seconds` is the requested quote lifetime in seconds from quote creation. If omitted, the mint uses its default lifetime.

Mints **MUST** return error `11018` if `expiry_seconds` is not positive, exceeds their maximum, or cannot be honored exactly. Mints **MUST NOT** silently clamp it.

The mint responds with a `PostMintQuoteBolt12Response`:

```json
Expand All @@ -46,7 +51,7 @@ Where:

- `quote` is the quote ID
- `request` is the bolt12 offer
- `expiry` is the Unix timestamp until which the mint quote is valid
- `expiry` is the BOLT12 offer's absolute expiry, or `null` if it does not expire. If `expiry_seconds` was set, `expiry` **MUST** equal the quote creation time plus `expiry_seconds`
- `amount_paid` is the amount that has been paid to the mint via the bolt12 offer
- `amount_issued` is the amount of ecash that has been issued for the given mint quote
- `updated_at` is defined in [NUT-04][04]
Expand All @@ -57,7 +62,7 @@ Where:

```bash
curl -X POST http://localhost:3338/v1/mint/quote/bolt12 -d \
'{"amount": 10, "unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac"}' \
'{"amount": 10, "unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac", "expiry_seconds": 100}' \
-H "Content-Type: application/json"
```

Expand Down Expand Up @@ -132,6 +137,8 @@ Unlike BOLT11 invoices, BOLT12 offers can be paid multiple times, allowing the w

A `description` option **SHOULD** be set to indicate whether the `bolt12` payment method backend supports providing an offer description.

`max_expiry_seconds` is the maximum `expiry_seconds` accepted by the mint. If omitted, the maximum is unknown.

### Example `MintMethodSetting`

```json
Expand All @@ -141,7 +148,8 @@ A `description` option **SHOULD** be set to indicate whether the `bolt12` paymen
"min_amount": <int|null>,
"max_amount": <int|null>,
"options": {
"description": true
"description": true,
"max_expiry_seconds": 86400
}
}
```
Expand Down
20 changes: 15 additions & 5 deletions 30.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@ For the `onchain` method, the wallet includes the following specific `PostMintQu
```json
{
"unit": <str_enum[UNIT]>,
"pubkey": <str>
"pubkey": <str>,
"expiry_seconds": <int> // Optional
}
```

> **Note:** A [NUT-20][20] `pubkey` is required in this NUT and the mint **MUST NOT** issue a mint quote if one is not included.

`expiry_seconds` is the requested quote lifetime in seconds from quote creation. If omitted, the quote does not expire.

Mints **MUST** return error `11018` if `expiry_seconds` is not positive, exceeds their maximum, or cannot be honored exactly. Mints **MUST NOT** silently clamp it.

The mint responds with a `PostMintQuoteOnchainResponse`:

```json
Expand All @@ -41,21 +46,23 @@ Where:

- `quote` is the quote ID
- `request` is the Bitcoin address to send funds to
- `expiry` is the Unix timestamp until which the mint quote is valid
- `expiry` is the Unix timestamp until which the mint quote is valid, or `null` if `expiry_seconds` was omitted
- `pubkey` is the public key from the request
- `amount_paid` is the total confirmed amount paid to the request in UTXOs that are eligible for minting
- `amount_issued` is the amount of ecash that has been issued for the given mint quote
- `updated_at` is defined in [NUT-04][04]

If `expiry` is not `null`, the wallet **SHOULD NOT** send payments to the request after `expiry`. Mints **MUST** keep monitoring transactions they detected before `expiry` until the transaction reaches the required number of confirmations or is evicted or replaced. Payments first detected by the mint after `expiry` **MUST NOT** increase `amount_paid`.
The Bitcoin address does not expire; `expiry` only limits when payments are credited to the quote. If `expiry_seconds` was set, `expiry` **MUST** equal the quote creation time plus `expiry_seconds`.

When `expiry` is not `null`, the wallet **SHOULD NOT** send payments that may be detected after it, and the mint **MUST** keep monitoring transactions detected before it until they reach the required number of confirmations or are evicted or replaced. The mint **MUST NOT** increase `amount_paid` for payments first detected after `expiry`.

### Example

**Request** with curl:

```bash
curl -X POST http://localhost:3338/v1/mint/quote/onchain -d \
'{"unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac"}' \
'{"unit": "sat", "pubkey": "03d56ce4e446a85bbdaa547b4ec2b073d40ff802831352b8272b7dd7a4de5a7cac", "expiry_seconds": 100}' \
-H "Content-Type: application/json"
```

Expand Down Expand Up @@ -152,6 +159,8 @@ A `confirmations` option **SHOULD** be set to indicate the minimum depth in the

For the `onchain` mint method, `min_amount` indicates both the minimum mint operation amount and the minimum amount of an individual UTXO that the mint will credit to `amount_paid`. Wallets **SHOULD NOT** send onchain payments below `min_amount` to a quote address.

`max_expiry_seconds` is the maximum `expiry_seconds` accepted by the mint. If omitted, the maximum is unknown.

### Example `MintMethodSetting`

```json
Expand All @@ -161,7 +170,8 @@ For the `onchain` mint method, `min_amount` indicates both the minimum mint oper
"min_amount": <int|null>,
"max_amount": <int|null>,
"options": {
"confirmations": <int>
"confirmations": <int>,
"max_expiry_seconds": 86400
}
}
```
Expand Down
4 changes: 4 additions & 0 deletions error_codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
| 11015 | Max outputs exceeded | [NUT-03][03], [NUT-04][04], [NUT-05][05] |
| 11016 | Duplicate quote IDs provided | [NUT-29][29] |
| 11017 | Max batch size exceeded | [NUT-29][29] |
| 11018 | Requested expiry cannot be honored | [NUT-23][23], [NUT-25][25], [NUT-30][30] |
| 12001 | Keyset is not known | [NUT-02][02], [NUT-04][04] |
| 12002 | Keyset is inactive, cannot sign messages | [NUT-02][02], [NUT-03][03], [NUT-04][04] |
| 12003 | Keyset has expired | [NUT-02][02], [NUT-03][03], [NUT-04][04], [NUT-05][05] |
Expand Down Expand Up @@ -55,4 +56,7 @@
[20]: 20.md
[21]: 21.md
[22]: 22.md
[23]: 23.md
[25]: 25.md
[29]: 29.md
[30]: 30.md
Loading