Skip to main content

sui_gql_client/queries/
object_dof_by_name.rs

1use 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}