sui_gql_client/queries/
multi_get_objects.rs1use af_sui_types::{Address, Object, Version};
2use itertools::Itertools as _;
3use sui_gql_schema::scalars::Base64Bcs;
4
5use super::fragments::ObjectKey;
6use crate::queries::Error;
7use crate::{GraphQlClient, GraphQlResponseExt as _, schema};
8
9pub(super) async fn query<C: GraphQlClient>(
10 client: &C,
11 objects: impl IntoIterator<Item = (Address, Version)> + Send,
12) -> super::Result<Vec<Object>, C> {
13 let mut object_keys = objects
14 .into_iter()
15 .sorted()
16 .dedup()
17 .map(|(object_id, version)| ObjectKey { object_id, version })
18 .collect_vec();
19
20 let vars = Variables { keys: &object_keys };
21
22 let data = client
23 .query::<Query, _>(vars)
24 .await
25 .map_err(Error::Client)?
26 .try_into_data()?;
27
28 graphql_extract::extract!(data => {
29 objects: multi_get_objects
30 });
31
32 let returned = objects
33 .into_iter()
34 .flatten()
35 .filter_map(|o| o.object)
36 .map(Base64Bcs::into_inner)
37 .inspect(|o| {
38 object_keys
39 .iter()
40 .position(|k| k.object_id == o.object_id() && k.version == o.version())
41 .map(|p| object_keys.swap_remove(p));
42 })
43 .collect_vec();
44
45 if !object_keys.is_empty() {
46 return Err(Error::MissingData(format!("Objects {object_keys:?}")));
47 }
48 Ok(returned)
49}
50
51#[cfg(test)]
52#[allow(clippy::unwrap_used)]
53#[test]
54fn gql_output() -> color_eyre::Result<()> {
55 use cynic::QueryBuilder as _;
56
57 let vars = Variables { keys: &[] };
59
60 let operation = Query::build(vars);
61 insta::assert_snapshot!(operation.query, @r###"
62 query Query($keys: [ObjectKey!]!) {
63 multiGetObjects(keys: $keys) {
64 object: bcs
65 }
66 }
67 "###);
68 Ok(())
69}
70
71#[derive(cynic::QueryVariables, Clone, Debug)]
72struct Variables<'a> {
73 keys: &'a [ObjectKey],
74}
75
76#[derive(cynic::QueryFragment, Clone, Debug)]
77#[cynic(variables = "Variables")]
78struct Query {
79 #[arguments(keys: $keys)]
80 multi_get_objects: Vec<Option<ObjectGql>>,
81}
82
83#[derive(cynic::QueryFragment, Debug, Clone)]
84#[cynic(graphql_type = "Object")]
85struct ObjectGql {
86 #[cynic(alias, rename = "bcs")]
87 object: Option<Base64Bcs<Object>>,
88}