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}