sui_gql_client/queries/
owner_dof_content.rs1use af_sui_types::Address as SuiAddress;
2use cynic::GraphQlResponse;
3
4use super::Error;
5use super::fragments::MoveValueRaw;
6use super::outputs::{ObjectKey, RawMoveStruct, RawMoveValue};
7use crate::{GraphQlClient, GraphQlResponseExt, missing_data, scalars, schema};
8
9pub async fn query<C: GraphQlClient>(
10 client: &C,
11 address: SuiAddress,
12 RawMoveValue {
13 type_: df_name_type,
14 bcs: df_name_bcs,
15 }: RawMoveValue,
16 root_version: Option<u64>,
17) -> Result<(ObjectKey, RawMoveStruct), Error<C::Error>> {
18 let vars = QueryVariables {
19 address,
20 root_version,
21 name: DynamicFieldName {
22 type_: scalars::TypeTag(df_name_type),
23 bcs: scalars::Base64::new(df_name_bcs),
24 },
25 };
26 let result: GraphQlResponse<Query> = client.query(vars).await.map_err(Error::Client)?;
27 let data = result
28 .try_into_data()?
29 .ok_or(missing_data!("Response empty"))?;
30 let df_value = data
31 .owner
32 .ok_or(missing_data!("Owner not found"))?
33 .dynamic_object_field
34 .ok_or(missing_data!("Dynamic object field not found"))?
35 .value
36 .ok_or(missing_data!("No dynamic field value"))?;
37 match df_value {
38 DynamicFieldValue::MoveObject(MoveObject {
39 object_id,
40 version,
41 contents,
42 }) => {
43 let struct_ = contents
44 .ok_or(missing_data!("No contents for DOF"))?
45 .try_into()
46 .expect("Only Move structs can be top-level objects");
47 Ok((ObjectKey { object_id, version }, struct_))
48 }
49 DynamicFieldValue::Unknown => Err(missing_data!("Not a dynamic object field")),
50 }
51}
52
53#[cfg(test)]
54#[allow(clippy::unwrap_used)]
55#[test]
56fn gql_output() {
57 use cynic::QueryBuilder as _;
58 let vars = QueryVariables {
59 address: SuiAddress::new(rand::random()),
60 root_version: None,
61 name: DynamicFieldName {
62 type_: scalars::TypeTag("0x2::sui::SUI".parse().unwrap()),
63 bcs: scalars::Base64::new(vec![]),
64 },
65 };
66 let operation = Query::build(vars);
67 insta::assert_snapshot!(operation.query, @r"
68 query Query($address: SuiAddress!, $name: DynamicFieldName!, $rootVersion: UInt53) {
69 owner(address: $address, rootVersion: $rootVersion) {
70 dynamicObjectField(name: $name) {
71 value {
72 __typename
73 ... on MoveObject {
74 address
75 version
76 contents {
77 type {
78 repr
79 }
80 bcs
81 }
82 }
83 }
84 }
85 }
86 }
87 ");
88}
89
90#[derive(cynic::QueryVariables, Debug)]
95struct QueryVariables {
96 address: SuiAddress,
97 name: DynamicFieldName,
98 root_version: Option<af_sui_types::Version>,
99}
100
101#[derive(cynic::InputObject, Debug)]
102struct DynamicFieldName {
103 #[cynic(rename = "type")]
104 type_: scalars::TypeTag,
105 bcs: scalars::Base64<Vec<u8>>,
106}
107
108#[derive(cynic::QueryFragment, Debug)]
109#[cynic(variables = "QueryVariables")]
110struct Query {
111 #[arguments(address: $address, rootVersion: $root_version)]
112 owner: Option<Owner>,
113}
114
115#[derive(cynic::QueryFragment, Debug)]
116#[cynic(variables = "QueryVariables")]
117struct Owner {
118 #[arguments(name: $name)]
119 dynamic_object_field: Option<_DynamicField>,
120}
121
122#[derive(cynic::QueryFragment, Debug)]
123#[cynic(graphql_type = "DynamicField")]
124struct _DynamicField {
125 value: Option<DynamicFieldValue>,
126}
127
128#[derive(cynic::InlineFragments, Debug)]
129enum DynamicFieldValue {
130 MoveObject(MoveObject),
131 #[cynic(fallback)]
132 Unknown,
133}
134
135#[derive(cynic::QueryFragment, Debug)]
136struct MoveObject {
137 #[cynic(rename = "address")]
138 object_id: SuiAddress,
139 version: af_sui_types::Version,
140 contents: Option<MoveValueRaw>,
141}