sui_indexer_alt_framework/ingestion/
rpc_client.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use anyhow::anyhow;
5use async_trait::async_trait;
6use prost_types::FieldMask;
7use std::str::FromStr;
8use sui_rpc::Client as RpcClient;
9use sui_rpc::field::FieldMaskUtil;
10use sui_rpc::proto::sui::rpc::v2::GetCheckpointRequest;
11use sui_rpc::proto::sui::rpc::v2::GetServiceInfoRequest;
12use sui_types::digests::ChainIdentifier;
13use sui_types::digests::CheckpointDigest;
14use sui_types::full_checkpoint_content::Checkpoint;
15use tonic::Code;
16
17use crate::ingestion::ingestion_client::CheckpointData;
18use crate::ingestion::ingestion_client::CheckpointError;
19use crate::ingestion::ingestion_client::CheckpointResult;
20use crate::ingestion::ingestion_client::IngestionClientTrait;
21
22#[async_trait]
23impl IngestionClientTrait for RpcClient {
24    async fn chain_id(&self) -> anyhow::Result<ChainIdentifier> {
25        let request = GetServiceInfoRequest::const_default();
26        let response = self
27            .clone()
28            .ledger_client()
29            .get_service_info(request)
30            .await?
31            .into_inner();
32        Ok(CheckpointDigest::from_str(response.chain_id())?.into())
33    }
34
35    async fn checkpoint(&self, checkpoint: u64) -> CheckpointResult {
36        let request: GetCheckpointRequest = GetCheckpointRequest::by_sequence_number(checkpoint)
37            .with_read_mask(FieldMask::from_paths([
38                "summary.bcs",
39                "signature",
40                "contents.bcs",
41                "transactions.transaction.bcs",
42                "transactions.effects.bcs",
43                "transactions.effects.unchanged_loaded_runtime_objects",
44                "transactions.events.bcs",
45                "objects.objects.bcs",
46            ]));
47
48        let response = self
49            .clone()
50            .ledger_client()
51            .get_checkpoint(request)
52            .await
53            .map_err(|status| match status.code() {
54                Code::NotFound => CheckpointError::NotFound,
55                _ => CheckpointError::Transient {
56                    reason: "get_checkpoint",
57                    error: anyhow!(status),
58                },
59            })?
60            .into_inner();
61
62        let checkpoint = Checkpoint::try_from(response.checkpoint()).map_err(|e| {
63            CheckpointError::Permanent {
64                reason: "proto_conversion",
65                error: e.into(),
66            }
67        })?;
68
69        Ok(CheckpointData::Checkpoint(checkpoint))
70    }
71}