iota_indexer/apis/
write_api.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use async_trait::async_trait;
6use fastcrypto::encoding::Base64;
7use iota_json_rpc::IotaRpcModule;
8use iota_json_rpc_api::{WriteApiClient, WriteApiServer, error_object_from_rpc};
9use iota_json_rpc_types::{
10    DevInspectArgs, DevInspectResults, DryRunTransactionBlockResponse,
11    IotaTransactionBlockResponse, IotaTransactionBlockResponseOptions,
12};
13use iota_open_rpc::Module;
14use iota_types::{
15    base_types::IotaAddress, iota_serde::BigInt, quorum_driver_types::ExecuteTransactionRequestType,
16};
17use jsonrpsee::{RpcModule, core::RpcResult, http_client::HttpClient};
18
19use crate::{
20    optimistic_indexing::OptimisticTransactionExecutor,
21    types::IotaTransactionBlockResponseWithOptions,
22};
23
24pub(crate) struct WriteApi {
25    fullnode: HttpClient,
26}
27
28pub(crate) struct OptimisticWriteApi {
29    write_api: WriteApi,
30    optimistic_tx_executor: OptimisticTransactionExecutor,
31}
32
33impl WriteApi {
34    pub fn new(fullnode_client: HttpClient) -> Self {
35        Self {
36            fullnode: fullnode_client,
37        }
38    }
39}
40
41impl OptimisticWriteApi {
42    pub fn new(write_api: WriteApi, optimistic_tx_executor: OptimisticTransactionExecutor) -> Self {
43        Self {
44            write_api,
45            optimistic_tx_executor,
46        }
47    }
48}
49
50#[async_trait]
51impl WriteApiServer for WriteApi {
52    async fn execute_transaction_block(
53        &self,
54        tx_bytes: Base64,
55        signatures: Vec<Base64>,
56        options: Option<IotaTransactionBlockResponseOptions>,
57        request_type: Option<ExecuteTransactionRequestType>,
58    ) -> RpcResult<IotaTransactionBlockResponse> {
59        let iota_transaction_response = self
60            .fullnode
61            .execute_transaction_block(tx_bytes, signatures, options.clone(), request_type)
62            .await
63            .map_err(error_object_from_rpc)?;
64        Ok(IotaTransactionBlockResponseWithOptions {
65            response: iota_transaction_response,
66            options: options.unwrap_or_default(),
67        }
68        .into())
69    }
70
71    async fn dev_inspect_transaction_block(
72        &self,
73        sender_address: IotaAddress,
74        tx_bytes: Base64,
75        gas_price: Option<BigInt<u64>>,
76        epoch: Option<BigInt<u64>>,
77        additional_args: Option<DevInspectArgs>,
78    ) -> RpcResult<DevInspectResults> {
79        self.fullnode
80            .dev_inspect_transaction_block(
81                sender_address,
82                tx_bytes,
83                gas_price,
84                epoch,
85                additional_args,
86            )
87            .await
88            .map_err(error_object_from_rpc)
89    }
90
91    async fn dry_run_transaction_block(
92        &self,
93        tx_bytes: Base64,
94    ) -> RpcResult<DryRunTransactionBlockResponse> {
95        self.fullnode
96            .dry_run_transaction_block(tx_bytes)
97            .await
98            .map_err(error_object_from_rpc)
99    }
100}
101
102#[async_trait]
103impl WriteApiServer for OptimisticWriteApi {
104    async fn execute_transaction_block(
105        &self,
106        tx_bytes: Base64,
107        signatures: Vec<Base64>,
108        options: Option<IotaTransactionBlockResponseOptions>,
109        _request_type: Option<ExecuteTransactionRequestType>,
110    ) -> RpcResult<IotaTransactionBlockResponse> {
111        let iota_transaction_response = self
112            .optimistic_tx_executor
113            .execute_and_index_transaction(tx_bytes, signatures, options.clone())
114            .await?;
115        Ok(IotaTransactionBlockResponseWithOptions {
116            response: iota_transaction_response,
117            options: options.unwrap_or_default(),
118        }
119        .into())
120    }
121
122    async fn dev_inspect_transaction_block(
123        &self,
124        sender_address: IotaAddress,
125        tx_bytes: Base64,
126        gas_price: Option<BigInt<u64>>,
127        epoch: Option<BigInt<u64>>,
128        additional_args: Option<DevInspectArgs>,
129    ) -> RpcResult<DevInspectResults> {
130        self.write_api
131            .dev_inspect_transaction_block(
132                sender_address,
133                tx_bytes,
134                gas_price,
135                epoch,
136                additional_args,
137            )
138            .await
139    }
140
141    async fn dry_run_transaction_block(
142        &self,
143        tx_bytes: Base64,
144    ) -> RpcResult<DryRunTransactionBlockResponse> {
145        self.write_api.dry_run_transaction_block(tx_bytes).await
146    }
147}
148
149impl IotaRpcModule for WriteApi {
150    fn rpc(self) -> RpcModule<Self> {
151        self.into_rpc()
152    }
153
154    fn rpc_doc_module() -> Module {
155        iota_json_rpc_api::WriteApiOpenRpc::module_doc()
156    }
157}
158
159impl IotaRpcModule for OptimisticWriteApi {
160    fn rpc(self) -> RpcModule<Self> {
161        self.into_rpc()
162    }
163
164    fn rpc_doc_module() -> Module {
165        iota_json_rpc_api::WriteApiOpenRpc::module_doc()
166    }
167}