Skip to content

Commit

Permalink
Fix dynamic fields
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan-mysten committed Oct 17, 2024
1 parent fbc7748 commit 307cde4
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 27 deletions.
86 changes: 62 additions & 24 deletions crates/sui-graphql-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use query_types::TransactionMetadata;
use query_types::TransactionsFilter;
use query_types::Validator;

use serde::de::DeserializeOwned;
use serde::Serialize;
use sui_types::types::framework::Coin;
use sui_types::types::Address;
Expand Down Expand Up @@ -104,6 +105,7 @@ pub struct DynamicFieldName {
pub struct DynamicFieldOutput {
pub name: DynamicFieldName,
pub json: Option<serde_json::Value>,
pub value: Option<(String, Vec<u8>)>,
}

/// Helper struct for passing a value that has a type that implements Serialize, for the dynamic
Expand Down Expand Up @@ -149,6 +151,13 @@ impl From<BcsName> for Name {
}
}

impl DynamicFieldOutput {
pub fn deserialize<T: DeserializeOwned>(&self) -> Result<T, anyhow::Error> {
let bcs = &self.name.bcs;
bcs::from_bytes::<T>(&bcs).map_err(|_| anyhow!("Cannot decode BCS bytes"))
}
}

/// The GraphQL client for interacting with the Sui blockchain.
/// By default, it uses the `reqwest` crate as the HTTP client.
pub struct Client {
Expand Down Expand Up @@ -878,33 +887,62 @@ impl Client {
}
}

/// Return the contents JSON of an object that is a Move object.
/// Return the contents' JSON of an object that is a Move object.
///
/// If the object does not exist (e.g., due to prunning), this will return `Ok(None)`.
/// Similarly, if this is not an object but an address, it will return `Ok(None)`.
// pub async fn object_move_contents(
// &self,
// address: Address,
// version: Option<u64>,
// ) -> Result<Option<serde_json::Value>, Error> {
// let operation = ObjectQuery::build(ObjectQueryArgs { address, version });
//
// let response = self.run_query(&operation).await?;
//
// if let Some(errors) = response.errors {
// return Err(Error::msg(format!("{:?}", errors)));
// }
//
// if let Some(object) = response.data {
// Ok(object
// .object
// .and_then(|o| o.as_move_object)
// .and_then(|o| o.contents)
// .and_then(|mv| mv.json))
// } else {
// Ok(None)
// }
// }
pub async fn object_move_contents(
&self,
address: Address,
version: Option<u64>,
) -> Result<Option<serde_json::Value>, Error> {
let operation = ObjectQuery::build(ObjectQueryArgs { address, version });

let response = self.run_query(&operation).await?;

if let Some(errors) = response.errors {
return Err(Error::msg(format!("{:?}", errors)));
}

if let Some(object) = response.data {
Ok(object
.object
.and_then(|o| o.as_move_object)
.and_then(|o| o.contents)
.and_then(|mv| mv.json))
} else {
Ok(None)
}
}
/// Return the BCS of an object that is a Move object.
///
/// If the object does not exist (e.g., due to prunning), this will return `Ok(None)`.
/// Similarly, if this is not an object but an address, it will return `Ok(None)`.
pub async fn object_move_contents_bcs(
&self,
address: Address,
version: Option<u64>,
) -> Result<Option<Vec<u8>>, Error> {
let operation = ObjectQuery::build(ObjectQueryArgs { address, version });

let response = self.run_query(&operation).await?;

if let Some(errors) = response.errors {
return Err(Error::msg(format!("{:?}", errors)));
}

if let Some(object) = response.data {
object
.object
.and_then(|o| o.as_move_object)
.and_then(|o| o.contents)
.map(|bcs| base64ct::Base64::decode_vec(bcs.bcs.0.as_str()))
.transpose()
.map_err(|e| Error::msg(format!("Cannot decode Base64 object bcs bytes: {e}")))
} else {
Ok(None)
}
}

// ===========================================================================
// Dry Run API
Expand Down
18 changes: 17 additions & 1 deletion crates/sui-graphql-client/src/query_types/dynamic_fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,22 @@ impl DynamicFieldValue {
_ => None,
}
}

pub fn type_bcs(&self) -> Option<(String, Vec<u8>)> {
match self {
DynamicFieldValue::MoveObject(mo) => Some((
mo.contents.as_ref().unwrap().__typename.clone(),
mo.contents.as_ref().unwrap().bcs.0.clone().into(),
// base64ct::Base64::decode_vec(mo.contents.as_ref().unwrap().bcs.0.as_ref()).unwrap(),
)),
DynamicFieldValue::MoveValue(mv) => Some((
mv.__typename.clone(),
mv.bcs.0.clone().into(),
// base64ct::Base64::decode_vec(mv.bcs.0.as_ref()).unwrap(),
)),
_ => None,
}
}
}

impl DynamicField {
Expand Down Expand Up @@ -157,8 +173,8 @@ impl From<DynamicField> for DynamicFieldOutput {
.unwrap(),
json: val.name.as_ref().unwrap().json.clone(),
},
// object,
json: val.field_value_json(),
value: val.value.and_then(|x| x.type_bcs()),
}
}
}
4 changes: 2 additions & 2 deletions crates/sui-graphql-client/src/query_types/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::query_types::schema;
use crate::query_types::Address;
use crate::query_types::Base64;
use crate::query_types::MoveObject;
use crate::query_types::MoveObjectContents;
use crate::query_types::PageInfo;

// ===========================================================================
Expand Down Expand Up @@ -51,7 +51,7 @@ pub struct ObjectsQueryArgs<'a> {
#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema = "rpc", graphql_type = "Object")]
pub struct Object {
pub as_move_object: Option<MoveObject>,
pub as_move_object: Option<MoveObjectContents>,
pub bcs: Option<Base64>,
}

Expand Down

0 comments on commit 307cde4

Please sign in to comment.