Skip to main content

bybit/models/
instrument_request.rs

1use crate::prelude::*;
2
3/// Parameters for requesting instrument information.
4///
5/// This struct defines the parameters for querying instrument details via the `/v5/market/instruments-info` endpoint.
6/// For perpetual futures, instrument info includes leverage, price filters, and lot size filters, which are critical
7/// for configuring trading bot parameters.
8#[derive(Clone, Default)]
9pub struct InstrumentRequest<'a> {
10    /// The product category (e.g., Linear, Inverse, Spot, Option).
11    ///
12    /// Specifies the instrument type. For perpetual futures, use `Linear` or `Inverse`.
13    /// Bots must set this to filter relevant instruments.
14    pub category: Category,
15
16    /// The trading pair symbol (e.g., "BTCUSDT").
17    ///
18    /// Optionally specifies a single trading pair. If unset, the API returns data for all instruments
19    /// in the category, which may be voluminous. Bots should set this for specific pairs to reduce
20    /// response size and latency.
21    pub symbol: Option<Cow<'a, str>>,
22
23    /// Symbol type filter (e.g., "spot", "linear", "inverse").
24    ///
25    /// The region to which the trading pair belongs. Only applicable for `linear`, `inverse`, and `spot` categories.
26    /// This can be used to filter instruments by their regional classification.
27    pub symbol_type: Option<Cow<'a, str>>,
28
29    /// Instrument status filter.
30    ///
31    /// Filters instruments by their trading status:
32    /// - `linear` & `inverse` & `spot`: By default returns only `Trading` symbols
33    /// - `option`: By default returns `PreLaunch`, `Trading`, and `Delivering`
34    /// - Spot has `Trading` only
35    /// - `linear` & `inverse`: when status=PreLaunch, it returns Pre-Market contracts
36    pub status: Option<Cow<'a, str>>,
37
38    /// The base coin of the instrument (e.g., "BTC").
39    ///
40    /// Filters instruments by their base asset. For example, setting `base_coin` to `"BTC"` returns
41    /// all BTC-based instruments. Applies to `linear`, `inverse`, and `option` categories only.
42    /// For `option` category, returns BTC by default if not specified.
43    pub base_coin: Option<Cow<'a, str>>,
44
45    /// The maximum number of instruments to return (1-1000, default: 500).
46    ///
47    /// Controls the response size. Bots should set a reasonable limit to balance data completeness
48    /// and performance, especially when querying all instruments in a category.
49    /// Note: Spot does not support pagination, so `limit` and `cursor` are invalid for spot category.
50    pub limit: Option<u64>,
51
52    /// Cursor for pagination.
53    ///
54    /// Use the `nextPageCursor` token from the response to retrieve the next page of the result set.
55    /// Note: Spot does not support pagination, so `limit` and `cursor` are invalid for spot category.
56    pub cursor: Option<Cow<'a, str>>,
57}
58
59impl<'a> InstrumentRequest<'a> {
60    /// Creates a default Instrument request.
61    ///
62    /// Returns a request with `category` set to `Linear` and `symbol` set to `"BTCUSDT"`.
63    /// Suitable for testing but should be customized for production to match specific trading needs.
64    pub fn default() -> InstrumentRequest<'a> {
65        InstrumentRequest::new(
66            Category::Linear,
67            Some("BTCUSDT"),
68            None,
69            None,
70            None,
71            None,
72            None,
73        )
74    }
75
76    /// Constructs a new Instrument request with specified parameters.
77    ///
78    /// Allows full customization. Bots should use this to tailor requests to their strategy,
79    /// ensuring `category` and `symbol` align with the instruments being traded.
80    pub fn new(
81        category: Category,
82        symbol: Option<&'a str>,
83        symbol_type: Option<&'a str>,
84        status: Option<&'a str>,
85        base_coin: Option<&'a str>,
86        limit: Option<u64>,
87        cursor: Option<&'a str>,
88    ) -> InstrumentRequest<'a> {
89        InstrumentRequest {
90            category,
91            symbol: symbol.map(Cow::Borrowed),
92            symbol_type: symbol_type.map(Cow::Borrowed),
93            status: status.map(Cow::Borrowed),
94            base_coin: base_coin.map(Cow::Borrowed),
95            limit,
96            cursor: cursor.map(Cow::Borrowed),
97        }
98    }
99
100    /// Validates the request parameters according to API constraints.
101    ///
102    /// Returns `Ok(())` if the request is valid, or `Err(String)` with an error message.
103    pub fn validate(&self) -> Result<(), String> {
104        // Validate limit range
105        if let Some(limit) = self.limit {
106            if limit == 0 || limit > 1000 {
107                return Err("Limit must be between 1 and 1000 inclusive".to_string());
108            }
109        }
110
111        // Validate category-specific constraints
112        match self.category {
113            Category::Spot => {
114                // Spot does not support pagination
115                if self.limit.is_some() || self.cursor.is_some() {
116                    return Err(
117                        "Spot category does not support limit or cursor parameters".to_string()
118                    );
119                }
120            }
121            Category::Option => {
122                // Option requires either symbol or base_coin
123                if self.symbol.is_none() && self.base_coin.is_none() {
124                    return Err(
125                        "Option category requires either symbol or base_coin parameter".to_string(),
126                    );
127                }
128            }
129            _ => {} // Linear and Inverse have no special validation
130        }
131
132        Ok(())
133    }
134
135    /// Creates a request for linear perpetual futures.
136    ///
137    /// Convenience method for creating requests for USDT-margined perpetual futures.
138    pub fn linear(
139        symbol: Option<&'a str>,
140        symbol_type: Option<&'a str>,
141        status: Option<&'a str>,
142        base_coin: Option<&'a str>,
143        limit: Option<u64>,
144        cursor: Option<&'a str>,
145    ) -> InstrumentRequest<'a> {
146        InstrumentRequest::new(
147            Category::Linear,
148            symbol,
149            symbol_type,
150            status,
151            base_coin,
152            limit,
153            cursor,
154        )
155    }
156
157    /// Creates a request for inverse perpetual futures.
158    ///
159    /// Convenience method for creating requests for coin-margined perpetual futures.
160    pub fn inverse(
161        symbol: Option<&'a str>,
162        symbol_type: Option<&'a str>,
163        status: Option<&'a str>,
164        base_coin: Option<&'a str>,
165        limit: Option<u64>,
166        cursor: Option<&'a str>,
167    ) -> InstrumentRequest<'a> {
168        InstrumentRequest::new(
169            Category::Inverse,
170            symbol,
171            symbol_type,
172            status,
173            base_coin,
174            limit,
175            cursor,
176        )
177    }
178
179    /// Creates a request for spot trading pairs.
180    ///
181    /// Convenience method for creating requests for spot markets.
182    pub fn spot(
183        symbol: Option<&'a str>,
184        symbol_type: Option<&'a str>,
185        status: Option<&'a str>,
186    ) -> InstrumentRequest<'a> {
187        InstrumentRequest::new(
188            Category::Spot,
189            symbol,
190            symbol_type,
191            status,
192            None, // base_coin not applicable for spot
193            None, // limit not supported for spot
194            None, // cursor not supported for spot
195        )
196    }
197
198    /// Creates a request for options contracts.
199    ///
200    /// Convenience method for creating requests for options markets.
201    pub fn option(
202        symbol: Option<&'a str>,
203        status: Option<&'a str>,
204        base_coin: Option<&'a str>,
205        limit: Option<u64>,
206        cursor: Option<&'a str>,
207    ) -> InstrumentRequest<'a> {
208        InstrumentRequest::new(
209            Category::Option,
210            symbol,
211            None, // symbol_type not applicable for options
212            status,
213            base_coin,
214            limit,
215            cursor,
216        )
217    }
218}