sui_gql_client/queries/
objects_content.rs1use std::collections::HashMap;
2
3use af_sui_types::ObjectId;
4use futures::TryStreamExt as _;
5use sui_gql_schema::schema;
6
7use super::fragments::{MoveValueRaw, ObjectFilterV2};
8use super::objects_flat::Variables;
9use super::outputs::RawMoveStruct;
10use super::{objects_flat, Error};
11use crate::{missing_data, GraphQlClient, GraphQlResponseExt as _};
12
13pub(super) async fn query<C: GraphQlClient>(
14 client: &C,
15 object_ids: Vec<ObjectId>,
16) -> super::Result<HashMap<ObjectId, RawMoveStruct>, C> {
17 let vars = Variables {
18 after: None,
19 first: None,
20 filter: Some(ObjectFilterV2 {
21 object_ids: Some(&object_ids),
22 ..Default::default()
23 }),
24 };
25
26 let mut stream = std::pin::pin!(super::stream::forward(client, vars, request));
27
28 let mut raw_objs = HashMap::new();
29
30 while let Some(object) = stream.try_next().await? {
31 let object_id = object.object_id;
32 let struct_ = object
33 .as_move_object
34 .ok_or(missing_data!("Not a Move object"))?
35 .contents
36 .ok_or(missing_data!("Object contents"))?
37 .try_into()
38 .expect("Only structs can be top-level objects");
39 raw_objs.insert(object_id, struct_);
40 }
41
42 Ok(raw_objs)
43}
44
45type Query = objects_flat::Query<Object>;
46
47async fn request<C: GraphQlClient>(
48 client: &C,
49 vars: Variables<'_>,
50) -> super::Result<super::stream::Page<impl Iterator<Item = super::Result<Object, C>> + 'static>, C>
51{
52 let data = client
53 .query::<Query, _>(vars)
54 .await
55 .map_err(Error::Client)?
56 .try_into_data()?;
57
58 graphql_extract::extract!(data => {
59 objects
60 });
61
62 Ok(super::stream::Page {
63 info: objects.page_info.into(),
64 data: objects.nodes.into_iter().map(Ok),
65 })
66}
67
68#[cfg(test)]
69#[allow(clippy::unwrap_used)]
70#[test]
71fn gql_output() {
72 use cynic::QueryBuilder as _;
73
74 let vars = Variables {
75 filter: None,
76 first: None,
77 after: None,
78 };
79 let operation = Query::build(vars);
80 insta::assert_snapshot!(operation.query, @r###"
81 query Query($filter: ObjectFilter, $after: String, $first: Int) {
82 objects(filter: $filter, first: $first, after: $after) {
83 nodes {
84 address
85 asMoveObject {
86 contents {
87 type {
88 repr
89 }
90 bcs
91 }
92 }
93 }
94 pageInfo {
95 hasNextPage
96 endCursor
97 }
98 }
99 }
100 "###);
101}
102
103#[derive(cynic::QueryFragment, Clone, Debug)]
104struct Object {
105 #[cynic(rename = "address")]
106 object_id: ObjectId,
107 as_move_object: Option<super::fragments::MoveObjectContent<MoveValueRaw>>,
108}