Skip to content

Expose BOLT 12 refunds over gRPC - #262

Open
benthecarman wants to merge 1 commit into
lightningdevkit:mainfrom
benthecarman:2026-08-pruned-bitcoind-docs
Open

Expose BOLT 12 refunds over gRPC#262
benthecarman wants to merge 1 commit into
lightningdevkit:mainfrom
benthecarman:2026-08-pruned-bitcoind-docs

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Clients need both parts of the BOLT 12 refund flow. Add RPCs for creating a refund and requesting its payment, and expose them through the Rust client and CLI.

Add end-to-end coverage for the reverse payment flow and document the new endpoints.

@ldk-reviews-bot

ldk-reviews-bot commented Aug 27, 2026

Copy link
Copy Markdown

👋 Thanks for assigning @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@benthecarman
benthecarman requested review from jkczyz and removed request for wpaulino August 27, 2026 05:37
Comment thread ldk-server/src/api/bolt12_refund.rs Outdated
Comment on lines +43 to +46
let invoice = context.node.bolt12_payment().request_refund_payment(&refund)?;
let payment_id = invoice.payment_hash().to_string();

Ok(Bolt12RequestRefundResponse { payment_id })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm... we can't do this unfortunately as LDK Node was updated to decouple PaymentId from PaymentHash in lightningdevkit/ldk-node#948. Even more unfortunately, we rely on LDK for generating the PaymentId when the payment is received, so LDK Node will only know it when it processes the PaymentClaimable event.

We'll likely want to model Bolt11ReceiveResponse, which returns the PaymentHash, since they are both inbound payments. So in practice we just need to rename the field in the response and update the docs.

@benthecarman benthecarman Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made Bolt12ReceiveRefundResponse return payment_hash

let route_parameters = build_route_parameters_config_from_proto(request.route_parameters)?;
let refund = context.node.bolt12_payment().initiate_refund(
request.amount_msat,
request.expiry_secs,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we reject a 0-expiry? The CLI will give a more reasonable default if left unset, but other clients may forget to set it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment thread docs/api-guide.md Outdated
|------------------------|-------------------------------------------------------------------------|
| `Bolt12Receive` | Create a BOLT12 offer (fixed or variable amount) |
| `Bolt12Send` | Pay a BOLT12 offer (with optional quantity, payer note, routing config) |
| `Bolt12InitiateRefund` | Create a BOLT12 refund |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment thread ldk-server-grpc/src/proto/api.proto Outdated
Comment on lines +404 to +408
message Bolt12InitiateRefundResponse {

// A BOLT12 refund that the recipient can use to request the refund payment.
string refund = 1;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is equivalent to an outbound payment, we should have a payment_id here, but LDK Node doesn't return it. We'll want to do so upstream, IIUC, so we can return it here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, seems more systemic than this PR tho, can defer for now?

Comment thread ldk-server-grpc/src/proto/api.proto Outdated
Comment on lines +1020 to +1023
// Return a BOLT12 refund.
rpc Bolt12InitiateRefund(Bolt12InitiateRefundRequest) returns (Bolt12InitiateRefundResponse);
// Request payment for a BOLT12 refund.
rpc Bolt12RequestRefund(Bolt12RequestRefundRequest) returns (Bolt12RequestRefundResponse);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to break with the LDK Node naming convention and call these Bolt12SendRefund and Bolt12ReceiveRefund, though I don't have a strong opinion. The double "request" is just a bit icky.

@benthecarman benthecarman Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this is better, fixed

Comment thread ldk-server-grpc/src/proto/api.proto Outdated
Comment on lines +1020 to +1023
// Return a BOLT12 refund.
rpc Bolt12InitiateRefund(Bolt12InitiateRefundRequest) returns (Bolt12InitiateRefundResponse);
// Request payment for a BOLT12 refund.
rpc Bolt12RequestRefund(Bolt12RequestRefundRequest) returns (Bolt12RequestRefundResponse);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also need MCP handlers for these.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Clients need both parts of the BOLT 12 refund flow. Add RPCs for
creating a refund and requesting its payment, and expose them through
the Rust client and CLI.

Add end-to-end coverage for the reverse payment flow and document the
new endpoints.

This change was developed with OpenAI Codex assistance.
@benthecarman
benthecarman force-pushed the 2026-08-pruned-bitcoind-docs branch from f6eb35b to 5d630e7 Compare August 28, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants