sui_gql_client/queries/
owner_df_contents.rsuse std::collections::HashMap;
use af_sui_types::{Address as SuiAddress, ObjectId};
use super::fragments::MoveValueRaw;
use super::outputs::{DynamicField as OutputDf, ObjectKey, RawMoveValue};
use super::Error;
use crate::{missing_data, schema, GraphQlClient, GraphQlResponseExt as _};
pub async fn query<C: GraphQlClient>(
client: &C,
address: SuiAddress,
root_version: Option<u64>,
first: Option<i32>,
after: Option<String>,
) -> Result<(HashMap<RawMoveValue, OutputDf>, Option<String>), Error<C::Error>> {
let vars = QueryVariables {
address,
root_version,
first,
after,
};
let data = client
.query::<Query, QueryVariables>(vars)
.await
.map_err(Error::Client)?
.try_into_data()?
.ok_or(missing_data!("Response empty"))?;
let DynamicFieldConnection { nodes, page_info } = data
.owner
.ok_or(missing_data!("No owner found"))?
.dynamic_fields;
let next_cursor = if page_info.has_next_page {
page_info.end_cursor
} else {
None
};
let mut df_map = HashMap::new();
for DynamicField { name, value } in nodes {
let name = name
.ok_or(missing_data!("Dynamic field found but with no name"))?
.into();
let instance = value.ok_or(missing_data!("Dynamic field found but with no value"))?;
let out = match instance {
DynamicFieldValue::MoveObject(MoveObject {
object_id,
version,
contents,
}) => {
let struct_ = contents
.ok_or(missing_data!("No contents for DOF"))?
.try_into()
.expect("Only Move structs can be top-level objects");
OutputDf::Object(ObjectKey { object_id, version }, struct_)
}
DynamicFieldValue::MoveValue(value) => OutputDf::Field(value.into()),
DynamicFieldValue::Unknown => return Err(missing_data!("Unknown dynamic field type")),
};
df_map.insert(name, out);
}
Ok((df_map, next_cursor))
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
#[test]
fn gql_output() {
use cynic::QueryBuilder as _;
let vars = QueryVariables {
address: SuiAddress::new(rand::random()),
root_version: None,
first: None,
after: None,
};
let operation = Query::build(vars);
insta::assert_snapshot!(operation.query);
}
#[derive(cynic::QueryVariables, Debug)]
struct QueryVariables {
address: SuiAddress,
root_version: Option<af_sui_types::Version>,
after: Option<String>,
first: Option<i32>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(variables = "QueryVariables")]
struct Query {
#[arguments(address: $address, rootVersion: $root_version)]
owner: Option<Owner>,
}
#[derive(cynic::QueryFragment, Debug)]
#[cynic(variables = "QueryVariables")]
struct Owner {
#[arguments(first: $first, after: $after)]
dynamic_fields: DynamicFieldConnection,
}
#[derive(cynic::QueryFragment, Debug)]
struct MoveObject {
#[cynic(rename = "address")]
object_id: ObjectId,
version: af_sui_types::Version,
contents: Option<MoveValueRaw>,
}
#[derive(cynic::QueryFragment, Debug)]
struct DynamicFieldConnection {
nodes: Vec<DynamicField>,
page_info: PageInfo,
}
#[derive(cynic::QueryFragment, Debug)]
struct PageInfo {
has_next_page: bool,
end_cursor: Option<String>,
}
#[derive(cynic::QueryFragment, Debug)]
struct DynamicField {
name: Option<MoveValueRaw>,
value: Option<DynamicFieldValue>,
}
#[derive(cynic::InlineFragments, Debug)]
enum DynamicFieldValue {
MoveObject(MoveObject),
MoveValue(MoveValueRaw),
#[cynic(fallback)]
Unknown,
}