diff --git a/CHANGELOG.md b/CHANGELOG.md index 94f244a048..7cb8ae67a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## Next release - chore: remove crates that have been copy-pasted from plkdtSDK +- fix: Wait for 1 minute for transaction to be processed in + get_transaction_receipt rpc - ci: Fix starknet foundry sncast not found - fix: Ensure transaction checks are compatible with starknet-rs - ci: Run Starknet Foundry tests against Madara RPC diff --git a/Cargo.lock b/Cargo.lock index c0eb2942ef..a74ac0d8d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6682,6 +6682,7 @@ dependencies = [ "starknet-ff", "starknet_api", "thiserror", + "tokio", ] [[package]] diff --git a/crates/client/rpc-core/src/lib.rs b/crates/client/rpc-core/src/lib.rs index d35b0b718f..efaacba4ae 100644 --- a/crates/client/rpc-core/src/lib.rs +++ b/crates/client/rpc-core/src/lib.rs @@ -134,5 +134,8 @@ pub trait StarknetRpcApi { /// Returns the receipt of a transaction by transaction hash. #[method(name = "getTransactionReceipt")] - fn get_transaction_receipt(&self, transaction_hash: FieldElement) -> RpcResult; + async fn get_transaction_receipt( + &self, + transaction_hash: FieldElement, + ) -> RpcResult; } diff --git a/crates/client/rpc/Cargo.toml b/crates/client/rpc/Cargo.toml index f06525a1c5..1a2542f1cc 100644 --- a/crates/client/rpc/Cargo.toml +++ b/crates/client/rpc/Cargo.toml @@ -53,6 +53,7 @@ mp-hashers = { workspace = true } mp-transactions = { workspace = true, features = ["client"] } serde_json = { workspace = true, default-features = true } thiserror = { workspace = true } +tokio = { workspace = true, default-features = true, features = ["time"] } [dev-dependencies] rstest = { workspace = true } diff --git a/crates/client/rpc/src/lib.rs b/crates/client/rpc/src/lib.rs index 18adec8113..e8a30c97f8 100644 --- a/crates/client/rpc/src/lib.rs +++ b/crates/client/rpc/src/lib.rs @@ -14,6 +14,7 @@ use std::sync::Arc; use errors::StarknetRpcApiError; use jsonrpsee::core::{async_trait, RpcResult}; use log::error; +use mc_db::Backend as MadaraBackend; pub use mc_rpc_core::utils::*; use mc_rpc_core::Felt; pub use mc_rpc_core::StarknetRpcApiServer; @@ -887,24 +888,53 @@ where /// # Arguments /// /// * `transaction_hash` - Transaction hash corresponding to the transaction. - fn get_transaction_receipt(&self, transaction_hash: FieldElement) -> RpcResult { - let block_hash_from_db = self - .backend - .mapping() - .block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be())) - .map_err(|e| { - error!("Failed to get transaction's substrate block hash from mapping_db: {e}"); - StarknetRpcApiError::TxnHashNotFound - })?; + async fn get_transaction_receipt( + &self, + transaction_hash: FieldElement, + ) -> RpcResult { + async fn wait_for_tx_inclusion( + madara_backend: Arc>, + transaction_hash: FieldElement, + ) -> Result<::Hash, StarknetRpcApiError> { + let substrate_block_hash; + + loop { + let block_hash_from_db = madara_backend + .mapping() + .block_hash_from_transaction_hash(H256::from(transaction_hash.to_bytes_be())) + .map_err(|e| { + error!("Failed to interact with db backend error: {e}"); + StarknetRpcApiError::InternalServerError + })?; + + match block_hash_from_db { + Some(block_hash) => { + substrate_block_hash = block_hash; + break; + } + None => { + // TODO: hardcoded to match the blocktime; make it dynamic + tokio::time::sleep(std::time::Duration::from_millis(6000)).await; + continue; + } + }; + } - let substrate_block_hash = match block_hash_from_db { - Some(block_hash) => block_hash, - None => { - // If the transaction is still in the pool, the receipt - // is not available, thus considered as not found. + Ok(substrate_block_hash) + } + + let substrate_block_hash = match tokio::time::timeout( + std::time::Duration::from_millis(60000), + wait_for_tx_inclusion(self.backend.clone(), transaction_hash), + ) + .await + { + Err(_) => { + error!("did not receive tx hash within 1 minute"); return Err(StarknetRpcApiError::TxnHashNotFound.into()); } - }; + Ok(res) => res, + }?; let block: mp_block::Block = get_block_by_block_hash(self.client.as_ref(), substrate_block_hash).unwrap_or_default(); @@ -920,6 +950,7 @@ where StarknetRpcApiError::InternalServerError })? .ok_or(StarknetRpcApiError::BlockNotFound)?; + let chain_id = self.chain_id()?.0.into(); let (tx_type, events) = self