upbit/api_deposit/
deposit_info.rs1use reqwest::header::{ACCEPT, AUTHORIZATION};
2use reqwest::{Response, Url};
3
4use crate::request::RequestWithQuery;
5use crate::response::{TransactionInfo, TransactionInfoSource};
6
7use super::{
8 super::constant::{URL_DEPOSIT, URL_SERVER},
9 super::response::ResponseError,
10};
11
12impl TransactionInfo {
13 pub async fn get_deposit_info_by_currency(currency: &str) -> Result<Self, ResponseError> {
14 let res = Self::request_deposit_by_currency(currency).await?;
15 let res_serialized = res
16 .text()
17 .await
18 .map_err(crate::response::response_error_from_reqwest)?;
19
20 if res_serialized.contains("error") {
21 return Err(serde_json::from_str(&res_serialized)
22 .map(crate::response::response_error)
23 .ok()
24 .unwrap());
25 }
26
27 Self::deserialize_order_status_response(&res_serialized)
28 }
29
30 pub async fn get_deposit_info_by_uuid(uuid: &str) -> Result<Self, ResponseError> {
31 let res = Self::request_deposit_by_uuid(uuid).await?;
32 let res_serialized = res
33 .text()
34 .await
35 .map_err(crate::response::response_error_from_reqwest)?;
36
37 if res_serialized.contains("error") {
38 return Err(serde_json::from_str(&res_serialized)
39 .map(crate::response::response_error)
40 .ok()
41 .unwrap());
42 }
43
44 Self::deserialize_order_status_response(&res_serialized)
45 }
46
47 pub async fn get_deposit_info_by_txid(txid: &str) -> Result<Self, ResponseError> {
48 let res = Self::request_deposit_by_txid(txid).await?;
49 let res_serialized = res
50 .text()
51 .await
52 .map_err(crate::response::response_error_from_reqwest)?;
53
54 if res_serialized.contains("error") {
55 return Err(serde_json::from_str(&res_serialized)
56 .map(crate::response::response_error)
57 .ok()
58 .unwrap());
59 }
60
61 Self::deserialize_order_status_response(&res_serialized)
62 }
63
64 async fn request_deposit_by_currency(currency: &str) -> Result<Response, ResponseError> {
65 let mut url = Url::parse(&format!("{URL_SERVER}{URL_DEPOSIT}"))
66 .map_err(crate::response::response_error_internal_url_parse_error)?;
67
68 url.query_pairs_mut().append_pair("currency", currency);
69
70 let token_string = Self::set_token_with_query(url.as_str())?;
71
72 reqwest::Client::new()
73 .get(url.as_str())
74 .header(ACCEPT, "application/json")
75 .header(AUTHORIZATION, &token_string)
76 .send()
77 .await
78 .map_err(crate::response::response_error_from_reqwest)
79 }
80
81 async fn request_deposit_by_uuid(uuid: &str) -> Result<Response, ResponseError> {
82 let mut url = Url::parse(&format!("{URL_SERVER}{URL_DEPOSIT}"))
83 .map_err(crate::response::response_error_internal_url_parse_error)?;
84
85 url.query_pairs_mut().append_pair("uuid", uuid);
86
87 let token_string = Self::set_token_with_query(url.as_str())?;
88
89 reqwest::Client::new()
90 .get(url.as_str())
91 .header(ACCEPT, "application/json")
92 .header(AUTHORIZATION, &token_string)
93 .send()
94 .await
95 .map_err(crate::response::response_error_from_reqwest)
96 }
97
98 async fn request_deposit_by_txid(txid: &str) -> Result<Response, ResponseError> {
99 let mut url = Url::parse(&format!("{URL_SERVER}{URL_DEPOSIT}"))
100 .map_err(crate::response::response_error_internal_url_parse_error)?;
101
102 url.query_pairs_mut().append_pair("txid", txid);
103
104 let token_string = Self::set_token_with_query(url.as_str())?;
105
106 reqwest::Client::new()
107 .get(url.as_str())
108 .header(ACCEPT, "application/json")
109 .header(AUTHORIZATION, &token_string)
110 .send()
111 .await
112 .map_err(crate::response::response_error_from_reqwest)
113 }
114
115 fn deserialize_order_status_response(res_serialized: &str) -> Result<Self, ResponseError> {
116 serde_json::from_str(res_serialized)
117 .map(|x: TransactionInfoSource| Self {
118 r#type: x.r#type(),
119 uuid: x.uuid(),
120 currency: x.currency(),
121 net_type: x.net_type(),
122 txid: x.txid(),
123 state: x.state(),
124 created_at: x.created_at(),
125 done_at: x.done_at(),
126 amount: x.amount(),
127 fee: x.fee(),
128 transaction_type: x.transaction_type(),
129
130 holder: None,
131 bank: None,
132 fiat_amount: None,
133 memo: None,
134 fiat_currency: None,
135 confirmations: None,
136 krw_amount: None,
137 network_name: None,
138 cancelable: None,
139 blockchain_url: None,
140 state_i18n: None,
141 address: None,
142 })
143 .map_err(crate::response::response_error_from_json)
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use std::collections::{HashMap, HashSet};
150
151 use serde_json::Value;
152
153 use crate::response::TransactionInfo;
154
155 #[tokio::test]
156 async fn test_get_deposit_info_by_currency() {
157 crate::test_utils::setup_test_keys();
158
159 let res = TransactionInfo::request_deposit_by_currency("KRW")
160 .await
161 .unwrap();
162 let res_serialized = res
163 .text()
164 .await
165 .map_err(crate::response::response_error_from_reqwest)
166 .unwrap();
167
168 if res_serialized.contains("error") {
169 assert!(false, "Error response: {res_serialized}");
170 }
171
172 let json = serde_json::from_str::<Value>(&res_serialized).unwrap();
173 let expected_structure = serde_json::json!({
174 "type": "",
175 "uuid": "",
176 "currency": "",
177 "net_type": "",
178 "txid": "",
179 "state": "",
180 "created_at": "",
181 "done_at": "",
182 "amount": "",
183 "fee": "",
184 "transaction_type": ""
185 });
186
187 let expected_structure = expected_structure
188 .as_object()
189 .unwrap()
190 .iter()
191 .map(|(k, v)| (k.as_str(), v.clone()))
192 .collect::<HashMap<&str, Value>>();
193
194 let (missing_keys, extra_keys) = compare_keys(&json, &expected_structure, "");
195
196 if !missing_keys.is_empty() {
197 println!("[test_get_deposit_info] Missing keys: {missing_keys:?}");
198 assert!(false);
199 } else {
200 println!("[test_get_deposit_info] No keys are missing");
201 }
202
203 if !extra_keys.is_empty() {
204 println!("[test_get_deposit_info] Extra keys: {extra_keys:?}");
205 assert!(false);
206 } else {
207 println!("[test_get_deposit_info] No extra keys found.");
208 }
209
210 assert!(true);
211 }
212
213 fn compare_keys(
214 json: &Value,
215 expected: &HashMap<&str, Value>,
216 path: &str,
217 ) -> (Vec<String>, Vec<String>) {
218 let mut missing_keys = Vec::new();
219 let mut extra_keys = Vec::new();
220
221 if let Value::Object(map) = json {
222 let json_keys: HashSet<&str> = map.keys().map(|k| k.as_str()).collect();
223 let expected_keys: HashSet<&str> = expected.keys().cloned().collect();
224
225 for key in expected_keys.difference(&json_keys) {
226 missing_keys.push(format!("{path}{key}"));
227 }
228
229 for key in json_keys.difference(&expected_keys) {
230 extra_keys.push(format!("{path}{key}"));
231 }
232
233 for key in expected_keys.intersection(&json_keys) {
234 if let Some(expected_value) = expected.get(*key) {
235 let new_path = format!("{}{}.", path, key);
236 if let Value::Object(_) = expected_value {
237 let expected_map = expected_value
238 .as_object()
239 .unwrap()
240 .iter()
241 .map(|(k, v)| (k.as_str(), v.clone()))
242 .collect::<HashMap<&str, Value>>();
243 let (mut missing, mut extra) =
244 compare_keys(&map[*key], &expected_map, &new_path);
245 missing_keys.append(&mut missing);
246 extra_keys.append(&mut extra);
247 }
248 }
249 }
250 }
251
252 (missing_keys, extra_keys)
253 }
254}