1use reqwest::Client;
2use serde::{Deserialize, Serialize};
3use url::Url;
4
5use crate::{
6 error::DataApiError,
7 request::{QueryBuilder, Request},
8 types::{
9 Activity, ActivitySortBy, ActivityType, ClosedPosition, ClosedPositionSortBy, Position,
10 PositionSortBy, SortDirection, Trade, TradeFilterType, TradeSide, UserValue,
11 },
12};
13
14#[derive(Clone)]
16pub struct UserApi {
17 pub(crate) client: Client,
18 pub(crate) base_url: Url,
19 pub(crate) user_address: String,
20}
21
22impl UserApi {
23 pub fn list_positions(&self) -> ListPositions {
25 let mut request = Request::new(
26 self.client.clone(),
27 self.base_url.clone(),
28 "/positions".to_string(),
29 );
30 request = request.query("user", &self.user_address);
31
32 ListPositions { request }
33 }
34
35 pub fn positions_value(&self) -> GetPositionValue {
37 let mut request = Request::new(
38 self.client.clone(),
39 self.base_url.clone(),
40 "/value".to_string(),
41 );
42 request = request.query("user", &self.user_address);
43
44 GetPositionValue { request }
45 }
46
47 pub fn closed_positions(&self) -> ListClosedPositions {
49 let mut request = Request::new(
50 self.client.clone(),
51 self.base_url.clone(),
52 "/closed-positions".to_string(),
53 );
54 request = request.query("user", &self.user_address);
55
56 ListClosedPositions { request }
57 }
58
59 pub fn trades(&self) -> ListUserTrades {
61 let mut request = Request::new(
62 self.client.clone(),
63 self.base_url.clone(),
64 "/trades".to_string(),
65 );
66 request = request.query("user", &self.user_address);
67
68 ListUserTrades { request }
69 }
70
71 pub fn activity(&self) -> ListActivity {
73 let mut request = Request::new(
74 self.client.clone(),
75 self.base_url.clone(),
76 "/activity".to_string(),
77 );
78 request = request.query("user", &self.user_address);
79
80 ListActivity { request }
81 }
82
83 pub async fn traded(&self) -> Result<UserTraded, DataApiError> {
85 let url = self.base_url.join("/traded")?;
86 let response = self
87 .client
88 .get(url)
89 .query(&[("user", &self.user_address)])
90 .send()
91 .await?;
92 let status = response.status();
93
94 if !status.is_success() {
95 return Err(DataApiError::from_response(response).await);
96 }
97
98 let traded: UserTraded = response.json().await?;
99 Ok(traded)
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct UserTraded {
106 pub user: String,
108 pub traded: u64,
110}
111
112pub struct ListPositions {
114 request: Request<Vec<Position>>,
115}
116
117impl ListPositions {
118 pub fn market(mut self, condition_ids: impl IntoIterator<Item = impl ToString>) -> Self {
120 let ids: Vec<String> = condition_ids.into_iter().map(|s| s.to_string()).collect();
121 if !ids.is_empty() {
122 self.request = self.request.query("market", ids.join(","));
123 }
124 self
125 }
126
127 pub fn event_id(mut self, event_ids: impl IntoIterator<Item = impl ToString>) -> Self {
129 let ids: Vec<String> = event_ids.into_iter().map(|s| s.to_string()).collect();
130 if !ids.is_empty() {
131 self.request = self.request.query("eventId", ids.join(","));
132 }
133 self
134 }
135
136 pub fn size_threshold(mut self, threshold: f64) -> Self {
138 self.request = self.request.query("sizeThreshold", threshold);
139 self
140 }
141
142 pub fn redeemable(mut self, redeemable: bool) -> Self {
144 self.request = self.request.query("redeemable", redeemable);
145 self
146 }
147
148 pub fn mergeable(mut self, mergeable: bool) -> Self {
150 self.request = self.request.query("mergeable", mergeable);
151 self
152 }
153
154 pub fn limit(mut self, limit: u32) -> Self {
156 self.request = self.request.query("limit", limit);
157 self
158 }
159
160 pub fn offset(mut self, offset: u32) -> Self {
162 self.request = self.request.query("offset", offset);
163 self
164 }
165
166 pub fn sort_by(mut self, sort_by: PositionSortBy) -> Self {
168 self.request = self.request.query("sortBy", sort_by);
169 self
170 }
171
172 pub fn sort_direction(mut self, direction: SortDirection) -> Self {
174 self.request = self.request.query("sortDirection", direction);
175 self
176 }
177
178 pub fn title(mut self, title: impl Into<String>) -> Self {
180 self.request = self.request.query("title", title.into());
181 self
182 }
183
184 pub async fn send(self) -> Result<Vec<Position>, DataApiError> {
186 self.request.send().await
187 }
188}
189
190pub struct GetPositionValue {
192 request: Request<Vec<UserValue>>,
193}
194
195impl GetPositionValue {
196 pub fn market(mut self, condition_ids: impl IntoIterator<Item = impl ToString>) -> Self {
198 let ids: Vec<String> = condition_ids.into_iter().map(|s| s.to_string()).collect();
199 if !ids.is_empty() {
200 self.request = self.request.query("market", ids.join(","));
201 }
202 self
203 }
204
205 pub async fn send(self) -> Result<Vec<UserValue>, DataApiError> {
207 self.request.send().await
208 }
209}
210
211pub struct ListClosedPositions {
213 request: Request<Vec<ClosedPosition>>,
214}
215
216impl ListClosedPositions {
217 pub fn market(mut self, condition_ids: impl IntoIterator<Item = impl ToString>) -> Self {
219 let ids: Vec<String> = condition_ids.into_iter().map(|s| s.to_string()).collect();
220 if !ids.is_empty() {
221 self.request = self.request.query("market", ids.join(","));
222 }
223 self
224 }
225
226 pub fn event_id(mut self, event_ids: impl IntoIterator<Item = impl ToString>) -> Self {
228 let ids: Vec<String> = event_ids.into_iter().map(|s| s.to_string()).collect();
229 if !ids.is_empty() {
230 self.request = self.request.query("eventId", ids.join(","));
231 }
232 self
233 }
234
235 pub fn title(mut self, title: impl Into<String>) -> Self {
237 self.request = self.request.query("title", title.into());
238 self
239 }
240
241 pub fn limit(mut self, limit: u32) -> Self {
243 self.request = self.request.query("limit", limit);
244 self
245 }
246
247 pub fn offset(mut self, offset: u32) -> Self {
249 self.request = self.request.query("offset", offset);
250 self
251 }
252
253 pub fn sort_by(mut self, sort_by: ClosedPositionSortBy) -> Self {
255 self.request = self.request.query("sortBy", sort_by);
256 self
257 }
258
259 pub fn sort_direction(mut self, direction: SortDirection) -> Self {
261 self.request = self.request.query("sortDirection", direction);
262 self
263 }
264
265 pub async fn send(self) -> Result<Vec<ClosedPosition>, DataApiError> {
267 self.request.send().await
268 }
269}
270
271pub struct ListUserTrades {
273 request: Request<Vec<Trade>>,
274}
275
276impl ListUserTrades {
277 pub fn market(mut self, condition_ids: impl IntoIterator<Item = impl ToString>) -> Self {
280 let ids: Vec<String> = condition_ids.into_iter().map(|s| s.to_string()).collect();
281 if !ids.is_empty() {
282 self.request = self.request.query("market", ids.join(","));
283 }
284 self
285 }
286
287 pub fn event_id(mut self, event_ids: impl IntoIterator<Item = impl ToString>) -> Self {
290 let ids: Vec<String> = event_ids.into_iter().map(|s| s.to_string()).collect();
291 if !ids.is_empty() {
292 self.request = self.request.query("eventId", ids.join(","));
293 }
294 self
295 }
296
297 pub fn side(mut self, side: TradeSide) -> Self {
299 self.request = self.request.query("side", side);
300 self
301 }
302
303 pub fn taker_only(mut self, taker_only: bool) -> Self {
305 self.request = self.request.query("takerOnly", taker_only);
306 self
307 }
308
309 pub fn filter_type(mut self, filter_type: TradeFilterType) -> Self {
311 self.request = self.request.query("filterType", filter_type);
312 self
313 }
314
315 pub fn filter_amount(mut self, amount: f64) -> Self {
317 self.request = self.request.query("filterAmount", amount);
318 self
319 }
320
321 pub fn limit(mut self, limit: u32) -> Self {
323 self.request = self.request.query("limit", limit);
324 self
325 }
326
327 pub fn offset(mut self, offset: u32) -> Self {
329 self.request = self.request.query("offset", offset);
330 self
331 }
332
333 pub async fn send(self) -> Result<Vec<Trade>, DataApiError> {
335 self.request.send().await
336 }
337}
338
339pub struct ListActivity {
341 request: Request<Vec<Activity>>,
342}
343
344impl ListActivity {
345 pub fn market(mut self, condition_ids: impl IntoIterator<Item = impl ToString>) -> Self {
347 let ids: Vec<String> = condition_ids.into_iter().map(|s| s.to_string()).collect();
348 if !ids.is_empty() {
349 self.request = self.request.query("market", ids.join(","));
350 }
351 self
352 }
353
354 pub fn event_id(mut self, event_ids: impl IntoIterator<Item = impl ToString>) -> Self {
356 let ids: Vec<String> = event_ids.into_iter().map(|s| s.to_string()).collect();
357 if !ids.is_empty() {
358 self.request = self.request.query("eventId", ids.join(","));
359 }
360 self
361 }
362
363 pub fn activity_type(mut self, types: impl IntoIterator<Item = ActivityType>) -> Self {
365 let type_strs: Vec<String> = types.into_iter().map(|t| t.to_string()).collect();
366 if !type_strs.is_empty() {
367 self.request = self.request.query("type", type_strs.join(","));
368 }
369 self
370 }
371
372 pub fn side(mut self, side: TradeSide) -> Self {
374 self.request = self.request.query("side", side);
375 self
376 }
377
378 pub fn start(mut self, timestamp: i64) -> Self {
380 self.request = self.request.query("start", timestamp);
381 self
382 }
383
384 pub fn end(mut self, timestamp: i64) -> Self {
386 self.request = self.request.query("end", timestamp);
387 self
388 }
389
390 pub fn limit(mut self, limit: u32) -> Self {
392 self.request = self.request.query("limit", limit);
393 self
394 }
395
396 pub fn offset(mut self, offset: u32) -> Self {
398 self.request = self.request.query("offset", offset);
399 self
400 }
401
402 pub fn sort_by(mut self, sort_by: ActivitySortBy) -> Self {
404 self.request = self.request.query("sortBy", sort_by);
405 self
406 }
407
408 pub fn sort_direction(mut self, direction: SortDirection) -> Self {
410 self.request = self.request.query("sortDirection", direction);
411 self
412 }
413
414 pub async fn send(self) -> Result<Vec<Activity>, DataApiError> {
416 self.request.send().await
417 }
418}