helium_api/models/transactions/
payment_v2.rs1use crate::models::{Hnt, Hst, Iot, Mobile};
2use serde::{Deserialize, Serialize};
3
4#[derive(Clone, Serialize, Deserialize, Debug)]
5pub struct PaymentV2 {
6 pub hash: String,
7 pub fee: u64,
9 pub nonce: u64,
10 pub payer: String,
11 pub payments: Vec<PaymentV2Payment>,
12}
13
14#[derive(Clone, Serialize, Debug)]
15#[serde(tag = "token_type", rename_all = "snake_case")]
16pub enum PaymentV2Payment {
17 Iot(IotPayment),
18 Hnt(HntPayment),
19 Hst(HstPayment),
20 Mobile(MobilePayment),
21}
22
23macro_rules! payment {
24 ($payment_type:ident, $token:ident) => {
25 #[derive(Clone, Serialize, Deserialize, Debug)]
26 pub struct $payment_type {
27 pub amount: $token,
28 pub memo: Option<String>,
29 pub payee: String,
30 }
31 };
32}
33payment!(HstPayment, Hst);
34payment!(IotPayment, Iot);
35payment!(HntPayment, Hnt);
36payment!(MobilePayment, Mobile);
37
38use serde::Deserializer;
39
40impl<'de> Deserialize<'de> for PaymentV2Payment {
41 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42 where
43 D: Deserializer<'de>,
44 {
45 #[derive(Deserialize)]
46 #[serde(rename_all = "snake_case")]
47 enum Type {
48 Iot,
49 Hnt,
50 Hst,
51 Mobile,
52 }
53
54 #[derive(Deserialize)]
55 struct Inner {
56 pub token_type: Option<Type>,
57 pub amount: u64,
58 pub memo: Option<String>,
59 pub payee: String,
60 }
61
62 let i: Inner = Inner::deserialize(deserializer)?;
63
64 Ok(match i.token_type {
65 None => PaymentV2Payment::Hnt(HntPayment {
66 amount: Hnt::from(i.amount),
67 memo: i.memo,
68 payee: i.payee,
69 }),
70 Some(tag) => match tag {
71 Type::Iot => PaymentV2Payment::Iot(IotPayment {
72 amount: Iot::from(i.amount),
73 memo: i.memo,
74 payee: i.payee,
75 }),
76 Type::Hnt => PaymentV2Payment::Hnt(HntPayment {
77 amount: Hnt::from(i.amount),
78 memo: i.memo,
79 payee: i.payee,
80 }),
81 Type::Hst => PaymentV2Payment::Hst(HstPayment {
82 amount: Hst::from(i.amount),
83 memo: i.memo,
84 payee: i.payee,
85 }),
86 Type::Mobile => PaymentV2Payment::Mobile(MobilePayment {
87 amount: Mobile::from(i.amount),
88 memo: i.memo,
89 payee: i.payee,
90 }),
91 },
92 })
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use std::str::FromStr;
100
101 #[test]
102 fn deser_json_hst() {
103 let json_str = "\
104 {\
105 \"token_type\": \"hst\",\
106 \"payee\": \"1bdkwatM2APjn5cvo7eKiJGidoHAKJsHg8ReeguH49dtLacK6cR\",\
107 \"memo\": \"HNTAAAAAAAA=\",\
108 \"max\": false,\
109 \"amount\": 160000000\
110 }\
111 ";
112 let hnt_payment: PaymentV2Payment =
113 serde_json::from_str(json_str).expect("hst_payment deserialization");
114 if let PaymentV2Payment::Hst(hst) = hnt_payment {
115 assert_eq!(hst.amount, Hst::from_str("1.6").expect("HST"));
116 } else {
117 assert!(false)
118 }
119 }
120
121 #[test]
122 fn deser_json_hnt() {
123 let json_str = "\
125 {\
126 \"payee\": \"1bdkwatM2APjn5cvo7eKiJGidoHAKJsHg8ReeguH49dtLacK6cR\",\
127 \"memo\": \"HNTAAAAAAAA=\",\
128 \"max\": false,\
129 \"amount\": 160000000\
130 }\
131 ";
132 let hnt_payment: PaymentV2Payment =
133 serde_json::from_str(json_str).expect("hnt_payment deserialization");
134 if let PaymentV2Payment::Hnt(hnt) = hnt_payment {
135 assert_eq!(hnt.amount, Hnt::from_str("1.6").expect("HNT"));
136 } else {
137 assert!(false)
138 }
139 }
140}