polyoxide_data/api/pnl.rs
1use polyoxide_core::{HttpClient, QueryBuilder, Request};
2
3use crate::{
4 error::DataApiError,
5 types::{PnlFidelity, PnlPoint},
6};
7
8/// PnL namespace — `GET /user-pnl` on `user-pnl-api.polymarket.com`.
9///
10/// # Stability
11///
12/// This host is **not covered by any published Polymarket OpenAPI spec**. It
13/// backs the PnL chart on the Polymarket web app and was verified live, but it
14/// carries no documented compatibility guarantee — treat it as more likely to
15/// change without notice than the rest of this crate. The base URL is
16/// configurable via
17/// [`DataApiBuilder::pnl_base_url`](crate::DataApiBuilder::pnl_base_url).
18#[derive(Clone)]
19pub struct PnlApi {
20 pub(crate) http_client: HttpClient,
21}
22
23impl PnlApi {
24 /// Get a user's realized-plus-unrealized PnL time series.
25 ///
26 /// Returns points of `{ t, p }` — Unix timestamp in seconds and PnL in
27 /// USDC. `user_address` is required by the upstream API.
28 pub fn history(&self, user_address: impl Into<String>) -> UserPnlRequest {
29 UserPnlRequest {
30 request: Request::new(self.http_client.clone(), "/user-pnl")
31 .query("user_address", user_address.into()),
32 }
33 }
34}
35
36/// Request builder for a user's PnL time series.
37pub struct UserPnlRequest {
38 request: Request<Vec<PnlPoint>, DataApiError>,
39}
40
41impl UserPnlRequest {
42 /// Restrict the series to a trailing window (e.g. `"1d"`, `"1w"`, `"all"`).
43 ///
44 /// Omitted by default, which yields the upstream default window. Unlike
45 /// [`fidelity`](Self::fidelity), the accepted values are not enumerated by
46 /// the API's own error messages, so this takes a string.
47 pub fn interval(mut self, interval: impl Into<String>) -> Self {
48 self.request = self.request.query("interval", interval.into());
49 self
50 }
51
52 /// Set the sampling resolution of the returned series.
53 pub fn fidelity(mut self, fidelity: PnlFidelity) -> Self {
54 self.request = self.request.query("fidelity", fidelity);
55 self
56 }
57
58 /// Execute the request.
59 pub async fn send(self) -> Result<Vec<PnlPoint>, DataApiError> {
60 self.request.send().await
61 }
62}