{"id":"8d3b049a20f9d6a0c9ee432f52a39b8706b15b6723d8c40c724399676fe29754","pubkey":"d1678e7ef965374bbea308a1215609a78376dc158277a7d657680f9d5efd5c38","created_at":1783082300,"kind":30817,"tags":[["d","nut-23"],["title","NUT-23: BOLT11"],["summary","Minting and melting with bolt11 Lightning invoices, the method specifics on top of the shared mint and melt flows."],["s","optional"],["t","cashu"],["t","ecash"],["t","nut"],["alt","A specification: NUT-23: BOLT11"],["client","openspecs-import"],["published_at","1748772883"],["proxy","https://github.com/cashubtc/nuts/blob/a845dfc998abae501fc3419592d53dc995d34b12/23.md","web"],["x","83b6c11cf0c81fec7edb0fb1f2dfe10051ccaf6dd6819100953251efaff56ca6"]],"content":"# NUT-23: BOLT11\n\n`optional`\n\n`depends on: NUT-04 NUT-05`\n\n---\n\nThis document describes minting and melting ecash with the `bolt11` payment method, which uses Lightning Network invoices. It is an extension of [NUT-04][04] and [NUT-05][05] which cover the protocol steps of minting and melting ecash shared by any supported payment method.\n\n## Mint Quote\n\nFor the `bolt11` method, the wallet includes the following specific `PostMintQuoteBolt11Request` data:\n\n```json\n{\n  \"amount\": <int>,\n  \"unit\": <str_enum[UNIT]>,\n  \"description\": <str> // Optional\n}\n```\n\nThe mint responds with a `PostMintQuoteBolt11Response`:\n\n```json\n{\n  \"quote\": <str>,\n  \"request\": <str>, // The bolt11 invoice to pay\n  \"amount\": <int>,\n  \"unit\":  <str_enum[UNIT]>,\n  \"method\": \"bolt11\",\n  \"amount_paid\": <int>,\n  \"amount_issued\": <int>,\n  \"updated_at\": <int>,\n  \"state\": <str_enum[STATE]>, // Deprecated, optional\n  \"expiry\": <int|null>\n}\n```\n\n`amount_paid`, `amount_issued`, and `updated_at` are defined in [NUT-04][04].\n\n`state` is a deprecated enum string field with possible values `\"UNPAID\"`, `\"PAID\"`, `\"ISSUED\"`:\n\n- `\"UNPAID\"` means that the quote's request has not been paid yet.\n- `\"PAID\"` means that the quote's request has been paid but the ecash is not issued yet.\n- `\"ISSUED\"` means that the quote has been paid and the ecash has been issued.\n\nWallets **SHOULD** use `amount_paid` and `amount_issued` instead of `state` whenever these fields are present.\n\n`expiry` is the Unix timestamp until which the `request` can be paid (i.e. the bolt11 invoice expiry).\n\n### Example\n\nRequest with curl:\n\n```bash\ncurl -X POST http://localhost:3338/v1/mint/quote/bolt11 -d '{\"amount\": 10, \"unit\": \"sat\"}' -H \"Content-Type: application/json\"\n```\n\nResponse:\n\n```json\n{\n  \"quote\": \"019e6d5a-2347-7000-8322-05d51d498303\",\n  \"request\": \"lnbc100n1pj4apw9...\",\n  \"amount\": 10,\n  \"unit\": \"sat\",\n  \"method\": \"bolt11\",\n  \"amount_paid\": 0,\n  \"amount_issued\": 0,\n  \"updated_at\": 1701704657,\n  \"state\": \"UNPAID\",\n  \"expiry\": 1701704757\n}\n```\n\nCheck mint quote:\n\n```bash\ncurl -X GET http://localhost:3338/v1/mint/quote/bolt11/019e6d5a-2347-7000-8322-05d51d498303\n```\n\nMinting tokens:\n\n```bash\ncurl -X POST https://mint.host:3338/v1/mint/bolt11 -H \"Content-Type: application/json\" -d \\\n'{\n  \"quote\": \"019e6d5a-2347-7000-8322-05d51d498303\",\n  \"outputs\": [\n    {\n      \"amount\": 8,\n      \"id\": \"009a1f293253e41e\",\n      \"B_\": \"035015e6d7ade60ba8426cefaf1832bbd27257636e44a76b922d78e79b47cb689d\"\n    },\n    {\n      \"amount\": 2,\n      \"id\": \"009a1f293253e41e\",\n      \"B_\": \"0288d7649652d0a83fc9c966c969fb217f15904431e61a44b14999fabc1b5d9ac6\"\n    }\n  ]\n}'\n```\n\nResponse:\n\n```json\n{\n  \"signatures\": [\n    {\n      \"id\": \"009a1f293253e41e\",\n      \"amount\": 2,\n      \"C_\": \"0224f1c4c564230ad3d96c5033efdc425582397a5a7691d600202732edc6d4b1ec\"\n    },\n    {\n      \"id\": \"009a1f293253e41e\",\n      \"amount\": 8,\n      \"C_\": \"0277d1de806ed177007e5b94a8139343b6382e472c752a74e99949d511f7194f6c\"\n    }\n  ]\n}\n```\n\n## Mint Settings\n\nA `description` option **MUST** be set to indicate whether the `bolt11` payment method backend supports providing an invoice description.\n\n### Example `MintMethodSetting`\n\n```json\n{\n  \"method\": \"bolt11\",\n  \"unit\": \"sat\",\n  \"min_amount\": 0,\n  \"max_amount\": 10000,\n  \"options\": {\n    \"description\": true\n  }\n}\n```\n\n## Melt Quote\n\nFor the `bolt11` method, the wallet includes the following specific `PostMeltQuoteBolt11Request` data:\n\n```json\n{\n  \"request\": <str>,\n  \"unit\": <str_enum[UNIT]>,\n  \"options\": { // Optional\n    \"amountless\": {\n      \"amount_msat\": <int>\n    }\n  }\n}\n```\n\nHere, `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.\n\nThe mint responds with a `PostMeltQuoteBolt11Response`:\n\n```json\n{\n  \"quote\": <str>,\n  \"request\": <str>,\n  \"amount\": <int>,\n  \"unit\": <str_enum[UNIT]>,\n  \"method\": \"bolt11\",\n  \"fee_reserve\": <int>,\n  \"state\": <str_enum[STATE]>,\n  \"expiry\": <int>,\n  \"payment_preimage\": <str|null>\n}\n```\n\nWhere `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].\n\n### Melting Tokens\n\nFor 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]):\n\n```json\n{\n  \"quote\": <str>,\n  \"inputs\": <Array[Proof]>,\n  \"outputs\": <Array[BlindedMessage]> // Optional\n}\n```\n\nIf 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:\n\n```json\n{\n  \"quote\": <str>,\n  \"request\": <str>,\n  \"amount\": <int>,\n  \"unit\": <str_enum[UNIT]>,\n  \"method\": \"bolt11\",\n  \"fee_reserve\": <int>,\n  \"state\": <str_enum[STATE]>,\n  \"expiry\": <int>,\n  \"payment_preimage\": <str>,\n  \"change\": <Array[BlindSignature]> // Present if outputs were included and there's change\n}\n```\n\n### Example\n\nMelt quote request:\n\n```bash\ncurl -X POST https://mint.host:3338/v1/melt/quote/bolt11 -d \\\n'{\"request\": \"lnbc100n1p3kdrv5sp5lpdxzghe5j67q...\", \"unit\": \"sat\"}'\n```\n\nMelt quote response:\n\n```json\n{\n  \"quote\": \"019e6d5a-2347-7000-8449-370fefb42fed\",\n  \"request\": \"lnbc100n1p3kdrv5sp5lpdxzghe5j67q...\",\n  \"amount\": 10,\n  \"unit\": \"sat\",\n  \"method\": \"bolt11\",\n  \"fee_reserve\": 2,\n  \"state\": \"UNPAID\",\n  \"expiry\": 1701704757\n}\n```\n\nCheck quote state:\n\n```bash\ncurl -X GET http://localhost:3338/v1/melt/quote/bolt11/019e6d5a-2347-7000-8449-370fefb42fed\n```\n\nMelt request:\n\n```bash\ncurl -X POST https://mint.host:3338/v1/melt/bolt11 -d \\\n'{\"quote\": \"019e6d5a-2347-7000-813e-a11ea6e419e7\", \"inputs\": [...]}'\n```\n\nSuccessful melt response:\n\n```json\n{\n  \"quote\": \"019e6d5a-2347-7000-8449-370fefb42fed\",\n  \"request\": \"lnbc100n1p3kdrv5sp5lpdxzghe5j67q...\",\n  \"amount\": 10,\n  \"unit\": \"sat\",\n  \"method\": \"bolt11\",\n  \"fee_reserve\": 2,\n  \"state\": \"PAID\",\n  \"expiry\": 1701704757,\n  \"payment_preimage\": \"c5a1ae1f639e1f4a3872e81500fd028bece7bedc1152f740cba5c3417b748c1b\"\n}\n```\n\n### Example `MeltMethodSetting`\n\n```json\n{\n  \"method\": \"bolt11\",\n  \"unit\": \"sat\",\n  \"min_amount\": 100,\n  \"max_amount\": 10000,\n  \"options\": {\n    \"amountless\": true\n  }\n}\n```\n\n[04]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595crg74fknc\n[05]: nostr:naddr1qvzqqqrcvypzp5t83el0jefhfwl2xz9py9tqnfurwmwptqnh5lt9w6q0n4006hpcqqrxuat595cr2dsg4q4\n","sig":"dc3e8ac036a9fbe82c54caebe4d123ed5a73d64bbe9e5ff953f9aa7ab48d543934d75e52f9cba274497be57d21bb25319c0038fe8e22d639afe091b70f2d1631"}