polyte_data/api/
holders.rs

1use polyte_core::{QueryBuilder, Request};
2use reqwest::Client;
3use serde::{Deserialize, Serialize};
4use url::Url;
5
6use crate::error::DataApiError;
7
8/// Holders namespace for holder-related operations
9#[derive(Clone)]
10pub struct Holders {
11    pub(crate) client: Client,
12    pub(crate) base_url: Url,
13}
14
15impl Holders {
16    /// Get top holders for markets
17    pub fn list(&self, markets: impl IntoIterator<Item = impl ToString>) -> ListHolders {
18        let market_ids: Vec<String> = markets.into_iter().map(|s| s.to_string()).collect();
19        let mut request = Request::new(self.client.clone(), self.base_url.clone(), "/holders");
20        if !market_ids.is_empty() {
21            request = request.query("market", market_ids.join(","));
22        }
23
24        ListHolders { request }
25    }
26}
27
28/// Request builder for getting top holders
29pub struct ListHolders {
30    request: Request<Vec<MarketHolders>, DataApiError>,
31}
32
33impl ListHolders {
34    /// Set maximum number of results per market (0-500, default: 100)
35    pub fn limit(mut self, limit: u32) -> Self {
36        self.request = self.request.query("limit", limit);
37        self
38    }
39
40    /// Set minimum balance filter (0-999999, default: 1)
41    pub fn min_balance(mut self, min_balance: u32) -> Self {
42        self.request = self.request.query("minBalance", min_balance);
43        self
44    }
45
46    /// Execute the request
47    pub async fn send(self) -> crate::error::Result<Vec<MarketHolders>> {
48        self.request.send().await
49    }
50}
51
52/// Market holders response containing token and its holders
53#[derive(Debug, Clone, Serialize, Deserialize)]
54#[serde(rename_all(deserialize = "camelCase"))]
55pub struct MarketHolders {
56    /// Token identifier
57    pub token: String,
58    /// List of holders for this token
59    pub holders: Vec<Holder>,
60}
61
62/// Individual holder of a market token
63#[derive(Debug, Clone, Serialize, Deserialize)]
64#[serde(rename_all(deserialize = "camelCase"))]
65pub struct Holder {
66    /// Proxy wallet address
67    pub proxy_wallet: String,
68    /// User bio
69    pub bio: Option<String>,
70    /// Asset identifier (token ID)
71    pub asset: Option<String>,
72    /// User pseudonym
73    pub pseudonym: Option<String>,
74    /// Amount held
75    pub amount: f64,
76    /// Whether username is displayed publicly
77    pub display_username_public: Option<bool>,
78    /// Outcome index (0 or 1 for binary markets)
79    pub outcome_index: u32,
80    /// User display name
81    pub name: Option<String>,
82    /// User profile image URL
83    pub profile_image: Option<String>,
84    /// Optimized profile image URL
85    pub profile_image_optimized: Option<String>,
86}