1use crate::eip712_structs::{Cancellation, ListTriggerOrders};
2use crate::eip712_structs::{CancellationProducts, Order};
3use crate::engine::{ExecuteResponse, PlaceOrder, Status};
4use crate::serialize_utils::{deserialize_i128, serialize_i128, WrappedBytes32};
5use ethers::types::{Bytes, H256};
6use eyre::Result;
7use serde::{Deserialize, Serialize};
8
9#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum CancelReason {
12 UserRequested,
13 LinkedSignerChanged,
14 Expired,
15 AccountHealth,
16 IsolatedSubaccountClosed,
17}
18
19#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
20#[serde(rename_all = "snake_case")]
21pub enum TriggerOrderStatus {
22 Pending,
23 Triggering,
24 Triggered(ExecuteResponse),
25 Cancelled(CancelReason),
26 InternalError(String),
27}
28
29impl TriggerOrderStatus {
30 pub fn pending(&self) -> bool {
31 match self {
32 TriggerOrderStatus::Pending => true,
33 _ => false,
34 }
35 }
36
37 pub fn byte(&self) -> i32 {
38 match self {
39 TriggerOrderStatus::Pending => 0,
40 TriggerOrderStatus::Triggering => 1,
41 TriggerOrderStatus::Triggered(_) => 2,
42 TriggerOrderStatus::Cancelled(_) => 3,
43 TriggerOrderStatus::InternalError(_) => 4,
44 }
45 }
46
47 pub fn byte_from_str(s: &str) -> Result<i32> {
48 match s {
49 "pending" => Ok(0),
50 "triggering" => Ok(1),
51 "triggered" => Ok(2),
52 "cancelled" => Ok(3),
53 "internal_error" => Ok(4),
54 _ => Err(eyre::eyre!("Invalid status string")),
55 }
56 }
57
58 pub fn data(&self) -> Vec<u8> {
59 serde_json::to_vec(self).unwrap()
60 }
61
62 pub fn from_status_data(data: &[u8]) -> Self {
63 serde_json::from_slice(data).unwrap()
64 }
65}
66
67#[derive(Clone, Serialize, Deserialize, Debug)]
68#[serde(rename_all = "snake_case")]
69pub enum TriggerCriteria {
70 PriceAbove(
72 #[serde(
73 serialize_with = "serialize_i128",
74 deserialize_with = "deserialize_i128"
75 )]
76 i128,
77 ),
78 PriceBelow(
79 #[serde(
80 serialize_with = "serialize_i128",
81 deserialize_with = "deserialize_i128"
82 )]
83 i128,
84 ),
85
86 LastPriceAbove(
87 #[serde(
88 serialize_with = "serialize_i128",
89 deserialize_with = "deserialize_i128"
90 )]
91 i128,
92 ),
93 LastPriceBelow(
94 #[serde(
95 serialize_with = "serialize_i128",
96 deserialize_with = "deserialize_i128"
97 )]
98 i128,
99 ),
100}
101
102impl TriggerCriteria {
103 pub fn byte(&self) -> i32 {
104 match self {
105 TriggerCriteria::PriceAbove(_) => 0,
106 TriggerCriteria::PriceBelow(_) => 1,
107 TriggerCriteria::LastPriceAbove(_) => 2,
108 TriggerCriteria::LastPriceBelow(_) => 3,
109 }
110 }
111
112 pub fn price(&self) -> String {
113 let p = match self {
114 TriggerCriteria::PriceAbove(price) => *price,
115 TriggerCriteria::PriceBelow(price) => *price,
116 TriggerCriteria::LastPriceAbove(price) => *price,
117 TriggerCriteria::LastPriceBelow(price) => *price,
118 };
119 format!("{:0>40}", p)
120 }
121}
122
123#[derive(Clone, Debug, Serialize, Deserialize)]
124#[serde(rename_all = "snake_case")]
125pub struct PlaceTriggerOrder {
126 pub order: Order,
127 pub signature: Bytes,
128 pub product_id: u32,
129 pub spot_leverage: Option<bool>,
130 pub trigger: TriggerCriteria,
131 pub digest: Option<H256>,
132 pub id: Option<u64>,
133}
134
135impl PlaceTriggerOrder {
136 pub fn to_place_order(&self) -> PlaceOrder {
137 PlaceOrder {
138 order: self.order.clone(),
139 signature: self.signature.to_vec(),
140 product_id: self.product_id,
141 digest: None,
142 id: self.id,
143 spot_leverage: self.spot_leverage,
144 }
145 }
146
147 pub fn order_data(&self) -> Vec<u8> {
148 bincode::serialize(self).unwrap()
149 }
150
151 pub fn from_order_data(data: &[u8]) -> Self {
152 #[derive(Clone, Debug, Serialize, Deserialize)]
153 #[serde(rename_all = "snake_case")]
154 pub struct PlaceTriggerOrderOld {
155 pub order: Order,
156 pub signature: Bytes,
157 pub product_id: u32,
158 pub spot_leverage: Option<bool>,
159 pub trigger: TriggerCriteria,
160 pub digest: Option<H256>,
161 }
162
163 match bincode::deserialize(data) {
164 Ok(p) => p,
165 Err(_) => {
166 let p_old = bincode::deserialize::<PlaceTriggerOrderOld>(data).unwrap();
167 PlaceTriggerOrder {
168 order: p_old.order,
169 signature: p_old.signature,
170 product_id: p_old.product_id,
171 spot_leverage: p_old.spot_leverage,
172 trigger: p_old.trigger,
173 digest: p_old.digest,
174 id: None,
175 }
176 }
177 }
178 }
179
180 pub fn expiration(&self) -> u64 {
181 self.order.expiration()
182 }
183
184 pub fn is_bid(&self) -> bool {
185 self.order.amount.is_positive()
186 }
187}
188
189#[derive(Clone, Serialize, Deserialize, Debug)]
190#[serde(rename_all = "snake_case")]
191pub enum Execute {
194 PlaceOrder(PlaceTriggerOrder),
195 CancelOrders {
196 tx: Cancellation,
197 signature: Bytes,
198 },
199 CancelProductOrders {
200 tx: CancellationProducts,
201 signature: Bytes,
202 },
203}
204
205#[derive(Debug, Deserialize, Serialize)]
206#[serde(rename_all = "snake_case")]
207#[serde(tag = "type")]
208pub enum Query {
209 ListTriggerOrders {
210 tx: ListTriggerOrders,
211 signature: Bytes,
212 product_id: Option<u32>,
213 pending: bool,
214 max_update_time: Option<u64>,
215 max_digest: Option<WrappedBytes32>,
216 digests: Option<Vec<WrappedBytes32>>,
217 limit: Option<u32>,
218 },
219}
220
221#[derive(Clone, Debug, Serialize, Deserialize)]
222pub struct TriggerOrderInfo {
223 pub order: PlaceTriggerOrder,
224 pub status: TriggerOrderStatus,
225 pub updated_at: u64,
226}
227
228#[derive(Clone, Debug, Serialize, Deserialize)]
229pub struct ListTriggerOrdersResponse {
230 pub orders: Vec<TriggerOrderInfo>,
231}
232
233impl ListTriggerOrdersResponse {
234 pub fn contains_digest(&self, digest: H256) -> bool {
235 self.orders
236 .iter()
237 .any(|order| order.order.digest == Some(digest))
238 }
239}
240
241#[derive(Clone, Debug, Serialize, Deserialize)]
242#[serde(rename_all = "snake_case")]
243#[serde(untagged)]
244pub enum QueryResponseData {
245 ListTriggerOrders(ListTriggerOrdersResponse),
246 Error(String),
247}
248
249#[derive(Clone, Debug, Serialize, Deserialize)]
250#[serde(rename_all = "snake_case")]
253pub struct QueryResponse {
254 pub status: Status,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub data: Option<QueryResponseData>,
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub error_code: Option<i32>,
259 #[serde(skip_serializing_if = "Option::is_none")]
260 pub error: Option<String>,
261 #[serde(skip_serializing_if = "Option::is_none")]
262 pub request_type: Option<String>,
263}