Appearance
Sending Payments
Lightning payments are used to pay invoices, which are typically encoded as a string in accordance with BOLT 11. After parsing the invoice, you'll need to find a route from your node to the recipient and then make the payment using ChannelManager.
rust
use lightning_invoice::Bolt11Invoice;
use lightning::ln::channelmanager::{PaymentId, Retry, RouteParametersConfig};
use bitcoin::hashes::Hash;
use std::str::FromStr;
use std::time::Duration;
// Parse the invoice.
let invoice = Bolt11Invoice::from_str(encoded_invoice)
.expect("ERROR: failed to parse invoice");
// `pay_for_bolt11_invoice` derives the route parameters and retries internally.
// The old `router::get_route` + `send_payment(&route, ..)` flow and the
// `InvoicePayer` abstraction were removed.
let payment_id = PaymentId((*invoice.payment_hash()).to_byte_array());
channel_manager
.pay_for_bolt11_invoice(
&invoice,
payment_id,
None, // amount_msats: None uses the invoice's amount
RouteParametersConfig::default(),
Retry::Timeout(Duration::from_secs(10)),
)
.expect("ERROR: failed to send payment");java
// Get an invoice from the recipient/payee
val parseRes = Bolt11Invoice.from_str(recipientInvoice)
val invoice = (parseRes as Result_Bolt11InvoiceParseOrSemanticErrorZ.Result_Bolt11InvoiceParseOrSemanticErrorZ_OK).res
// `UtilMethods.payment_parameters_from_invoice` was removed —
// `pay_for_bolt11_invoice` builds the route parameters for you.
val res = channelManager.pay_for_bolt11_invoice(
invoice,
paymentId, // ByteArray (32) — your idempotency id
Option_u64Z.none(), // amount_msats (none = use invoice amount)
RouteParametersConfig.with_default(),
Retry.attempts(5)
)
if (res.is_ok) {
// Payment success
}typescript
import * as ldk from "lightningdevkit";
// Parse the invoice.
const parsed = ldk.Bolt11Invoice.constructor_from_str(invoiceString);
if (!(parsed instanceof ldk.Result_Bolt11InvoiceParseOrSemanticErrorZ_OK)) {
return; // invalid invoice
}
const invoice = parsed.res;
// The TS bindings have no `pay_for_bolt11_invoice` helper, and
// `payment_parameters_from_invoice` was removed — build route params from the
// invoice, then call `send_payment`.
const paymentParams = ldk.PaymentParameters.constructor_from_bolt11_invoice(invoice);
const amtMsat = (invoice.amount_milli_satoshis() as ldk.Option_u64Z_Some).some;
const routeParams = ldk.RouteParameters.constructor_from_payment_params_and_value(
paymentParams,
amtMsat
);
const res = channelManager.send_payment(
invoice.payment_hash(), // Uint8Array
ldk.RecipientOnionFields.constructor_secret_only(invoice.payment_secret()),
paymentId, // Uint8Array — your idempotency id
routeParams,
ldk.Retry.constructor_attempts(5)
);
if (res.is_ok()) {
// Payment sent
}PaymentSent & PaymentFailed Event Handling
An event is generated once a payment has completed. Successful payments result in a PaymentSent event with the preimage of the payment hash. Be sure to look out for a PaymentFailed event, if the payment fails for some reason, and act accordingly.
rust
// In the async event handler passed to process_events_async.
// Note `PaymentFailed` now carries `payment_id` + optional `reason`
// (the old `rejected_by_dest` field is gone).
match event {
Event::PaymentSent { payment_preimage, payment_hash, .. } => {
// Handle successful payment
}
Event::PaymentFailed { payment_id, payment_hash, reason } => {
// Handle failed payment
}
// ...
_ => {}
}java
// In your ChannelManagerConstructor.EventHandler
if (event is Event.PaymentSent) {
// Handle successful payment
}
if (event is Event.PaymentFailed) {
// Handle failed payment
}typescript
import * as ldk from "lightningdevkit";
// In your EventHandler (see Handling Events)
if (event instanceof ldk.Event_PaymentSent) {
// Handle successful payment
} else if (event instanceof ldk.Event_PaymentFailed) {
// Handle failed payment
}References: Rust PaymentSent docs, Rust PaymentFailed docs, Java/Kotlin Event bindings, TypeScript Event bindings