1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//! Generic functions and structs for the API
//!
//! This module contains the generic functions and structs for the API.
//! These are used by the `Client`, and public for the whole crate
use chrono::prelude::*;
use std::fmt::Debug;
use reqwest::StatusCode;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use crate::error::{Error, LemonError};
/// Module for interacting with the account related endpoints
mod market_data;
mod orders;
mod trading;
/// Generic struct for Endpoints that returns pagination information alongside data
///
/// Properties:
///
/// * `time`: The time the request was made.
/// * `status`: The status of the request.
/// * `mode`: The mode of the request.
/// * `results`: The actual results of the query.
/// * `previous`: The URL of the previous page of results.
/// * `next`: The URL for the next page of results.
/// * `total`: The total number of results available.
/// * `page`: The current page number
/// * `pages`: The total number of pages in the response.
#[derive(Deserialize, Serialize, Debug)]
pub struct PaginationResponse<T> {
/// The time the request was made.
pub time: DateTime<Utc>,
/// The status of the request.
pub status: Option<String>,
/// The mode of the request. Can be paper, live, or market_data
pub mode: Option<Mode>,
/// The actual results of the query. Depends upon the given generics
pub results: Option<Vec<T>>,
/// The URL of the previous page of results.
pub previous: Option<String>,
/// The URL for the next page of results.
pub next: Option<String>,
/// The total number of results available.
pub total: i64,
/// The current page number
pub page: i64,
/// The total number of pages in the response.
pub pages: i64,
}
/// General response struct
#[derive(Deserialize, Debug)]
pub struct Response {
/// Timestamp of your request
pub time: String,
/// Environment the request was placed in: "paper" or "money"
// TODO: Make this an enum
pub mode: Mode,
/// Status of the request. Returns 'ok' if successful
pub status: String,
}
/// Generic response struct
#[derive(Deserialize, Debug)]
pub struct GenericResponse<T> {
/// Timestamp of your request
pub time: DateTime<Utc>,
/// Environment the request was placed in: "paper" or "money"
// TODO: Make this an enum
pub mode: Mode,
/// Status of the request.
pub status: String,
/// The actual results of the query. Depends upon the given generics
pub results: Option<T>,
}
/// Trading mode
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "lowercase")]
pub enum Mode {
/// Paper trading mode
Paper,
/// Live trading mode
Live,
/// Market data mode
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"),
}
}
}
/// Traits with API methods that are common across all calls
pub(crate) trait Requests {
/// Generic get request
fn get<T: DeserializeOwned + Debug>(&self, path: &str) -> Result<T, Error>;
/// Generic get request with query parameters
fn get_with_query<T: DeserializeOwned + Debug, Q: IntoIterator + Serialize>(
&self,
path: &str,
query: Q,
) -> Result<T, Error>;
/// Generic post request
fn post<T: DeserializeOwned, B: Serialize>(&self, path: &str, body: B) -> Result<T, Error>;
/// Generic delete request
fn delete<T: DeserializeOwned>(&self, path: &str, path_param: &str) -> Result<T, Error>;
/// Crate wide function to handle responses and errors
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()))
}
}
}
/// Crate wide function to handle query params
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);
}
}
}