1use derive_builder::Builder;
2use rust_decimal::Decimal;
3use strum_macros::{Display, EnumString};
4use time::OffsetDateTime;
5
6use crate::{Extensions, MarketKind, Symbol};
7
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[non_exhaustive]
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct OrderId(pub String);
12
13impl OrderId {
14 pub fn new(value: impl Into<String>) -> Self {
15 Self(value.into())
16 }
17}
18
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[non_exhaustive]
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct ClientOrderId(pub String);
23
24impl ClientOrderId {
25 pub fn new(value: impl Into<String>) -> Self {
26 Self(value.into())
27 }
28}
29
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31#[non_exhaustive]
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
33pub enum OrderKey {
34 Exchange(OrderId),
35 Client(ClientOrderId),
36}
37
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39#[non_exhaustive]
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
41#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
42pub enum OrderSide {
43 Buy,
44 Sell,
45}
46
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48#[non_exhaustive]
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
50#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
51pub enum OrderType {
52 Market,
53 Limit,
54 StopMarket,
55 StopLimit,
56 PostOnly,
57}
58
59#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
60#[non_exhaustive]
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
62#[strum(serialize_all = "SCREAMING_SNAKE_CASE", ascii_case_insensitive)]
63pub enum TimeInForce {
64 Gtc,
65 Ioc,
66 Fok,
67 Gtx,
68}
69
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71#[non_exhaustive]
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
73#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
74pub enum OrderStatus {
75 New,
76 PartiallyFilled,
77 Filled,
78 Canceled,
79 Rejected,
80 Expired,
81}
82
83#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84#[non_exhaustive]
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
86#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
87pub enum PositionSide {
88 Long,
89 Short,
90 Both,
91}
92
93#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
94#[non_exhaustive]
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumString)]
96#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
97pub enum MarginMode {
98 Cross,
99 Isolated,
100}
101
102#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
103#[non_exhaustive]
104#[derive(Debug, Clone, PartialEq, Builder)]
105#[builder(pattern = "owned", setter(into))]
106pub struct SpotOrderRequest {
107 pub symbol: Symbol,
108 pub side: OrderSide,
109 pub order_type: OrderType,
110 pub quantity: Decimal,
111 #[builder(default)]
112 pub price: Option<Decimal>,
113 #[builder(default)]
114 pub time_in_force: Option<TimeInForce>,
115 #[builder(default)]
116 pub client_order_id: Option<ClientOrderId>,
117 #[builder(default)]
118 pub extensions: Extensions,
119}
120
121impl SpotOrderRequest {
122 pub fn builder() -> SpotOrderRequestBuilder {
123 SpotOrderRequestBuilder::default()
124 }
125}
126
127#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
128#[non_exhaustive]
129#[derive(Debug, Clone, PartialEq, Builder)]
130#[builder(pattern = "owned", setter(into))]
131pub struct FuturesOrderRequest {
132 pub symbol: Symbol,
133 pub side: OrderSide,
134 pub order_type: OrderType,
135 pub quantity: Decimal,
136 #[builder(default)]
137 pub price: Option<Decimal>,
138 #[builder(default)]
139 pub time_in_force: Option<TimeInForce>,
140 #[builder(default)]
141 pub position_side: Option<PositionSide>,
142 #[builder(default)]
143 pub reduce_only: bool,
144 #[builder(default)]
145 pub client_order_id: Option<ClientOrderId>,
146 #[builder(default)]
147 pub extensions: Extensions,
148}
149
150impl FuturesOrderRequest {
151 pub fn builder() -> FuturesOrderRequestBuilder {
152 FuturesOrderRequestBuilder::default()
153 }
154}
155
156#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
157#[non_exhaustive]
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub struct SpotCancelOrderRequest {
160 pub symbol: Symbol,
161 pub key: OrderKey,
162}
163
164impl SpotCancelOrderRequest {
165 pub fn new(symbol: Symbol, key: OrderKey) -> Self {
166 Self { symbol, key }
167 }
168}
169
170#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
171#[non_exhaustive]
172#[derive(Debug, Clone, PartialEq, Eq)]
173pub struct FuturesCancelOrderRequest {
174 pub symbol: Symbol,
175 pub key: OrderKey,
176}
177
178impl FuturesCancelOrderRequest {
179 pub fn new(symbol: Symbol, key: OrderKey) -> Self {
180 Self { symbol, key }
181 }
182}
183
184#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
185#[non_exhaustive]
186#[derive(Debug, Clone, PartialEq, Eq)]
187pub struct SpotOrderQuery {
188 pub symbol: Symbol,
189 pub key: OrderKey,
190}
191
192impl SpotOrderQuery {
193 pub fn new(symbol: Symbol, key: OrderKey) -> Self {
194 Self { symbol, key }
195 }
196}
197
198#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
199#[non_exhaustive]
200#[derive(Debug, Clone, PartialEq, Eq)]
201pub struct FuturesOrderQuery {
202 pub symbol: Symbol,
203 pub key: OrderKey,
204}
205
206impl FuturesOrderQuery {
207 pub fn new(symbol: Symbol, key: OrderKey) -> Self {
208 Self { symbol, key }
209 }
210}
211
212#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
213#[non_exhaustive]
214#[derive(Debug, Clone, PartialEq, Builder)]
215#[builder(pattern = "owned", setter(into))]
216pub struct Order {
217 pub id: OrderId,
218 #[builder(default)]
219 pub client_order_id: Option<ClientOrderId>,
220 pub symbol: Symbol,
221 pub market_kind: MarketKind,
222 pub side: OrderSide,
223 pub order_type: OrderType,
224 pub status: OrderStatus,
225 #[builder(default)]
226 pub time_in_force: Option<TimeInForce>,
227 #[builder(default)]
228 pub price: Option<Decimal>,
229 #[builder(default)]
230 pub average_price: Option<Decimal>,
231 pub quantity: Decimal,
232 pub filled_quantity: Decimal,
233 #[builder(default)]
234 pub original_quote_quantity: Option<Decimal>,
235 #[builder(default)]
236 pub cumulative_quote_quantity: Option<Decimal>,
237 #[cfg_attr(
238 feature = "serde",
239 serde(with = "time::serde::timestamp::milliseconds")
240 )]
241 pub created_at: OffsetDateTime,
242 #[cfg_attr(
243 feature = "serde",
244 serde(with = "time::serde::timestamp::milliseconds::option")
245 )]
246 #[builder(default)]
247 pub updated_at: Option<OffsetDateTime>,
248 #[builder(default)]
249 pub extensions: Extensions,
250}
251
252impl Order {
253 pub fn builder() -> OrderBuilder {
254 OrderBuilder::default()
255 }
256}
257
258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
259#[non_exhaustive]
260#[derive(Debug, Clone, PartialEq, Builder)]
261#[builder(pattern = "owned", setter(into))]
262pub struct Fill {
263 #[builder(default)]
264 pub id: Option<String>,
265 pub order_id: OrderId,
266 pub symbol: Symbol,
267 pub side: OrderSide,
268 pub price: Decimal,
269 pub quantity: Decimal,
270 #[builder(default)]
271 pub fee: Option<Decimal>,
272 #[builder(default)]
273 pub fee_asset: Option<String>,
274 #[cfg_attr(
275 feature = "serde",
276 serde(with = "time::serde::timestamp::milliseconds")
277 )]
278 pub timestamp: OffsetDateTime,
279 #[builder(default)]
280 pub extensions: Extensions,
281}
282
283impl Fill {
284 pub fn builder() -> FillBuilder {
285 FillBuilder::default()
286 }
287}
288
289#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
290#[non_exhaustive]
291#[derive(Debug, Clone, PartialEq, Builder)]
292#[builder(pattern = "owned", setter(into))]
293pub struct SetLeverageRequest {
294 pub symbol: Symbol,
295 pub leverage: Decimal,
296 #[builder(default)]
297 pub margin_mode: Option<MarginMode>,
298 #[builder(default)]
299 pub position_side: Option<PositionSide>,
300}
301
302impl SetLeverageRequest {
303 pub fn builder() -> SetLeverageRequestBuilder {
304 SetLeverageRequestBuilder::default()
305 }
306}