NUT-05: Melting tokens¶
mandatory
used in: NUT-08, NUT-15
Melting tokens is the opposite of minting tokens (see NUT-04). Like minting tokens, melting is a two-step process: requesting a melt quote and melting tokens. Here, we describe both steps.
In the first request the wallet asks the mint for a quote for a request
it wants paid by the mint and the unit
the wallet would like to spend as inputs. The mint responds with a quote that includes a quote
id and an amount
the mint demands in the requested unit. For the method bolt11
, the mint includes a fee_reserve
field indicating the reserve fee for a Lightning payment.
In the second request, the wallet includes the quote
id and provides inputs
that sum up to amount+fee_reserve
in the first response. For the method bolt11
, the wallet can also include outputs
in order for the mint to return overpaid Lightning fees (see NUT-08). The mint responds with a payment state
. If the state
is "PAID"
the response includes a payment_preimage
as a proof of payment. If the request included outputs
, the mint may respond with change
for the overpaid fees (see NUT-08).
We limit this document to mint quotes of unit="sat"
and method="bolt11"
which requests a bolt11 Lightning payment (typically paid by the mint from its Bitcoin reserves) using ecash denominated in Satoshis.
Melt quote¶
To request a melt quote, the wallet of Alice
makes a POST /v1/melt/quote/{method}
request where method
is the payment method requested (here bolt11
).
POST https://mint.host:3338/v1/melt/quote/bolt11
The wallet Alice
includes the following PostMeltQuoteBolt11Request
data in its request:
{
"request": <str>,
"unit": <str_enum["sat"]>
}
Here, request
is the bolt11 Lightning invoice to be paid and unit
is the unit the wallet would like to pay with.
The mint Bob
then responds with a PostMeltQuoteBolt11Response
:
{
"quote": <str>,
"amount": <int>,
"fee_reserve": <int>,
"state": <str_enum[STATE]>,
"expiry": <int>,
"payment_preimage": <str|null>
}
Where quote
is the quote ID, amount
the amount that needs to be provided, and fee_reserve
the additional fee reserve that is required. The mint expects Alice
to include Proofs
of at least total_amount = amount + fee_reserve
. expiry
is the Unix timestamp until which the melt quote is valid. payment_preimage
is the bolt11 payment preimage in case of a successful payment.
state
is an enum string field with possible values "UNPAID"
, "PENDING"
, "PAID"
:
"UNPAID"
means that the request has not been paid yet."PENDING"
means that the request is currently being paid."PAID"
means that the request has been paid successfully.
Example¶
Request of Alice
with curl:
curl -X POST https://mint.host:3338/v1/melt/quote/bolt11 -d \
{
"request": "lnbc100n1p3kdrv5sp5lpdxzghe5j67q...",
"unit": "sat"
}
Response of Bob
:
{
"quote": "TRmjduhIsPxd...",
"amount": 10,
"fee_reserve": 2,
"state": "UNPAID",
"expiry": 1701704757
}
Check melt quote state¶
To check whether a melt quote has been paid, Alice
makes a GET /v1/melt/quote/bolt11/{quote_id}
.
GET https://mint.host:3338/v1/melt/quote/bolt11/{quote_id}
Like before, the mint Bob
responds with a PostMeltQuoteBolt11Response
.
Example request of Alice
with curl:
curl -X GET http://localhost:3338/v1/melt/quote/bolt11/TRmjduhIsPxd...
Melting tokens¶
Now that Alice
knows what the total amount is (amount + fee_reserve
) in her requested unit
, she can proceed to melting tokens for which a payment will be executed by the mint. She calls the POST /v1/melt/{method}
endpoint where method
is the payment method requested (here bolt11
).
POST https://mint.host:3338/v1/melt/bolt11
⚠️ Attention: This call will block until the Lightning payment either succeeds or fails. This can take quite a long time in case the Lightning payment is slow. Make sure to use no (or a very long) timeout when making this call!
The wallet of Alice
includes the following PostMeltBolt11Request
data in its request
{
"quote": <str>,
"inputs": <Array[Proof]>
}
Here, quote
is the melt quote ID to be paid and inputs
are the proofs with a total amount of at least amount + fee_reserve
(see previous melt quote response).
Like before, the mint Bob
then responds with a PostMeltQuoteBolt11Response
. If the payment was successful, the state
field is set to "PAID"
and the response includes the payment_preimage
field containing the payment secret of the bolt11 payment.
If state=="PAID"
, Alice
's wallet can delete the inputs
from her database (or move them to a history). If state=="UNPAID"
, Alice
can repeat the same request again until the payment is successful.
Example¶
Request of Alice
with curl:
curl -X POST https://mint.host:3338/v1/melt/bolt11 -d \
'{
"quote": "od4CN5smMMS3K3QVHkbGGNCTxfcAIyIXeq8IrfhP",
"inputs": [
{
"amount": 4,
"id": "009a1f293253e41e",
"secret": "429700b812a58436be2629af8731a31a37fce54dbf8cbbe90b3f8553179d23f5",
"C": "03b01869f528337e161a6768b480fcf9f75fd248b649c382f5e352489fd84fd011",
},
{
"amount": 8,
"id": "009a1f293253e41e",
"secret": "4f3155acef6481108fcf354f6d06e504ce8b441e617d30c88924991298cdbcad",
"C": "0278ab1c1af35487a5ea903b693e96447b2034d0fd6bac529e753097743bf73ca9",
}
]
}'
Response PostMeltQuoteBolt11Response
of Bob
:
{
"quote": "TRmjduhIsPxd...",
"amount": 10,
"fee_reserve": 2,
"state": "PAID",
"expiry": 1701704757,
"payment_preimage": "c5a1ae1f639e1f4a3872e81500fd028bece7bedc1152f740cba5c3417b748c1b"
}
Settings¶
The mint's settings for this nut indicate the supported method-unit pairs for melting. They are part of the info response of the mint (NUT-06) which in this case reads
{
"5": {
"methods": [
<MeltMethodSetting>,
...
],
"disabled": <bool>
}
}
MeltMethodSetting
indicates supported method
and unit
pairs and additional settings of the mint. disabled
indicates whether melting is disabled.
MeltMethodSetting
is of the form:
{
"method": <str>,
"unit": <str>,
"min_amount": <int|null>,
"max_amount": <int|null>
}
min_amount
and max_amount
indicate the minimum and maximum amount for an operation of this method-unit pair.
Example MeltMethodSetting
:
{
"method": "bolt11",
"unit": "sat",
"min_amount": 100,
"max_amount": 10000
}