diff --git a/crates/rpc/rpc-builder/tests/it/http.rs b/crates/rpc/rpc-builder/tests/it/http.rs index dd0621fe01..22c11bd227 100644 --- a/crates/rpc/rpc-builder/tests/it/http.rs +++ b/crates/rpc/rpc-builder/tests/it/http.rs @@ -95,6 +95,7 @@ where .await .unwrap(); EthApiClient::syncing(client).await.unwrap(); + EthApiClient::send_transaction(client, transaction_request).await.unwrap_err(); // Unimplemented assert!(is_unimplemented(EthApiClient::author(client).await.err().unwrap())); @@ -115,9 +116,6 @@ where .err() .unwrap() )); - assert!(is_unimplemented( - EthApiClient::send_transaction(client, transaction_request).await.err().unwrap() - )); assert!(is_unimplemented( EthApiClient::sign_transaction(client, call_request.clone()).await.err().unwrap() )); diff --git a/crates/rpc/rpc/src/eth/api/server.rs b/crates/rpc/rpc/src/eth/api/server.rs index db5a3098e1..299d1fdbee 100644 --- a/crates/rpc/rpc/src/eth/api/server.rs +++ b/crates/rpc/rpc/src/eth/api/server.rs @@ -265,9 +265,9 @@ where &self, block_count: U64, newest_block: BlockId, - _reward_percentiles: Option>, + reward_percentiles: Option>, ) -> Result { - trace!(target: "rpc::eth", ?block_count, ?newest_block, ?_reward_percentiles, "Serving eth_feeHistory"); + trace!(target: "rpc::eth", ?block_count, ?newest_block, ?reward_percentiles, "Serving eth_feeHistory"); let block_count = block_count.as_u64(); if block_count == 0 { @@ -389,14 +389,15 @@ where } /// Handler for: `eth_sendTransaction` - async fn send_transaction(&self, _request: TransactionRequest) -> Result { - Err(internal_rpc_err("unimplemented")) + async fn send_transaction(&self, request: TransactionRequest) -> Result { + trace!(target: "rpc::eth", ?request, "Serving eth_sendTransaction"); + Ok(EthTransactions::send_transaction(self, request).await?) } /// Handler for: `eth_sendRawTransaction` async fn send_raw_transaction(&self, tx: Bytes) -> Result { trace!(target: "rpc::eth", ?tx, "Serving eth_sendRawTransaction"); - Ok(EthApi::send_raw_transaction(self, tx).await?) + Ok(EthTransactions::send_raw_transaction(self, tx).await?) } /// Handler for: `eth_sign` diff --git a/crates/rpc/rpc/src/eth/api/transactions.rs b/crates/rpc/rpc/src/eth/api/transactions.rs index 8bc0a92b3e..a4d2de7df6 100644 --- a/crates/rpc/rpc/src/eth/api/transactions.rs +++ b/crates/rpc/rpc/src/eth/api/transactions.rs @@ -1,14 +1,12 @@ //! Contains RPC handler implementations specific to transactions use crate::{ eth::{ - error::{EthApiError, EthResult}, + error::{EthApiError, EthResult, SignError}, utils::recover_raw_transaction, }, EthApi, }; use async_trait::async_trait; - -use crate::eth::error::SignError; use reth_primitives::{ Address, BlockId, BlockNumberOrTag, Bytes, FromRecoveredTransaction, IntoRecoveredTransaction, Receipt, Transaction as PrimitiveTransaction, @@ -60,6 +58,15 @@ pub trait EthTransactions: Send + Sync { /// Returns None if the transaction does not exist or is pending /// Note: The tx receipt is not available for pending transactions. async fn transaction_receipt(&self, hash: H256) -> EthResult>; + + /// Decodes and recovers the transaction and submits it to the pool. + /// + /// Returns the hash of the transaction. + async fn send_raw_transaction(&self, tx: Bytes) -> EthResult; + + /// Signs transaction with a matching signer, if any and submits the transaction to the pool. + /// Returns the hash of the signed transaction. + async fn send_transaction(&self, request: TransactionRequest) -> EthResult; } #[async_trait] @@ -168,20 +175,19 @@ where Self::build_transaction_receipt(tx, meta, receipt).map(Some) } -} -// === impl EthApi === + async fn send_raw_transaction(&self, tx: Bytes) -> EthResult { + let recovered = recover_raw_transaction(tx)?; -impl EthApi -where - Pool: TransactionPool + 'static, - Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static, - Network: 'static, -{ - /// Send a transaction to the pool - /// - /// This will sign the transaction and submit it to the pool - pub(crate) async fn send_transaction(&self, request: TransactionRequest) -> EthResult { + let pool_transaction = ::from_recovered_transaction(recovered); + + // submit the transaction to the pool with a `Local` origin + let hash = self.pool().add_transaction(TransactionOrigin::Local, pool_transaction).await?; + + Ok(hash) + } + + async fn send_transaction(&self, request: TransactionRequest) -> EthResult { let from = match request.from { Some(from) => from, None => return Err(SignError::NoAccount.into()), @@ -206,7 +212,16 @@ where Ok(hash) } +} +// === impl EthApi === + +impl EthApi +where + Pool: TransactionPool + 'static, + Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static, + Network: 'static, +{ pub(crate) fn sign_request( &self, from: &Address, @@ -252,20 +267,6 @@ where Ok(None) } - /// Decodes and recovers the transaction and submits it to the pool. - /// - /// Returns the hash of the transaction. - pub(crate) async fn send_raw_transaction(&self, tx: Bytes) -> EthResult { - let recovered = recover_raw_transaction(tx)?; - - let pool_transaction = ::from_recovered_transaction(recovered); - - // submit the transaction to the pool with a `Local` origin - let hash = self.pool().add_transaction(TransactionOrigin::Local, pool_transaction).await?; - - Ok(hash) - } - /// Helper function for `eth_getTransactionReceipt` /// /// Returns the receipt @@ -422,13 +423,12 @@ impl From for Transaction { #[cfg(test)] mod tests { - use crate::eth::cache::EthStateCache; + use super::*; + use crate::{eth::cache::EthStateCache, EthApi}; use reth_primitives::{hex_literal::hex, Bytes}; use reth_provider::test_utils::NoopProvider; use reth_transaction_pool::{test_utils::testing_pool, TransactionPool}; - use crate::EthApi; - #[tokio::test] async fn send_raw_transaction() { let noop_provider = NoopProvider::default();