From ac2ffa08a496c2bbccdd34ca31926587ba8d7933 Mon Sep 17 00:00:00 2001 From: Roman Dmitrienko Date: Thu, 20 Jun 2024 22:02:06 +0200 Subject: [PATCH] feat: store created_at timestamp for payments --- bindings/ldk_node.udl | 1 + src/event.rs | 1 + src/payment/bolt11.rs | 6 ++++++ src/payment/spontaneous.rs | 2 ++ src/payment/store.rs | 30 +++++++++++++++++++++++++++++- 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/bindings/ldk_node.udl b/bindings/ldk_node.udl index 2a0499ce2..c0345351d 100644 --- a/bindings/ldk_node.udl +++ b/bindings/ldk_node.udl @@ -264,6 +264,7 @@ dictionary PaymentDetails { PaymentStatus status; u64 last_update; u64? fee_msat; + u64 created_at; }; // [NonExhaustive] diff --git a/src/event.rs b/src/event.rs index 4df8f687a..3183528ba 100644 --- a/src/event.rs +++ b/src/event.rs @@ -586,6 +586,7 @@ where .unwrap_or(time::Duration::ZERO) .as_secs(), fee_msat: None, + created_at: 0, }; match self.payment_store.insert(payment) { diff --git a/src/payment/bolt11.rs b/src/payment/bolt11.rs index a48ad5f30..9a8d025a9 100644 --- a/src/payment/bolt11.rs +++ b/src/payment/bolt11.rs @@ -115,6 +115,7 @@ impl Bolt11Payment { status: PaymentStatus::Pending, last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; @@ -139,6 +140,7 @@ impl Bolt11Payment { status: PaymentStatus::Failed, last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; @@ -232,6 +234,7 @@ impl Bolt11Payment { status: PaymentStatus::Pending, last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; @@ -256,6 +259,7 @@ impl Bolt11Payment { status: PaymentStatus::Failed, last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; @@ -323,6 +327,7 @@ impl Bolt11Payment { status: PaymentStatus::Pending, last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; @@ -455,6 +460,7 @@ impl Bolt11Payment { status: PaymentStatus::Pending, last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; diff --git a/src/payment/spontaneous.rs b/src/payment/spontaneous.rs index c5ebb56fb..83c7dc283 100644 --- a/src/payment/spontaneous.rs +++ b/src/payment/spontaneous.rs @@ -98,6 +98,7 @@ impl SpontaneousPayment { amount_msat: Some(amount_msat), last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; @@ -122,6 +123,7 @@ impl SpontaneousPayment { amount_msat: Some(amount_msat), last_update: 0, fee_msat: None, + created_at: 0, }; self.payment_store.insert(payment)?; diff --git a/src/payment/store.rs b/src/payment/store.rs index bd58821af..b174d5f6b 100644 --- a/src/payment/store.rs +++ b/src/payment/store.rs @@ -38,6 +38,8 @@ pub struct PaymentDetails { pub last_update: u64, /// Fee paid. pub fee_msat: Option, + /// Payment creation timestamp, as seconds since Unix epoch. + pub created_at: u64, } impl Writeable for PaymentDetails { @@ -57,6 +59,7 @@ impl Writeable for PaymentDetails { (10, self.status, required), (131074, Some(self.last_update), option), (131076, self.fee_msat, option), + (131078, Some(self.created_at), option), }); Ok(()) } @@ -75,6 +78,7 @@ impl Readable for PaymentDetails { (10, status, required), (131074, last_update, option), (131076, fee_msat, option), + (131078, created_at, option), }); let id: PaymentId = id.0.ok_or(DecodeError::InvalidValue)?; @@ -84,6 +88,7 @@ impl Readable for PaymentDetails { let direction: PaymentDirection = direction.0.ok_or(DecodeError::InvalidValue)?; let status: PaymentStatus = status.0.ok_or(DecodeError::InvalidValue)?; let last_update: u64 = last_update.unwrap_or(0); + let created_at: u64 = created_at.unwrap_or(0); let kind = if let Some(kind) = kind_opt { // If we serialized the payment kind, use it. @@ -112,7 +117,16 @@ impl Readable for PaymentDetails { } }; - Ok(PaymentDetails { id, kind, amount_msat, direction, status, last_update, fee_msat }) + Ok(PaymentDetails { + id, + kind, + amount_msat, + direction, + status, + last_update, + fee_msat, + created_at, + }) } } @@ -288,6 +302,19 @@ where pub(crate) fn insert(&self, payment: PaymentDetails) -> Result { let mut locked_payments = self.payments.lock().unwrap(); + // If the payment already exists, reuse its timestamp instead of overwriting it. + let created_at = locked_payments.get(&payment.id).map_or_else( + || { + time::SystemTime::now() + .duration_since(time::UNIX_EPOCH) + .unwrap_or(time::Duration::ZERO) + .as_secs() + }, + |p| p.created_at, + ); + + let payment = PaymentDetails { created_at, ..payment }; + let updated = locked_payments.insert(payment.id, payment.clone()).is_some(); self.persist_info(&payment.id, &payment)?; Ok(updated) @@ -464,6 +491,7 @@ mod tests { status: PaymentStatus::Pending, last_update: 0, fee_msat: None, + created_at: 0, }; assert_eq!(Ok(false), payment_store.insert(payment.clone()));