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