use core::fmt;
use core::fmt::{Debug, Display, Formatter};
+use core::future::Future;
use core::ops::Deref;
use core::time::Duration;
#[cfg(feature = "std")]
#[cfg(feature = "no-std")]
type ConfiguredTime = time_utils::Eternity;
+/// Sealed trait with a blanket implementation to allow both sync and async implementations of event
+/// handling to exist within the InvoicePayer.
+mod sealed {
+ pub trait BaseEventHandler {}
+ impl<T> BaseEventHandler for T {}
+}
+
/// (C-not exported) generally all users should use the [`InvoicePayer`] type alias.
-pub struct InvoicePayerUsingTime<P: Deref, R: ScoringRouter, L: Deref, E: EventHandler, T: Time>
-where
+pub struct InvoicePayerUsingTime<
+ P: Deref,
+ R: ScoringRouter,
+ L: Deref,
+ E: sealed::BaseEventHandler,
+ T: Time
+> where
P::Target: Payer,
L::Target: Logger,
{
Sending(PaymentSendFailure),
}
-impl<P: Deref, R: ScoringRouter, L: Deref, E: EventHandler, T: Time> InvoicePayerUsingTime<P, R, L, E, T>
+impl<P: Deref, R: ScoringRouter, L: Deref, E: sealed::BaseEventHandler, T: Time>
+ InvoicePayerUsingTime<P, R, L, E, T>
where
P::Target: Payer,
L::Target: Logger,
} else { false }
}
-impl<P: Deref, R: ScoringRouter, L: Deref, E: EventHandler, T: Time> EventHandler for InvoicePayerUsingTime<P, R, L, E, T>
+impl<P: Deref, R: ScoringRouter, L: Deref, E: sealed::BaseEventHandler, T: Time>
+ InvoicePayerUsingTime<P, R, L, E, T>
where
P::Target: Payer,
L::Target: Logger,
{
- fn handle_event(&self, event: &Event) {
+ /// Returns a bool indicating whether the processed event should be forwarded to a user-provided
+ /// event handler.
+ fn handle_event_internal(&self, event: &Event) -> bool {
match event {
Event::PaymentPathFailed { payment_hash, path, .. }
| Event::PaymentPathSuccessful { path, payment_hash: Some(payment_hash), .. }
self.payer.abandon_payment(payment_id.unwrap());
} else if self.retry_payment(payment_id.unwrap(), *payment_hash, retry.as_ref().unwrap()).is_ok() {
// We retried at least somewhat, don't provide the PaymentPathFailed event to the user.
- return;
+ return false;
} else {
self.payer.abandon_payment(payment_id.unwrap());
}
}
// Delegate to the decorated event handler unless the payment is retried.
- self.event_handler.handle_event(event)
+ true
+ }
+}
+
+impl<P: Deref, R: ScoringRouter, L: Deref, E: EventHandler, T: Time>
+ EventHandler for InvoicePayerUsingTime<P, R, L, E, T>
+where
+ P::Target: Payer,
+ L::Target: Logger,
+{
+ fn handle_event(&self, event: &Event) {
+ let should_forward = self.handle_event_internal(&event);
+ if should_forward {
+ self.event_handler.handle_event(&event)
+ }
+ }
+}
+
+impl<P: Deref, R: ScoringRouter, L: Deref, T: Time, F: Future, H: Fn(Event) -> F>
+ InvoicePayerUsingTime<P, R, L, H, T>
+where
+ P::Target: Payer,
+ L::Target: Logger,
+{
+ /// Intercepts events required by the [`InvoicePayer`] and forwards them to the underlying event
+ /// handler, if necessary, to handle them asynchronously.
+ pub async fn handle_event_async(&self, event: Event) {
+ let should_forward = self.handle_event_internal(&event);
+ if should_forward {
+ (self.event_handler)(event).await;
+ }
}
}
#[test]
fn pays_invoice_on_first_attempt() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn pays_invoice_on_retry() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn pays_invoice_on_partial_failure() {
- let event_handler = |_: &_| { panic!() };
+ let event_handler = |_: &Event| { panic!() };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn retries_payment_path_for_unknown_payment() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_paying_invoice_after_max_retry_counts() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_paying_invoice_after_max_retry_timeout() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_paying_invoice_with_missing_retry_params() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_paying_invoice_after_expiration() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payer = TestPayer::new();
let router = TestRouter::new(TestScorer::new());
#[test]
fn fails_retrying_invoice_after_expiration() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_paying_invoice_after_retry_error() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_paying_invoice_after_rejected_by_payee() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn fails_repaying_invoice_with_pending_payment() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
let router = FailingRouter {};
let logger = TestLogger::new();
let invoice_payer =
- InvoicePayer::new(&payer, router, &logger, |_: &_| {}, Retry::Attempts(0));
+ InvoicePayer::new(&payer, router, &logger, |_: &Event| {}, Retry::Attempts(0));
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
let router = TestRouter::new(TestScorer::new());
let logger = TestLogger::new();
let invoice_payer =
- InvoicePayer::new(&payer, router, &logger, |_: &_| {}, Retry::Attempts(0));
+ InvoicePayer::new(&payer, router, &logger, |_: &Event| {}, Retry::Attempts(0));
match invoice_payer.pay_invoice(&invoice) {
Err(PaymentError::Sending(_)) => {},
#[test]
fn pays_zero_value_invoice_using_amount() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = zero_value_invoice(payment_preimage);
#[test]
fn fails_paying_zero_value_invoice_with_amount() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payer = TestPayer::new();
let router = TestRouter::new(TestScorer::new());
#[test]
fn pays_pubkey_with_amount() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let pubkey = pubkey();
let payment_preimage = PaymentPreimage([1; 32]);
#[test]
fn scores_failed_channel() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn scores_successful_channels() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
#[test]
fn generates_correct_inflight_map_data() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice = invoice(payment_preimage);
fn considers_inflight_htlcs_between_invoice_payments_when_path_succeeds() {
// First, let's just send a payment through, but only make sure one of the path completes
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let payment_invoice = invoice(payment_preimage);
fn considers_inflight_htlcs_between_retries() {
// First, let's just send a payment through, but only make sure one of the path completes
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let payment_invoice = invoice(payment_preimage);
#[test]
fn accounts_for_some_inflight_htlcs_sent_during_partial_failure() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice_to_pay = invoice(payment_preimage);
#[test]
fn accounts_for_all_inflight_htlcs_sent_during_partial_failure() {
let event_handled = core::cell::RefCell::new(false);
- let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
+ let event_handler = |_: &Event| { *event_handled.borrow_mut() = true; };
let payment_preimage = PaymentPreimage([1; 32]);
let invoice_to_pay = invoice(payment_preimage);
route.paths[1][0].fee_msat = 50_000_000;
router.expect_find_route(Ok(route.clone()));
- let event_handler = |_: &_| { panic!(); };
+ let event_handler = |_: &Event| { panic!(); };
let invoice_payer = InvoicePayer::new(nodes[0].node, router, nodes[0].logger, event_handler, Retry::Attempts(1));
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(
route.paths[1][0].fee_msat = 50_000_001;
router.expect_find_route(Ok(route.clone()));
- let event_handler = |_: &_| { panic!(); };
+ let event_handler = |_: &Event| { panic!(); };
let invoice_payer = InvoicePayer::new(nodes[0].node, router, nodes[0].logger, event_handler, Retry::Attempts(1));
assert!(invoice_payer.pay_invoice(&create_invoice_from_channelmanager_and_duration_since_epoch(