1use std::fmt;
6
7use crate::live::market::Side;
8use crate::utils::{Address, Dec};
9use serde::{Deserialize, Deserializer, de};
10use serde_json::value::RawValue;
11
12pub use crate::account::fill::{Fill, FillLiquidation, TwapSliceFill};
14
15#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
17#[serde(rename_all = "camelCase")]
18pub struct UserFills {
19 pub user: Address,
20 #[serde(default)]
21 pub is_snapshot: bool,
22 pub fills: Vec<Fill>,
23}
24
25pub use crate::account::order::OpenOrder as Order;
27
28#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
31#[serde(rename_all = "camelCase")]
32pub struct OrderUpdate {
33 pub order: Order,
34 pub status: String,
35 pub status_timestamp: u64,
37}
38
39pub use crate::account::order::FrontendOrder as OpenOrder;
42
43#[derive(Debug, Clone, PartialEq, Eq)]
45pub enum UserEvent {
46 Fills(Vec<Fill>),
47 Funding(Funding),
48 Liquidation(Liquidation),
49 NonUserCancel(Vec<Cancel>),
51 TwapHistory(Vec<TwapEvent>),
52 TwapSliceFills(Vec<TwapSliceFill>),
53 Other {
55 key: String,
56 data: String,
57 },
58}
59
60impl<'de> Deserialize<'de> for UserEvent {
61 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
62 struct Event;
63
64 impl<'de> de::Visitor<'de> for Event {
65 type Value = UserEvent;
66
67 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 f.write_str("an object with one event in it")
69 }
70
71 fn visit_map<A: de::MapAccess<'de>>(self, mut map: A) -> Result<UserEvent, A::Error> {
72 let key: String = map.next_key()?.ok_or_else(|| de::Error::custom("an event with nothing in it"))?;
73 let event = match key.as_str() {
74 "fills" => UserEvent::Fills(map.next_value()?),
75 "funding" => UserEvent::Funding(map.next_value()?),
76 "liquidation" => UserEvent::Liquidation(map.next_value()?),
77 "nonUserCancel" => UserEvent::NonUserCancel(map.next_value()?),
78 "twapHistory" => UserEvent::TwapHistory(map.next_value()?),
79 "twapSliceFills" => UserEvent::TwapSliceFills(map.next_value()?),
80 _ => {
81 let data: Box<RawValue> = map.next_value()?;
82 UserEvent::Other { key, data: data.get().to_owned() }
83 }
84 };
85 if map.next_key::<de::IgnoredAny>()?.is_some() {
86 return Err(de::Error::custom("more than one event in a frame"));
87 }
88 Ok(event)
89 }
90 }
91
92 deserializer.deserialize_map(Event)
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
98#[serde(rename_all = "camelCase")]
99pub struct Funding {
100 pub time: u64,
102 pub coin: String,
103 pub usdc: Dec,
105 pub szi: Dec,
107 pub funding_rate: Dec,
108 #[serde(default)]
109 pub n_samples: Option<u64>,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
114pub struct Liquidation {
115 pub lid: u64,
116 pub liquidator: Address,
117 pub liquidated_user: Address,
118 pub liquidated_ntl_pos: Dec,
119 pub liquidated_account_value: Dec,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
124pub struct Cancel {
125 pub coin: String,
126 pub oid: u64,
127}
128
129#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
131#[serde(rename_all = "camelCase")]
132pub struct UserFundings {
133 pub user: Address,
134 #[serde(default)]
135 pub is_snapshot: bool,
136 pub fundings: Vec<Funding>,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
142#[serde(rename_all = "camelCase")]
143pub struct Ledger {
144 pub user: Address,
145 #[serde(default)]
146 pub is_snapshot: bool,
147 #[serde(rename = "nonFundingLedgerUpdates")]
148 pub updates: Vec<LedgerUpdate>,
149}
150
151pub use crate::account::ledger::{Delta, LedgerUpdate};
154
155pub use crate::account::clearinghouse::{
158 AssetPosition, Clearinghouse, CumFunding, Leverage, MarginMode as Margin, MarginSummary, Position,
159};
160
161#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
163#[serde(rename_all = "camelCase")]
164pub struct DexState {
165 pub dex: String,
166 pub user: Address,
167 #[serde(rename = "clearinghouseState")]
168 pub state: Clearinghouse,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct AllDexsState {
175 pub user: Address,
176 #[serde(rename = "clearinghouseStates")]
177 pub states: Vec<(String, Clearinghouse)>,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
182pub struct OpenOrders {
183 pub dex: String,
184 pub user: Address,
185 pub orders: Vec<OpenOrder>,
186}
187
188#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
190#[serde(rename_all = "camelCase")]
191pub struct SpotState {
192 pub user: Address,
193 #[serde(rename = "spotState")]
195 pub state: crate::account::clearinghouse::SpotState,
196}
197
198pub use crate::account::clearinghouse::SpotBalance as Balance;
201
202#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
204pub struct TwapStates {
205 pub dex: String,
206 pub user: Address,
207 pub states: Vec<(u64, TwapState)>,
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
211#[serde(rename_all = "camelCase")]
212pub struct TwapState {
213 pub coin: String,
214 pub user: Address,
215 pub side: Side,
216 pub sz: Dec,
217 pub executed_sz: Dec,
218 pub executed_ntl: Dec,
219 pub minutes: u32,
220 pub reduce_only: bool,
221 pub randomize: bool,
222 pub timestamp: u64,
224}
225
226#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
228#[serde(rename_all = "camelCase")]
229pub struct TwapSliceFills {
230 pub user: Address,
231 #[serde(default)]
232 pub is_snapshot: bool,
233 #[serde(rename = "twapSliceFills")]
234 pub fills: Vec<TwapSliceFill>,
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
239#[serde(rename_all = "camelCase")]
240pub struct TwapEvent {
241 pub time: u64,
243 pub state: TwapState,
244 pub status: TwapStatus,
245 #[serde(default)]
246 pub twap_id: Option<u64>,
247}
248
249#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
250pub struct TwapStatus {
251 pub status: String,
253 #[serde(default)]
255 pub description: Option<String>,
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
260#[serde(rename_all = "camelCase")]
261pub struct TwapHistory {
262 pub user: Address,
263 #[serde(default)]
264 pub is_snapshot: bool,
265 pub history: Vec<TwapEvent>,
266}
267
268#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
271#[serde(rename_all = "camelCase")]
272pub struct WebData3 {
273 pub user_state: UserState,
274 pub perp_dex_states: Vec<PerpDexState>,
275}
276
277#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
278#[serde(rename_all = "camelCase")]
279pub struct UserState {
280 pub user: Address,
281 #[serde(default)]
282 pub agent_address: Option<Address>,
283 #[serde(default)]
285 pub agent_valid_until: Option<u64>,
286 pub server_time: u64,
288 pub cum_ledger: Dec,
289 pub is_vault: bool,
290 #[serde(default)]
292 pub abstraction: Option<String>,
293 #[serde(default)]
294 pub dex_abstraction_enabled: bool,
295 #[serde(default)]
296 pub opt_out_of_spot_dusting: bool,
297}
298
299#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
301#[serde(rename_all = "camelCase")]
302pub struct PerpDexState {
303 pub total_vault_equity: Dec,
304 #[serde(default)]
305 pub perps_at_open_interest_cap: Vec<String>,
306 #[serde(default)]
307 pub leading_vaults: Vec<LeadingVault>,
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
311pub struct LeadingVault {
312 pub address: Address,
313 pub name: String,
314}
315
316pub use crate::account::clearinghouse::ActiveAssetData as AssetData;
318
319#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
321#[serde(rename_all = "camelCase")]
322pub struct HistoricalOrders {
323 pub user: Address,
324 #[serde(default)]
325 pub is_snapshot: bool,
326 #[serde(rename = "orderHistory")]
327 pub orders: Vec<HistoricalOrder>,
328}
329
330pub use crate::account::order::OrderRecord as HistoricalOrder;