From 75197494e3523008bdbcc05d1734793e3b068909 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Wed, 25 Mar 2026 11:05:53 +0100 Subject: [PATCH] lightningd: include offer_id in invoice_creation notification When a BOLT 12 invoice is created via createinvoice and is associated with a local offer, include the offer_id in the invoice_creation event notification. This allows plugins to determine which offer triggered an invoice creation without having to call listinvoices for every created invoice. For bolt11 invoices and bolt12 invoices not associated with a local offer, the field is omitted. Fixes #8191 Changelog-Added: The `invoice_creation` notification now includes `offer_id` when the invoice is associated with a BOLT 12 offer. --- .../plugin-development/event-notifications.md | 13 +++++++++++++ lightningd/invoice.c | 6 +++--- lightningd/notification.c | 10 +++++++--- lightningd/notification.h | 3 ++- lightningd/test/run-invoice-select-inchan.c | 3 ++- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/doc/developers-guide/plugin-development/event-notifications.md b/doc/developers-guide/plugin-development/event-notifications.md index 4ee034a8548d..ef0779bfd2c5 100644 --- a/doc/developers-guide/plugin-development/event-notifications.md +++ b/doc/developers-guide/plugin-development/event-notifications.md @@ -181,6 +181,19 @@ A notification for topic `invoice_creation` is sent every time an invoice is cre } ``` +If the invoice is associated with a BOLT 12 offer, an `offer_id` field will be present: + +```json +{ + "invoice_creation": { + "label": "unique-label-for-invoice", + "preimage": "0000000000000000000000000000000000000000000000000000000000000000", + "msat": 10000, + "offer_id": "b1d1062abc09790a68be83e4c257614a57978e4053a954bfee5909ed71e23e03" + } +} +``` + Before version `23.11` the `msat` field was a string with msat-suffix, e.g: `"10000msat"`. ### `warning` diff --git a/lightningd/invoice.c b/lightningd/invoice.c index aa9546850404..fefa63ab7366 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -872,7 +872,7 @@ invoice_complete(struct invoice_info *info, json_add_u64(response, "created_index", details->created_index); notify_invoice_creation(info->cmd->ld, info->b11->msat, - &info->payment_preimage, info->label); + &info->payment_preimage, info->label, NULL); if (warning_no_listincoming) json_add_string(response, "warning_listincoming", @@ -1725,7 +1725,7 @@ static struct command_result *json_createinvoice(struct command *cmd, NULL)) return fail_exists(cmd, label); - notify_invoice_creation(cmd->ld, b11->msat, preimage, label); + notify_invoice_creation(cmd->ld, b11->msat, preimage, label, NULL); } else { struct tlv_invoice *inv; struct sha256 offer_id, *local_offer_id; @@ -1822,7 +1822,7 @@ static struct command_result *json_createinvoice(struct command *cmd, local_offer_id)) return fail_exists(cmd, label); - notify_invoice_creation(cmd->ld, &msat, preimage, label); + notify_invoice_creation(cmd->ld, &msat, preimage, label, local_offer_id); } response = json_stream_success(cmd); diff --git a/lightningd/notification.c b/lightningd/notification.c index b2adb64eb72c..c340ced99922 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -221,13 +221,16 @@ void notify_invoice_payment(struct lightningd *ld, static void invoice_creation_notification_serialize(struct json_stream *stream, const struct amount_msat *amount, const struct preimage *preimage, - const struct json_escape *label) + const struct json_escape *label, + const struct sha256 *offer_id) { if (amount != NULL) json_add_amount_msat(stream, "msat", *amount); json_add_preimage(stream, "preimage", preimage); json_add_escaped_string(stream, "label", label); + if (offer_id) + json_add_sha256(stream, "offer_id", offer_id); } REGISTER_NOTIFICATION(invoice_creation) @@ -235,12 +238,13 @@ REGISTER_NOTIFICATION(invoice_creation) void notify_invoice_creation(struct lightningd *ld, const struct amount_msat *amount, const struct preimage *preimage, - const struct json_escape *label) + const struct json_escape *label, + const struct sha256 *offer_id) { struct jsonrpc_notification *n = notify_start(ld, "invoice_creation"); if (!n) return; - invoice_creation_notification_serialize(n->stream, amount, preimage, label); + invoice_creation_notification_serialize(n->stream, amount, preimage, label, offer_id); notify_send(ld, n); } diff --git a/lightningd/notification.h b/lightningd/notification.h index 91454a550ceb..8dff546ccca5 100644 --- a/lightningd/notification.h +++ b/lightningd/notification.h @@ -42,7 +42,8 @@ void notify_invoice_payment(struct lightningd *ld, void notify_invoice_creation(struct lightningd *ld, const struct amount_msat *amount, const struct preimage *preimage, - const struct json_escape *label); + const struct json_escape *label, + const struct sha256 *offer_id); void notify_channel_opened(struct lightningd *ld, const struct node_id *node_id, diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index fc00a7c9c25e..6934417d66d7 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -530,7 +530,8 @@ void notify_disconnect(struct lightningd *ld UNNEEDED, const struct node_id *nod void notify_invoice_creation(struct lightningd *ld UNNEEDED, const struct amount_msat *amount UNNEEDED, const struct preimage *preimage UNNEEDED, - const struct json_escape *label UNNEEDED) + const struct json_escape *label UNNEEDED, + const struct sha256 *offer_id UNNEEDED) { fprintf(stderr, "notify_invoice_creation called!\n"); abort(); } /* Generated stub for notify_invoice_payment */ void notify_invoice_payment(struct lightningd *ld UNNEEDED,