sui_gql_client/queries/
packages_published_epoch.rs1use 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
106impl 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#[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}