feat: Initial Support for Bolt12 (Offers, Invoice Fetching and Payment support at API level with CLN RPC)
-I started modifying the code to add Bolt12 offer support to LNBits. -It is now possible to receive payments to invoices associated to a known offer, when using the CLN RPC wallet. -There is a new apioffers table that was created for the DB. Some offer-related fields were also added to apipayments, -In apipayments, I retained the existing format as much as possible, including for the bolt11 field. For bolt12-related invoices, I generate an artificial bolt11 invoice so payments do not get broken for extensions that decode that field. -A create_offer service was added, but currently it is not hooked to any UI or extension (there is however a test for it). -A fetch_invoice function was added to the CLN RPC wallet, but otherwise I have not yet added support to pay to Bolt12 offers.
The bolt12 python package from Rusty is obsolete and is incompatible with the new bolt12 strings. The best I was able to find is to use the CLN RPC to decode bolt12 invoices. When sending to bolt12 offers, a decoded format of the offers will also be required within LNbits. Is it reasonable to assume that wallets can provide bolt12 encoding/decoding functionalities?
I want to see bolt12 integrated into Lnbits but I have a really hard time believing that all of these changes / additions are necessary in order to make that happen.
I want to see bolt12 integrated into Lnbits but I have a really hard time believing that all of these changes / additions are necessary in order to make that happen.
Well, everything about offers has to be added, and bolt11 decoding functionalities in LNBits run pretty deep in the code base, so this requires some changes as well. As of now the API allows to create offers, list them, enable and disable them. It is also possible to fetch invoices and pay invoices using bolt12 (support only with CLN RPC). The code is still using these "fake" bolt11 invoices for the payment functionalities that rely on them (the bolt11 field of the apipayments table is still storing bolt11 invoices, not bolt12). I would be cleaner to accept bolt12 data for this field as well, but this would likely break more things.
If any reviewer could give me some initial feedback about this support for bolt12 it would be great! Thanks!
Besides the bolt11 field in the apipayments table, another area that I have not modified yet and where I could use input is the decode functionality of the payment API, which I have not modified yet. Currently it is returning a bolt11-specific dictionary. Whenever I needed decoding for the payment services code, I used a new decode_invoice function I wrote for the wallets, which uses an unified format for the main invoice data (InvoiceData) that can work for both bolt11 and bolt12. However if the decode API functionality is meant to provide access to all fields, it might be more challenging to modify this to use a unified data format that could also work for bolt12, while maintaining backward compatibility for existing code. Another option would be to output a different dictionary depending on the type of invoice, with an added key identifying if bolt12 has been decoded or not, but this somewhat pushes the issue to the user of /decode...
thanks for your contribution, i like it :D bolt12 is a huge topic and we need to make sure we implement it the right way. in some places your pr feels a bit heavy weight, but in general its good. someone in the lnbits core need to fully champion the bolt12 integration and this is a good place to start.
thanks for your contribution, i like it :D bolt12 is a huge topic and we need to make sure we implement it the right way. in some places your pr feels a bit heavy weight, but in general its good. someone in the lnbits core need to fully champion the bolt12 integration and this is a good place to start.
Thank you for looking at it. I am working on other components around this PR (dependencies, extension) to make it fully usable. Please let me know if there are other things I could do to help.
I think it might be a good idea to keep those components separate so that this PR can be processed in bite-sized pieces. Honestly, if there was a way to break this apart into a few different PRs that might help move this along. I know that the LNBits folks have it on their radar, though.
I think it might be a good idea to keep those components separate so that this PR can be processed in bite-sized pieces. Honestly, if there was a way to break this apart into a few different PRs that might help move this along. I know that the LNBits folks have it on their radar, though.
Thank you. Yes I was not planning to lump the new stuff with this PR. Glad to hear that this is on their radar! :)
I have been working at implementing support for this in an extension, and I am now considering to add a bolt12 column to the apipayments table, so the invoice string is directly accessible from a Payment class instance if desired. In multiple places LNbits uses bolt11_decode to extract the payment_hash and/or the description from the bolt11 string, so I was thinking of maybe leaving in the fake bolt11 invoice I have been generating in order to avoid breaking backward compatibility, but this bolt12 column could be used by the code that supports it. What do you think? Thanks
I have found another thing. Internal invoices are not working with the current version of this PR, as invoices are only discovered once a payment is received, due to the inexistence of push notification from CLN regarding invoice creation. So the best way I see for internal bolt12 payments in _pay_internal_invoice is to search for an offer with a matching offer_id in the apioffers table, then if there is one, look for a matching invoice at the funding source level using the payment_hash, then tag the payment as internal if this is the case.
I have found another thing. Internal invoices are not working with the current version of this PR, as invoices are only discovered once a payment is received, due to the inexistence of push notification from CLN regarding invoice creation. So the best way I see for internal bolt12 payments in _pay_internal_invoice is to search for an offer with a matching offer_id in the apioffers table, then if there is one, look for a matching invoice at the funding source level using the payment_hash, then tag the payment as internal if this is the case.
It is now fixed: https://github.com/lnbits/lnbits/pull/3092/commits/ff11d955da719097271349d790e36c942b2630df
I just sent a PR to add bolt12 support to the NWC Provider extension, building on the work to add bolt12 support to lnbits: https://github.com/riccardobl/nwcprovider/pull/12
I just sent a PR to add bolt12 support to NWC (NIP-47): https://github.com/nostr-protocol/nips/pull/1952