1use axum::extract::State;
5use axum::{Extension, Json};
6use axum_extra::extract::WithRejection;
7use prost_types::FieldMask;
8use sui_rpc::field::FieldMaskUtil;
9use sui_rpc::proto::sui::rpc::v2::GetTransactionRequest;
10use tracing::debug;
11
12use crate::operations::Operations;
13use crate::types::{
14 BlockRequest, BlockResponse, BlockTransactionRequest, BlockTransactionResponse, Transaction,
15 TransactionIdentifier,
16};
17use crate::{Error, OnlineServerContext, SuiEnv};
18
19pub async fn block(
24 State(state): State<OnlineServerContext>,
25 Extension(env): Extension<SuiEnv>,
26 WithRejection(Json(request), _): WithRejection<Json<BlockRequest>, Error>,
27) -> Result<BlockResponse, Error> {
28 debug!("Called /block endpoint: {:?}", request.block_identifier);
29 env.check_network_identifier(&request.network_identifier)?;
30 let blocks = state.blocks();
31 if let Some(index) = request.block_identifier.index {
32 blocks.get_block_by_index(index).await
33 } else if let Some(hash) = request.block_identifier.hash {
34 blocks.get_block_by_hash(hash).await
35 } else {
36 blocks.current_block().await
37 }
38}
39
40pub async fn transaction(
43 State(context): State<OnlineServerContext>,
44 Extension(env): Extension<SuiEnv>,
45 WithRejection(Json(request), _): WithRejection<Json<BlockTransactionRequest>, Error>,
46) -> Result<BlockTransactionResponse, Error> {
47 env.check_network_identifier(&request.network_identifier)?;
48 let digest = request.transaction_identifier.hash;
49
50 let request = GetTransactionRequest::default()
51 .with_digest(digest.to_string())
52 .with_read_mask(FieldMask::from_paths([
53 "digest",
54 "transaction.sender",
55 "transaction.gas_payment",
56 "transaction.kind",
57 "effects.gas_object",
58 "effects.gas_used",
59 "effects.status",
60 "balance_changes",
61 "events.events.event_type",
62 "events.events.json",
63 "events.events.contents",
64 ]));
65
66 let mut client = context.client.clone();
67 let response = client
68 .ledger_client()
69 .get_transaction(request)
70 .await?
71 .into_inner();
72
73 let operations = Operations::try_from_executed_transaction(
74 response
75 .transaction
76 .ok_or_else(|| Error::DataError("Response missing transaction".to_string()))?,
77 &context.coin_metadata_cache,
78 )
79 .await?;
80
81 let transaction = Transaction {
82 transaction_identifier: TransactionIdentifier { hash: digest },
83 operations,
84 related_transactions: vec![],
85 metadata: None,
86 };
87
88 Ok(BlockTransactionResponse { transaction })
89}