1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use anyhow::{format_err, Result};
pub mod payment_methods;

pub type Name = String;
pub type PaymentMethodName = String;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Payee {
    #[serde(rename = "unique-id")]
    unique_id: uuid::Uuid,
    #[serde(rename = "payment-methods")]
    payment_methods: std::collections::BTreeMap<PaymentMethodName, serde_json::Value>,
}

impl Payee {
    pub fn payment_methods(&self) -> Result<Vec<Box<dyn payment_methods::PaymentMethod>>> {
        let mut methods = Vec::<Box<dyn payment_methods::PaymentMethod>>::new();
        for (name, json_value) in &self.payment_methods {
            let method = match name.as_str() {
                "paypal" => Box::new(serde_json::value::from_value::<payment_methods::PayPal>(
                    json_value.clone(),
                )?) as Box<dyn payment_methods::PaymentMethod>,
                "btc_lightning_keysend" => Box::new(serde_json::value::from_value::<
                    payment_methods::BtcLightningKeysend,
                >(json_value.clone())?)
                    as Box<dyn payment_methods::PaymentMethod>,
                _ => {
                    return Err(format_err!("Unknown payment method: {}", name));
                }
            };
            methods.push(method);
        }
        Ok(methods)
    }

    pub fn set_payment_method(
        &mut self,
        payment_method: &Box<dyn payment_methods::PaymentMethod>,
    ) -> Result<()> {
        let name = payment_method.name();
        self.payment_methods
            .insert(name, payment_method.to_serde_json_value()?);
        Ok(())
    }

    pub fn remove_payment_method(&mut self, name: &String) -> Result<()> {
        self.payment_methods.remove(name);
        Ok(())
    }
}

impl std::default::Default for Payee {
    fn default() -> Self {
        Self {
            unique_id: uuid::Uuid::new_v4(),
            payment_methods: std::collections::BTreeMap::<_, _>::new(),
        }
    }
}

pub fn unique_name(payee_name: &Name, payee: &Payee) -> Name {
    let unique_id = payee.unique_id.to_string()[..13].to_string();
    format!("{payee_name}___{unique_id}")
}

pub fn get_lock_payee(
    payee: &Payee,
    all_lock_payees: &std::collections::BTreeMap<Name, Payee>,
) -> Option<(Name, Payee)> {
    for (name, existing_payee) in all_lock_payees {
        if payee.unique_id == existing_payee.unique_id {
            return Some((name.clone(), existing_payee.clone()));
        }
    }
    None
}