sui_gql_client/queries/
packages.rs

1use af_sui_types::Address;
2
3use super::Error;
4use super::model::fragments::PageInfoForward;
5use crate::queries::model::fragments::MovePackageConnection;
6use crate::{GraphQlClient, Paged, PagedResponse, missing_data, schema};
7
8pub async fn query<C: GraphQlClient>(
9    client: &C,
10    package_id: Address,
11) -> Result<Vec<(Address, u64)>, Error<C::Error>> {
12    let vars = Variables {
13        address: package_id,
14        first: None,
15        after: None,
16    };
17
18    let response: PagedResponse<Query> = client.query_paged(vars).await.map_err(Error::Client)?;
19    let (init, pages) = response
20        .try_into_data()?
21        .ok_or_else(|| missing_data!("No data"))?;
22
23    let pages = pages
24        .into_iter()
25        .map(|x| {
26            x.package_versions
27                .ok_or_else(|| missing_data!("No pages data"))
28        })
29        .collect::<Result<Vec<_>, _>>()?;
30
31    let mut result = vec![];
32
33    for p in init
34        .package_versions
35        .ok_or_else(|| missing_data!("No init data"))?
36        .nodes
37        .into_iter()
38        .chain(pages.into_iter().flat_map(|p| p.nodes))
39    {
40        let v = p
41            .version
42            .ok_or_else(|| missing_data!("No version for package"))?;
43        result.push((p.address, v));
44    }
45
46    Ok(result)
47}
48
49#[derive(cynic::QueryVariables, Clone, Debug)]
50pub struct Variables {
51    address: Address,
52    after: Option<String>,
53    first: Option<i32>,
54}
55
56#[derive(cynic::QueryFragment, Debug)]
57#[cynic(variables = "Variables")]
58pub struct Query {
59    #[arguments(address: $address, first: $first, after: $after)]
60    pub package_versions: Option<MovePackageConnection>,
61}
62
63impl Paged for Query {
64    type Input = Variables;
65    type NextPage = Self;
66    type NextInput = Variables;
67
68    fn next_variables(&self, mut prev_vars: Self::Input) -> Option<Self::NextInput> {
69        if let Some(MovePackageConnection {
70            page_info:
71                PageInfoForward {
72                    has_next_page,
73                    end_cursor,
74                },
75            ..
76        }) = &self.package_versions
77        {
78            if *has_next_page {
79                prev_vars.after.clone_from(end_cursor);
80                Some(prev_vars)
81            } else {
82                None
83            }
84        } else {
85            None
86        }
87    }
88}
89
90#[cfg(test)]
91#[allow(clippy::unwrap_used)]
92#[test]
93fn gql_output() {
94    use cynic::QueryBuilder as _;
95
96    let vars = Variables {
97        address: Address::new(rand::random()).into(),
98        first: None,
99        after: None,
100    };
101    let operation = Query::build(vars);
102    insta::assert_snapshot!(operation.query, @r###"
103    query Query($address: SuiAddress!, $after: String, $first: Int) {
104      packageVersions(address: $address, first: $first, after: $after) {
105        nodes {
106          address
107          version
108        }
109        pageInfo {
110          hasNextPage
111          endCursor
112        }
113      }
114    }
115    "###);
116}