use std::collections::HashMap;
use std::error::Error;
use reqwest::Url;
use serde::{Deserialize, Serialize};
use crate::{builder_setter, client};
use crate::client::OneInchClient;
use crate::consts::{BASIC_URL, SPOT_PRICE_API_VERSION};
use crate::utils::builder::BasicBuilderError;
#[derive(Default)]
pub struct TokensPricesRequestBuilder {
addresses : Option<Vec<String>>,
currency : Option<client::SupportedCurrencies>,
}
impl TokensPricesRequestBuilder {
pub fn new() -> TokensPricesRequestBuilder {
TokensPricesRequestBuilder::default()
}
builder_setter!(addresses, Vec<String>);
builder_setter!(currency, client::SupportedCurrencies);
pub fn build(&self) -> Result<TokensPricesRequestDetails, BasicBuilderError> {
Ok(TokensPricesRequestDetails {
addresses : self.addresses.clone().ok_or(BasicBuilderError::MissingField("addresses"))?,
currency: self.currency.clone()
})
}
}
#[derive(Debug, Clone)]
pub struct TokensPricesRequestDetails {
pub addresses : Vec<String>,
pub currency : Option<client::SupportedCurrencies>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct TokenPricesResponse {
#[serde(flatten)]
pub prices: HashMap<String, String>,
}
impl OneInchClient {
pub async fn get_tokens_price(
&self,
details: TokensPricesRequestDetails,
) -> Result<TokenPricesResponse, Box<dyn Error>> {
let base_url = format!(
"{}/price/{}/{}/",
BASIC_URL,
SPOT_PRICE_API_VERSION,
self.network_id
);
let comma_separated_addresses = details.addresses.iter()
.map(|addr| addr.to_string())
.map(|addr| addr.to_lowercase())
.collect::<Vec<String>>()
.join(",");
let mut url_with_params = format!("{}{}", base_url, comma_separated_addresses);
if let Some(currency) = details.currency {
url_with_params = format!("{}?currency={}", url_with_params, currency);
}
let url = Url::parse(&url_with_params).map_err(|e| Box::new(e) as Box<dyn Error>)?;
dbg!(&url.clone().to_string());
let request_result = self
.http_client
.get(url)
.header("Authorization", &self.token)
.send()
.await;
let response = request_result
.map_err(|e| Box::new(e) as Box<dyn Error>)?
.error_for_status()
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
let tokens_prices_response: TokenPricesResponse = response
.json()
.await
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
Ok(tokens_prices_response)
}
}