NUT-23: BOLT11¶
optional
depends on: NUT-04 NUT-05
This document describes minting and melting ecash with the bolt11
payment method, which uses Lightning Network invoices. It is an extension of NUT-04 and NUT-05 which cover the protocol steps of minting and melting ecash shared by any supported payment method.
Mint Quote¶
For the bolt11
method, the wallet includes the following specific PostMintQuoteBolt11Request
data:
{
"amount": <int>,
"unit": <str_enum[UNIT]>,
"description": <str> // Optional
}
The mint responds with a PostMintQuoteBolt11Response
:
{
"quote": <str>,
"request": <str>, // The bolt11 invoice to pay
"amount": <int>,
"unit": <str_enum[UNIT]>,
"state": <str_enum[STATE]>,
"expiry": <int|null>
}
state
is an enum string field with possible values "UNPAID"
, "PAID"
, "ISSUED"
:
"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.
expiry
is the Unix timestamp until which the request
can be paid (i.e. the bolt11 invoice expiry).
Example¶
Request with curl:
curl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{"amount": 10, "unit": "sat"}' -H "Content-Type: application/json"
Response:
{
"quote": "DSGLX9kevM...",
"request": "lnbc100n1pj4apw9...",
"amount": 10,
"unit": "sat",
"state": "UNPAID",
"expiry": 1701704757
}
Check quote state:
curl -X GET http://localhost:3338/v1/mint/quote/bolt11/DSGLX9kevM...
Minting tokens:
curl -X POST https://mint.host:3338/v1/mint/bolt11 -H "Content-Type: application/json" -d \
'{
"quote": "DSGLX9kevM...",
"outputs": [
{
"amount": 8,
"id": "009a1f293253e41e",
"B_": "035015e6d7ade60ba8426cefaf1832bbd27257636e44a76b922d78e79b47cb689d"
},
{
"amount": 2,
"id": "009a1f293253e41e",
"B_": "0288d7649652d0a83fc9c966c969fb217f15904431e61a44b14999fabc1b5d9ac6"
}
]
}'
Response:
{
"signatures": [
{
"id": "009a1f293253e41e",
"amount": 2,
"C_": "0224f1c4c564230ad3d96c5033efdc425582397a5a7691d600202732edc6d4b1ec"
},
{
"id": "009a1f293253e41e",
"amount": 8,
"C_": "0277d1de806ed177007e5b94a8139343b6382e472c752a74e99949d511f7194f6c"
}
]
}
Mint Settings¶
A description
option MUST be set to indicate whether the bolt11
payment method backend supports providing an invoice description.
Example MintMethodSetting
¶
{
"method": "bolt11",
"unit": "sat",
"min_amount": 0,
"max_amount": 10000,
"options": {
"description": true
}
}
Melt Quote¶
For the bolt11
method, the wallet includes the following specific PostMeltQuoteBolt11Request
data:
{
"request": <str>,
"unit": <str_enum[UNIT]>,
"options": { // Optional
"amountless": {
"amount_msat": <int>
}
}
}
Here, request
is the bolt11 Lightning invoice to be paid and unit
is the unit the wallet would like to pay with. The options
field can include support for amountless invoices if supported by the mint.
The mint responds with a PostMeltQuoteBolt11Response
:
{
"quote": <str>,
"request": <str>,
"amount": <int>,
"unit": <str_enum[UNIT]>,
"fee_reserve": <int>,
"state": <str_enum[STATE]>,
"expiry": <int>,
"payment_preimage": <str|null>
}
Where fee_reserve
is the additional fee reserve required for the Lightning payment. The mint expects the wallet to include Proofs
of at least total_amount = amount + fee_reserve + fee
where fee
is calculated from the keyset's input_fee_ppk
as described in [NUT-02][02].
Melting Tokens¶
For the bolt11
method, the wallet can include an optional outputs
field in the melt request to receive change for overpaid Lightning fees (see [NUT-08][08]):
{
"quote": <str>,
"inputs": <Array[Proof]>,
"outputs": <Array[BlindedMessage]> // Optional
}
If the outputs
field is included and there is excess from the fee_reserve
, the mint will respond with a change
field containing blind signatures for the overpaid amount:
{
"quote": <str>,
"request": <str>,
"amount": <int>,
"unit": <str_enum[UNIT]>,
"fee_reserve": <int>,
"state": <str_enum[STATE]>,
"expiry": <int>,
"payment_preimage": <str>,
"change": <Array[BlindSignature]> // Present if outputs were included and there's change
}
Example¶
Melt quote request:
curl -X POST https://mint.host:3338/v1/melt/quote/bolt11 -d \
'{"request": "lnbc100n1p3kdrv5sp5lpdxzghe5j67q...", "unit": "sat"}'
Melt quote response:
{
"quote": "TRmjduhIsPxd...",
"request": "lnbc100n1p3kdrv5sp5lpdxzghe5j67q...",
"amount": 10,
"unit": "sat",
"fee_reserve": 2,
"state": "UNPAID",
"expiry": 1701704757
}
Check quote state:
curl -X GET http://localhost:3338/v1/melt/quote/bolt11/TRmjduhIsPxd...
Melt request:
curl -X POST https://mint.host:3338/v1/melt/bolt11 -d \
'{"quote": "od4CN5smMMS3K3QVHkbGGNCTxfcAIyIXeq8IrfhP", "inputs": [...]}'
Successful melt response:
{
"quote": "TRmjduhIsPxd...",
"request": "lnbc100n1p3kdrv5sp5lpdxzghe5j67q...",
"amount": 10,
"unit": "sat",
"fee_reserve": 2,
"state": "PAID",
"expiry": 1701704757,
"payment_preimage": "c5a1ae1f639e1f4a3872e81500fd028bece7bedc1152f740cba5c3417b748c1b"
}
Example MeltMethodSetting
¶
{
"method": "bolt11",
"unit": "sat",
"min_amount": 100,
"max_amount": 10000,
"options": {
"amountless": true
}
}