df_hyperliquid_core/trade/orders/
mod.rs1pub mod cloid;
6pub mod close;
7pub mod entry;
8pub mod limit;
9pub mod market;
10pub mod order_type;
11pub mod scale;
12pub mod tpsl;
13pub mod trigger;
14pub mod twap;
15
16pub use cloid::Cloid;
17pub use close::{Close, close};
18pub use entry::{OrderIntent, Price, order};
19pub use order_type::{Grouping, OrderType, Tif, Tpsl};
20pub use scale::{LEAST_LEVELS, MOST_LEVELS, Scale, scale};
21pub use tpsl::{Covers, TriggerIntent, trigger};
22pub use trigger::{Exit, ExitPrice, TRIGGER_SLIPPAGE};
23pub use twap::{MINIMUM_TWAP_VALUE, Twap, TwapCancel, TwapIntent, twap};
24
25use crate::trade::builder::{Builder, OverCap};
26use crate::utils::sign::{L1Action, Map, Value};
27use crate::utils::{Asset, AssetKind, Dec};
28
29pub use crate::markets::Side;
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub struct Order {
36 asset: Asset,
37 side: Side,
38 price: Dec,
39 size: Dec,
40 reduce_only: bool,
41 order_type: OrderType,
42 cloid: Option<Cloid>,
43}
44
45impl Order {
46 #[must_use]
48 pub const fn limit(asset: Asset, side: Side, price: Dec, size: Dec, tif: Tif) -> Order {
49 Order { asset, side, price, size, reduce_only: false, order_type: OrderType::Limit(tif), cloid: None }
50 }
51
52 #[must_use]
57 pub const fn market(asset: Asset, side: Side, bound: Dec, size: Dec) -> Order {
58 Order::limit(asset, side, bound, size, Tif::FrontendMarket)
59 }
60
61 #[must_use]
65 pub const fn trigger(
66 asset: Asset,
67 side: Side,
68 price: Dec,
69 size: Dec,
70 trigger: Dec,
71 tpsl: Tpsl,
72 is_market: bool,
73 ) -> Order {
74 Order {
75 asset,
76 side,
77 price,
78 size,
79 reduce_only: false,
80 order_type: OrderType::Trigger { is_market, trigger, tpsl },
81 cloid: None,
82 }
83 }
84
85 #[must_use]
87 pub const fn reduce_only(mut self) -> Order {
88 self.reduce_only = true;
89 self
90 }
91
92 #[must_use]
93 pub const fn with_cloid(mut self, cloid: Cloid) -> Order {
94 self.cloid = Some(cloid);
95 self
96 }
97
98 #[must_use]
99 pub const fn asset(&self) -> Asset {
100 self.asset
101 }
102
103 #[must_use]
104 pub const fn side(&self) -> Side {
105 self.side
106 }
107
108 #[must_use]
109 pub const fn price(&self) -> Dec {
110 self.price
111 }
112
113 #[must_use]
114 pub const fn size(&self) -> Dec {
115 self.size
116 }
117
118 #[must_use]
119 pub const fn is_reduce_only(&self) -> bool {
120 self.reduce_only
121 }
122
123 #[must_use]
124 pub const fn order_type(&self) -> OrderType {
125 self.order_type
126 }
127
128 #[must_use]
129 pub const fn cloid(&self) -> Option<Cloid> {
130 self.cloid
131 }
132
133 #[must_use]
135 pub const fn tif(&self) -> Option<Tif> {
136 match self.order_type {
137 OrderType::Limit(tif) => Some(tif),
138 OrderType::Trigger { .. } => None,
139 }
140 }
141
142 #[must_use]
143 pub const fn is_market(&self) -> bool {
144 matches!(self.order_type, OrderType::Limit(Tif::FrontendMarket))
145 }
146
147 #[must_use]
148 pub const fn is_trigger(&self) -> bool {
149 matches!(self.order_type, OrderType::Trigger { .. })
150 }
151
152 #[must_use]
154 pub fn wire(&self) -> Map {
155 Map::new()
156 .put("a", self.asset)
157 .put("b", self.side.is_buy())
158 .put("p", self.price.to_wire())
159 .put("s", self.size.to_wire())
160 .put("r", self.reduce_only)
161 .put("t", self.order_type.wire())
162 .put_some("c", self.cloid.map(Cloid::to_hex))
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq)]
168pub struct PlaceOrder {
169 orders: Vec<Order>,
170 grouping: Grouping,
171 builder: Option<Builder>,
172}
173
174impl PlaceOrder {
175 #[must_use]
177 pub fn new(orders: Vec<Order>) -> PlaceOrder {
178 PlaceOrder { orders, grouping: Grouping::Na, builder: None }
179 }
180
181 #[must_use]
182 pub fn one(order: Order) -> PlaceOrder {
183 PlaceOrder::new(vec![order])
184 }
185
186 #[must_use]
187 pub fn grouped(mut self, grouping: Grouping) -> PlaceOrder {
188 self.grouping = grouping;
189 self
190 }
191
192 #[must_use]
193 pub fn through(mut self, builder: Builder) -> PlaceOrder {
194 self.builder = Some(builder);
195 self
196 }
197
198 #[must_use]
199 pub fn orders(&self) -> &[Order] {
200 &self.orders
201 }
202
203 #[must_use]
204 pub const fn grouping(&self) -> Grouping {
205 self.grouping
206 }
207
208 #[must_use]
209 pub const fn builder(&self) -> Option<Builder> {
210 self.builder
211 }
212
213 #[must_use]
216 pub fn over_builder_cap(&self) -> Option<OverCap> {
217 let fee = self.builder?.fee();
218 let kind = AssetKind::strictest(self.orders.iter().map(Order::asset))?;
219 let cap = kind.builder_cap();
220 (fee > cap).then_some(OverCap { fee, cap, kind })
221 }
222}
223
224impl L1Action for PlaceOrder {
225 fn action(&self) -> Map {
226 Map::new()
227 .put("type", "order")
228 .put("orders", Value::array(self.orders.iter().map(Order::wire)))
229 .put("grouping", self.grouping.wire())
230 .put_some("builder", self.builder.as_ref().map(Builder::wire))
231 }
232}
233
234#[cfg(test)]
235#[path = "tests/order/mod.rs"]
236mod tests;