sui_gql_client/queries/
owner_df_contents.rs1use std::collections::HashMap;
2
3use af_sui_types::Address as SuiAddress;
4
5use super::Error;
6use super::fragments::MoveValueRaw;
7use super::outputs::{DynamicField as OutputDf, ObjectKey, RawMoveValue};
8use crate::{GraphQlClient, GraphQlResponseExt as _, missing_data, schema};
9
10pub async fn query<C: GraphQlClient>(
11 client: &C,
12 address: SuiAddress,
13 root_version: Option<u64>,
14 first: Option<i32>,
15 after: Option<String>,
16) -> Result<(HashMap<RawMoveValue, OutputDf>, Option<String>), Error<C::Error>> {
17 let vars = QueryVariables {
18 address,
19 root_version,
20 first,
21 after,
22 };
23 let data = client
24 .query::<Query, QueryVariables>(vars)
25 .await
26 .map_err(Error::Client)?
27 .try_into_data()?
28 .ok_or(missing_data!("Response empty"))?;
29
30 let DynamicFieldConnection { nodes, page_info } = data
31 .owner
32 .ok_or(missing_data!("No owner found"))?
33 .dynamic_fields;
34
35 let next_cursor = if page_info.has_next_page {
36 page_info.end_cursor
37 } else {
38 None
39 };
40
41 let mut df_map = HashMap::new();
42 for DynamicField { name, value } in nodes {
43 let name = name
44 .ok_or(missing_data!("Dynamic field found but with no name"))?
45 .into();
46 let instance = value.ok_or(missing_data!("Dynamic field found but with no value"))?;
47 let out = match instance {
48 DynamicFieldValue::MoveObject(MoveObject {
49 object_id,
50 version,
51 contents,
52 }) => {
53 let struct_ = contents
54 .ok_or(missing_data!("No contents for DOF"))?
55 .try_into()
56 .expect("Only Move structs can be top-level objects");
57 OutputDf::Object(ObjectKey { object_id, version }, struct_)
58 }
59 DynamicFieldValue::MoveValue(value) => OutputDf::Field(value.into()),
60 DynamicFieldValue::Unknown => return Err(missing_data!("Unknown dynamic field type")),
61 };
62 df_map.insert(name, out);
63 }
64
65 Ok((df_map, next_cursor))
66}
67
68#[cfg(test)]
69#[allow(clippy::unwrap_used)]
70#[test]
71fn gql_output() {
72 use cynic::QueryBuilder as _;
73 let vars = QueryVariables {
74 address: SuiAddress::new(rand::random()),
75 root_version: None,
76 first: None,
77 after: None,
78 };
79 let operation = Query::build(vars);
80 insta::assert_snapshot!(operation.query, @r###"
81 query Query($address: SuiAddress!, $rootVersion: UInt53, $after: String, $first: Int) {
82 owner(address: $address, rootVersion: $rootVersion) {
83 dynamicFields(first: $first, after: $after) {
84 nodes {
85 name {
86 type {
87 repr
88 }
89 bcs
90 }
91 value {
92 __typename
93 ... on MoveObject {
94 address
95 version
96 contents {
97 type {
98 repr
99 }
100 bcs
101 }
102 }
103 ... on MoveValue {
104 type {
105 repr
106 }
107 bcs
108 }
109 }
110 }
111 pageInfo {
112 hasNextPage
113 endCursor
114 }
115 }
116 }
117 }
118 "###);
119}
120
121#[derive(cynic::QueryVariables, Debug)]
126struct QueryVariables {
127 address: SuiAddress,
128 root_version: Option<af_sui_types::Version>,
129 after: Option<String>,
130 first: Option<i32>,
131}
132
133#[derive(cynic::QueryFragment, Debug)]
134#[cynic(variables = "QueryVariables")]
135struct Query {
136 #[arguments(address: $address, rootVersion: $root_version)]
137 owner: Option<Owner>,
138}
139
140#[derive(cynic::QueryFragment, Debug)]
141#[cynic(variables = "QueryVariables")]
142struct Owner {
143 #[arguments(first: $first, after: $after)]
144 dynamic_fields: DynamicFieldConnection,
145}
146
147#[derive(cynic::QueryFragment, Debug)]
148struct MoveObject {
149 #[cynic(rename = "address")]
150 object_id: SuiAddress,
151 version: af_sui_types::Version,
152 contents: Option<MoveValueRaw>,
153}
154
155#[derive(cynic::QueryFragment, Debug)]
156struct DynamicFieldConnection {
157 nodes: Vec<DynamicField>,
158 page_info: PageInfo,
159}
160
161#[derive(cynic::QueryFragment, Debug)]
162struct PageInfo {
163 has_next_page: bool,
164 end_cursor: Option<String>,
165}
166
167#[derive(cynic::QueryFragment, Debug)]
168struct DynamicField {
169 name: Option<MoveValueRaw>,
170 value: Option<DynamicFieldValue>,
171}
172
173#[derive(cynic::InlineFragments, Debug)]
174enum DynamicFieldValue {
175 MoveObject(MoveObject),
176 MoveValue(MoveValueRaw),
177 #[cynic(fallback)]
178 Unknown,
179}