Skip to main content

polyoxide_data/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// User's total position value
4#[cfg_attr(feature = "specta", derive(specta::Type))]
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct UserValue {
7    /// User address
8    pub user: String,
9    /// Total value of positions
10    pub value: f64,
11}
12
13/// Open interest for a market
14#[cfg_attr(feature = "specta", derive(specta::Type))]
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct OpenInterest {
17    /// Market condition ID
18    pub market: String,
19    /// Open interest value
20    pub value: f64,
21}
22
23/// Sort field options for position queries
24#[cfg_attr(feature = "specta", derive(specta::Type))]
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
26#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
27pub enum PositionSortBy {
28    /// Sort by current value
29    Current,
30    /// Sort by initial value
31    Initial,
32    /// Sort by token count
33    Tokens,
34    /// Sort by cash P&L
35    CashPnl,
36    /// Sort by percentage P&L
37    PercentPnl,
38    /// Sort by market title
39    Title,
40    /// Sort by resolving status
41    Resolving,
42    /// Sort by price
43    Price,
44    /// Sort by average price
45    AvgPrice,
46}
47
48impl std::fmt::Display for PositionSortBy {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        match self {
51            Self::Current => write!(f, "CURRENT"),
52            Self::Initial => write!(f, "INITIAL"),
53            Self::Tokens => write!(f, "TOKENS"),
54            Self::CashPnl => write!(f, "CASHPNL"),
55            Self::PercentPnl => write!(f, "PERCENTPNL"),
56            Self::Title => write!(f, "TITLE"),
57            Self::Resolving => write!(f, "RESOLVING"),
58            Self::Price => write!(f, "PRICE"),
59            Self::AvgPrice => write!(f, "AVGPRICE"),
60        }
61    }
62}
63
64/// Sort direction for queries
65#[cfg_attr(feature = "specta", derive(specta::Type))]
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
67#[serde(rename_all = "UPPERCASE")]
68pub enum SortDirection {
69    /// Ascending order
70    Asc,
71    /// Descending order (default)
72    #[default]
73    Desc,
74}
75
76impl std::fmt::Display for SortDirection {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        match self {
79            Self::Asc => write!(f, "ASC"),
80            Self::Desc => write!(f, "DESC"),
81        }
82    }
83}
84
85/// Sort field options for closed position queries
86#[cfg_attr(feature = "specta", derive(specta::Type))]
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
88#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
89pub enum ClosedPositionSortBy {
90    /// Sort by realized P&L (default)
91    #[default]
92    RealizedPnl,
93    /// Sort by market title
94    Title,
95    /// Sort by price
96    Price,
97    /// Sort by average price
98    AvgPrice,
99    /// Sort by timestamp
100    Timestamp,
101}
102
103impl std::fmt::Display for ClosedPositionSortBy {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        match self {
106            Self::RealizedPnl => write!(f, "REALIZEDPNL"),
107            Self::Title => write!(f, "TITLE"),
108            Self::Price => write!(f, "PRICE"),
109            Self::AvgPrice => write!(f, "AVGPRICE"),
110            Self::Timestamp => write!(f, "TIMESTAMP"),
111        }
112    }
113}
114
115/// Closed position record
116#[cfg_attr(feature = "specta", derive(specta::Type))]
117#[derive(Debug, Clone, Serialize, Deserialize)]
118#[serde(rename_all = "camelCase")]
119pub struct ClosedPosition {
120    /// Proxy wallet address
121    pub proxy_wallet: String,
122    /// Asset identifier (token ID)
123    pub asset: String,
124    /// Condition ID of the market
125    pub condition_id: String,
126    /// Average entry price
127    pub avg_price: f64,
128    /// Total amount bought
129    pub total_bought: f64,
130    /// Realized profit and loss
131    pub realized_pnl: f64,
132    /// Current market price
133    pub cur_price: f64,
134    /// Timestamp when position was closed
135    #[cfg_attr(feature = "specta", specta(type = f64))]
136    pub timestamp: i64,
137    /// Market title
138    pub title: String,
139    /// Market slug
140    pub slug: String,
141    /// Market icon URL
142    pub icon: Option<String>,
143    /// Event slug
144    pub event_slug: Option<String>,
145    /// Outcome name (e.g., "Yes", "No")
146    pub outcome: String,
147    /// Outcome index (0 or 1 for binary markets)
148    pub outcome_index: u32,
149    /// Opposite outcome name
150    pub opposite_outcome: String,
151    /// Opposite outcome asset ID
152    pub opposite_asset: String,
153    /// Market end date
154    pub end_date: Option<String>,
155}
156
157/// Trade side (buy or sell)
158#[cfg_attr(feature = "specta", derive(specta::Type))]
159#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
160#[serde(rename_all = "UPPERCASE")]
161pub enum TradeSide {
162    /// Buy order
163    Buy,
164    /// Sell order
165    Sell,
166}
167
168impl std::fmt::Display for TradeSide {
169    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170        match self {
171            Self::Buy => write!(f, "BUY"),
172            Self::Sell => write!(f, "SELL"),
173        }
174    }
175}
176
177/// Filter type for trade queries
178#[cfg_attr(feature = "specta", derive(specta::Type))]
179#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
180#[serde(rename_all = "UPPERCASE")]
181pub enum TradeFilterType {
182    /// Filter by cash amount
183    Cash,
184    /// Filter by token amount
185    Tokens,
186}
187
188impl std::fmt::Display for TradeFilterType {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        match self {
191            Self::Cash => write!(f, "CASH"),
192            Self::Tokens => write!(f, "TOKENS"),
193        }
194    }
195}
196
197/// Trade record
198#[cfg_attr(feature = "specta", derive(specta::Type))]
199#[derive(Debug, Clone, Serialize, Deserialize)]
200#[serde(rename_all = "camelCase")]
201pub struct Trade {
202    /// Proxy wallet address
203    pub proxy_wallet: String,
204    /// Trade side (BUY or SELL)
205    pub side: TradeSide,
206    /// Asset identifier (token ID)
207    pub asset: String,
208    /// Condition ID of the market
209    pub condition_id: String,
210    /// Trade size (number of shares)
211    pub size: f64,
212    /// Trade price
213    pub price: f64,
214    /// Trade timestamp
215    #[cfg_attr(feature = "specta", specta(type = f64))]
216    pub timestamp: i64,
217    /// Market title
218    pub title: String,
219    /// Market slug
220    pub slug: String,
221    /// Market icon URL
222    pub icon: Option<String>,
223    /// Event slug
224    pub event_slug: Option<String>,
225    /// Outcome name (e.g., "Yes", "No")
226    pub outcome: String,
227    /// Outcome index (0 or 1 for binary markets)
228    pub outcome_index: u32,
229    /// User display name
230    pub name: Option<String>,
231    /// User pseudonym
232    pub pseudonym: Option<String>,
233    /// User bio
234    pub bio: Option<String>,
235    /// User profile image URL
236    pub profile_image: Option<String>,
237    /// Optimized profile image URL
238    pub profile_image_optimized: Option<String>,
239    /// Transaction hash
240    pub transaction_hash: Option<String>,
241}
242
243/// Activity type
244#[cfg_attr(feature = "specta", derive(specta::Type))]
245#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
246#[serde(rename_all = "UPPERCASE")]
247pub enum ActivityType {
248    /// Trade activity
249    Trade,
250    /// Split activity
251    Split,
252    /// Merge activity
253    Merge,
254    /// Redeem activity
255    Redeem,
256    /// Reward activity
257    Reward,
258    /// Conversion activity
259    Conversion,
260}
261
262impl std::fmt::Display for ActivityType {
263    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
264        match self {
265            Self::Trade => write!(f, "TRADE"),
266            Self::Split => write!(f, "SPLIT"),
267            Self::Merge => write!(f, "MERGE"),
268            Self::Redeem => write!(f, "REDEEM"),
269            Self::Reward => write!(f, "REWARD"),
270            Self::Conversion => write!(f, "CONVERSION"),
271        }
272    }
273}
274
275/// Sort field options for activity queries
276#[cfg_attr(feature = "specta", derive(specta::Type))]
277#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
278#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
279pub enum ActivitySortBy {
280    /// Sort by timestamp (default)
281    #[default]
282    Timestamp,
283    /// Sort by token amount
284    Tokens,
285    /// Sort by cash amount
286    Cash,
287}
288
289impl std::fmt::Display for ActivitySortBy {
290    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
291        match self {
292            Self::Timestamp => write!(f, "TIMESTAMP"),
293            Self::Tokens => write!(f, "TOKENS"),
294            Self::Cash => write!(f, "CASH"),
295        }
296    }
297}
298
299/// User activity record
300#[cfg_attr(feature = "specta", derive(specta::Type))]
301#[derive(Debug, Clone, Serialize, Deserialize)]
302#[serde(rename_all = "camelCase")]
303pub struct Activity {
304    /// Proxy wallet address
305    pub proxy_wallet: String,
306    /// Activity timestamp
307    #[cfg_attr(feature = "specta", specta(type = f64))]
308    pub timestamp: i64,
309    /// Condition ID of the market
310    pub condition_id: String,
311    /// Activity type
312    #[serde(rename = "type")]
313    pub activity_type: ActivityType,
314    /// Token quantity
315    pub size: f64,
316    /// USD value
317    pub usdc_size: f64,
318    /// On-chain transaction hash
319    pub transaction_hash: Option<String>,
320    /// Execution price
321    pub price: Option<f64>,
322    /// Asset identifier (token ID)
323    pub asset: Option<String>,
324    // ! Deserialize into String because the API can return an empty string
325    /// Trade side (BUY or SELL)
326    pub side: Option<String>,
327    /// Outcome index (0 or 1 for binary markets)
328    pub outcome_index: Option<u32>,
329    /// Market title
330    pub title: Option<String>,
331    /// Market slug
332    pub slug: Option<String>,
333    /// Market icon URL
334    pub icon: Option<String>,
335    /// Outcome name (e.g., "Yes", "No")
336    pub outcome: Option<String>,
337    /// User display name
338    pub name: Option<String>,
339    /// User pseudonym
340    pub pseudonym: Option<String>,
341    /// User bio
342    pub bio: Option<String>,
343    /// User profile image URL
344    pub profile_image: Option<String>,
345    /// Optimized profile image URL
346    pub profile_image_optimized: Option<String>,
347}
348
349/// User position in a market
350#[cfg_attr(feature = "specta", derive(specta::Type))]
351#[derive(Debug, Clone, Serialize, Deserialize)]
352#[serde(rename_all = "camelCase")]
353pub struct Position {
354    /// Proxy wallet address
355    pub proxy_wallet: String,
356    /// Asset identifier (token ID)
357    pub asset: String,
358    /// Condition ID of the market
359    pub condition_id: String,
360    /// Position size (number of shares)
361    pub size: f64,
362    /// Average entry price
363    pub avg_price: f64,
364    /// Initial value of position
365    pub initial_value: f64,
366    /// Current value of position
367    pub current_value: f64,
368    /// Cash profit and loss
369    pub cash_pnl: f64,
370    /// Percentage profit and loss
371    pub percent_pnl: f64,
372    /// Total amount bought
373    pub total_bought: f64,
374    /// Realized profit and loss
375    pub realized_pnl: f64,
376    /// Percentage realized P&L
377    pub percent_realized_pnl: f64,
378    /// Current market price
379    pub cur_price: f64,
380    /// Whether position is redeemable
381    pub redeemable: bool,
382    /// Whether position is mergeable
383    pub mergeable: bool,
384    /// Market title
385    pub title: String,
386    /// Market slug
387    pub slug: String,
388    /// Market icon URL
389    pub icon: Option<String>,
390    /// Event slug
391    pub event_slug: Option<String>,
392    /// Outcome name (e.g., "Yes", "No")
393    pub outcome: String,
394    /// Outcome index (0 or 1 for binary markets)
395    pub outcome_index: u32,
396    /// Opposite outcome name
397    pub opposite_outcome: String,
398    /// Opposite outcome asset ID
399    pub opposite_asset: String,
400    /// Market end date
401    pub end_date: Option<String>,
402    /// Whether this is a negative risk market
403    pub negative_risk: bool,
404}