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_MIN_INTERVAL: Duration = Duration::from_millis(100);
21const WAIT_FOR_LOCAL_EXECUTION_MAX_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 let mut backoff = iota_common::backoff::ExponentialBackoff::new(
75 WAIT_FOR_LOCAL_EXECUTION_MIN_INTERVAL,
76 WAIT_FOR_LOCAL_EXECUTION_MAX_INTERVAL,
77 );
78 loop {
79 tokio::time::sleep(backoff.next().unwrap()).await;
84
85 if let Ok(poll_response) = self
86 .api
87 .http
88 .get_transaction_block(*tx.digest(), Some(options.clone()))
89 .await
90 {
91 break poll_response;
92 }
93 }
94 })
95 .await
96 .map_err(|_| {
97 Error::FailToConfirmTransactionStatus(*tx.digest(), start.elapsed().as_secs())
98 })?;
99
100 poll_response.confirmed_local_execution = Some(true);
101 Ok(poll_response)
102 }
103}