iota_grpc_api/client/
checkpoint.rs1use futures::{Stream, StreamExt};
5use iota_grpc_types::{CertifiedCheckpointSummary, CheckpointData};
6use tonic::transport::Channel;
7
8use crate::checkpoint::checkpoint_service_client::CheckpointServiceClient;
9
10#[derive(Debug, Clone)]
12pub enum CheckpointContent {
13 Data(CheckpointData),
14 Summary(CertifiedCheckpointSummary),
15}
16
17#[derive(Clone)]
22pub struct CheckpointClient {
23 client: CheckpointServiceClient<Channel>,
24}
25
26impl CheckpointClient {
27 pub(super) fn new(channel: Channel) -> Self {
29 Self {
30 client: CheckpointServiceClient::new(channel),
31 }
32 }
33
34 pub async fn stream_checkpoints(
44 &mut self,
45 start_sequence_number: Option<u64>,
46 end_sequence_number: Option<u64>,
47 full: bool,
48 ) -> Result<impl Stream<Item = Result<CheckpointContent, tonic::Status>>, tonic::Status> {
49 let request = crate::checkpoint::CheckpointStreamRequest {
50 start_sequence_number,
51 end_sequence_number,
52 full,
53 };
54 let stream = self.client.stream_checkpoints(request).await?.into_inner();
55
56 Ok(stream.map(|result| {
57 result.and_then(|checkpoint| {
58 Self::deserialize_checkpoint(&checkpoint).map_err(|e| {
59 tonic::Status::internal(format!("Failed to deserialize checkpoint: {e}"))
60 })
61 })
62 }))
63 }
64
65 pub async fn get_epoch_first_checkpoint_sequence_number(
67 &mut self,
68 epoch: u64,
69 ) -> Result<u64, tonic::Status> {
70 let request = crate::checkpoint::EpochRequest { epoch };
71 let response = self
72 .client
73 .get_epoch_first_checkpoint_sequence_number(request)
74 .await?;
75 Ok(response.into_inner().sequence_number)
76 }
77
78 fn deserialize_checkpoint(
86 checkpoint: &crate::checkpoint::Checkpoint,
87 ) -> anyhow::Result<CheckpointContent> {
88 let bcs_data = checkpoint
89 .bcs_data
90 .as_ref()
91 .ok_or_else(|| anyhow::anyhow!("Missing BCS data in checkpoint"))?;
92
93 if checkpoint.is_full {
94 let checkpoint_data = bcs_data.deserialize_into::<CheckpointData>()?;
95 Ok(CheckpointContent::Data(checkpoint_data))
96 } else {
97 let checkpoint_summary = bcs_data.deserialize_into::<CertifiedCheckpointSummary>()?;
98 Ok(CheckpointContent::Summary(checkpoint_summary))
99 }
100 }
101}