raiden_primitives/
payments.rs

1#![warn(clippy::missing_docs_in_private_items)]
2
3use std::collections::HashMap;
4
5use tokio::sync::oneshot;
6
7use crate::types::{
8	Address,
9	PaymentIdentifier,
10	TokenAmount,
11	TokenNetworkAddress,
12};
13
14/// Payment status variants.
15pub enum PaymentStatus {
16	Success(Address, PaymentIdentifier),
17	Error(Address, PaymentIdentifier, String),
18}
19
20/// Represents an ongoing payment with means to notify once the payment is completed.
21pub struct Payment {
22	pub identifier: PaymentIdentifier,
23	pub token_network_address: TokenNetworkAddress,
24	pub amount: TokenAmount,
25	pub notifier: Option<oneshot::Sender<PaymentStatus>>,
26}
27
28/// A collection of ongoing payments.
29#[derive(Default)]
30pub struct PaymentsRegistry {
31	/// A mapping for payments (Target address -> Payment Identifier -> Payment)
32	payments: HashMap<Address, HashMap<PaymentIdentifier, Payment>>,
33}
34
35impl PaymentsRegistry {
36	/// Returns an instance of `PaymentsRegistry`.
37	pub fn new() -> Self {
38		Self { payments: HashMap::new() }
39	}
40
41	/// Returns a payment instance if found.
42	pub fn get(&self, target: Address, identifier: PaymentIdentifier) -> Option<&Payment> {
43		if let Some(payments) = self.payments.get(&target) {
44			return payments.get(&identifier)
45		}
46		None
47	}
48
49	/// Register a new ongoing payment.
50	pub fn register(
51		&mut self,
52		token_network_address: TokenNetworkAddress,
53		target: Address,
54		identifier: PaymentIdentifier,
55		amount: TokenAmount,
56	) -> oneshot::Receiver<PaymentStatus> {
57		let (sender, receiver) = oneshot::channel();
58
59		if self.payments.get(&target).is_none() {
60			self.payments.insert(target, HashMap::new());
61		}
62
63		let payments = self.payments.get_mut(&target).expect("Just created above");
64		payments.insert(
65			identifier,
66			Payment { identifier, token_network_address, amount, notifier: Some(sender) },
67		);
68		receiver
69	}
70
71	/// Mark an ongoing payment as complete with status.
72	pub fn complete(&mut self, status: PaymentStatus) {
73		let (target, identifier) = match status {
74			PaymentStatus::Success(target, identifier) => (target, identifier),
75			PaymentStatus::Error(target, identifier, _) => (target, identifier),
76		};
77		let payments = match self.payments.get_mut(&target) {
78			Some(payments) => payments,
79			None => return,
80		};
81
82		let payment = match payments.get_mut(&identifier) {
83			Some(payment) => payment,
84			None => return,
85		};
86
87		if let Some(notifier) = payment.notifier.take() {
88			let _ = notifier.send(status);
89		}
90	}
91}