sui_gql_client/queries/
events_backward.rs

1use af_sui_types::Address as SuiAddress;
2use sui_gql_schema::scalars;
3
4use super::Error;
5use super::fragments::MoveValueRaw;
6use crate::{GraphQlClient, GraphQlResponseExt as _, schema};
7
8#[derive(cynic::InputObject, Debug, Clone)]
9pub struct EventFilter {
10    pub sender: Option<SuiAddress>,
11    pub transaction_digest: Option<String>,
12    pub emitting_module: Option<String>,
13    pub event_type: Option<String>,
14}
15
16#[derive(cynic::QueryFragment, Debug, Clone)]
17pub struct EventEdge {
18    pub node: Event,
19    pub cursor: String,
20}
21
22#[derive(cynic::QueryFragment, Debug, Clone)]
23pub struct Event {
24    pub timestamp: Option<scalars::DateTime>,
25    pub contents: Option<MoveValueRaw>,
26}
27
28/// Return a single page of events + cursors and a flag indicating if there's a previous page.
29///
30/// If `page_size` is left `None`, the server decides the size of the page.
31///
32/// The edges are returned in reverse order of which they where returned by the server
33pub async fn query<C: GraphQlClient>(
34    client: &C,
35    filter: Option<EventFilter>,
36    cursor: Option<String>,
37    page_size: Option<u32>,
38) -> super::Result<(Vec<EventEdge>, bool), C> {
39    let vars = Variables {
40        filter,
41        before: cursor,
42        last: page_size.map(|v| v as i32),
43    };
44    let data: Option<Query> = client
45        .query(vars)
46        .await
47        .map_err(Error::Client)?
48        .try_into_data()?;
49    graphql_extract::extract!(data => {
50        events {
51            edges
52            page_info {
53                has_previous_page
54            }
55        }
56    });
57    Ok((edges, has_previous_page))
58}
59
60// =============================================================================
61//  Initial query
62// =============================================================================
63
64#[derive(cynic::QueryVariables, Debug, Clone)]
65struct Variables {
66    last: Option<i32>,
67    before: Option<String>,
68    filter: Option<EventFilter>,
69}
70
71#[derive(cynic::QueryFragment, Debug)]
72#[cynic(graphql_type = "Query", variables = "Variables")]
73struct Query {
74    #[arguments(before: $before, filter: $filter, last: $last)]
75    events: EventConnection,
76}
77
78#[cfg(test)]
79#[allow(clippy::unwrap_used)]
80#[test]
81fn init_gql_output() {
82    use cynic::QueryBuilder as _;
83    let filter = EventFilter {
84        sender: None,
85        transaction_digest: None,
86        emitting_module: None,
87        event_type: None,
88    };
89    let vars = Variables {
90        filter: Some(filter),
91        before: None,
92        last: None,
93    };
94    let operation = Query::build(vars);
95    insta::assert_snapshot!(operation.query, @r###"
96    query Query($last: Int, $before: String, $filter: EventFilter) {
97      events(before: $before, filter: $filter, last: $last) {
98        edges {
99          node {
100            timestamp
101            contents {
102              type {
103                repr
104              }
105              bcs
106            }
107          }
108          cursor
109        }
110        pageInfo {
111          hasPreviousPage
112        }
113      }
114    }
115    "###);
116}
117
118// =============================================================================
119//  Inner query fragments
120// =============================================================================
121
122#[derive(cynic::QueryFragment, Clone, Debug)]
123struct EventConnection {
124    edges: Vec<EventEdge>,
125    page_info: HasPreviousPage,
126}
127
128#[derive(cynic::QueryFragment, Clone, Debug)]
129#[cynic(graphql_type = "PageInfo")]
130pub struct HasPreviousPage {
131    pub has_previous_page: bool,
132}