diff --git a/crates/common/types/transaction.rs b/crates/common/types/transaction.rs index d080b0d26cb..09c5727f234 100644 --- a/crates/common/types/transaction.rs +++ b/crates/common/types/transaction.rs @@ -7,7 +7,9 @@ use ethrex_crypto::keccak::keccak_hash; pub use mempool::MempoolTransaction; use rkyv::{Archive, Deserialize as RDeserialize, Serialize as RSerialize}; use serde::{Serialize, ser::SerializeStruct}; -pub use serde_impl::{AccessListEntry, GenericTransaction, GenericTransactionError}; +pub use serde_impl::{ + AccessListEntry, AuthorizationTupleEntry, GenericTransaction, GenericTransactionError, +}; /// The serialized length of a default eip1559 transaction pub const EIP1559_DEFAULT_SERIALIZED_LENGTH: usize = 15; diff --git a/crates/l2/networking/rpc/clients.rs b/crates/l2/networking/rpc/clients.rs index 386fd58b4a7..1f7273569b6 100644 --- a/crates/l2/networking/rpc/clients.rs +++ b/crates/l2/networking/rpc/clients.rs @@ -1,12 +1,17 @@ +use std::str::FromStr; + use crate::l2::batch::RpcBatch; +use bytes::Bytes; use ethrex_common::Address; use ethrex_common::H256; use ethrex_common::U256; +use ethrex_common::types::{AuthorizationList, AuthorizationTupleEntry}; use ethrex_l2_common::l1_messages::L1MessageProof; use ethrex_rpc::clients::eth::errors::GetL1BlobBaseFeeRequestError; use ethrex_rpc::clients::eth::errors::GetL1FeeVaultAddressError; use ethrex_rpc::clients::eth::errors::GetOperatorFeeError; use ethrex_rpc::clients::eth::errors::GetOperatorFeeVaultAddressError; +use ethrex_rpc::clients::eth::errors::SendEthrexTransactionError; use ethrex_rpc::types::block_identifier::BlockIdentifier; use ethrex_rpc::{ EthClient, @@ -14,11 +19,15 @@ use ethrex_rpc::{ EthClientError, eth::{ RpcResponse, - errors::{GetBaseFeeVaultAddressError, GetBatchByNumberError, GetMessageProofError}, + errors::{ + GetBaseFeeVaultAddressError, GetBatchByNumberError, GetBatchNumberError, + GetMessageProofError, + }, }, }, utils::RpcRequest, }; +use hex; use serde_json::json; pub async fn get_message_proof( @@ -55,6 +64,27 @@ pub async fn get_batch_by_number( } } +pub async fn get_batch_number(client: &EthClient) -> Result { + let request = RpcRequest::new("ethrex_batchNumber", None); + + match client.send_request(request).await? { + RpcResponse::Success(result) => { + let batch_number_hex: String = serde_json::from_value(result.result) + .map_err(GetBatchNumberError::SerdeJSONError) + .map_err(EthClientError::from)?; + let hex_str = batch_number_hex + .strip_prefix("0x") + .unwrap_or(&batch_number_hex); + u64::from_str_radix(hex_str, 16) + .map_err(GetBatchNumberError::ParseIntError) + .map_err(EthClientError::from) + } + RpcResponse::Error(error_response) => { + Err(GetBatchNumberError::RPCError(error_response.error.message).into()) + } + } +} + pub async fn get_base_fee_vault_address( client: &EthClient, block: BlockIdentifier, @@ -139,3 +169,37 @@ pub async fn get_l1_blob_base_fee_per_gas( } } } + +pub async fn send_ethrex_transaction( + client: &EthClient, + to: Address, + data: Bytes, + authorization_list: Option, +) -> Result { + let authorization_list = authorization_list.map(|list| { + list.iter() + .map(AuthorizationTupleEntry::from) + .collect::>() + }); + + let payload = json!({ + "to": format!("{to:#x}"), + "data": format!("0x{}", hex::encode(data)), + "authorizationList": authorization_list, + }); + let request = RpcRequest::new("ethrex_sendTransaction", Some(vec![payload])); + + match client.send_request(request).await? { + RpcResponse::Success(result) => { + let tx_hash_str: String = serde_json::from_value(result.result) + .map_err(SendEthrexTransactionError::SerdeJSONError) + .map_err(EthClientError::from)?; + H256::from_str(&tx_hash_str) + .map_err(|e| SendEthrexTransactionError::ParseHashError(e.to_string())) + .map_err(EthClientError::from) + } + RpcResponse::Error(error_response) => { + Err(SendEthrexTransactionError::RPCError(error_response.error.message).into()) + } + } +} diff --git a/crates/networking/rpc/clients/eth/errors.rs b/crates/networking/rpc/clients/eth/errors.rs index 98b2d5febae..7210f15a72c 100644 --- a/crates/networking/rpc/clients/eth/errors.rs +++ b/crates/networking/rpc/clients/eth/errors.rs @@ -65,6 +65,8 @@ pub enum EthClientError { FailedToGetTxPool(#[from] TxPoolContentError), #[error("ethrex_getBatchByNumber request error: {0}")] GetBatchByNumberError(#[from] GetBatchByNumberError), + #[error("ethrex_batchNumber request error: {0}")] + GetBatchNumberError(#[from] GetBatchNumberError), #[error("ethrex_getBlobBaseFee request error: {0}")] GetBlobBaseFeeError(#[from] GetBlobBaseFeeRequestError), #[error("All RPC calls failed")] @@ -83,6 +85,8 @@ pub enum EthClientError { GetL1FeeVaultAddressError(#[from] GetL1FeeVaultAddressError), #[error("ethrex_getL1BlobBaseFee request error: {0}")] GetL1BlobBaseFeeError(#[from] GetL1BlobBaseFeeRequestError), + #[error("ethrex_sendTransaction request error: {0}")] + SendEthrexTransactionError(#[from] SendEthrexTransactionError), } #[derive(Debug, thiserror::Error)] @@ -327,6 +331,16 @@ pub enum GetBatchByNumberError { RPCError(String), } +#[derive(Debug, thiserror::Error)] +pub enum GetBatchNumberError { + #[error("{0}")] + SerdeJSONError(#[from] serde_json::Error), + #[error("{0}")] + RPCError(String), + #[error("{0}")] + ParseIntError(#[from] std::num::ParseIntError), +} + #[derive(Debug, thiserror::Error)] pub enum GetEthConfigError { #[error("{0}")] @@ -374,3 +388,13 @@ pub enum GetL1BlobBaseFeeRequestError { #[error("{0}")] ParseIntError(#[from] std::num::ParseIntError), } + +#[derive(Debug, thiserror::Error)] +pub enum SendEthrexTransactionError { + #[error("{0}")] + SerdeJSONError(#[from] serde_json::Error), + #[error("{0}")] + RPCError(String), + #[error("{0}")] + ParseHashError(String), +}