Skip to main content

nautilus_bybit/http/
query.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Builder types for Bybit REST query parameters and filters.
17
18use derive_builder::Builder;
19use serde::{Deserialize, Serialize};
20
21use crate::common::{
22    enums::{
23        BybitAccountType, BybitExecType, BybitInstrumentStatus, BybitKlineInterval,
24        BybitMarginMode, BybitMarketUnit, BybitOpenOnly, BybitOptionType, BybitOrderFilter,
25        BybitOrderSide, BybitOrderStatus, BybitOrderType, BybitPositionIdx, BybitPositionMode,
26        BybitProductType, BybitSmpType, BybitStopOrderType, BybitTimeInForce, BybitTpSlMode,
27        BybitTriggerDirection, BybitTriggerType,
28    },
29    parse::opt_bool_as_int,
30};
31
32/// Query parameters for `GET /v5/market/instruments-info`.
33///
34/// # References
35/// - <https://bybit-exchange.github.io/docs/v5/market/instrument>
36#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
37#[serde(rename_all = "camelCase")]
38#[builder(default)]
39#[builder(setter(into))]
40pub struct BybitInstrumentsInfoParams {
41    pub category: BybitProductType,
42    #[builder(setter(strip_option))]
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub symbol: Option<String>,
45    #[builder(setter(strip_option))]
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub status: Option<BybitInstrumentStatus>,
48    #[builder(setter(strip_option))]
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub base_coin: Option<String>,
51    #[builder(setter(strip_option))]
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub limit: Option<u32>,
54    #[builder(setter(strip_option))]
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub cursor: Option<String>,
57}
58
59/// Query parameters for `GET /v5/market/tickers`.
60///
61/// # References
62/// - <https://bybit-exchange.github.io/docs/v5/market/tickers>
63#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
64#[serde(rename_all = "camelCase")]
65#[builder(default)]
66#[builder(setter(into))]
67pub struct BybitTickersParams {
68    pub category: BybitProductType,
69    #[serde(skip_serializing_if = "Option::is_none")]
70    #[builder(setter(strip_option))]
71    pub symbol: Option<String>,
72    #[serde(skip_serializing_if = "Option::is_none")]
73    #[builder(setter(strip_option))]
74    pub base_coin: Option<String>,
75    #[serde(skip_serializing_if = "Option::is_none")]
76    #[builder(setter(strip_option))]
77    pub exp_date: Option<String>,
78}
79
80/// Query parameters for `GET /v5/market/kline`.
81///
82/// # References
83/// - <https://bybit-exchange.github.io/docs/v5/market/kline>
84#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
85#[serde(rename_all = "camelCase")]
86#[builder(setter(into, strip_option), default)]
87pub struct BybitKlinesParams {
88    pub category: BybitProductType,
89    pub symbol: String,
90    pub interval: BybitKlineInterval,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub start: Option<i64>,
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub end: Option<i64>,
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub limit: Option<u32>,
97}
98
99impl Default for BybitKlinesParams {
100    fn default() -> Self {
101        Self {
102            category: BybitProductType::Linear,
103            symbol: String::new(),
104            interval: BybitKlineInterval::Minute1,
105            start: None,
106            end: None,
107            limit: None,
108        }
109    }
110}
111
112/// Query parameters for `GET /v5/market/recent-trade`.
113///
114/// # References
115/// - <https://bybit-exchange.github.io/docs/v5/market/recent-trade>
116#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
117#[serde(rename_all = "camelCase")]
118#[builder(setter(into, strip_option), default)]
119pub struct BybitTradesParams {
120    pub category: BybitProductType,
121    pub symbol: String,
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub base_coin: Option<String>,
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub option_type: Option<BybitOptionType>,
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub limit: Option<u32>,
128}
129
130impl Default for BybitTradesParams {
131    fn default() -> Self {
132        Self {
133            category: BybitProductType::Linear,
134            symbol: String::new(),
135            base_coin: None,
136            option_type: None,
137            limit: None,
138        }
139    }
140}
141
142/// Query parameters for `GET /v5/market/funding/history`.
143///
144/// # References
145/// - <https://bybit-exchange.github.io/docs/v5/market/history-fund-rate>
146#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
147#[serde(rename_all = "camelCase")]
148#[builder(setter(into, strip_option), default)]
149pub struct BybitFundingParams {
150    pub category: BybitProductType,
151    pub symbol: String,
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub start_time: Option<i64>,
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub end_time: Option<i64>,
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub limit: Option<u32>,
158}
159
160impl Default for BybitFundingParams {
161    fn default() -> Self {
162        Self {
163            category: BybitProductType::Linear,
164            symbol: String::new(),
165            start_time: None,
166            end_time: None,
167            limit: None,
168        }
169    }
170}
171
172/// Query parameters for `GET /v5/market/orderbook`.
173///
174/// # References
175/// - <https://bybit-exchange.github.io/docs/v5/market/orderbook>
176#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
177#[builder(setter(into, strip_option), default)]
178pub struct BybitOrderbookParams {
179    pub category: BybitProductType,
180    pub symbol: String,
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub limit: Option<u32>,
183}
184
185impl Default for BybitOrderbookParams {
186    fn default() -> Self {
187        Self {
188            category: BybitProductType::Linear,
189            symbol: String::new(),
190            limit: None,
191        }
192    }
193}
194
195/// Query parameters for `GET /v5/asset/coin/query-info`.
196///
197/// # References
198/// - <https://bybit-exchange.github.io/docs/v5/asset/coin-info>
199#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
200#[serde(rename_all = "camelCase")]
201#[builder(default)]
202#[builder(setter(into))]
203pub struct BybitCoinInfoParams {
204    #[serde(skip_serializing_if = "Option::is_none")]
205    #[builder(setter(strip_option))]
206    pub coin: Option<String>,
207}
208
209/// Query parameters for `GET /v5/account/fee-rate`.
210///
211/// # References
212/// - <https://bybit-exchange.github.io/docs/v5/account/fee-rate>
213#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
214#[serde(rename_all = "camelCase")]
215#[builder(default)]
216#[builder(setter(into))]
217pub struct BybitFeeRateParams {
218    pub category: BybitProductType,
219    #[builder(setter(strip_option))]
220    #[serde(skip_serializing_if = "Option::is_none")]
221    pub symbol: Option<String>,
222    #[builder(setter(strip_option))]
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub base_coin: Option<String>,
225}
226
227/// Query parameters for `GET /v5/account/wallet-balance`.
228///
229/// # References
230/// - <https://bybit-exchange.github.io/docs/v5/account/wallet-balance>
231#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
232#[serde(rename_all = "camelCase")]
233pub struct BybitWalletBalanceParams {
234    pub account_type: BybitAccountType,
235    #[serde(skip_serializing_if = "Option::is_none")]
236    #[builder(setter(strip_option))]
237    pub coin: Option<String>,
238}
239
240/// Query parameters for `GET /v5/position/list`.
241///
242/// # References
243/// - <https://bybit-exchange.github.io/docs/v5/position>
244#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
245#[serde(rename_all = "camelCase")]
246#[builder(default)]
247#[builder(setter(into))]
248pub struct BybitPositionListParams {
249    pub category: BybitProductType,
250    #[serde(skip_serializing_if = "Option::is_none")]
251    #[builder(setter(strip_option))]
252    pub symbol: Option<String>,
253    #[serde(skip_serializing_if = "Option::is_none")]
254    #[builder(setter(strip_option))]
255    pub base_coin: Option<String>,
256    #[serde(skip_serializing_if = "Option::is_none")]
257    #[builder(setter(strip_option))]
258    pub settle_coin: Option<String>,
259    #[serde(skip_serializing_if = "Option::is_none")]
260    #[builder(setter(strip_option))]
261    pub limit: Option<u32>,
262    #[serde(skip_serializing_if = "Option::is_none")]
263    #[builder(setter(strip_option))]
264    pub cursor: Option<String>,
265}
266
267/// Body parameters for `POST /v5/account/set-margin-mode`.
268///
269/// # References
270/// - <https://bybit-exchange.github.io/docs/v5/account/set-margin-mode>
271#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
272#[serde(rename_all = "camelCase")]
273pub struct BybitSetMarginModeParams {
274    pub set_margin_mode: BybitMarginMode,
275}
276
277/// Body parameters for `POST /v5/position/set-leverage`.
278///
279/// # References
280/// - <https://bybit-exchange.github.io/docs/v5/position/leverage>
281#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
282#[serde(rename_all = "camelCase")]
283pub struct BybitSetLeverageParams {
284    pub category: BybitProductType,
285    pub symbol: String,
286    pub buy_leverage: String,
287    pub sell_leverage: String,
288}
289
290/// Body parameters for `POST /v5/position/switch-mode`.
291///
292/// # References
293/// - <https://bybit-exchange.github.io/docs/v5/position/position-mode>
294#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
295#[serde(rename_all = "camelCase")]
296pub struct BybitSwitchModeParams {
297    pub category: BybitProductType,
298    #[builder(default)]
299    #[serde(skip_serializing_if = "Option::is_none")]
300    #[builder(setter(strip_option))]
301    pub symbol: Option<String>,
302    #[builder(default)]
303    #[serde(skip_serializing_if = "Option::is_none")]
304    #[builder(setter(strip_option))]
305    pub coin: Option<String>,
306    pub mode: BybitPositionMode,
307}
308
309/// Body parameters for `POST /v5/position/trading-stop`.
310///
311/// # References
312/// - <https://bybit-exchange.github.io/docs/v5/position/trading-stop>
313#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
314#[serde(rename_all = "camelCase")]
315pub struct BybitSetTradingStopParams {
316    pub category: BybitProductType,
317    pub symbol: String,
318    pub position_idx: BybitPositionIdx,
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub take_profit: Option<String>,
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub stop_loss: Option<String>,
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub trailing_stop: Option<String>,
325    #[serde(skip_serializing_if = "Option::is_none")]
326    pub tp_trigger_by: Option<BybitTriggerType>,
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub sl_trigger_by: Option<BybitTriggerType>,
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub active_price: Option<String>,
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub tpsl_mode: Option<BybitTpSlMode>,
333    #[serde(skip_serializing_if = "Option::is_none")]
334    pub tp_size: Option<String>,
335    #[serde(skip_serializing_if = "Option::is_none")]
336    pub sl_size: Option<String>,
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub tp_limit_price: Option<String>,
339    #[serde(skip_serializing_if = "Option::is_none")]
340    pub sl_limit_price: Option<String>,
341    #[serde(skip_serializing_if = "Option::is_none")]
342    pub tp_order_type: Option<BybitOrderType>,
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub sl_order_type: Option<BybitOrderType>,
345}
346
347/// Body parameters for `POST /v5/account/borrow`.
348///
349/// # References
350///
351/// - <https://bybit-exchange.github.io/docs/v5/account/borrow>
352#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
353#[serde(rename_all = "camelCase")]
354pub struct BybitBorrowParams {
355    pub coin: String,
356    pub amount: String,
357}
358
359/// Body parameters for `POST /v5/account/no-convert-repay`.
360///
361/// # References
362///
363/// - <https://bybit-exchange.github.io/docs/v5/account/no-convert-repay>
364#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
365#[serde(rename_all = "camelCase")]
366pub struct BybitNoConvertRepayParams {
367    pub coin: String,
368    #[serde(skip_serializing_if = "Option::is_none")]
369    #[builder(setter(strip_option), default)]
370    pub amount: Option<String>,
371}
372
373/// Order entry payload for `POST /v5/order/create-batch`.
374///
375/// # References
376/// - <https://bybit-exchange.github.io/docs/v5/order/batch-place>
377#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
378#[serde(rename_all = "camelCase")]
379pub struct BybitBatchPlaceOrderEntry {
380    pub symbol: String,
381    #[builder(default)]
382    #[serde(skip_serializing_if = "Option::is_none")]
383    pub is_leverage: Option<i32>,
384    pub side: BybitOrderSide,
385    pub order_type: BybitOrderType,
386    pub qty: String,
387    #[builder(default)]
388    #[serde(skip_serializing_if = "Option::is_none")]
389    pub price: Option<String>,
390    #[builder(default)]
391    #[serde(skip_serializing_if = "Option::is_none")]
392    pub market_unit: Option<BybitMarketUnit>,
393    #[builder(default)]
394    #[serde(skip_serializing_if = "Option::is_none")]
395    pub trigger_direction: Option<BybitTriggerDirection>,
396    #[builder(default)]
397    #[serde(skip_serializing_if = "Option::is_none")]
398    pub order_filter: Option<BybitOrderFilter>,
399    #[builder(default)]
400    #[serde(skip_serializing_if = "Option::is_none")]
401    pub trigger_price: Option<String>,
402    #[builder(default)]
403    #[serde(skip_serializing_if = "Option::is_none")]
404    pub trigger_by: Option<BybitTriggerType>,
405    #[builder(default)]
406    #[serde(skip_serializing_if = "Option::is_none")]
407    pub order_iv: Option<String>,
408    #[builder(default)]
409    #[serde(skip_serializing_if = "Option::is_none")]
410    pub time_in_force: Option<BybitTimeInForce>,
411    #[builder(default)]
412    #[serde(skip_serializing_if = "Option::is_none")]
413    pub position_idx: Option<BybitPositionIdx>,
414    #[builder(default)]
415    #[serde(skip_serializing_if = "Option::is_none")]
416    #[builder(setter(strip_option))]
417    pub order_link_id: Option<String>,
418    #[builder(default)]
419    #[serde(skip_serializing_if = "Option::is_none")]
420    pub take_profit: Option<String>,
421    #[builder(default)]
422    #[serde(skip_serializing_if = "Option::is_none")]
423    pub stop_loss: Option<String>,
424    #[builder(default)]
425    #[serde(skip_serializing_if = "Option::is_none")]
426    pub tp_trigger_by: Option<BybitTriggerType>,
427    #[builder(default)]
428    #[serde(skip_serializing_if = "Option::is_none")]
429    pub sl_trigger_by: Option<BybitTriggerType>,
430    #[builder(default)]
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub reduce_only: Option<bool>,
433    #[builder(default)]
434    #[serde(skip_serializing_if = "Option::is_none")]
435    pub close_on_trigger: Option<bool>,
436    #[builder(default)]
437    #[serde(skip_serializing_if = "Option::is_none")]
438    pub smp_type: Option<BybitSmpType>,
439    #[builder(default)]
440    #[serde(skip_serializing_if = "Option::is_none")]
441    pub mmp: Option<bool>,
442    #[builder(default)]
443    #[serde(skip_serializing_if = "Option::is_none")]
444    pub tpsl_mode: Option<BybitTpSlMode>,
445    #[builder(default)]
446    #[serde(skip_serializing_if = "Option::is_none")]
447    pub tp_limit_price: Option<String>,
448    #[builder(default)]
449    #[serde(skip_serializing_if = "Option::is_none")]
450    pub sl_limit_price: Option<String>,
451    #[builder(default)]
452    #[serde(skip_serializing_if = "Option::is_none")]
453    pub tp_order_type: Option<BybitOrderType>,
454    #[builder(default)]
455    #[serde(skip_serializing_if = "Option::is_none")]
456    pub sl_order_type: Option<BybitOrderType>,
457}
458
459/// Body parameters for `POST /v5/order/create-batch`.
460///
461/// # References
462/// - <https://bybit-exchange.github.io/docs/v5/order/batch-place>
463#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
464#[serde(rename_all = "camelCase")]
465pub struct BybitBatchPlaceOrderParams {
466    pub category: BybitProductType,
467    pub request: Vec<BybitBatchPlaceOrderEntry>,
468}
469
470/// Body parameters for `POST /v5/order/create`.
471///
472/// # References
473/// - <https://bybit-exchange.github.io/docs/v5/order/create-order>
474#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
475#[serde(rename_all = "camelCase")]
476pub struct BybitPlaceOrderParams {
477    #[serde(flatten)]
478    pub order: BybitBatchPlaceOrderEntry,
479    pub category: BybitProductType,
480    #[builder(default)]
481    #[serde(skip_serializing_if = "Option::is_none")]
482    pub slippage_tolerance_type: Option<String>,
483    #[builder(default)]
484    #[serde(skip_serializing_if = "Option::is_none")]
485    pub slippage_tolerance: Option<String>,
486}
487
488/// Amend entry for `POST /v5/order/amend-batch`.
489///
490/// # References
491/// - <https://bybit-exchange.github.io/docs/v5/order/batch-amend>
492#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
493#[serde(rename_all = "camelCase")]
494pub struct BybitBatchAmendOrderEntry {
495    pub symbol: String,
496    #[serde(skip_serializing_if = "Option::is_none")]
497    #[builder(setter(strip_option))]
498    pub order_id: Option<String>,
499    #[serde(skip_serializing_if = "Option::is_none")]
500    #[builder(setter(strip_option))]
501    pub order_link_id: Option<String>,
502    #[serde(skip_serializing_if = "Option::is_none")]
503    pub order_iv: Option<String>,
504    #[serde(skip_serializing_if = "Option::is_none")]
505    pub trigger_price: Option<String>,
506    #[serde(skip_serializing_if = "Option::is_none")]
507    pub qty: Option<String>,
508    #[serde(skip_serializing_if = "Option::is_none")]
509    pub price: Option<String>,
510    #[serde(skip_serializing_if = "Option::is_none")]
511    pub tpsl_mode: Option<BybitTpSlMode>,
512    #[serde(skip_serializing_if = "Option::is_none")]
513    pub take_profit: Option<String>,
514    #[serde(skip_serializing_if = "Option::is_none")]
515    pub stop_loss: Option<String>,
516    #[serde(skip_serializing_if = "Option::is_none")]
517    pub tp_trigger_by: Option<BybitTriggerType>,
518    #[serde(skip_serializing_if = "Option::is_none")]
519    pub sl_trigger_by: Option<BybitTriggerType>,
520    #[serde(skip_serializing_if = "Option::is_none")]
521    pub trigger_by: Option<BybitTriggerType>,
522    #[serde(skip_serializing_if = "Option::is_none")]
523    pub tp_limit_price: Option<String>,
524    #[serde(skip_serializing_if = "Option::is_none")]
525    pub sl_limit_price: Option<String>,
526}
527
528/// Body parameters for `POST /v5/order/amend-batch`.
529///
530/// # References
531/// - <https://bybit-exchange.github.io/docs/v5/order/batch-amend>
532#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
533#[serde(rename_all = "camelCase")]
534pub struct BybitBatchAmendOrderParams {
535    pub category: BybitProductType,
536    pub request: Vec<BybitBatchAmendOrderEntry>,
537}
538
539/// Body parameters for `POST /v5/order/amend`.
540///
541/// # References
542/// - <https://bybit-exchange.github.io/docs/v5/order/amend-order>
543#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
544#[serde(rename_all = "camelCase")]
545pub struct BybitAmendOrderParams {
546    #[serde(flatten)]
547    pub order: BybitBatchAmendOrderEntry,
548    pub category: BybitProductType,
549}
550
551/// Cancel entry for `POST /v5/order/cancel-batch`.
552///
553/// # References
554/// - <https://bybit-exchange.github.io/docs/v5/order/batch-cancel>
555#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
556#[serde(rename_all = "camelCase")]
557pub struct BybitBatchCancelOrderEntry {
558    pub symbol: String,
559    #[serde(skip_serializing_if = "Option::is_none")]
560    #[builder(setter(strip_option))]
561    pub order_id: Option<String>,
562    #[serde(skip_serializing_if = "Option::is_none")]
563    #[builder(setter(strip_option))]
564    pub order_link_id: Option<String>,
565    #[serde(skip_serializing_if = "Option::is_none")]
566    pub order_filter: Option<BybitOrderFilter>,
567}
568
569/// Body parameters for `POST /v5/order/cancel-batch`.
570///
571/// # References
572/// - <https://bybit-exchange.github.io/docs/v5/order/batch-cancel>
573#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
574#[serde(rename_all = "camelCase")]
575pub struct BybitBatchCancelOrderParams {
576    pub category: BybitProductType,
577    pub request: Vec<BybitBatchCancelOrderEntry>,
578}
579
580/// Body parameters for `POST /v5/order/cancel`.
581///
582/// # References
583/// - <https://bybit-exchange.github.io/docs/v5/order/cancel-order>
584#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
585#[serde(rename_all = "camelCase")]
586pub struct BybitCancelOrderParams {
587    #[serde(flatten)]
588    pub order: BybitBatchCancelOrderEntry,
589    pub category: BybitProductType,
590}
591
592/// Body parameters for `POST /v5/order/cancel-all`.
593///
594/// # References
595/// - <https://bybit-exchange.github.io/docs/v5/order/cancel-all>
596#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
597#[serde(rename_all = "camelCase")]
598#[builder(default)]
599#[builder(setter(into))]
600pub struct BybitCancelAllOrdersParams {
601    pub category: BybitProductType,
602    #[serde(skip_serializing_if = "Option::is_none")]
603    #[builder(setter(strip_option))]
604    pub symbol: Option<String>,
605    #[serde(skip_serializing_if = "Option::is_none")]
606    #[builder(setter(strip_option))]
607    pub base_coin: Option<String>,
608    #[serde(skip_serializing_if = "Option::is_none")]
609    #[builder(setter(strip_option))]
610    pub settle_coin: Option<String>,
611    #[serde(skip_serializing_if = "Option::is_none")]
612    #[builder(setter(strip_option))]
613    pub order_filter: Option<BybitOrderFilter>,
614    #[serde(skip_serializing_if = "Option::is_none")]
615    #[builder(setter(strip_option))]
616    pub stop_order_type: Option<BybitStopOrderType>,
617}
618
619/// Query parameters for `GET /v5/order/realtime`.
620///
621/// # References
622/// - <https://bybit-exchange.github.io/docs/v5/order/open-order>
623#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
624#[serde(rename_all = "camelCase")]
625#[builder(default)]
626#[builder(setter(into))]
627pub struct BybitOpenOrdersParams {
628    pub category: BybitProductType,
629    #[serde(skip_serializing_if = "Option::is_none")]
630    #[builder(setter(strip_option))]
631    pub symbol: Option<String>,
632    #[serde(skip_serializing_if = "Option::is_none")]
633    #[builder(setter(strip_option))]
634    pub base_coin: Option<String>,
635    #[serde(skip_serializing_if = "Option::is_none")]
636    #[builder(setter(strip_option))]
637    pub settle_coin: Option<String>,
638    #[serde(skip_serializing_if = "Option::is_none")]
639    #[builder(setter(strip_option))]
640    pub order_id: Option<String>,
641    #[serde(skip_serializing_if = "Option::is_none")]
642    #[builder(setter(strip_option))]
643    pub order_link_id: Option<String>,
644    #[serde(skip_serializing_if = "Option::is_none")]
645    #[builder(setter(strip_option))]
646    pub open_only: Option<BybitOpenOnly>,
647    #[serde(skip_serializing_if = "Option::is_none")]
648    #[builder(setter(strip_option))]
649    pub order_filter: Option<BybitOrderFilter>,
650    #[serde(skip_serializing_if = "Option::is_none")]
651    #[builder(setter(strip_option))]
652    pub limit: Option<u32>,
653    #[serde(skip_serializing_if = "Option::is_none")]
654    #[builder(setter(strip_option))]
655    pub cursor: Option<String>,
656}
657
658/// Query parameters for `GET /v5/order/history`.
659///
660/// # References
661/// - <https://bybit-exchange.github.io/docs/v5/order/order-list>
662#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
663#[serde(rename_all = "camelCase")]
664#[builder(default)]
665#[builder(setter(into))]
666pub struct BybitOrderHistoryParams {
667    pub category: BybitProductType,
668    #[serde(skip_serializing_if = "Option::is_none")]
669    #[builder(setter(strip_option))]
670    pub symbol: Option<String>,
671    #[serde(skip_serializing_if = "Option::is_none")]
672    #[builder(setter(strip_option))]
673    pub base_coin: Option<String>,
674    #[serde(skip_serializing_if = "Option::is_none")]
675    #[builder(setter(strip_option))]
676    pub settle_coin: Option<String>,
677    #[serde(skip_serializing_if = "Option::is_none")]
678    #[builder(setter(strip_option))]
679    pub order_id: Option<String>,
680    #[serde(skip_serializing_if = "Option::is_none")]
681    #[builder(setter(strip_option))]
682    pub order_link_id: Option<String>,
683    #[serde(skip_serializing_if = "Option::is_none")]
684    #[builder(setter(strip_option))]
685    pub open_only: Option<BybitOpenOnly>,
686    #[serde(skip_serializing_if = "Option::is_none")]
687    #[builder(setter(strip_option))]
688    pub order_filter: Option<BybitOrderFilter>,
689    #[serde(skip_serializing_if = "Option::is_none")]
690    #[builder(setter(strip_option))]
691    pub order_status: Option<BybitOrderStatus>,
692    #[serde(skip_serializing_if = "Option::is_none")]
693    #[builder(setter(strip_option))]
694    pub start_time: Option<i64>,
695    #[serde(skip_serializing_if = "Option::is_none")]
696    #[serde(rename = "endTime")]
697    #[builder(setter(strip_option))]
698    pub end_time: Option<i64>,
699    #[serde(skip_serializing_if = "Option::is_none")]
700    #[builder(setter(strip_option))]
701    pub limit: Option<u32>,
702    #[serde(skip_serializing_if = "Option::is_none")]
703    #[builder(setter(strip_option))]
704    pub cursor: Option<String>,
705}
706
707/// Query parameters for `GET /v5/execution/list`.
708///
709/// # References
710/// - <https://bybit-exchange.github.io/docs/v5/order/execution>
711#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
712#[serde(rename_all = "camelCase")]
713#[builder(default)]
714#[builder(setter(into))]
715pub struct BybitTradeHistoryParams {
716    pub category: BybitProductType,
717    #[serde(skip_serializing_if = "Option::is_none")]
718    #[builder(setter(strip_option))]
719    pub symbol: Option<String>,
720    #[serde(skip_serializing_if = "Option::is_none")]
721    #[builder(setter(strip_option))]
722    pub base_coin: Option<String>,
723    #[serde(skip_serializing_if = "Option::is_none")]
724    #[builder(setter(strip_option))]
725    pub order_id: Option<String>,
726    #[serde(skip_serializing_if = "Option::is_none")]
727    #[builder(setter(strip_option))]
728    pub order_link_id: Option<String>,
729    #[serde(skip_serializing_if = "Option::is_none")]
730    #[builder(setter(strip_option))]
731    pub start_time: Option<i64>,
732    #[serde(skip_serializing_if = "Option::is_none")]
733    #[serde(rename = "endTime")]
734    #[builder(setter(strip_option))]
735    pub end_time: Option<i64>,
736    #[serde(skip_serializing_if = "Option::is_none")]
737    #[builder(setter(strip_option))]
738    pub exec_type: Option<BybitExecType>,
739    #[serde(skip_serializing_if = "Option::is_none")]
740    #[builder(setter(strip_option))]
741    pub limit: Option<u32>,
742    #[serde(skip_serializing_if = "Option::is_none")]
743    #[builder(setter(strip_option))]
744    pub cursor: Option<String>,
745}
746
747/// Request-side permission patch for API-key update endpoints (`PascalCase`).
748///
749/// Kept separate from the response-side
750/// [`crate::http::models::BybitApiKeyPermissions`]: every field here is
751/// `Option<Vec<String>>` with `skip_serializing_if`, so an unset bucket is
752/// omitted from the request body entirely rather than being serialised as an
753/// explicit empty array (which the venue treats as "clear all permissions").
754///
755/// The field set is the superset of the master and sub-account permission
756/// tables. Buckets that only appear for master-account keys (`FiatP2P`,
757/// `FiatBybitPay`, `FiatBitPay`, `FiatConvertBroker`, `BitCard`, `ByXPost`)
758/// must not be set when calling `POST /v5/user/update-sub-api`; callers are
759/// expected to only populate the buckets documented for the endpoint being
760/// invoked.
761///
762/// # References
763/// - <https://bybit-exchange.github.io/docs/v5/user/modify-sub-apikey>
764/// - <https://bybit-exchange.github.io/docs/v5/user/modify-master-apikey>
765#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
766#[serde(rename_all = "PascalCase")]
767#[builder(default)]
768#[builder(setter(into, strip_option))]
769pub struct BybitApiKeyPermissionUpdate {
770    #[serde(skip_serializing_if = "Option::is_none")]
771    pub contract_trade: Option<Vec<String>>,
772    #[serde(skip_serializing_if = "Option::is_none")]
773    pub spot: Option<Vec<String>>,
774    #[serde(skip_serializing_if = "Option::is_none")]
775    pub wallet: Option<Vec<String>>,
776    #[serde(skip_serializing_if = "Option::is_none")]
777    pub options: Option<Vec<String>>,
778    #[serde(skip_serializing_if = "Option::is_none")]
779    pub derivatives: Option<Vec<String>>,
780    #[serde(skip_serializing_if = "Option::is_none")]
781    pub exchange: Option<Vec<String>>,
782    #[serde(skip_serializing_if = "Option::is_none")]
783    pub earn: Option<Vec<String>>,
784    #[serde(skip_serializing_if = "Option::is_none")]
785    pub affiliate: Option<Vec<String>>,
786    #[serde(skip_serializing_if = "Option::is_none")]
787    pub block_trade: Option<Vec<String>>,
788    #[serde(skip_serializing_if = "Option::is_none")]
789    pub copy_trading: Option<Vec<String>>,
790    // Bybit ships this key uppercase (`"NFT"`); the struct-level PascalCase
791    // rule would otherwise emit `"Nft"` and the venue would ignore the field.
792    #[serde(rename = "NFT", skip_serializing_if = "Option::is_none")]
793    pub nft: Option<Vec<String>>,
794    // Bybit uses `"FiatP2P"` — PascalCase rename would emit `"FiatP2p"`.
795    #[serde(rename = "FiatP2P", skip_serializing_if = "Option::is_none")]
796    pub fiat_p2p: Option<Vec<String>>,
797    #[serde(skip_serializing_if = "Option::is_none")]
798    pub fiat_bybit_pay: Option<Vec<String>>,
799    #[serde(skip_serializing_if = "Option::is_none")]
800    pub fiat_bit_pay: Option<Vec<String>>,
801    #[serde(skip_serializing_if = "Option::is_none")]
802    pub fiat_convert_broker: Option<Vec<String>>,
803    #[serde(skip_serializing_if = "Option::is_none")]
804    pub bit_card: Option<Vec<String>>,
805    // Bybit uses `"ByXPost"` — PascalCase rename would emit `"ByxPost"`.
806    #[serde(rename = "ByXPost", skip_serializing_if = "Option::is_none")]
807    pub byx_post: Option<Vec<String>>,
808}
809
810/// Body parameters for `POST /v5/user/update-sub-api`.
811///
812/// `api_key` is only required when a master key is editing a sub-account key;
813/// it is omitted when a sub key edits itself.
814///
815/// # References
816/// - <https://bybit-exchange.github.io/docs/v5/user/modify-sub-apikey>
817#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
818#[serde(rename_all = "camelCase")]
819#[builder(default)]
820#[builder(setter(into))]
821pub struct BybitUpdateSubApiParams {
822    #[serde(skip_serializing_if = "Option::is_none")]
823    #[builder(setter(strip_option))]
824    pub api_key: Option<String>,
825    // Bybit accepts `readOnly` as a 0/1 integer on the wire; the builder takes
826    // a `bool` and `opt_bool_as_int` serialises it to match.
827    #[serde(skip_serializing_if = "Option::is_none", with = "opt_bool_as_int")]
828    #[builder(setter(strip_option))]
829    pub read_only: Option<bool>,
830    #[serde(skip_serializing_if = "Option::is_none")]
831    #[builder(setter(strip_option))]
832    pub ips: Option<String>,
833    #[serde(skip_serializing_if = "Option::is_none")]
834    #[builder(setter(strip_option))]
835    pub permissions: Option<BybitApiKeyPermissionUpdate>,
836}
837
838/// Body parameters for `POST /v5/user/update-api`.
839///
840/// Can only modify the caller's own master key.
841///
842/// The official request parameter table lists only `readOnly` and
843/// `permissions`; `ips` appears in the response but is not a request field,
844/// so it is deliberately excluded here.
845///
846/// # References
847/// - <https://bybit-exchange.github.io/docs/v5/user/modify-master-apikey>
848#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
849#[serde(rename_all = "camelCase")]
850#[builder(default)]
851#[builder(setter(into))]
852pub struct BybitUpdateMasterApiParams {
853    #[serde(skip_serializing_if = "Option::is_none", with = "opt_bool_as_int")]
854    #[builder(setter(strip_option))]
855    pub read_only: Option<bool>,
856    #[serde(skip_serializing_if = "Option::is_none")]
857    #[builder(setter(strip_option))]
858    pub permissions: Option<BybitApiKeyPermissionUpdate>,
859}
860
861/// Query parameters for cursor-paginated sub-account listings.
862///
863/// Shared by `GET /v5/user/submembers` and `GET /v5/user/escrow_sub_members`,
864/// which take the same pagination shape (`pageSize` up to 100 plus
865/// `nextCursor`). Bybit documents `pageSize` as a string, but the URL encoder
866/// serialises any numeric value as text anyway, so `u32` is used on the Rust
867/// side for compile-time type safety.
868///
869/// # References
870/// - <https://bybit-exchange.github.io/docs/v5/user/page-subuid>
871/// - <https://bybit-exchange.github.io/docs/v5/user/fund-subuid-list>
872#[derive(Clone, Debug, Deserialize, Serialize, Default, Builder)]
873#[serde(rename_all = "camelCase")]
874#[builder(default)]
875#[builder(setter(into))]
876pub struct BybitSubMembersPageParams {
877    #[serde(skip_serializing_if = "Option::is_none")]
878    #[builder(setter(strip_option))]
879    pub page_size: Option<u32>,
880    #[serde(skip_serializing_if = "Option::is_none")]
881    #[builder(setter(strip_option))]
882    pub next_cursor: Option<String>,
883}
884
885/// Query parameters for `GET /v5/user/sub-apikeys`.
886///
887/// `sub_member_id` is required, so this struct intentionally does not carry
888/// `#[builder(default)]`; the generated builder returns `Err` when the field
889/// is missing, matching the convention used by `BybitBorrowParams`.
890///
891/// # References
892/// - <https://bybit-exchange.github.io/docs/v5/user/list-sub-apikeys>
893#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
894#[serde(rename_all = "camelCase")]
895#[builder(setter(into))]
896pub struct BybitSubApiKeysParams {
897    pub sub_member_id: String,
898    #[serde(skip_serializing_if = "Option::is_none")]
899    #[builder(setter(strip_option), default)]
900    pub limit: Option<u32>,
901    #[serde(skip_serializing_if = "Option::is_none")]
902    #[builder(setter(strip_option), default)]
903    pub cursor: Option<String>,
904}