Skip to content

Commit 8233d54

Browse files
committed
feat: add get_messages_status
1 parent 2bbb2c1 commit 8233d54

File tree

21 files changed

+299
-10
lines changed

21 files changed

+299
-10
lines changed

madara/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

madara/crates/client/gateway/server/src/handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ pub async fn handle_get_block_traces(
246246
}
247247

248248
let traces = v0_7_1_trace_block_transactions(
249-
&Starknet::new(backend, add_transaction_provider, Default::default(), None, ctx),
249+
&Starknet::new(backend, add_transaction_provider, Default::default(), None, None, ctx),
250250
block_id,
251251
)
252252
.await?;

madara/crates/client/rpc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ mp-convert = { workspace = true, default-features = true }
3636
mp-gateway = { workspace = true }
3737
mp-receipt = { workspace = true }
3838
mp-rpc = { workspace = true }
39+
mc-settlement-client = { workspace = true }
3940
mp-state-update = { workspace = true }
4041
mp-transactions = { workspace = true }
4142
mp-utils = { workspace = true }

madara/crates/client/rpc/src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod versions;
1313
use jsonrpsee::RpcModule;
1414
use mc_db::db_block_id::DbBlockIdResolvable;
1515
use mc_db::MadaraBackend;
16+
use mc_settlement_client::client::SettlementLayerProvider;
1617
use mc_submit_tx::SubmitTransaction;
1718
use mp_block::{BlockId, BlockTag, MadaraMaybePendingBlock, MadaraMaybePendingBlockInfo};
1819
use mp_chain_config::ChainConfig;
@@ -49,6 +50,7 @@ pub struct Starknet {
4950
pub(crate) add_transaction_provider: Arc<dyn SubmitTransaction>,
5051
storage_proof_config: StorageProofConfig,
5152
pub(crate) block_prod_handle: Option<mc_block_production::BlockProductionHandle>,
53+
pub(crate) settlement_client: Option<Arc<dyn SettlementLayerProvider>>,
5254
pub ctx: ServiceContext,
5355
}
5456

@@ -58,10 +60,19 @@ impl Starknet {
5860
add_transaction_provider: Arc<dyn SubmitTransaction>,
5961
storage_proof_config: StorageProofConfig,
6062
block_prod_handle: Option<mc_block_production::BlockProductionHandle>,
63+
settlement_client: Option<Arc<dyn SettlementLayerProvider>>,
6164
ctx: ServiceContext,
6265
) -> Self {
6366
let ws_handles = Arc::new(WsSubscribeHandles::new());
64-
Self { backend, ws_handles, add_transaction_provider, storage_proof_config, block_prod_handle, ctx }
67+
Self {
68+
backend,
69+
ws_handles,
70+
add_transaction_provider,
71+
storage_proof_config,
72+
block_prod_handle,
73+
settlement_client,
74+
ctx,
75+
}
6576
}
6677

6778
pub fn clone_backend(&self) -> Arc<MadaraBackend> {
@@ -72,6 +83,10 @@ impl Starknet {
7283
Arc::clone(self.backend.chain_config())
7384
}
7485

86+
pub fn settlement_client(&self) -> Option<Arc<dyn SettlementLayerProvider>> {
87+
self.settlement_client.clone()
88+
}
89+
7590
pub fn get_block_info(
7691
&self,
7792
block_id: &impl DbBlockIdResolvable,

madara/crates/client/rpc/src/versions/user/v0_8_1/api.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use jsonrpsee::core::RpcResult;
22
use m_proc_macros::versioned_rpc;
33
use mp_block::BlockId;
4+
use mp_rpc::v0_8_1::{L1TxnHash, TxnHashWithStatus};
45
use starknet_types_core::felt::Felt;
56

67
type SubscriptionItemPendingTxs = super::methods::ws::SubscriptionItem<mp_rpc::v0_8_1::PendingTxnInfo>;
@@ -65,4 +66,7 @@ pub trait StarknetReadRpcApi {
6566
contract_addresses: Option<Vec<Felt>>,
6667
contracts_storage_keys: Option<Vec<mp_rpc::v0_8_1::ContractStorageKeysItem>>,
6768
) -> RpcResult<mp_rpc::v0_8_1::GetStorageProofResult>;
69+
70+
#[method(name = "getMessagesStatus")]
71+
async fn get_messages_status(&self, tx_hash_l1: L1TxnHash) -> RpcResult<Vec<TxnHashWithStatus>>;
6872
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use mc_settlement_client::error::SettlementClientError;
2+
use mp_rpc::v0_8_1::{L1TxnHash, TxnHashWithStatus};
3+
4+
use crate::{
5+
utils::display_internal_server_error,
6+
versions::user::v0_7_1::methods::read::get_transaction_status::get_transaction_status, Starknet,
7+
StarknetRpcApiError, StarknetRpcResult,
8+
};
9+
10+
pub async fn get_messages_status(
11+
starknet: &Starknet,
12+
transaction_hash: L1TxnHash,
13+
) -> StarknetRpcResult<Vec<TxnHashWithStatus>> {
14+
let transaction_hash = transaction_hash.into();
15+
let settlement_client = starknet.settlement_client().ok_or(StarknetRpcApiError::InternalServerError)?;
16+
let l1_handlers = settlement_client.get_messages_to_l2(transaction_hash).await.map_err(|e| match e {
17+
SettlementClientError::TxNotFound => StarknetRpcApiError::TxnHashNotFound,
18+
e => {
19+
display_internal_server_error(format!(
20+
"Error getting messages to L2 for L1 transaction {transaction_hash:?}: {e}"
21+
));
22+
StarknetRpcApiError::InternalServerError
23+
}
24+
})?;
25+
26+
let mut results = Vec::new();
27+
for msg in l1_handlers {
28+
let transaction_hash = msg.tx.compute_hash(starknet.chain_id(), false, false);
29+
let finality_status = get_transaction_status(starknet, transaction_hash).await?.finality_status;
30+
results.push(TxnHashWithStatus { transaction_hash, finality_status });
31+
}
32+
Ok(results)
33+
}

madara/crates/client/rpc/src/versions/user/v0_8_1/methods/read/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use crate::Starknet;
33
use jsonrpsee::core::{async_trait, RpcResult};
44
use mp_block::BlockId;
55
use mp_chain_config::RpcVersion;
6-
use mp_rpc::v0_8_1::{ContractStorageKeysItem, GetStorageProofResult};
6+
use mp_rpc::v0_8_1::{ContractStorageKeysItem, GetStorageProofResult, L1TxnHash, TxnHashWithStatus};
77
use starknet_types_core::felt::Felt;
88

99
pub mod get_compiled_casm;
10+
pub mod get_messages_status;
1011
pub mod get_storage_proof;
1112

1213
#[async_trait]
@@ -28,4 +29,8 @@ impl StarknetReadRpcApiV0_8_1Server for Starknet {
2829
) -> RpcResult<GetStorageProofResult> {
2930
get_storage_proof::get_storage_proof(self, block_id, class_hashes, contract_addresses, contracts_storage_keys)
3031
}
32+
33+
async fn get_messages_status(&self, tx_hash_l1: L1TxnHash) -> RpcResult<Vec<TxnHashWithStatus>> {
34+
Ok(get_messages_status::get_messages_status(self, tx_hash_l1).await?)
35+
}
3136
}

madara/crates/client/settlement_client/src/client.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::messaging::MessageToL2WithMetadata;
33
use crate::state_update::{StateUpdate, StateUpdateWorker};
44
use async_trait::async_trait;
55
use futures::stream::BoxStream;
6+
use mp_convert::L1TransactionHash;
67
use mp_transactions::L1HandlerTransactionWithFee;
78
use mp_utils::service::ServiceContext;
89

@@ -108,6 +109,18 @@ pub trait SettlementLayerProvider: Send + Sync {
108109
/// - An Error if the call fail
109110
async fn message_to_l2_is_pending(&self, msg_hash: &[u8]) -> Result<bool, SettlementClientError>;
110111

112+
/// Fetches L1 to L2 messages associated with a specific L1 transaction hash
113+
///
114+
/// # Arguments
115+
/// * `l1_tx_hash` - The hash of the L1 transaction
116+
/// # Returns
117+
/// - A vector of L1 to L2 messages associated with the given L1 transaction hash
118+
/// - An error if the call fails
119+
async fn get_messages_to_l2(
120+
&self,
121+
l1_tx_hash: L1TransactionHash,
122+
) -> Result<Vec<L1HandlerTransactionWithFee>, SettlementClientError>;
123+
111124
/// Return a block timestamp in second.
112125
///
113126
/// # Arguments

madara/crates/client/settlement_client/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ pub enum SettlementClientError {
1010
#[error("Starknet client error: {0}")]
1111
Starknet(StarknetClientError),
1212

13+
#[error("Transaction not found")]
14+
TxNotFound,
15+
1316
#[error("Missing required field: {0}")]
1417
MissingField(&'static str),
1518

madara/crates/client/settlement_client/src/eth/mod.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::utils::convert_log_state_update;
88
use alloy::eips::{BlockId, BlockNumberOrTag};
99
use alloy::primitives::{keccak256, Address, B256, I256, U256};
1010
use alloy::providers::{Provider, ProviderBuilder, ReqwestProvider, RootProvider};
11-
use alloy::rpc::types::Filter;
11+
use alloy::rpc::types::{Filter, FilteredParams};
1212
use alloy::sol;
1313
use alloy::sol_types::SolValue;
1414
use alloy::transports::http::{Client, Http};
@@ -17,7 +17,7 @@ use bitvec::macros::internal::funty::Fundamental;
1717
use error::EthereumClientError;
1818
use futures::stream::BoxStream;
1919
use futures::StreamExt;
20-
use mp_convert::{FeltExt, ToFelt};
20+
use mp_convert::{FeltExt, L1TransactionHash, ToFelt};
2121
use mp_transactions::L1HandlerTransactionWithFee;
2222
use mp_utils::service::ServiceContext;
2323
use std::str::FromStr;
@@ -306,6 +306,33 @@ impl SettlementLayerProvider for EthereumClient {
306306
Ok(cancellation_timestamp._0 != U256::ZERO)
307307
}
308308

309+
async fn get_messages_to_l2(
310+
&self,
311+
l1_tx_hash: L1TransactionHash,
312+
) -> Result<Vec<L1HandlerTransactionWithFee>, SettlementClientError> {
313+
let l1_tx_hash = B256::from(l1_tx_hash.into_eth().0);
314+
let receipt = self
315+
.provider
316+
.get_transaction_receipt(l1_tx_hash)
317+
.await
318+
.map_err(|e| -> SettlementClientError {
319+
EthereumClientError::Rpc(format!("Failed to get transaction receipt: {}", e)).into()
320+
})?
321+
.ok_or(SettlementClientError::TxNotFound)?;
322+
323+
let filter = FilteredParams::new(Some(self.l1_core_contract.LogMessageToL2_filter().filter));
324+
325+
receipt
326+
.inner
327+
.logs()
328+
.iter()
329+
.filter(|log| filter.filter_address(&log.address()) && filter.filter_topics(log.topics()))
330+
.filter_map(|log| log.log_decode::<LogMessageToL2>().ok())
331+
.map(|log| log.inner.data)
332+
.map(TryInto::try_into)
333+
.collect::<Result<Vec<L1HandlerTransactionWithFee>, _>>()
334+
}
335+
309336
async fn get_block_n_timestamp(&self, l1_block_n: u64) -> Result<u64, SettlementClientError> {
310337
let block = self
311338
.provider

0 commit comments

Comments
 (0)