1use std::sync::Arc;
4use reqwest::Client;
5use crate::error::FxapiError;
6use crate::{error, models, utils};
7use crate::utils::baseline::construct_base_url;
8
9#[derive(Debug, Clone)]
11pub struct Settings {
12 api_key: String,
13}
14
15#[derive(Debug, Clone)]
18pub struct Fxapi {
19 client: Client,
20 settings: Arc<Settings>,
21}
22
23impl<'a> Fxapi {
24 pub fn new(api_key: &'a str) -> Result<Self, FxapiError> {
27 let settings = std::sync::Arc::new(Settings {
28 api_key: String::from(api_key),
29 });
30 let client = utils::baseline::construct_client(None, &settings)?;
31 Ok(Self { client, settings })
32 }
33
34 pub async fn status(
35 &self,
36 ) -> Result<models::DetailsResponse, error::FxapiError> {
37 let mut url = construct_base_url(&self.settings.api_key, Some("status"))?;
38 let res_body = self
39 .client
40 .get(url)
41 .send()
42 .await
43 .map_err(|err| error::FxapiError::RequestError { source: err })?
44 .text()
45 .await
46 .map_err(|err| error::FxapiError::RequestError { source: err })?;
47 serde_json::from_str::<models::DetailsResponse>(&res_body)
48 .map_err(|_| error::FxapiError::ResponseParsingError { body: res_body })
49 }
50
51 pub async fn currencies(
52 &self,
53 ) -> Result<models::DetailsResponse, error::FxapiError> {
54 let mut url = construct_base_url(&self.settings.api_key, Some("currencies"))?;
55 let res_body = self
56 .client
57 .get(url)
58 .send()
59 .await
60 .map_err(|err| error::FxapiError::RequestError { source: err })?
61 .text()
62 .await
63 .map_err(|err| error::FxapiError::RequestError { source: err })?;
64 serde_json::from_str::<models::DetailsResponse>(&res_body)
65 .map_err(|_| error::FxapiError::ResponseParsingError { body: res_body })
66 }
67
68 pub async fn latest(
69 &self,
70 base_currency: &'a str,
71 currencies: &'a str,
72 ) -> Result<models::DetailsResponse, error::FxapiError> {
73 let mut url = construct_base_url(&self.settings.api_key, Some("latest"))?;
74 url.query_pairs_mut()
75 .append_pair("base_currency", base_currency)
76 .append_pair("currencies", currencies);
77 let res_body = self
78 .client
79 .get(url)
80 .send()
81 .await
82 .map_err(|err| error::FxapiError::RequestError { source: err })?
83 .text()
84 .await
85 .map_err(|err| error::FxapiError::RequestError { source: err })?;
86 serde_json::from_str::<models::DetailsResponse>(&res_body)
87 .map_err(|_| error::FxapiError::ResponseParsingError { body: res_body })
88 }
89
90 pub async fn historical(
91 &self,
92 base_currency: &'a str,
93 date: &'a str,
94 currencies: &'a str,
95 ) -> Result<models::DetailsResponse, error::FxapiError> {
96 let mut url = construct_base_url(&self.settings.api_key, Some("historical"))?;
97 url.query_pairs_mut()
98 .append_pair("base_currency", base_currency)
99 .append_pair("date", date)
100 .append_pair("currencies", currencies);
101 let res_body = self
102 .client
103 .get(url)
104 .send()
105 .await
106 .map_err(|err| error::FxapiError::RequestError { source: err })?
107 .text()
108 .await
109 .map_err(|err| error::FxapiError::RequestError { source: err })?;
110 serde_json::from_str::<models::DetailsResponse>(&res_body)
111 .map_err(|_| error::FxapiError::ResponseParsingError { body: res_body })
112 }
113
114 pub async fn convert(
115 &self,
116 base_currency: &'a str,
117 date: &'a str,
118 value: i8,
119 currencies: &'a str,
120 ) -> Result<models::DetailsResponse, error::FxapiError> {
121 let mut url = construct_base_url(&self.settings.api_key, Some("convert"))?;
122 url.query_pairs_mut()
123 .append_pair("base_currency", base_currency)
124 .append_pair("date", date)
125 .append_pair("value", &value.to_string())
126 .append_pair("currencies", currencies);
127 let res_body = self
128 .client
129 .get(url)
130 .send()
131 .await
132 .map_err(|err| error::FxapiError::RequestError { source: err })?
133 .text()
134 .await
135 .map_err(|err| error::FxapiError::RequestError { source: err })?;
136 serde_json::from_str::<models::DetailsResponse>(&res_body)
137 .map_err(|_| error::FxapiError::ResponseParsingError { body: res_body })
138 }
139
140 pub async fn range(
141 &self,
142 base_currency: &'a str,
143 datetime_start: &'a str,
144 datetime_end: &'a str,
145 currencies: &'a str,
146 accuracy: &'a str,
147 ) -> Result<models::DetailsResponse, error::FxapiError> {
148 let mut url = construct_base_url(&self.settings.api_key, Some("range"))?;
149 url.query_pairs_mut()
150 .append_pair("base_currency", base_currency)
151 .append_pair("datetime_start", datetime_start)
152 .append_pair("datetime_end", datetime_end)
153 .append_pair("accuracy", accuracy)
154 .append_pair("currencies", currencies);
155 let res_body = self
156 .client
157 .get(url)
158 .send()
159 .await
160 .map_err(|err| error::FxapiError::RequestError { source: err })?
161 .text()
162 .await
163 .map_err(|err| error::FxapiError::RequestError { source: err })?;
164 serde_json::from_str::<models::DetailsResponse>(&res_body)
165 .map_err(|_| error::FxapiError::ResponseParsingError { body: res_body })
166 }
167}