iota_sdk/apis/
quorum_driver.rs1use std::{
6 sync::Arc,
7 time::{Duration, Instant},
8};
9
10use iota_json_rpc_api::{ReadApiClient, WriteApiClient};
11use iota_json_rpc_types::{IotaTransactionBlockResponse, IotaTransactionBlockResponseOptions};
12use iota_types::{quorum_driver_types::ExecuteTransactionRequestType, transaction::Transaction};
13
14use crate::{
15 RpcClient,
16 error::{Error, IotaRpcResult},
17};
18
19const WAIT_FOR_LOCAL_EXECUTION_TIMEOUT: Duration = Duration::from_secs(60);
20const WAIT_FOR_LOCAL_EXECUTION_DELAY: Duration = Duration::from_millis(200);
21const WAIT_FOR_LOCAL_EXECUTION_INTERVAL: Duration = Duration::from_secs(2);
22
23#[derive(Clone)]
25pub struct QuorumDriverApi {
26 api: Arc<RpcClient>,
27}
28
29impl QuorumDriverApi {
30 pub(crate) fn new(api: Arc<RpcClient>) -> Self {
31 Self { api }
32 }
33
34 pub async fn execute_transaction_block(
43 &self,
44 tx: Transaction,
45 options: IotaTransactionBlockResponseOptions,
46 request_type: impl Into<Option<ExecuteTransactionRequestType>>,
47 ) -> IotaRpcResult<IotaTransactionBlockResponse> {
48 let (tx_bytes, signatures) = tx.to_tx_bytes_and_signatures();
49 let request_type = request_type
50 .into()
51 .unwrap_or_else(|| options.default_execution_request_type());
52
53 let start = Instant::now();
54 let response = self
55 .api
56 .http
57 .execute_transaction_block(
58 tx_bytes.clone(),
59 signatures.clone(),
60 Some(options.clone()),
61 None,
64 )
65 .await?;
66
67 if let ExecuteTransactionRequestType::WaitForEffectsCert = request_type {
68 return Ok(response);
69 }
70
71 let mut poll_response = tokio::time::timeout(WAIT_FOR_LOCAL_EXECUTION_TIMEOUT, async {
74 tokio::time::sleep(WAIT_FOR_LOCAL_EXECUTION_DELAY).await;
76
77 let mut interval = tokio::time::interval(WAIT_FOR_LOCAL_EXECUTION_INTERVAL);
78 loop {
79 interval.tick().await;
80
81 if let Ok(poll_response) = self
82 .api
83 .http
84 .get_transaction_block(*tx.digest(), Some(options.clone()))
85 .await
86 {
87 break poll_response;
88 }
89 }
90 })
91 .await
92 .map_err(|_| {
93 Error::FailToConfirmTransactionStatus(*tx.digest(), start.elapsed().as_secs())
94 })?;
95
96 poll_response.confirmed_local_execution = Some(true);
97 Ok(poll_response)
98 }
99}