From 86c2a274825c6d9d775437594927db6982eb62f1 Mon Sep 17 00:00:00 2001 From: Martin Saposnic Date: Wed, 7 Jan 2026 16:47:25 -0300 Subject: [PATCH 1/4] Add wait_for_payment_secs to pay_bolt12_offer Bolt12 payments are async - the node sends an invoice request via onion message, waits for the invoice response, then pays. Without waiting, the node shuts down before the flow completes. This adds the same wait_for_payment_secs parameter that pay_lnurl uses, plus additional debug logging for troubleshooting. --- src/lib.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b1a8ab1..f7f5a9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -934,7 +934,17 @@ impl MdkNode { &self, bolt12_offer_string: String, amount_msat: i64, + wait_for_payment_secs: Option, ) -> napi::Result { + eprintln!( + "[lightning-js] pay_bolt12_offer called amount_msat={} wait_for_payment_secs={:?}", + amount_msat, wait_for_payment_secs + ); + eprintln!( + "[lightning-js] pay_bolt12_offer bolt12_offer={}", + bolt12_offer_string + ); + if amount_msat <= 0 { return Err(napi::Error::new( Status::InvalidArg, @@ -949,9 +959,28 @@ impl MdkNode { ) })?; + let wait_for_payment_secs = wait_for_payment_secs.unwrap_or(0); + let wait_for_payment_secs = if wait_for_payment_secs > 0 { + Some(wait_for_payment_secs as u64) + } else { + None + }; + eprintln!( + "[lightning-js] pay_bolt12_offer wait_for_payment_secs_normalized={wait_for_payment_secs:?}" + ); + let bolt12_offer = Offer::from_str(&bolt12_offer_string) .map_err(|_| napi::Error::new(Status::InvalidArg, "invalid bolt12 offer".to_string()))?; + eprintln!( + "[lightning-js] pay_bolt12_offer parsed offer: id={} issuer_pubkey={:?} description={:?} amount={:?}", + bolt12_offer.id(), + bolt12_offer.issuer_signing_pubkey(), + bolt12_offer.description(), + bolt12_offer.amount() + ); + + eprintln!("[lightning-js] pay_bolt12_offer starting node"); self.node.start().map_err(|error| { napi::Error::new( Status::GenericFailure, @@ -959,19 +988,30 @@ impl MdkNode { ) })?; + eprintln!("[lightning-js] pay_bolt12_offer syncing wallets"); if let Err(err) = self.node.sync_wallets() { eprintln!("[lightning-js] Failed to sync wallets: {err}"); panic!("failed to sync wallets: {err}"); } + eprintln!("[lightning-js] pay_bolt12_offer wallet sync complete"); - let available_balance_msat: u64 = self - .node - .list_channels() - .into_iter() + let channels = self.node.list_channels(); + let ready_channels: Vec<_> = channels + .iter() .filter(|channel| channel.is_channel_ready) + .collect(); + let available_balance_msat: u64 = ready_channels + .iter() .map(|channel| channel.outbound_capacity_msat) .sum(); + eprintln!( + "[lightning-js] pay_bolt12_offer channels: total={} ready={} available_balance_msat={}", + channels.len(), + ready_channels.len(), + available_balance_msat + ); + if available_balance_msat == 0 { if let Err(err) = self.node.stop() { eprintln!( @@ -998,6 +1038,11 @@ impl MdkNode { None => amount_msat_u64, }; + eprintln!( + "[lightning-js] pay_bolt12_offer amount_to_send_msat={}", + amount_to_send_msat + ); + if amount_to_send_msat == 0 { if let Err(err) = self.node.stop() { eprintln!("[lightning-js] Failed to stop node after zero-amount bolt12 offer: {err}"); @@ -1021,6 +1066,12 @@ impl MdkNode { )); } + eprintln!( + "[lightning-js] pay_bolt12_offer sending payment: offer_id={} amount_msat={}", + bolt12_offer.id(), + amount_to_send_msat + ); + let payment_id = match self.node.bolt12_payment().send_using_amount( &bolt12_offer, amount_to_send_msat, @@ -1029,6 +1080,7 @@ impl MdkNode { ) { Ok(payment_id) => payment_id, Err(error) => { + eprintln!("[lightning-js] pay_bolt12_offer send error: {error}"); if let Err(stop_error) = self.node.stop() { eprintln!("[lightning-js] Failed to stop node after bolt12 send error: {stop_error}"); } @@ -1038,18 +1090,29 @@ impl MdkNode { )); } }; + eprintln!( + "[lightning-js] pay_bolt12_offer send ok payment_id={}", + bytes_to_hex(&payment_id.0) + ); - if let Err(err) = self.node.stop() { - eprintln!("[lightning-js] Failed to stop node after successful bolt12 payment: {err}"); - } + if let Some(wait_secs) = wait_for_payment_secs { + eprintln!("[lightning-js] pay_bolt12_offer waiting for payment outcome wait_secs={wait_secs}"); + let wait_result = self.wait_for_payment_outcome(&payment_id, wait_secs); + + if let Err(err) = self.node.stop() { + eprintln!("[lightning-js] Failed to stop node after bolt12 payment wait: {err}"); + } - let payment_id_bytes = payment_id.0; - let mut payment_id_hex = String::with_capacity(payment_id_bytes.len() * 2); - for byte in payment_id_bytes { - write!(&mut payment_id_hex, "{:02x}", byte).unwrap(); + wait_result?; + } else if let Err(err) = self.node.stop() { + eprintln!("[lightning-js] Failed to stop node after successful bolt12 payment: {err}"); } - Ok(payment_id_hex) + eprintln!( + "[lightning-js] pay_bolt12_offer returning payment_id={}", + bytes_to_hex(&payment_id.0) + ); + Ok(bytes_to_hex(&payment_id.0)) } } From 7f53c14417761061516daac74000011e07d16dbd Mon Sep 17 00:00:00 2001 From: Martin Saposnic Date: Wed, 7 Jan 2026 16:49:11 -0300 Subject: [PATCH 2/4] 0.1.55 --- npm/android-arm-eabi/package.json | 2 +- npm/android-arm64/package.json | 2 +- npm/darwin-arm64/package.json | 2 +- npm/darwin-x64/package.json | 2 +- npm/freebsd-x64/package.json | 2 +- npm/linux-arm-gnueabihf/package.json | 2 +- npm/linux-arm64-gnu/package.json | 2 +- npm/linux-arm64-musl/package.json | 2 +- npm/linux-x64-gnu/package.json | 2 +- npm/linux-x64-musl/package.json | 2 +- npm/win32-arm64-msvc/package.json | 2 +- npm/win32-ia32-msvc/package.json | 2 +- npm/win32-x64-msvc/package.json | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/npm/android-arm-eabi/package.json b/npm/android-arm-eabi/package.json index df7b670..95ca8e9 100644 --- a/npm/android-arm-eabi/package.json +++ b/npm/android-arm-eabi/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-android-arm-eabi", - "version": "0.1.54", + "version": "0.1.55", "os": [ "android" ], diff --git a/npm/android-arm64/package.json b/npm/android-arm64/package.json index 320e1f3..9d774ef 100644 --- a/npm/android-arm64/package.json +++ b/npm/android-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-android-arm64", - "version": "0.1.54", + "version": "0.1.55", "os": [ "android" ], diff --git a/npm/darwin-arm64/package.json b/npm/darwin-arm64/package.json index e50ac55..5eb053d 100644 --- a/npm/darwin-arm64/package.json +++ b/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-darwin-arm64", - "version": "0.1.54", + "version": "0.1.55", "os": [ "darwin" ], diff --git a/npm/darwin-x64/package.json b/npm/darwin-x64/package.json index c8b01ae..7c02f9a 100644 --- a/npm/darwin-x64/package.json +++ b/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-darwin-x64", - "version": "0.1.54", + "version": "0.1.55", "os": [ "darwin" ], diff --git a/npm/freebsd-x64/package.json b/npm/freebsd-x64/package.json index 3b5a9fc..f9e919f 100644 --- a/npm/freebsd-x64/package.json +++ b/npm/freebsd-x64/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-freebsd-x64", - "version": "0.1.54", + "version": "0.1.55", "os": [ "freebsd" ], diff --git a/npm/linux-arm-gnueabihf/package.json b/npm/linux-arm-gnueabihf/package.json index b0b7019..7973d9c 100644 --- a/npm/linux-arm-gnueabihf/package.json +++ b/npm/linux-arm-gnueabihf/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-linux-arm-gnueabihf", - "version": "0.1.54", + "version": "0.1.55", "os": [ "linux" ], diff --git a/npm/linux-arm64-gnu/package.json b/npm/linux-arm64-gnu/package.json index 7bc7f97..17f9c29 100644 --- a/npm/linux-arm64-gnu/package.json +++ b/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-linux-arm64-gnu", - "version": "0.1.54", + "version": "0.1.55", "os": [ "linux" ], diff --git a/npm/linux-arm64-musl/package.json b/npm/linux-arm64-musl/package.json index f9187ae..1ffc695 100644 --- a/npm/linux-arm64-musl/package.json +++ b/npm/linux-arm64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-linux-arm64-musl", - "version": "0.1.54", + "version": "0.1.55", "os": [ "linux" ], diff --git a/npm/linux-x64-gnu/package.json b/npm/linux-x64-gnu/package.json index fd42639..d550588 100644 --- a/npm/linux-x64-gnu/package.json +++ b/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-linux-x64-gnu", - "version": "0.1.54", + "version": "0.1.55", "os": [ "linux" ], diff --git a/npm/linux-x64-musl/package.json b/npm/linux-x64-musl/package.json index 815b8c5..ab7d7a1 100644 --- a/npm/linux-x64-musl/package.json +++ b/npm/linux-x64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-linux-x64-musl", - "version": "0.1.54", + "version": "0.1.55", "os": [ "linux" ], diff --git a/npm/win32-arm64-msvc/package.json b/npm/win32-arm64-msvc/package.json index a37199d..3ca3f72 100644 --- a/npm/win32-arm64-msvc/package.json +++ b/npm/win32-arm64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-win32-arm64-msvc", - "version": "0.1.54", + "version": "0.1.55", "os": [ "win32" ], diff --git a/npm/win32-ia32-msvc/package.json b/npm/win32-ia32-msvc/package.json index 588ec10..41b8ac0 100644 --- a/npm/win32-ia32-msvc/package.json +++ b/npm/win32-ia32-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-win32-ia32-msvc", - "version": "0.1.54", + "version": "0.1.55", "os": [ "win32" ], diff --git a/npm/win32-x64-msvc/package.json b/npm/win32-x64-msvc/package.json index 3fd51e4..69cedb3 100644 --- a/npm/win32-x64-msvc/package.json +++ b/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js-win32-x64-msvc", - "version": "0.1.54", + "version": "0.1.55", "os": [ "win32" ], diff --git a/package-lock.json b/package-lock.json index 041ee00..88339e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@moneydevkit/lightning-js", - "version": "0.1.54", + "version": "0.1.55", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@moneydevkit/lightning-js", - "version": "0.1.54", + "version": "0.1.55", "license": "MIT", "devDependencies": { "@napi-rs/cli": "^2.18.4", diff --git a/package.json b/package.json index 4a24d4e..fb8fc04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@moneydevkit/lightning-js", - "version": "0.1.54", + "version": "0.1.55", "main": "index.js", "files": [ "index.d.ts", From da3e7e4f09522fe47e5a562cf3a1da0882c16813 Mon Sep 17 00:00:00 2001 From: Martin Saposnic Date: Wed, 7 Jan 2026 16:52:21 -0300 Subject: [PATCH 3/4] fix: format --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index f7f5a9d..38ebad0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1096,7 +1096,9 @@ impl MdkNode { ); if let Some(wait_secs) = wait_for_payment_secs { - eprintln!("[lightning-js] pay_bolt12_offer waiting for payment outcome wait_secs={wait_secs}"); + eprintln!( + "[lightning-js] pay_bolt12_offer waiting for payment outcome wait_secs={wait_secs}" + ); let wait_result = self.wait_for_payment_outcome(&payment_id, wait_secs); if let Err(err) = self.node.stop() { From 7b7cada9dae10497693b75e91bb5d7acaa698d75 Mon Sep 17 00:00:00 2001 From: Martin Saposnic Date: Wed, 7 Jan 2026 16:54:07 -0300 Subject: [PATCH 4/4] chore: regenerate types --- index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index d663ade..95ffec5 100644 --- a/index.d.ts +++ b/index.d.ts @@ -60,7 +60,7 @@ export declare class MdkNode { description: string, expirySecs: number, ): PaymentMetadata - payLnurl(lnurl: string, amountMsat: number, waitForPaymentSecs?: number): string + payLnurl(lnurl: string, amountMsat: number, waitForPaymentSecs?: number | undefined | null): string payBolt11(bolt11Invoice: string): string - payBolt12Offer(bolt12OfferString: string, amountMsat: number): string + payBolt12Offer(bolt12OfferString: string, amountMsat: number, waitForPaymentSecs?: number | undefined | null): string }