mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: Forward/discard more RPC methods
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -9280,6 +9280,7 @@ dependencies = [
|
|||||||
"alloy-evm",
|
"alloy-evm",
|
||||||
"alloy-genesis",
|
"alloy-genesis",
|
||||||
"alloy-json-abi",
|
"alloy-json-abi",
|
||||||
|
"alloy-json-rpc",
|
||||||
"alloy-network",
|
"alloy-network",
|
||||||
"alloy-primitives",
|
"alloy-primitives",
|
||||||
"alloy-rlp",
|
"alloy-rlp",
|
||||||
|
|||||||
@ -57,6 +57,7 @@ alloy-chains = "0.2.0"
|
|||||||
alloy-eips = "1.0.13"
|
alloy-eips = "1.0.13"
|
||||||
alloy-evm = "0.12"
|
alloy-evm = "0.12"
|
||||||
alloy-json-abi = { version = "1.0.0", default-features = false }
|
alloy-json-abi = { version = "1.0.0", default-features = false }
|
||||||
|
alloy-json-rpc = { version = "1.0.13", default-features = false }
|
||||||
alloy-dyn-abi = "1.2.0"
|
alloy-dyn-abi = "1.2.0"
|
||||||
alloy-network = "1.0.13"
|
alloy-network = "1.0.13"
|
||||||
alloy-primitives = { version = "1.2.0", default-features = false, features = ["map-foldhash"] }
|
alloy-primitives = { version = "1.2.0", default-features = false, features = ["map-foldhash"] }
|
||||||
|
|||||||
@ -1,15 +1,28 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use alloy_json_rpc::RpcObject;
|
||||||
|
use alloy_network::Ethereum;
|
||||||
use alloy_primitives::{Bytes, B256};
|
use alloy_primitives::{Bytes, B256};
|
||||||
|
use alloy_rpc_types::TransactionRequest;
|
||||||
use jsonrpsee::{
|
use jsonrpsee::{
|
||||||
http_client::{HttpClient, HttpClientBuilder},
|
http_client::{HttpClient, HttpClientBuilder},
|
||||||
proc_macros::rpc,
|
proc_macros::rpc,
|
||||||
types::{error::INTERNAL_ERROR_CODE, ErrorObject},
|
types::{error::INTERNAL_ERROR_CODE, ErrorObject},
|
||||||
};
|
};
|
||||||
use jsonrpsee_core::{async_trait, client::ClientT, ClientError, RpcResult};
|
use jsonrpsee_core::{async_trait, client::ClientT, ClientError, RpcResult};
|
||||||
|
use reth::rpc::{result::internal_rpc_err, server_types::eth::EthApiError};
|
||||||
|
use reth_rpc_eth_api::RpcReceipt;
|
||||||
|
|
||||||
#[rpc(server, namespace = "eth")]
|
#[rpc(server, namespace = "eth")]
|
||||||
pub trait EthForwarderApi {
|
pub trait EthForwarderApi<R: RpcObject> {
|
||||||
#[method(name = "sendRawTransaction")]
|
#[method(name = "sendRawTransaction")]
|
||||||
async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult<B256>;
|
async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult<B256>;
|
||||||
|
|
||||||
|
#[method(name = "eth_sendTransaction")]
|
||||||
|
async fn send_transaction(&self, _tx: TransactionRequest) -> RpcResult<B256>;
|
||||||
|
|
||||||
|
#[method(name = "eth_sendRawTransactionSync")]
|
||||||
|
async fn send_raw_transaction_sync(&self, tx: Bytes) -> RpcResult<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EthForwarderExt {
|
pub struct EthForwarderExt {
|
||||||
@ -23,22 +36,56 @@ impl EthForwarderExt {
|
|||||||
|
|
||||||
Self { client }
|
Self { client }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
fn from_client_error(e: ClientError, internal_error_prefix: &str) -> ErrorObject {
|
||||||
impl EthForwarderApiServer for EthForwarderExt {
|
|
||||||
async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult<B256> {
|
|
||||||
let txhash =
|
|
||||||
self.client.clone().request("eth_sendRawTransaction", vec![tx]).await.map_err(|e| {
|
|
||||||
match e {
|
match e {
|
||||||
ClientError::Call(e) => e,
|
ClientError::Call(e) => e,
|
||||||
_ => ErrorObject::owned(
|
_ => ErrorObject::owned(
|
||||||
INTERNAL_ERROR_CODE,
|
INTERNAL_ERROR_CODE,
|
||||||
format!("Failed to send transaction: {e:?}"),
|
format!("{internal_error_prefix}: {e:?}"),
|
||||||
Some(()),
|
Some(()),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
})?;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl EthForwarderApiServer<RpcReceipt<Ethereum>> for EthForwarderExt {
|
||||||
|
async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult<B256> {
|
||||||
|
let txhash = self
|
||||||
|
.client
|
||||||
|
.clone()
|
||||||
|
.request("eth_sendRawTransaction", vec![tx])
|
||||||
|
.await
|
||||||
|
.map_err(|e| Self::from_client_error(e, "Failed to send transaction"))?;
|
||||||
Ok(txhash)
|
Ok(txhash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_transaction(&self, _tx: TransactionRequest) -> RpcResult<B256> {
|
||||||
|
Err(internal_rpc_err("Unimplemented"))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_raw_transaction_sync(&self, tx: Bytes) -> RpcResult<RpcReceipt<Ethereum>> {
|
||||||
|
let hash = self.send_raw_transaction(tx).await?;
|
||||||
|
const TIMEOUT_DURATION: Duration = Duration::from_secs(30);
|
||||||
|
const INTERVAL: Duration = Duration::from_secs(1);
|
||||||
|
|
||||||
|
tokio::time::timeout(TIMEOUT_DURATION, async {
|
||||||
|
loop {
|
||||||
|
let receipt =
|
||||||
|
self.client.request("eth_getTransactionReceipt", vec![hash]).await.map_err(
|
||||||
|
|e| Self::from_client_error(e, "Failed to get transaction receipt"),
|
||||||
|
)?;
|
||||||
|
if let Some(receipt) = receipt {
|
||||||
|
return Ok(receipt);
|
||||||
|
}
|
||||||
|
tokio::time::sleep(INTERVAL).await;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|_elapsed| {
|
||||||
|
Err(EthApiError::TransactionConfirmationTimeout { hash, duration: TIMEOUT_DURATION }
|
||||||
|
.into())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user