Skip to main content

polymarket_client/
pagination.rs

1use crate::error::ListEventsError;
2use crate::error::ListMarketsError;
3use polymarket_types::PaginationCursor;
4
5#[derive(Clone, Debug)]
6pub struct Page<T> {
7    pub items: T,
8    pub has_more: bool,
9    pub next_cursor: Option<PaginationCursor>,
10}
11
12pub struct Paginator<T, E> {
13    fetch: Box<dyn FnMut(Option<PaginationCursor>) -> FetchFuture<T, E> + Send>,
14    cursor: Option<PaginationCursor>,
15    started: bool,
16    done: bool,
17}
18
19pub type FetchFuture<T, E> =
20    std::pin::Pin<Box<dyn std::future::Future<Output = Result<Page<T>, E>> + Send>>;
21
22impl<T, E> Paginator<T, E> {
23    pub fn new<F>(fetch: F, initial_cursor: Option<PaginationCursor>) -> Self
24    where
25        F: FnMut(Option<PaginationCursor>) -> FetchFuture<T, E> + Send + 'static,
26    {
27        Self {
28            fetch: Box::new(fetch),
29            cursor: initial_cursor,
30            started: false,
31            done: false,
32        }
33    }
34
35    pub async fn first_page(&mut self) -> Result<Page<T>, E> {
36        self.started = true;
37        let page = (self.fetch)(self.cursor.clone()).await?;
38        if page.has_more {
39            self.cursor.clone_from(&page.next_cursor);
40        } else {
41            self.done = true;
42        }
43        Ok(page)
44    }
45
46    pub fn from_cursor(
47        cursor: Option<PaginationCursor>,
48        fetch: impl FnMut(Option<PaginationCursor>) -> FetchFuture<T, E> + Send + 'static,
49    ) -> Self {
50        Self::new(fetch, cursor)
51    }
52
53    pub async fn next_page(&mut self) -> Result<Option<Page<T>>, E> {
54        if self.done {
55            return Ok(None);
56        }
57        if !self.started {
58            return Ok(Some(self.first_page().await?));
59        }
60        let page = (self.fetch)(self.cursor.clone()).await?;
61        if page.has_more {
62            self.cursor.clone_from(&page.next_cursor);
63        } else {
64            self.done = true;
65        }
66        Ok(Some(page))
67    }
68
69    pub async fn collect_all(&mut self) -> Result<Vec<Page<T>>, E> {
70        let mut pages = Vec::new();
71        pages.push(self.first_page().await?);
72        while let Some(page) = self.next_page().await? {
73            pages.push(page);
74        }
75        Ok(pages)
76    }
77}
78
79pub type ListMarketsPaginator =
80    Paginator<Vec<polymarket_bindings::gamma::Market>, ListMarketsError>;
81pub type ListEventsPaginator = Paginator<Vec<polymarket_bindings::gamma::Event>, ListEventsError>;