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