Skip to content

Commit

Permalink
sui-graphql-client: add total transaction blocks query (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan-mysten authored Oct 28, 2024
1 parent 89b289b commit 1daf680
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 5 deletions.
97 changes: 95 additions & 2 deletions crates/sui-graphql-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ use serde::de::DeserializeOwned;
use serde::Serialize;
use std::pin::Pin;

use crate::query_types::CheckpointTotalTxQuery;

const MAINNET_HOST: &str = "https://sui-mainnet.mystenlabs.com/graphql";
const TESTNET_HOST: &str = "https://sui-testnet.mystenlabs.com/graphql";
const DEVNET_HOST: &str = "https://sui-devnet.mystenlabs.com/graphql";
Expand Down Expand Up @@ -435,6 +437,62 @@ impl Client {
}
}

/// The total number of transaction blocks in the network by the end of the provided
/// checkpoint digest.
pub async fn total_transaction_blocks_by_digest(
&self,
digest: Digest,
) -> Result<Option<u64>, Error> {
self.internal_total_transaction_blocks(Some(digest.to_string()), None)
.await
}

/// The total number of transaction blocks in the network by the end of the provided checkpoint
/// sequence number.
pub async fn total_transaction_blocks_by_seq_num(
&self,
seq_num: u64,
) -> Result<Option<u64>, Error> {
self.internal_total_transaction_blocks(None, Some(seq_num))
.await
}

/// The total number of transaction blocks in the network by the end of the last known
/// checkpoint.
pub async fn total_transaction_blocks(&self) -> Result<Option<u64>, Error> {
self.internal_total_transaction_blocks(None, None).await
}

/// Internal function to get the total number of transaction blocks based on the provided
/// checkpoint digest or sequence number.
async fn internal_total_transaction_blocks(
&self,
digest: Option<String>,
seq_num: Option<u64>,
) -> Result<Option<u64>, Error> {
ensure!(
!(digest.is_some() && seq_num.is_some()),
"Cannot provide both digest and seq_num."
);

let operation = CheckpointTotalTxQuery::build(CheckpointArgs {
id: CheckpointId {
digest,
sequence_number: seq_num,
},
});
let response = self.run_query(&operation).await?;

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

Ok(response
.data
.and_then(|x| x.checkpoint)
.and_then(|c| c.network_total_transactions))
}

// ===========================================================================
// Balance API
// ===========================================================================
Expand Down Expand Up @@ -571,7 +629,7 @@ impl Client {
/// provided, it will use the last known checkpoint id.
pub async fn checkpoint(
&self,
digest: Option<String>,
digest: Option<Digest>,
seq_num: Option<u64>,
) -> Result<Option<CheckpointSummary>, Error> {
ensure!(
Expand All @@ -581,7 +639,7 @@ impl Client {

let operation = CheckpointQuery::build(CheckpointArgs {
id: CheckpointId {
digest,
digest: digest.map(|d| d.to_string()),
sequence_number: seq_num,
},
});
Expand Down Expand Up @@ -1587,4 +1645,39 @@ mod tests {
dynamic_fields.unwrap_err()
);
}

#[tokio::test]
async fn test_total_transaction_blocks() {
let client = test_client();
let total_transaction_blocks = client.total_transaction_blocks().await;
assert!(
total_transaction_blocks
.as_ref()
.is_ok_and(|f| f.is_some_and(|tx| tx > 0)),
"Total transaction blocks query failed for {} network. Error: {}",
client.rpc_server(),
total_transaction_blocks.unwrap_err()
);

let chckp = client.latest_checkpoint_sequence_number().await;
assert!(
chckp.is_ok(),
"Latest checkpoint sequence number query failed for {} network. Error: {}",
client.rpc_server(),
chckp.unwrap_err()
);
let chckp_id = chckp.unwrap().unwrap();
let total_transaction_blocks = client.total_transaction_blocks_by_seq_num(chckp_id).await;
assert!(total_transaction_blocks.is_ok());
assert!(total_transaction_blocks.unwrap().is_some_and(|tx| tx > 0));

let chckp = client.checkpoint(None, Some(chckp_id)).await;
assert!(chckp.is_ok());
let digest = chckp.unwrap().unwrap().content_digest;
let total_transaction_blocks = client
.total_transaction_blocks_by_digest(digest.into())
.await;
assert!(total_transaction_blocks.is_ok());
assert!(total_transaction_blocks.unwrap().is_some_and(|tx| tx > 0));
}
}
18 changes: 15 additions & 3 deletions crates/sui-graphql-client/src/query_types/checkpoint.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
use std::str::FromStr;

use anyhow::Error;
use chrono::DateTime as ChronoDT;
Expand All @@ -27,6 +26,19 @@ pub struct CheckpointQuery {
pub checkpoint: Option<Checkpoint>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema = "rpc", graphql_type = "Query", variables = "CheckpointArgs")]
pub struct CheckpointTotalTxQuery {
#[arguments(id: $id)]
pub checkpoint: Option<CheckpointTotalTx>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema = "rpc", graphql_type = "Checkpoint")]
pub struct CheckpointTotalTx {
pub network_total_transactions: Option<u64>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(schema = "rpc", graphql_type = "Query", variables = "CheckpointsArgs")]
pub struct CheckpointsQuery {
Expand Down Expand Up @@ -106,10 +118,10 @@ impl TryInto<CheckpointSummary> for Checkpoint {
.map_err(|e| Error::msg(format!("Cannot parse DateTime: {e}")))?
.timestamp_millis()
.try_into()?;
let content_digest = CheckpointContentsDigest::from_str(&self.digest)?;
let content_digest = CheckpointContentsDigest::from_base58(&self.digest)?;
let previous_digest = self
.previous_checkpoint_digest
.map(|d| CheckpointDigest::from_str(&d))
.map(|d| CheckpointDigest::from_base58(&d))
.transpose()?;
let epoch_rolling_gas_cost_summary = self
.rolling_gas_summary
Expand Down
1 change: 1 addition & 0 deletions crates/sui-graphql-client/src/query_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub use chain::ChainIdentifierQuery;
pub use checkpoint::CheckpointArgs;
pub use checkpoint::CheckpointId;
pub use checkpoint::CheckpointQuery;
pub use checkpoint::CheckpointTotalTxQuery;
pub use checkpoint::CheckpointsArgs;
pub use checkpoint::CheckpointsQuery;
pub use coin::CoinMetadata;
Expand Down

0 comments on commit 1daf680

Please sign in to comment.