use async_trait::async_trait;
use auto_impl::auto_impl;
use ethers_core::types::{
transaction::{eip2718::TypedTransaction, eip2930::AccessListWithGasUsed},
*,
};
use futures_util::future::join_all;
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;
use url::Url;
use crate::{
erc, EscalatingPending, EscalationPolicy, FilterKind, FilterWatcher, JsonRpcClient, LogQuery,
MiddlewareError, NodeInfo, PeerInfo, PendingTransaction, Provider, ProviderError, PubsubClient,
SubscriptionStream,
};
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[auto_impl(&, Box, Arc)]
pub trait Middleware: Sync + Send + Debug {
type Error: MiddlewareError<Inner = <<Self as Middleware>::Inner as Middleware>::Error>;
type Provider: JsonRpcClient;
type Inner: Middleware<Provider = Self::Provider>;
fn inner(&self) -> &Self::Inner;
fn convert_err(p: ProviderError) -> Self::Error {
Self::Error::from_provider_err(p)
}
fn provider(&self) -> &Provider<Self::Provider> {
self.inner().provider()
}
fn default_sender(&self) -> Option<Address> {
self.inner().default_sender()
}
async fn client_version(&self) -> Result<String, Self::Error> {
self.inner().client_version().await.map_err(MiddlewareError::from_err)
}
async fn fill_transaction(
&self,
tx: &mut TypedTransaction,
block: Option<BlockId>,
) -> Result<(), Self::Error> {
self.inner().fill_transaction(tx, block).await.map_err(MiddlewareError::from_err)
}
async fn get_block_number(&self) -> Result<U64, Self::Error> {
self.inner().get_block_number().await.map_err(MiddlewareError::from_err)
}
async fn get_header<T: Into<BlockId> + Send + Sync>(
&self,
block_hash_or_number: T,
) -> Result<Option<Block<Transaction>>, Self::Error> {
self.inner().get_header(block_hash_or_number).await.map_err(MiddlewareError::from_err)
}
async fn send_transaction<T: Into<TypedTransaction> + Send + Sync>(
&self,
tx: T,
block: Option<BlockId>,
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
self.inner().send_transaction(tx, block).await.map_err(MiddlewareError::from_err)
}
async fn send_escalating<'a>(
&'a self,
tx: &TypedTransaction,
escalations: usize,
policy: EscalationPolicy,
) -> Result<EscalatingPending<'a, Self::Provider>, Self::Error> {
let mut original = tx.clone();
self.fill_transaction(&mut original, None).await?;
if original.nonce().is_none() {
let nonce =
self.get_transaction_count(tx.from().copied().unwrap_or_default(), None).await?;
original.set_nonce(nonce);
}
let gas_price = original.gas_price().expect("filled");
let sign_futs: Vec<_> = (0..escalations)
.map(|i| {
let new_price = policy(gas_price, i);
let mut r = original.clone();
r.set_gas_price(new_price);
r
})
.map(|req| async move {
self.sign_transaction(&req, self.default_sender().unwrap_or_default())
.await
.map(|sig| req.rlp_signed(&sig))
})
.collect();
let mut signed = join_all(sign_futs).await.into_iter().collect::<Result<Vec<_>, _>>()?;
signed.reverse();
Ok(EscalatingPending::new(self.provider(), signed))
}
async fn resolve_name(&self, ens_name: &str) -> Result<Address, Self::Error> {
self.inner().resolve_name(ens_name).await.map_err(MiddlewareError::from_err)
}
async fn lookup_address(&self, address: Address) -> Result<String, Self::Error> {
self.inner().lookup_address(address).await.map_err(MiddlewareError::from_err)
}
async fn resolve_avatar(&self, ens_name: &str) -> Result<Url, Self::Error> {
self.inner().resolve_avatar(ens_name).await.map_err(MiddlewareError::from_err)
}
async fn resolve_nft(&self, token: erc::ERCNFT) -> Result<Url, Self::Error> {
self.inner().resolve_nft(token).await.map_err(MiddlewareError::from_err)
}
async fn resolve_field(&self, ens_name: &str, field: &str) -> Result<String, Self::Error> {
self.inner().resolve_field(ens_name, field).await.map_err(MiddlewareError::from_err)
}
async fn get_block<T: Into<BlockId> + Send + Sync>(
&self,
block_hash_or_number: T,
) -> Result<Option<Block<TxHash>>, Self::Error> {
self.inner().get_block(block_hash_or_number).await.map_err(MiddlewareError::from_err)
}
async fn get_block_with_txs<T: Into<BlockId> + Send + Sync>(
&self,
block_hash_or_number: T,
) -> Result<Option<Block<Transaction>>, Self::Error> {
self.inner()
.get_block_with_txs(block_hash_or_number)
.await
.map_err(MiddlewareError::from_err)
}
async fn get_uncle_count<T: Into<BlockId> + Send + Sync>(
&self,
block_hash_or_number: T,
) -> Result<U256, Self::Error> {
self.inner().get_uncle_count(block_hash_or_number).await.map_err(MiddlewareError::from_err)
}
async fn get_uncle<T: Into<BlockId> + Send + Sync>(
&self,
block_hash_or_number: T,
idx: U64,
) -> Result<Option<Block<H256>>, Self::Error> {
self.inner().get_uncle(block_hash_or_number, idx).await.map_err(MiddlewareError::from_err)
}
async fn get_transaction_count<T: Into<NameOrAddress> + Send + Sync>(
&self,
from: T,
block: Option<BlockId>,
) -> Result<U256, Self::Error> {
self.inner().get_transaction_count(from, block).await.map_err(MiddlewareError::from_err)
}
async fn estimate_gas(
&self,
tx: &TypedTransaction,
block: Option<BlockId>,
) -> Result<U256, Self::Error> {
self.inner().estimate_gas(tx, block).await.map_err(MiddlewareError::from_err)
}
async fn call(
&self,
tx: &TypedTransaction,
block: Option<BlockId>,
) -> Result<Bytes, Self::Error> {
self.inner().call(tx, block).await.map_err(MiddlewareError::from_err)
}
async fn syncing(&self) -> Result<SyncingStatus, Self::Error> {
self.inner().syncing().await.map_err(MiddlewareError::from_err)
}
async fn get_chainid(&self) -> Result<U256, Self::Error> {
self.inner().get_chainid().await.map_err(MiddlewareError::from_err)
}
async fn get_net_version(&self) -> Result<String, Self::Error> {
self.inner().get_net_version().await.map_err(MiddlewareError::from_err)
}
async fn get_balance<T: Into<NameOrAddress> + Send + Sync>(
&self,
from: T,
block: Option<BlockId>,
) -> Result<U256, Self::Error> {
self.inner().get_balance(from, block).await.map_err(MiddlewareError::from_err)
}
async fn get_transaction<T: Send + Sync + Into<TxHash>>(
&self,
transaction_hash: T,
) -> Result<Option<Transaction>, Self::Error> {
self.inner().get_transaction(transaction_hash).await.map_err(MiddlewareError::from_err)
}
async fn get_transaction_by_block_and_index<T: Into<BlockId> + Send + Sync>(
&self,
block_hash_or_number: T,
idx: U64,
) -> Result<Option<Transaction>, Self::Error> {
self.inner()
.get_transaction_by_block_and_index(block_hash_or_number, idx)
.await
.map_err(MiddlewareError::from_err)
}
async fn get_transaction_receipt<T: Send + Sync + Into<TxHash>>(
&self,
transaction_hash: T,
) -> Result<Option<TransactionReceipt>, Self::Error> {
self.inner()
.get_transaction_receipt(transaction_hash)
.await
.map_err(MiddlewareError::from_err)
}
async fn get_block_receipts<T: Into<BlockNumber> + Send + Sync>(
&self,
block: T,
) -> Result<Vec<TransactionReceipt>, Self::Error> {
self.inner().get_block_receipts(block).await.map_err(MiddlewareError::from_err)
}
async fn get_gas_price(&self) -> Result<U256, Self::Error> {
self.inner().get_gas_price().await.map_err(MiddlewareError::from_err)
}
async fn estimate_eip1559_fees(
&self,
estimator: Option<fn(U256, Vec<Vec<U256>>) -> (U256, U256)>,
) -> Result<(U256, U256), Self::Error> {
self.inner().estimate_eip1559_fees(estimator).await.map_err(MiddlewareError::from_err)
}
async fn get_accounts(&self) -> Result<Vec<Address>, Self::Error> {
self.inner().get_accounts().await.map_err(MiddlewareError::from_err)
}
async fn send_raw_transaction<'a>(
&'a self,
tx: Bytes,
) -> Result<PendingTransaction<'a, Self::Provider>, Self::Error> {
self.inner().send_raw_transaction(tx).await.map_err(MiddlewareError::from_err)
}
async fn is_signer(&self) -> bool {
self.inner().is_signer().await
}
async fn sign<T: Into<Bytes> + Send + Sync>(
&self,
data: T,
from: &Address,
) -> Result<Signature, Self::Error> {
self.inner().sign(data, from).await.map_err(MiddlewareError::from_err)
}
async fn sign_transaction(
&self,
tx: &TypedTransaction,
from: Address,
) -> Result<Signature, Self::Error> {
self.inner().sign_transaction(tx, from).await.map_err(MiddlewareError::from_err)
}
async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>, Self::Error> {
self.inner().get_logs(filter).await.map_err(MiddlewareError::from_err)
}
fn get_logs_paginated<'a>(
&'a self,
filter: &Filter,
page_size: u64,
) -> LogQuery<'a, Self::Provider> {
self.inner().get_logs_paginated(filter, page_size)
}
#[doc(hidden)]
async fn new_filter(&self, filter: FilterKind<'_>) -> Result<U256, Self::Error> {
self.inner().new_filter(filter).await.map_err(MiddlewareError::from_err)
}
#[doc(hidden)]
async fn uninstall_filter<T: Into<U256> + Send + Sync>(
&self,
id: T,
) -> Result<bool, Self::Error> {
self.inner().uninstall_filter(id).await.map_err(MiddlewareError::from_err)
}
async fn watch<'a>(
&'a self,
filter: &Filter,
) -> Result<FilterWatcher<'a, Self::Provider, Log>, Self::Error> {
self.inner().watch(filter).await.map_err(MiddlewareError::from_err)
}
async fn watch_pending_transactions(
&self,
) -> Result<FilterWatcher<'_, Self::Provider, H256>, Self::Error> {
self.inner().watch_pending_transactions().await.map_err(MiddlewareError::from_err)
}
#[doc(hidden)]
async fn get_filter_changes<T, R>(&self, id: T) -> Result<Vec<R>, Self::Error>
where
T: Into<U256> + Send + Sync,
R: Serialize + DeserializeOwned + Send + Sync + Debug,
{
self.inner().get_filter_changes(id).await.map_err(MiddlewareError::from_err)
}
async fn watch_blocks(&self) -> Result<FilterWatcher<'_, Self::Provider, H256>, Self::Error> {
self.inner().watch_blocks().await.map_err(MiddlewareError::from_err)
}
async fn get_code<T: Into<NameOrAddress> + Send + Sync>(
&self,
at: T,
block: Option<BlockId>,
) -> Result<Bytes, Self::Error> {
self.inner().get_code(at, block).await.map_err(MiddlewareError::from_err)
}
async fn get_storage_at<T: Into<NameOrAddress> + Send + Sync>(
&self,
from: T,
location: H256,
block: Option<BlockId>,
) -> Result<H256, Self::Error> {
self.inner().get_storage_at(from, location, block).await.map_err(MiddlewareError::from_err)
}
async fn get_proof<T: Into<NameOrAddress> + Send + Sync>(
&self,
from: T,
locations: Vec<H256>,
block: Option<BlockId>,
) -> Result<EIP1186ProofResponse, Self::Error> {
self.inner().get_proof(from, locations, block).await.map_err(MiddlewareError::from_err)
}
async fn mining(&self) -> Result<bool, Self::Error> {
self.inner().mining().await.map_err(MiddlewareError::from_err)
}
async fn import_raw_key(
&self,
private_key: Bytes,
passphrase: String,
) -> Result<Address, Self::Error> {
self.inner()
.import_raw_key(private_key, passphrase)
.await
.map_err(MiddlewareError::from_err)
}
async fn unlock_account<T: Into<Address> + Send + Sync>(
&self,
account: T,
passphrase: String,
duration: Option<u64>,
) -> Result<bool, Self::Error> {
self.inner()
.unlock_account(account, passphrase, duration)
.await
.map_err(MiddlewareError::from_err)
}
async fn add_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
self.inner().add_peer(enode_url).await.map_err(MiddlewareError::from_err)
}
async fn add_trusted_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
self.inner().add_trusted_peer(enode_url).await.map_err(MiddlewareError::from_err)
}
async fn node_info(&self) -> Result<NodeInfo, Self::Error> {
self.inner().node_info().await.map_err(MiddlewareError::from_err)
}
async fn peers(&self) -> Result<Vec<PeerInfo>, Self::Error> {
self.inner().peers().await.map_err(MiddlewareError::from_err)
}
async fn remove_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
self.inner().remove_peer(enode_url).await.map_err(MiddlewareError::from_err)
}
async fn remove_trusted_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
self.inner().remove_trusted_peer(enode_url).await.map_err(MiddlewareError::from_err)
}
async fn start_mining(&self) -> Result<(), Self::Error> {
self.inner().start_mining().await.map_err(MiddlewareError::from_err)
}
async fn stop_mining(&self) -> Result<(), Self::Error> {
self.inner().stop_mining().await.map_err(MiddlewareError::from_err)
}
async fn txpool_content(&self) -> Result<TxpoolContent, Self::Error> {
self.inner().txpool_content().await.map_err(MiddlewareError::from_err)
}
async fn txpool_inspect(&self) -> Result<TxpoolInspect, Self::Error> {
self.inner().txpool_inspect().await.map_err(MiddlewareError::from_err)
}
async fn txpool_status(&self) -> Result<TxpoolStatus, Self::Error> {
self.inner().txpool_status().await.map_err(MiddlewareError::from_err)
}
async fn debug_trace_transaction(
&self,
tx_hash: TxHash,
trace_options: GethDebugTracingOptions,
) -> Result<GethTrace, Self::Error> {
self.inner()
.debug_trace_transaction(tx_hash, trace_options)
.await
.map_err(MiddlewareError::from_err)
}
async fn debug_trace_call<T: Into<TypedTransaction> + Send + Sync>(
&self,
req: T,
block: Option<BlockId>,
trace_options: GethDebugTracingCallOptions,
) -> Result<GethTrace, Self::Error> {
self.inner()
.debug_trace_call(req, block, trace_options)
.await
.map_err(MiddlewareError::from_err)
}
async fn debug_trace_block_by_number(
&self,
block: Option<BlockNumber>,
trace_options: GethDebugTracingOptions,
) -> Result<Vec<GethTrace>, Self::Error> {
self.inner()
.debug_trace_block_by_number(block, trace_options)
.await
.map_err(MiddlewareError::from_err)
}
async fn debug_trace_block_by_hash(
&self,
block: H256,
trace_options: GethDebugTracingOptions,
) -> Result<Vec<GethTrace>, Self::Error> {
self.inner()
.debug_trace_block_by_hash(block, trace_options)
.await
.map_err(MiddlewareError::from_err)
}
async fn trace_call<T: Into<TypedTransaction> + Send + Sync>(
&self,
req: T,
trace_type: Vec<TraceType>,
block: Option<BlockNumber>,
) -> Result<BlockTrace, Self::Error> {
self.inner().trace_call(req, trace_type, block).await.map_err(MiddlewareError::from_err)
}
async fn trace_call_many<T: Into<TypedTransaction> + Send + Sync>(
&self,
req: Vec<(T, Vec<TraceType>)>,
block: Option<BlockNumber>,
) -> Result<Vec<BlockTrace>, Self::Error> {
self.inner().trace_call_many(req, block).await.map_err(MiddlewareError::from_err)
}
async fn trace_raw_transaction(
&self,
data: Bytes,
trace_type: Vec<TraceType>,
) -> Result<BlockTrace, Self::Error> {
self.inner()
.trace_raw_transaction(data, trace_type)
.await
.map_err(MiddlewareError::from_err)
}
async fn trace_replay_transaction(
&self,
hash: H256,
trace_type: Vec<TraceType>,
) -> Result<BlockTrace, Self::Error> {
self.inner()
.trace_replay_transaction(hash, trace_type)
.await
.map_err(MiddlewareError::from_err)
}
async fn trace_replay_block_transactions(
&self,
block: BlockNumber,
trace_type: Vec<TraceType>,
) -> Result<Vec<BlockTrace>, Self::Error> {
self.inner()
.trace_replay_block_transactions(block, trace_type)
.await
.map_err(MiddlewareError::from_err)
}
async fn trace_block(&self, block: BlockNumber) -> Result<Vec<Trace>, Self::Error> {
self.inner().trace_block(block).await.map_err(MiddlewareError::from_err)
}
async fn trace_filter(&self, filter: TraceFilter) -> Result<Vec<Trace>, Self::Error> {
self.inner().trace_filter(filter).await.map_err(MiddlewareError::from_err)
}
async fn trace_get<T: Into<U64> + Send + Sync>(
&self,
hash: H256,
index: Vec<T>,
) -> Result<Trace, Self::Error> {
self.inner().trace_get(hash, index).await.map_err(MiddlewareError::from_err)
}
async fn trace_transaction(&self, hash: H256) -> Result<Vec<Trace>, Self::Error> {
self.inner().trace_transaction(hash).await.map_err(MiddlewareError::from_err)
}
async fn parity_block_receipts<T: Into<BlockNumber> + Send + Sync>(
&self,
block: T,
) -> Result<Vec<TransactionReceipt>, Self::Error> {
self.inner().parity_block_receipts(block).await.map_err(MiddlewareError::from_err)
}
#[doc(hidden)]
async fn subscribe<T, R>(
&self,
params: T,
) -> Result<SubscriptionStream<'_, Self::Provider, R>, Self::Error>
where
T: Debug + Serialize + Send + Sync,
R: DeserializeOwned + Send + Sync,
<Self as Middleware>::Provider: PubsubClient,
{
self.inner().subscribe(params).await.map_err(MiddlewareError::from_err)
}
#[doc(hidden)]
async fn unsubscribe<T>(&self, id: T) -> Result<bool, Self::Error>
where
T: Into<U256> + Send + Sync,
<Self as Middleware>::Provider: PubsubClient,
{
self.inner().unsubscribe(id).await.map_err(MiddlewareError::from_err)
}
async fn subscribe_blocks(
&self,
) -> Result<SubscriptionStream<'_, Self::Provider, Block<TxHash>>, Self::Error>
where
<Self as Middleware>::Provider: PubsubClient,
{
self.inner().subscribe_blocks().await.map_err(MiddlewareError::from_err)
}
async fn subscribe_pending_txs(
&self,
) -> Result<SubscriptionStream<'_, Self::Provider, TxHash>, Self::Error>
where
<Self as Middleware>::Provider: PubsubClient,
{
self.inner().subscribe_pending_txs().await.map_err(MiddlewareError::from_err)
}
async fn subscribe_full_pending_txs(
&self,
) -> Result<SubscriptionStream<'_, Self::Provider, Transaction>, Self::Error>
where
<Self as Middleware>::Provider: PubsubClient,
{
self.inner().subscribe_full_pending_txs().await.map_err(MiddlewareError::from_err)
}
async fn subscribe_logs<'a>(
&'a self,
filter: &Filter,
) -> Result<SubscriptionStream<'a, Self::Provider, Log>, Self::Error>
where
<Self as Middleware>::Provider: PubsubClient,
{
self.inner().subscribe_logs(filter).await.map_err(MiddlewareError::from_err)
}
async fn fee_history<T: Into<U256> + serde::Serialize + Send + Sync>(
&self,
block_count: T,
last_block: BlockNumber,
reward_percentiles: &[f64],
) -> Result<FeeHistory, Self::Error> {
self.inner()
.fee_history(block_count, last_block, reward_percentiles)
.await
.map_err(MiddlewareError::from_err)
}
async fn create_access_list(
&self,
tx: &TypedTransaction,
block: Option<BlockId>,
) -> Result<AccessListWithGasUsed, Self::Error> {
self.inner().create_access_list(tx, block).await.map_err(MiddlewareError::from_err)
}
}
#[cfg(feature = "celo")]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait CeloMiddleware: Middleware {
async fn get_validators_bls_public_keys<T: Into<BlockId> + Send + Sync>(
&self,
block_id: T,
) -> Result<Vec<String>, ProviderError> {
self.provider()
.get_validators_bls_public_keys(block_id)
.await
.map_err(MiddlewareError::from_err)
}
}
#[cfg(feature = "celo")]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<T> CeloMiddleware for T where T: Middleware {}