Skip to content

Receiving Payments

To receive a payment, you'll need to create an invoice of your own with an amount and description. ChannelManager contains the remaining information needed for the invoice. Use the provided utility to generate an invoice and register a pending payment in ChannelManager.

rust
// The standalone `utils::create_invoice_from_channelmanager` was removed in
// lightning-invoice 0.34. Invoice creation now lives on the ChannelManager and
// takes a single `Bolt11InvoiceParameters`; it registers the inbound payment
// for you. The invoice currency is inferred from the manager's network.
use lightning::ln::channelmanager::Bolt11InvoiceParameters;

let mut invoice_params = Bolt11InvoiceParameters::default();
invoice_params.amount_msats = Some(amt_msat);
invoice_params.invoice_expiry_delta_secs = Some(expiry_secs);
// Set `description` and other fields on `invoice_params` as needed.

let invoice = match channel_manager.create_bolt11_invoice(invoice_params) {
    Ok(inv) => {
        println!("SUCCESS: generated invoice: {}", inv);
        inv
    }
    Err(e) => {
        println!("ERROR: failed to create invoice: {:?}", e);
        return;
    }
};
kotlin
// `UtilMethods.create_invoice_from_channelmanager` was removed — use
// `channelManager.create_bolt11_invoice(..)` instead.
val descriptionRes = Description.of("description")
val description = (descriptionRes as Result_DescriptionCreationErrorZ.Result_DescriptionCreationErrorZ_OK).res

val amtMsat: Long = 3_000_000
val invoice = channelManager.create_bolt11_invoice(
    Option_u64Z.some(amtMsat),                    // amount_msats
    Bolt11InvoiceDescription.direct(description),  // description
    Option_u32Z.some(300),                         // invoice_expiry_delta_secs
    Option_u16Z.some(144),                         // min_final_cltv_expiry_delta
    Option_ThirtyTwoBytesZ.none()                  // payment_hash (none = auto)
)

val invoiceResult = (invoice as Result_Bolt11InvoiceSignOrCreationErrorZ.Result_Bolt11InvoiceSignOrCreationErrorZ_OK).res
val encodedInvoice = invoiceResult.to_str()
typescript
import * as ldk from "lightningdevkit";

// `create_bolt11_invoice` lives on the ChannelManager (the old
// `UtilMethods.create_invoice_from_channelmanager` was removed).
const descRes = ldk.Description.constructor_new("description");
const description = (descRes as ldk.Result_DescriptionCreationErrorZ_OK).res;

const invoiceRes = channelManager.create_bolt11_invoice(
  ldk.Option_u64Z.constructor_some(BigInt(3_000_000)),  // amount_msats
  ldk.Bolt11InvoiceDescription.constructor_direct(description),
  ldk.Option_u32Z.constructor_some(300),                // invoice_expiry_delta_secs
  ldk.Option_u16Z.constructor_some(144),                // min_final_cltv_expiry_delta
  ldk.Option_ThirtyTwoBytesZ.constructor_none()         // payment_hash (none = auto)
);
if (invoiceRes instanceof ldk.Result_Bolt11InvoiceSignOrCreationErrorZ_OK) {
  const encodedInvoice = invoiceRes.res.to_str();
}

While it is possible to create an invoice without using the utility, ChannelManager will reject any incoming HTLCs for unregistered payments to protect your privacy. In this case, use either create_inbound_payment or create_inbound_payment_for_hash to register a payment with ChannelManager before creating the invoice with the returned payment hash and/or secret. You might also opt to for inbound_payment, useful for generating invoices for phantom node payments without a ChannelManager.

PaymentClaimable Event Handling

As with sending a payment, LDK will generate an event once a payment is received. It is your responsibility to handle the PaymentClaimable event by using ChannelManager to release the preimage and claim the funds.

rust
// `PaymentClaimable` has several more fields in 0.2; use `..` to ignore them.
// `PaymentPurpose::InvoicePayment` was split into BOLT11/BOLT12 variants.
Event::PaymentClaimable { payment_hash, purpose, amount_msat, .. } => {
    println!(
        "\nEVENT: received payment from payment hash {} of {} millisatoshis",
        payment_hash, amount_msat,
    );
    let payment_preimage = match purpose {
        PaymentPurpose::Bolt11InvoicePayment { payment_preimage, .. } => payment_preimage,
        PaymentPurpose::Bolt12OfferPayment { payment_preimage, .. } => payment_preimage,
        PaymentPurpose::Bolt12RefundPayment { payment_preimage, .. } => payment_preimage,
        PaymentPurpose::SpontaneousPayment(preimage) => Some(preimage),
    };
    if let Some(preimage) = payment_preimage {
        channel_manager.claim_funds(preimage);
    }
}
kotlin
if (event is Event.PaymentClaimable) {
    val purpose = event.purpose
    if (purpose is PaymentPurpose.Bolt11InvoicePayment) {
        val preimage = purpose.payment_preimage
        if (preimage is Option_ThirtyTwoBytesZ.Some) {
            channelManager.claim_funds(preimage.some)
        }
    }
}
typescript
import * as ldk from "lightningdevkit";

if (event instanceof ldk.Event_PaymentClaimable) {
  // `purpose.preimage()` returns the preimage for any purpose variant.
  const preimage = event.purpose.preimage();
  if (preimage instanceof ldk.Option_ThirtyTwoBytesZ_Some) {
    channelManager.claim_funds(preimage.some);
  }
}

References: Rust PaymentClaimable docs, Rust PaymentPurpose docs, Java/Kotlin Event bindings, TypeScript Event bindings