-
Notifications
You must be signed in to change notification settings - Fork 26
feat(client): GetMarketsRequest builder type to allow customizable queries #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| use bpx_api_types::markets::{ | ||
| Asset, FundingRate, Kline, MarkPrice, Market, OrderBookDepth, OrderBookDepthLimit, Ticker, | ||
| }; | ||
| use reqwest::Method; | ||
| use std::borrow::Cow; | ||
|
|
||
| use crate::BpxClient; | ||
| use crate::error::Result; | ||
| use crate::{BpxClient, BpxClientRequest, Error}; | ||
|
|
||
| const API_ASSETS: &str = "/api/v1/assets"; | ||
| const API_MARKETS: &str = "/api/v1/markets"; | ||
|
|
@@ -22,13 +24,19 @@ impl BpxClient { | |
| res.json().await.map_err(Into::into) | ||
| } | ||
|
|
||
| /// Retrieves a list of available markets. | ||
| /// Retrieves a list of available spot and perp markets. | ||
| /// | ||
| /// Note: If you want to retrieve other market types or filter by market type, use `GetMarketsRequest`. | ||
| pub async fn get_markets(&self) -> Result<Vec<Market>> { | ||
| let url = self.base_url.join(API_MARKETS)?; | ||
| let res = self.get(url).await?; | ||
| res.json().await.map_err(Into::into) | ||
| GetMarketsRequest::new() | ||
| .with_spot_markets() | ||
| .with_perp_markets() | ||
|
Comment on lines
+31
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a user I would expect that calling IMO we should not specify defaults here - the exchange backend already has defaults specified if no types are provided in the query: |
||
| .send(self) | ||
| .await | ||
| } | ||
|
|
||
| // pub async fn get_markets_with_filter | ||
|
|
||
| /// Retrieves mark price, index price and the funding rate for the current interval for all symbols, or the symbol specified. | ||
| pub async fn get_all_mark_prices(&self) -> Result<Vec<MarkPrice>> { | ||
| let url = self.base_url.join(API_MARK_PRICES)?; | ||
|
|
@@ -96,3 +104,75 @@ impl BpxClient { | |
| res.json().await.map_err(Into::into) | ||
| } | ||
| } | ||
|
|
||
| #[derive(Debug, Default, Clone)] | ||
| pub struct GetMarketsRequest(Vec<String>); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that performance really matters here, but could use |
||
|
|
||
| impl GetMarketsRequest { | ||
| pub fn new() -> Self { | ||
| Self::default() | ||
| } | ||
|
Comment on lines
+112
to
+114
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we add an additional overload that allows the user to pass a market type? This way if a new market type becomes available in the API it's still possible to query it without us having to add another method here. |
||
|
|
||
| pub fn with_spot_markets(mut self) -> Self { | ||
| self.0.push("SPOT".to_string()); | ||
| self | ||
| } | ||
|
|
||
| pub fn with_perp_markets(mut self) -> Self { | ||
| self.0.push("PERP".to_string()); | ||
| self | ||
| } | ||
|
|
||
| pub fn with_prediction_markets(mut self) -> Self { | ||
| self.0.push("PREDICTION".to_string()); | ||
| self | ||
| } | ||
|
|
||
| pub async fn send(self, client: &BpxClient) -> Result<Vec<Market>> { | ||
| if self.0.is_empty() { | ||
| return Err(Error::InvalidRequest( | ||
| "at least one market type must be specified".into(), | ||
| )); | ||
| } | ||
|
|
||
| let mut url = client.base_url.join(API_MARKETS)?; | ||
| for market_type in self.0 { | ||
| url.query_pairs_mut() | ||
| .append_pair("marketType", &market_type); | ||
| } | ||
|
|
||
| let res = client.get(url).await?; | ||
| res.json().await.map_err(Into::into) | ||
| } | ||
| } | ||
|
|
||
| impl BpxClientRequest for GetMarketsRequest { | ||
| const PATH: &'static str = API_MARKETS; | ||
| const METHOD: Method = Method::GET; | ||
| type Body = (); | ||
|
|
||
| fn query_params(&self) -> Vec<(Cow<'_, str>, Cow<'_, str>)> { | ||
| let mut params = Vec::new(); | ||
| for market_type in &self.0 { | ||
| params.push(( | ||
| Cow::Borrowed("marketType"), | ||
| Cow::Borrowed(market_type.as_str()), | ||
| )); | ||
| } | ||
| params | ||
| } | ||
|
|
||
| fn body(&self) -> Option<&Self::Body> { | ||
| None | ||
| } | ||
|
|
||
| fn validate(&self) -> Result<()> { | ||
| if self.0.is_empty() { | ||
| return Err(Error::InvalidRequest( | ||
| "at least one market type must be specified".into(), | ||
| )); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we have a method on BpxClient like:
Then users can do:
Feels a little more ergonomic than
req.send(client).await