polymarket_client/
pagination.rs1use 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>;