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]>,
"method": "bolt11",
"amount_paid": <int>,
"amount_issued": <int>,
"updated_at": <int>,
"state": <str_enum[STATE]>, // Deprecated, optional
"expiry": <int|null>
}
amount_paid, amount_issued, and
updated_at are defined in NUT-04.
state is a deprecated 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 quote’s request has been paid but the ecash is not issued yet."ISSUED"means that the quote has been paid and the ecash has been issued.
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).
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": "019e6d5a-2347-7000-8322-05d51d498303",
"request": "lnbc100n1pj4apw9...",
"amount": 10,
"unit": "sat",
"method": "bolt11",
"amount_paid": 0,
"amount_issued": 0,
"updated_at": 1701704657,
"state": "UNPAID",
"expiry": 1701704757
}
Check mint quote:
curl -X GET http://localhost:3338/v1/mint/quote/bolt11/019e6d5a-2347-7000-8322-05d51d498303
Minting tokens:
curl -X POST https://mint.host:3338/v1/mint/bolt11 -H "Content-Type: application/json" -d \
'{
"quote": "019e6d5a-2347-7000-8322-05d51d498303",
"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]>,
"method": "bolt11",
"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.
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):
{
"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]>,
"method": "bolt11",
"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": "019e6d5a-2347-7000-8449-370fefb42fed",
"request": "lnbc100n1p3kdrv5sp5lpdxzghe5j67q...",
"amount": 10,
"unit": "sat",
"method": "bolt11",
"fee_reserve": 2,
"state": "UNPAID",
"expiry": 1701704757
}
Check quote state:
curl -X GET http://localhost:3338/v1/melt/quote/bolt11/019e6d5a-2347-7000-8449-370fefb42fed
Melt request:
curl -X POST https://mint.host:3338/v1/melt/bolt11 -d \
'{"quote": "019e6d5a-2347-7000-8449-370fefb42fed", "inputs": [...]}'
Successful melt response:
{
"quote": "019e6d5a-2347-7000-8449-370fefb42fed",
"request": "lnbc100n1p3kdrv5sp5lpdxzghe5j67q...",
"amount": 10,
"unit": "sat",
"method": "bolt11",
"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
}
}