use chrono::prelude::*;
use std::fmt::Debug;
use reqwest::StatusCode;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use crate::error::{Error, LemonError};
mod market_data;
mod orders;
mod trading;
#[derive(Deserialize, Serialize, Debug)]
pub struct PaginationResponse<T> {
pub time: DateTime<Utc>,
pub status: Option<String>,
pub mode: Option<Mode>,
pub results: Option<Vec<T>>,
pub previous: Option<String>,
pub next: Option<String>,
pub total: i64,
pub page: i64,
pub pages: i64,
}
#[derive(Deserialize, Debug)]
pub struct Response {
pub time: String,
pub mode: Mode,
pub status: String,
}
#[derive(Deserialize, Debug)]
pub struct GenericResponse<T> {
pub time: DateTime<Utc>,
pub mode: Mode,
pub status: String,
pub results: Option<T>,
}
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "lowercase")]
pub enum Mode {
Paper,
Live,
MarketData,
}
impl std::fmt::Display for Mode {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
Mode::Paper => write!(f, "paper"),
Mode::Live => write!(f, "live"),
Mode::MarketData => write!(f, "market_data"),
}
}
}
pub(crate) trait Requests {
fn get<T: DeserializeOwned + Debug>(&self, path: &str) -> Result<T, Error>;
fn get_with_query<T: DeserializeOwned + Debug, Q: IntoIterator + Serialize>(
&self,
path: &str,
query: Q,
) -> Result<T, Error>;
fn post<T: DeserializeOwned, B: Serialize>(&self, path: &str, body: B) -> Result<T, Error>;
fn delete<T: DeserializeOwned>(&self, path: &str, path_param: &str) -> Result<T, Error>;
fn response_handler<T: DeserializeOwned>(
&self,
response: reqwest::blocking::Response,
) -> Result<T, Error> {
match response.status() {
StatusCode::OK => Ok(response.json::<T>()?),
_s => {
let message = response.json::<LemonError>()?;
Err(Error::Str(message.to_string()))
}
}
}
fn get_query_string<Q: Serialize>(query: Q, query_vector: &mut Vec<String>) {
if let Ok(query_string) = serde_urlencoded::to_string(&query) {
query_vector.push(query_string);
}
}
}