use crate::error::Result;
use crate::http::HttpClient;
use crate::request::PaginationParams;
use crate::types::{
BookParams, ConditionId, Market, MarketsResponse, MidpointResponse, NegRiskResponse,
OrderBookSummary, PriceHistoryResponse, PriceResponse, SimplifiedMarketsResponse,
SpreadResponse, TickSizeResponse, TokenId,
};
use crate::Side;
pub struct ClobClient {
http_client: HttpClient,
}
impl ClobClient {
pub fn new(host: impl Into<String>) -> Self {
Self {
http_client: HttpClient::new(host),
}
}
pub async fn get_ok(&self) -> Result<serde_json::Value> {
self.http_client.get("/", None).await
}
pub async fn get_server_time(&self) -> Result<serde_json::Value> {
self.http_client.get("/time", None).await
}
pub async fn get_midpoint(&self, token_id: &TokenId) -> Result<MidpointResponse> {
let path = format!("/midpoint?token_id={}", token_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_midpoints(&self, token_ids: &[TokenId]) -> Result<Vec<MidpointResponse>> {
let ids: Vec<&str> = token_ids.iter().map(|id| id.as_str()).collect();
self.http_client
.post("/midpoints", &serde_json::json!({ "token_ids": ids }), None)
.await
}
pub async fn get_price(&self, token_id: &TokenId, side: Side) -> Result<PriceResponse> {
let mut path = format!("/price?token_id={}", token_id.as_str());
path.push_str(&format!("&side={}", side.as_str()));
self.http_client.get(&path, None).await
}
pub async fn get_prices(&self, token_ids: &[TokenId]) -> Result<Vec<PriceResponse>> {
let ids: Vec<&str> = token_ids.iter().map(|id| id.as_str()).collect();
self.http_client
.post("/prices", &serde_json::json!({ "token_ids": ids }), None)
.await
}
pub async fn get_prices_history(
&self,
token_id: &TokenId,
interval: &str,
start_ts: Option<u64>,
end_ts: Option<u64>,
fidelity: Option<u64>,
) -> Result<PriceHistoryResponse> {
let mut path = format!("/prices-history?market={}", token_id.as_str());
path.push_str(&format!("&interval={}", interval));
path.push_str(&format!("&fidelity={}", fidelity.unwrap_or(10)));
if let Some(start) = start_ts {
path.push_str(&format!("&startTs={}", start));
}
if let Some(end) = end_ts {
path.push_str(&format!("&endTs={}", end));
}
self.http_client.get(&path, None).await
}
pub async fn get_spread(&self, token_id: &TokenId) -> Result<SpreadResponse> {
let path = format!("/spread?token_id={}", token_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_spreads(&self, token_ids: &[TokenId]) -> Result<Vec<SpreadResponse>> {
let ids: Vec<&str> = token_ids.iter().map(|id| id.as_str()).collect();
self.http_client
.post("/spreads", &serde_json::json!({ "token_ids": ids }), None)
.await
}
pub async fn get_tick_size(&self, token_id: &TokenId) -> Result<TickSizeResponse> {
let path = format!("/tick-size?token_id={}", token_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_neg_risk(&self, condition_id: &ConditionId) -> Result<NegRiskResponse> {
let path = format!("/neg-risk?condition_id={}", condition_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_order_book(&self, token_id: &TokenId) -> Result<OrderBookSummary> {
let path = format!("/book?token_id={}", token_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_order_books(&self, params: &[BookParams]) -> Result<Vec<OrderBookSummary>> {
self.http_client.post("/books", ¶ms, None).await
}
pub async fn get_last_trade_price(&self, token_id: &TokenId) -> Result<PriceResponse> {
let path = format!("/last-trade-price?token_id={}", token_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_last_trade_prices(&self, token_ids: &[TokenId]) -> Result<serde_json::Value> {
let ids: Vec<&str> = token_ids.iter().map(|id| id.as_str()).collect();
self.http_client
.post(
"/last-trades-prices",
&serde_json::json!({ "token_ids": ids }),
None,
)
.await
}
pub async fn get_sampling_markets(
&self,
pagination: Option<PaginationParams>,
) -> Result<MarketsResponse> {
let mut path = "/sampling-markets".to_string();
if let Some(p) = pagination {
let params = p.to_query_params();
if !params.is_empty() {
path.push_str("?next_cursor=");
path.push_str(¶ms[0].1);
}
}
self.http_client.get(&path, None).await
}
pub async fn get_sampling_simplified_markets(
&self,
pagination: Option<PaginationParams>,
) -> Result<SimplifiedMarketsResponse> {
let mut path = "/sampling-simplified-markets".to_string();
if let Some(p) = pagination {
let params = p.to_query_params();
if !params.is_empty() {
path.push_str("?next_cursor=");
path.push_str(¶ms[0].1);
}
}
self.http_client.get(&path, None).await
}
pub async fn get_markets(
&self,
pagination: Option<PaginationParams>,
) -> Result<MarketsResponse> {
let mut path = "/markets".to_string();
if let Some(p) = pagination {
let params = p.to_query_params();
if !params.is_empty() {
path.push_str("?next_cursor=");
path.push_str(¶ms[0].1);
}
}
self.http_client.get(&path, None).await
}
pub async fn get_simplified_markets(
&self,
pagination: Option<PaginationParams>,
) -> Result<SimplifiedMarketsResponse> {
let mut path = "/simplified-markets".to_string();
if let Some(p) = pagination {
let params = p.to_query_params();
if !params.is_empty() {
path.push_str("?next_cursor=");
path.push_str(¶ms[0].1);
}
}
self.http_client.get(&path, None).await
}
pub async fn get_market(&self, condition_id: &ConditionId) -> Result<Market> {
let path = format!("/markets/{}", condition_id.as_str());
self.http_client.get(&path, None).await
}
pub async fn get_market_by_slug(&self, market_slug: &str) -> Result<Market> {
let path = format!("/markets/slug/{}", market_slug);
self.http_client.get(&path, None).await
}
pub async fn get_market_trades_events(
&self,
condition_id: &ConditionId,
) -> Result<serde_json::Value> {
let path = format!("/live-activity/events/{}", condition_id.as_str());
self.http_client.get(&path, None).await
}
}