crypto_pay_api/models/
currency.rs

1use std::fmt::Display;
2
3use crate::utils::deserialize_currency_code;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Serialize, Deserialize)]
7pub struct Currency {
8    pub is_blockchain: bool,
9    pub is_stablecoin: bool,
10    pub is_fiat: bool,
11    pub name: String,
12    #[serde(deserialize_with = "deserialize_currency_code")]
13    pub code: CurrencyCode,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub url: Option<String>,
16    pub decimals: u8,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
20#[serde(untagged)]
21pub enum CurrencyCode {
22    Crypto(CryptoCurrencyCode),
23    Fiat(FiatCurrencyCode),
24}
25
26#[cfg(not(tarpaulin))]
27impl Display for CurrencyCode {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        match self {
30            CurrencyCode::Crypto(code) => write!(f, "{code}"),
31            CurrencyCode::Fiat(code) => write!(f, "{code}"),
32        }
33    }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
37#[serde(rename_all = "UPPERCASE")]
38pub enum CryptoCurrencyCode {
39    Usdt,
40    Ton,
41    Btc,
42    Eth,
43    Ltc,
44    Bnb,
45    Trx,
46    Usdc,
47    Doge,
48    Send,
49    Jet,
50    #[serde(other)]
51    Unknown,
52}
53
54#[cfg(not(tarpaulin))]
55impl Display for CryptoCurrencyCode {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        write!(f, "{self:?}")
58    }
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
62#[serde(rename_all = "UPPERCASE")]
63pub enum FiatCurrencyCode {
64    Usd,
65    Eur,
66    Rub,
67    Byn,
68    Uah,
69    Gbp,
70    Cny,
71    Kgs,
72    Kzt,
73    Uzs,
74    Gel,
75    Try,
76    Amd,
77    Thb,
78    Tjs,
79    Inr,
80    Brl,
81    Idr,
82    Azn,
83    Aed,
84    Pln,
85    Ils,
86    Lkr,
87    #[serde(other)]
88    Unknown,
89}
90
91#[cfg(not(tarpaulin))]
92impl Display for FiatCurrencyCode {
93    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94        write!(f, "{self:?}")
95    }
96}
97
98#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
99#[serde(rename_all = "lowercase")]
100pub enum CurrencyType {
101    Crypto,
102    Fiat,
103}
104
105#[cfg(not(tarpaulin))]
106impl Display for CurrencyType {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        write!(f, "{self:?}")
109    }
110}
111
112impl From<CryptoCurrencyCode> for CurrencyCode {
113    fn from(code: CryptoCurrencyCode) -> Self {
114        CurrencyCode::Crypto(code)
115    }
116}
117
118impl From<FiatCurrencyCode> for CurrencyCode {
119    fn from(code: FiatCurrencyCode) -> Self {
120        CurrencyCode::Fiat(code)
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    #[test]
129    fn test_currency_type_serialization() {
130        let crypto = CurrencyType::Crypto;
131        let fiat = CurrencyType::Fiat;
132
133        assert_eq!(serde_json::to_string(&crypto).unwrap(), "\"crypto\"");
134        assert_eq!(serde_json::to_string(&fiat).unwrap(), "\"fiat\"");
135    }
136
137    #[test]
138    fn test_crypto_currency_code_serialization() {
139        let btc = CryptoCurrencyCode::Btc;
140        let ton = CryptoCurrencyCode::Ton;
141
142        assert_eq!(serde_json::to_string(&btc).unwrap(), "\"BTC\"");
143        assert_eq!(serde_json::to_string(&ton).unwrap(), "\"TON\"");
144    }
145
146    #[test]
147    fn test_fiat_currency_code_serialization() {
148        let usd = FiatCurrencyCode::Usd;
149        let eur = FiatCurrencyCode::Eur;
150
151        assert_eq!(serde_json::to_string(&usd).unwrap(), "\"USD\"");
152        assert_eq!(serde_json::to_string(&eur).unwrap(), "\"EUR\"");
153    }
154
155    #[test]
156    fn test_currency_code_deserialization() {
157        let crypto: CryptoCurrencyCode = serde_json::from_str("\"BTC\"").unwrap();
158        let fiat: FiatCurrencyCode = serde_json::from_str("\"USD\"").unwrap();
159
160        assert_eq!(crypto, CryptoCurrencyCode::Btc);
161        assert_eq!(fiat, FiatCurrencyCode::Usd);
162
163        assert_eq!(
164            serde_json::from_str::<CryptoCurrencyCode>("\"btc\"").unwrap(),
165            CryptoCurrencyCode::Unknown
166        );
167        assert_eq!(
168            serde_json::from_str::<FiatCurrencyCode>("\"usd\"").unwrap(),
169            FiatCurrencyCode::Unknown
170        );
171    }
172
173    #[test]
174    fn test_currency_code_conversion() {
175        let crypto = CryptoCurrencyCode::Btc;
176        let fiat = FiatCurrencyCode::Usd;
177
178        let currency_code_crypto: CurrencyCode = crypto.into();
179        let currency_code_fiat: CurrencyCode = fiat.into();
180
181        assert!(matches!(
182            currency_code_crypto,
183            CurrencyCode::Crypto(CryptoCurrencyCode::Btc)
184        ));
185        assert!(matches!(currency_code_fiat, CurrencyCode::Fiat(FiatCurrencyCode::Usd)));
186    }
187}