af_iperps/graphql/
ch_vault.rs1use af_move_type::{FromRawStructError, MoveInstance};
2use af_sui_types::{Address, ObjectId};
3use enum_as_inner::EnumAsInner;
4use sui_gql_client::queries::Error as QueryError;
5use sui_gql_client::queries::fragments::{DynamicFieldName, MoveValueRaw};
6use sui_gql_client::queries::outputs::RawMoveStruct;
7use sui_gql_client::{GraphQlClient, GraphQlResponseExt, schema};
8
9use crate::keys;
10
11#[derive(thiserror::Error, Debug)]
12pub enum Error<C: std::error::Error> {
13 #[error(transparent)]
14 Query(#[from] QueryError<C>),
15 #[error("Deserializing Vault instance: {0}")]
16 ToVault(#[from] FromRawStructError),
17}
18
19type Vault = MoveInstance<crate::Vault>;
20
21pub(super) async fn query<C: GraphQlClient>(
22 client: &C,
23 package: Address,
24 ch: ObjectId,
25) -> Result<Vault, Error<C::Error>> {
26 let raw = request(client, package, ch).await?;
27 Ok(raw.try_into()?)
28}
29
30async fn request<C: GraphQlClient>(
31 client: &C,
32 package: Address,
33 ch: ObjectId,
34) -> Result<RawMoveStruct, QueryError<C::Error>> {
35 let vars = Variables {
36 ch,
37 vault: keys::MarketVault::new()
38 .move_instance(package)
39 .try_into()
40 .expect("BCS-serializable"),
41 };
42 let data = client
43 .query::<Query, _>(vars)
44 .await
45 .map_err(QueryError::Client)?
46 .try_into_data()?;
47 Ok(extract(data)?)
48}
49
50fn extract(data: Option<Query>) -> Result<RawMoveStruct, &'static str> {
51 graphql_extract::extract!(data => {
52 ch? {
53 vault? {
54 value? {
55 ... on VaultDfValue::MoveValue {
56 type_
57 bcs
58 }
59 }
60 }
61 }
62 });
63 let move_value = MoveValueRaw { type_, bcs };
64 Ok(move_value.try_into().expect("Vault is a struct"))
65}
66
67#[cfg(test)]
68#[allow(clippy::unwrap_used)]
69#[test]
70fn gql_output() {
71 use cynic::QueryBuilder as _;
72
73 let package = Address::ZERO;
74 let vars = Variables {
75 ch: ObjectId::ZERO,
76 vault: keys::MarketVault::new()
77 .move_instance(package)
78 .try_into()
79 .unwrap(),
80 };
81 let operation = Query::build(vars);
82 insta::assert_snapshot!(operation.query, @r###"
83 query Query($ch: SuiAddress!, $vault: DynamicFieldName!) {
84 ch: object(address: $ch) {
85 vault: dynamicField(name: $vault) {
86 value {
87 __typename
88 ... on MoveValue {
89 type {
90 repr
91 }
92 bcs
93 }
94 }
95 }
96 }
97 }
98 "###);
99}
100
101#[derive(cynic::QueryVariables, Debug)]
102struct Variables {
103 ch: ObjectId,
104 vault: DynamicFieldName,
105}
106
107#[derive(cynic::QueryFragment, Debug)]
108#[cynic(graphql_type = "Query", variables = "Variables")]
109struct Query {
110 #[arguments(address: $ch)]
111 #[cynic(alias, rename = "object")]
112 ch: Option<ClearingHouseObject>,
113}
114
115#[derive(cynic::QueryFragment, Debug)]
116#[cynic(graphql_type = "Object", variables = "Variables")]
117struct ClearingHouseObject {
118 #[arguments(name: $vault)]
119 #[cynic(alias, rename = "dynamicField")]
120 vault: Option<VaultDf>,
121}
122
123#[derive(cynic::QueryFragment, Debug)]
124#[cynic(graphql_type = "DynamicField")]
125struct VaultDf {
126 value: Option<VaultDfValue>,
127}
128
129#[derive(cynic::InlineFragments, Debug, EnumAsInner)]
130#[cynic(graphql_type = "DynamicFieldValue")]
131enum VaultDfValue {
132 MoveValue(MoveValueRaw),
133 #[cynic(fallback)]
134 Unknown,
135}