1use rust_decimal::Decimal;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct PredictMarket {
12 pub id: u64,
14 pub title: String,
16 pub question: String,
18 pub condition_id: String,
20 pub status: String,
22 pub category_slug: String,
24 pub is_neg_risk: bool,
26 pub is_yield_bearing: bool,
28 #[serde(default)]
30 pub fee_rate_bps: u64,
31 pub outcomes: Vec<PredictOutcome>,
33 pub created_at: String,
35
36 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub start_price: Option<Decimal>,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub price_feed_id: Option<String>,
44}
45
46impl PredictMarket {
47 pub fn strike_price(&self) -> Option<Decimal> {
49 self.start_price
50 }
51
52 pub fn set_strike_price(&mut self, start_price: Decimal, price_feed_id: String) {
54 self.start_price = Some(start_price);
55 self.price_feed_id = Some(price_feed_id);
56 }
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct PredictOutcome {
63 pub name: String,
65 pub index_set: u64,
67 pub on_chain_id: String,
69 pub status: Option<String>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct PredictOrderBook {
76 pub market_id: String,
78 pub best_bid: Option<Decimal>,
80 pub best_ask: Option<Decimal>,
82 pub bids: Vec<(Decimal, Decimal)>,
84 pub asks: Vec<(Decimal, Decimal)>,
86}
87
88#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename_all = "UPPERCASE")]
95pub enum OrderStatus {
96 Open,
97 Filled,
98 Expired,
99 Cancelled,
100 Invalidated,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105#[serde(rename_all = "camelCase")]
106pub struct PredictOrderData {
107 pub hash: String,
108 #[serde(deserialize_with = "string_or_number")]
109 pub salt: String,
110 pub maker: String,
111 pub signer: String,
112 pub taker: String,
113 pub token_id: String,
114 #[serde(deserialize_with = "string_or_number")]
115 pub maker_amount: String,
116 #[serde(deserialize_with = "string_or_number")]
117 pub taker_amount: String,
118 #[serde(deserialize_with = "string_or_number")]
119 pub expiration: String,
120 #[serde(deserialize_with = "string_or_number")]
121 pub nonce: String,
122 #[serde(deserialize_with = "string_or_number")]
123 pub fee_rate_bps: String,
124 pub side: u8,
126 pub signature_type: u8,
128 pub signature: String,
129}
130
131fn string_or_number<'de, D>(deserializer: D) -> std::result::Result<String, D::Error>
133where
134 D: serde::Deserializer<'de>,
135{
136 use serde::de;
137
138 struct StringOrNumberVisitor;
139
140 impl<'de> de::Visitor<'de> for StringOrNumberVisitor {
141 type Value = String;
142
143 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
144 formatter.write_str("a string or number")
145 }
146
147 fn visit_str<E: de::Error>(self, v: &str) -> std::result::Result<String, E> {
148 Ok(v.to_string())
149 }
150
151 fn visit_string<E: de::Error>(self, v: String) -> std::result::Result<String, E> {
152 Ok(v)
153 }
154
155 fn visit_u64<E: de::Error>(self, v: u64) -> std::result::Result<String, E> {
156 Ok(v.to_string())
157 }
158
159 fn visit_i64<E: de::Error>(self, v: i64) -> std::result::Result<String, E> {
160 Ok(v.to_string())
161 }
162
163 fn visit_f64<E: de::Error>(self, v: f64) -> std::result::Result<String, E> {
164 Ok(v.to_string())
165 }
166 }
167
168 deserializer.deserialize_any(StringOrNumberVisitor)
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173#[serde(rename_all = "camelCase")]
174pub struct PredictOrder {
175 pub id: String,
177 #[serde(deserialize_with = "deserialize_market_id")]
179 pub market_id: u64,
180 #[serde(default)]
182 pub currency: Option<String>,
183 pub amount: String,
185 pub amount_filled: String,
187 #[serde(default)]
189 pub is_neg_risk: bool,
190 #[serde(default)]
192 pub is_yield_bearing: bool,
193 #[serde(default)]
195 pub strategy: String,
196 pub status: OrderStatus,
198 pub order: PredictOrderData,
200}
201
202fn deserialize_market_id<'de, D>(deserializer: D) -> std::result::Result<u64, D::Error>
204where
205 D: serde::Deserializer<'de>,
206{
207 use serde::de;
208
209 struct MarketIdVisitor;
210
211 impl<'de> de::Visitor<'de> for MarketIdVisitor {
212 type Value = u64;
213
214 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
215 formatter.write_str("a number or string containing a number")
216 }
217
218 fn visit_u64<E: de::Error>(self, v: u64) -> std::result::Result<u64, E> {
219 Ok(v)
220 }
221
222 fn visit_i64<E: de::Error>(self, v: i64) -> std::result::Result<u64, E> {
223 Ok(v as u64)
224 }
225
226 fn visit_str<E: de::Error>(self, v: &str) -> std::result::Result<u64, E> {
227 v.parse::<u64>().map_err(de::Error::custom)
228 }
229 }
230
231 deserializer.deserialize_any(MarketIdVisitor)
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
240pub struct GetOrdersResponse {
241 pub success: bool,
242 pub cursor: Option<String>,
243 pub data: Vec<PredictOrder>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct PlaceOrderResponse {
249 pub success: bool,
250 pub data: Option<PlaceOrderData>,
251}
252
253#[derive(Debug, Clone, Serialize, Deserialize)]
255#[serde(rename_all = "camelCase")]
256pub struct PlaceOrderData {
257 pub code: Option<String>,
258 pub order_id: String,
259 pub order_hash: String,
260}
261
262#[derive(Debug, Clone, Serialize)]
264#[serde(rename_all = "camelCase")]
265pub struct CreateOrderRequest {
266 pub data: CreateOrderData,
267}
268
269#[derive(Debug, Clone, Serialize)]
271#[serde(rename_all = "camelCase")]
272pub struct CreateOrderData {
273 pub order: serde_json::Value,
274 pub price_per_share: String,
275 pub strategy: String,
276}
277
278#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct RemoveOrdersResponse {
281 pub success: bool,
282 pub removed: Vec<String>,
283 pub noop: Vec<String>,
284}
285
286#[derive(Debug, Clone, Serialize)]
288pub struct RemoveOrdersRequest {
289 pub data: RemoveOrdersData,
290}
291
292#[derive(Debug, Clone, Serialize)]
294pub struct RemoveOrdersData {
295 pub ids: Vec<String>,
296}
297
298#[derive(Debug, Clone, Deserialize)]
304pub struct AuthMessageResponse {
305 pub success: bool,
306 pub data: AuthMessageData,
307}
308
309#[derive(Debug, Clone, Deserialize)]
311pub struct AuthMessageData {
312 pub message: String,
313}
314
315#[derive(Debug, Clone, Serialize)]
317pub struct AuthRequest {
318 pub signer: String,
319 pub signature: String,
320 pub message: String,
321}
322
323#[derive(Debug, Clone, Deserialize)]
325pub struct AuthResponse {
326 pub success: bool,
327 pub data: AuthResponseData,
328}
329
330#[derive(Debug, Clone, Deserialize)]
332pub struct AuthResponseData {
333 pub token: String,
334}
335
336#[derive(Debug, Clone, Deserialize)]
342pub struct GetPositionsResponse {
343 pub success: bool,
344 pub cursor: Option<String>,
345 pub data: Vec<PredictPosition>,
346}
347
348#[derive(Debug, Clone, Deserialize)]
350#[serde(rename_all = "camelCase")]
351pub struct PredictPosition {
352 pub id: String,
353 pub market: PredictPositionMarket,
354 pub outcome: PredictPositionOutcome,
355 pub amount: String,
357 #[serde(default)]
359 pub value_usd: Option<String>,
360}
361
362#[derive(Debug, Clone, Deserialize)]
364#[serde(rename_all = "camelCase")]
365pub struct PredictPositionMarket {
366 pub id: u64,
367 pub title: String,
368 #[serde(default)]
369 pub condition_id: Option<String>,
370}
371
372#[derive(Debug, Clone, Deserialize)]
374#[serde(rename_all = "camelCase")]
375pub struct PredictPositionOutcome {
376 pub name: String,
377 pub index_set: u64,
378 pub on_chain_id: String,
379 pub status: Option<String>,
380}
381
382#[derive(Debug, Clone, Default)]
388pub struct WalletEventDetails {
389 pub price: Option<String>,
391 pub quantity: Option<String>,
393 pub quantity_filled: Option<String>,
395 pub outcome: Option<String>,
397 pub quote_type: Option<String>,
399}
400
401#[derive(Debug, Clone)]
403pub enum PredictWalletEvent {
404 OrderAccepted {
406 order_hash: String,
407 order_id: String,
408 },
409 OrderNotAccepted {
411 order_hash: String,
412 order_id: String,
413 reason: Option<String>,
414 },
415 OrderExpired {
417 order_hash: String,
418 order_id: String,
419 },
420 OrderCancelled {
422 order_hash: String,
423 order_id: String,
424 },
425 OrderTransactionSubmitted {
427 order_hash: String,
428 order_id: String,
429 tx_hash: Option<String>,
430 details: WalletEventDetails,
431 },
432 OrderTransactionSuccess {
434 order_hash: String,
435 order_id: String,
436 tx_hash: Option<String>,
437 details: WalletEventDetails,
438 },
439 OrderTransactionFailed {
441 order_hash: String,
442 order_id: String,
443 tx_hash: Option<String>,
444 details: WalletEventDetails,
445 },
446 Unknown {
448 event_type: String,
449 data: serde_json::Value,
450 },
451}
452
453#[derive(Debug, Clone, Serialize, Deserialize)]
459pub struct CategoryResponse {
460 pub success: bool,
461 pub data: PredictCategory,
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
469pub struct PredictCategory {
470 pub id: u64,
472 pub slug: String,
474 pub title: String,
476 pub markets: Vec<PredictMarket>,
478}