sui_gql_client/queries/
packages_published_epoch.rs

1use af_sui_types::{Address, Version};
2use futures::TryStreamExt as _;
3
4use super::fragments::{ObjectFilterV2, PageInfo, PageInfoForward};
5use super::{Error, stream};
6use crate::{GraphQlClient, GraphQlResponseExt as _, schema};
7
8type Item = (Address, u64, u64);
9
10pub async fn query<C: GraphQlClient>(
11    client: &C,
12    package_ids: Vec<Address>,
13) -> Result<impl Iterator<Item = Item> + use<C>, Error<C::Error>> {
14    let vars = QueryVariables {
15        filter: Some(ObjectFilterV2 {
16            type_: None,
17            owner: None,
18            object_ids: Some(&package_ids),
19        }),
20        first: None,
21        after: None,
22    };
23
24    let results: Vec<_> = stream::forward(client, vars, request).try_collect().await?;
25
26    Ok(results.into_iter())
27}
28
29async fn request<C: GraphQlClient>(
30    client: &C,
31    vars: QueryVariables<'_>,
32) -> super::Result<stream::Page<impl Iterator<Item = super::Result<Item, C>> + use<C>>, C> {
33    let data = client
34        .query::<Query, _>(vars)
35        .await
36        .map_err(Error::Client)?
37        .try_into_data()?;
38    graphql_extract::extract!(data => {
39        objects {
40            page_info
41            nodes[] {
42                address
43                as_move_package? {
44                    previous_transaction_block? {
45                        effects? {
46                            epoch? {
47                                epoch_id
48                            }
49                            checkpoint? {
50                                sequence_number
51                            }
52                        }
53                    }
54                }
55            }
56        }
57    });
58    Ok(stream::Page::new(
59        page_info,
60        nodes.map(|r| -> super::Result<_, C> {
61            let (address, (epoch_id, ckpt_seq)) = r?;
62            Ok((address, epoch_id, ckpt_seq))
63        }),
64    ))
65}
66
67#[cfg(test)]
68#[allow(clippy::unwrap_used)]
69#[test]
70fn gql_output() {
71    use cynic::QueryBuilder as _;
72
73    let vars = QueryVariables {
74        filter: None,
75        first: None,
76        after: None,
77    };
78    let operation = Query::build(vars);
79    insta::assert_snapshot!(operation.query, @r###"
80    query Query($after: String, $filter: ObjectFilter, $first: Int) {
81      objects(filter: $filter, first: $first, after: $after) {
82        nodes {
83          address
84          asMovePackage {
85            previousTransactionBlock {
86              effects {
87                epoch {
88                  epochId
89                }
90                checkpoint {
91                  sequenceNumber
92                }
93              }
94            }
95          }
96        }
97        pageInfo {
98          hasNextPage
99          endCursor
100        }
101      }
102    }
103    "###);
104}
105
106// ================================================================================
107
108impl stream::UpdatePageInfo for QueryVariables<'_> {
109    fn update_page_info(&mut self, info: &PageInfo) {
110        self.after.clone_from(&info.end_cursor)
111    }
112}
113
114// ================================================================================
115
116#[derive(cynic::QueryVariables, Clone, Debug)]
117struct QueryVariables<'a> {
118    after: Option<String>,
119    filter: Option<ObjectFilterV2<'a>>,
120    first: Option<i32>,
121}
122
123#[derive(cynic::QueryFragment, Debug)]
124#[cynic(variables = "QueryVariables")]
125struct Query {
126    #[arguments(filter: $filter, first: $first, after: $after)]
127    objects: ObjectConnection,
128}
129
130#[derive(cynic::QueryFragment, Debug)]
131struct ObjectConnection {
132    nodes: Vec<Object>,
133    page_info: PageInfoForward,
134}
135
136#[derive(cynic::QueryFragment, Debug)]
137struct Object {
138    address: Address,
139    as_move_package: Option<MovePackage>,
140}
141
142#[derive(cynic::QueryFragment, Debug)]
143struct MovePackage {
144    previous_transaction_block: Option<TransactionBlock>,
145}
146
147#[derive(cynic::QueryFragment, Debug)]
148struct TransactionBlock {
149    effects: Option<TransactionBlockEffects>,
150}
151
152#[derive(cynic::QueryFragment, Debug)]
153struct TransactionBlockEffects {
154    epoch: Option<Epoch>,
155    checkpoint: Option<Checkpoint>,
156}
157
158#[derive(cynic::QueryFragment, Debug)]
159struct Epoch {
160    epoch_id: Version,
161}
162
163#[derive(cynic::QueryFragment, Debug)]
164struct Checkpoint {
165    sequence_number: Version,
166}