Skip to main content

iota_data_ingestion/
common.rs

1// Copyright (c) 2025 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use std::ops::Range;
5
6use iota_grpc_client::{Client, ReadMask, read_mask_fields::EpochField};
7use iota_types::{committee::EpochId, messages_checkpoint::CheckpointSequenceNumber};
8
9/// Gets epoch id and its first checkpoint sequence number.
10///
11/// if `None`, returns the current epoch.
12pub async fn epoch_info(
13    client: &Client,
14    epoch_id: Option<EpochId>,
15) -> anyhow::Result<(EpochId, CheckpointSequenceNumber)> {
16    let epoch = client
17        .get_epoch(
18            epoch_id,
19            Some(ReadMask::from(&[
20                EpochField::EPOCH,
21                EpochField::FIRST_CHECKPOINT,
22            ])),
23        )
24        .await
25        .map_err(anyhow::Error::new)?
26        .into_inner();
27
28    epoch
29        .epoch_id()
30        .and_then(|epoch_id| {
31            epoch
32                .first_checkpoint_sequence_number()
33                .map(|ch| (epoch_id, ch))
34        })
35        .map_err(Into::into)
36}
37
38/// Get the range of [`CheckpointSequenceNumber`] from the first checkpoint of
39/// the epoch containing the watermark up to but not including the watermark.
40pub async fn checkpoint_sequence_number_range_to_watermark(
41    client: &Client,
42    watermark: CheckpointSequenceNumber,
43) -> anyhow::Result<Range<CheckpointSequenceNumber>> {
44    let chk = client
45        .get_checkpoint_by_sequence_number(watermark, None, None, None)
46        .await?
47        .into_inner();
48
49    let epoch_id = chk.summary()?.summary()?.epoch;
50    let (_, epoch_first_checkpoint_seq_num) = epoch_info(client, Some(epoch_id)).await?;
51    Ok(epoch_first_checkpoint_seq_num..watermark)
52}