nautilus_bybit/common/
models.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 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//! Shared data transfer objects used across Bybit HTTP and WebSocket payloads.
17
18use serde::{Deserialize, Serialize};
19
20use crate::common::enums::BybitProductType;
21
22/// Generic wrapper that contains a list payload returned by Bybit.
23#[derive(Clone, Debug, Default, Serialize, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct BybitList<T> {
26    /// Collection returned by the endpoint.
27    pub list: Vec<T>,
28}
29
30/// Generic list result that also carries pagination cursor information.
31#[derive(Clone, Debug, Default, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct BybitCursorList<T> {
34    /// Collection returned by the endpoint.
35    pub list: Vec<T>,
36    /// Pagination cursor for the next page, when provided.
37    pub next_page_cursor: Option<String>,
38    /// Optional product category when the API includes it.
39    #[serde(default)]
40    pub category: Option<BybitProductType>,
41}
42
43/// Common leverage filter that describes leverage bounds and step.
44#[derive(Clone, Debug, Serialize, Deserialize)]
45#[serde(rename_all = "camelCase")]
46pub struct LeverageFilter {
47    /// Minimum leverage supported.
48    pub min_leverage: String,
49    /// Maximum leverage supported.
50    pub max_leverage: String,
51    /// Step between successive leverage values.
52    pub leverage_step: String,
53}
54
55/// Price filter for linear/inverse contracts describing min/max and tick.
56#[derive(Clone, Debug, Serialize, Deserialize)]
57#[serde(rename_all = "camelCase")]
58pub struct LinearPriceFilter {
59    /// Minimum allowed order price.
60    pub min_price: String,
61    /// Maximum allowed order price.
62    pub max_price: String,
63    /// Tick size for price increments.
64    pub tick_size: String,
65}
66
67/// Price filter for spot instruments (only tick size is provided).
68#[derive(Clone, Debug, Serialize, Deserialize)]
69#[serde(rename_all = "camelCase")]
70pub struct SpotPriceFilter {
71    /// Tick size for price increments.
72    pub tick_size: String,
73}
74
75/// Lot size filter for spot instruments.
76#[derive(Clone, Debug, Serialize, Deserialize)]
77#[serde(rename_all = "camelCase")]
78pub struct SpotLotSizeFilter {
79    /// Base asset precision.
80    pub base_precision: String,
81    /// Quote asset precision.
82    pub quote_precision: String,
83    /// Minimum order quantity.
84    pub min_order_qty: String,
85    /// Maximum order quantity.
86    pub max_order_qty: String,
87    /// Minimum order notional.
88    pub min_order_amt: String,
89    /// Maximum order notional.
90    pub max_order_amt: String,
91}
92
93/// Lot size filter for derivatives instruments.
94#[derive(Clone, Debug, Serialize, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub struct LinearLotSizeFilter {
97    /// Maximum order quantity.
98    pub max_order_qty: String,
99    /// Minimum order quantity.
100    pub min_order_qty: String,
101    /// Quantity increment step.
102    pub qty_step: String,
103    /// Maximum order quantity for post-only orders.
104    #[serde(default)]
105    pub post_only_max_order_qty: Option<String>,
106    /// Maximum order quantity for market orders.
107    #[serde(default)]
108    pub max_mkt_order_qty: Option<String>,
109    /// Minimum notional value.
110    #[serde(default)]
111    pub min_notional_value: Option<String>,
112}
113
114/// Lot size filter for option instruments.
115#[derive(Clone, Debug, Serialize, Deserialize)]
116#[serde(rename_all = "camelCase")]
117pub struct OptionLotSizeFilter {
118    /// Maximum order quantity.
119    pub max_order_qty: String,
120    /// Minimum order quantity.
121    pub min_order_qty: String,
122    /// Quantity increment step.
123    pub qty_step: String,
124}
125
126/// Trait for Bybit response types that contain ret_code and ret_msg fields.
127pub trait BybitResponseCheck {
128    /// Returns the response code (0 = success).
129    fn ret_code(&self) -> i64;
130    /// Returns the response message.
131    fn ret_msg(&self) -> &str;
132}
133
134/// Lightweight struct for checking Bybit API errors without deserializing result.
135///
136/// Bybit error responses often have `result: null` which would fail deserialization
137/// into typed response structs. This struct ignores the result field entirely.
138#[derive(Clone, Debug, Deserialize)]
139#[serde(rename_all = "camelCase")]
140pub struct BybitErrorCheck {
141    /// Return code (0 = success).
142    pub ret_code: i64,
143    /// Textual message accompanying the response.
144    pub ret_msg: String,
145}
146
147/// Top-level response envelope returned by Bybit HTTP endpoints.
148#[derive(Clone, Debug, Serialize, Deserialize)]
149#[serde(rename_all = "camelCase")]
150pub struct BybitResponse<T> {
151    /// Return code (0 = success).
152    pub ret_code: i64,
153    /// Textual message accompanying the response.
154    pub ret_msg: String,
155    /// Actual payload returned by the endpoint.
156    pub result: T,
157    /// Additional metadata returned by some endpoints.
158    #[serde(default)]
159    pub ret_ext_info: Option<serde_json::Value>,
160    /// Server time in milliseconds when the response was produced.
161    #[serde(default)]
162    pub time: Option<i64>,
163}
164
165impl<T> BybitResponseCheck for BybitResponse<T> {
166    fn ret_code(&self) -> i64 {
167        self.ret_code
168    }
169
170    fn ret_msg(&self) -> &str {
171        &self.ret_msg
172    }
173}
174
175/// Convenience alias for responses that return a simple list.
176pub type BybitListResponse<T> = BybitResponse<BybitList<T>>;
177
178/// Convenience alias for responses that return a cursor-based list.
179pub type BybitCursorListResponse<T> = BybitResponse<BybitCursorList<T>>;