pub mod eip1559;
use std::{
io::{self, Error, ErrorKind},
ops::Div,
sync::Arc,
time::Duration,
};
use crate::{jsonrpc::client::evm as jsonrpc_client_evm, key, wallet};
use ethers::{
prelude::{
gas_escalator::{Frequency, GasEscalatorMiddleware, GeometricGasPrice},
NonceManagerMiddleware, SignerMiddleware,
},
utils::Units::Gwei,
};
use ethers_providers::{Http, Provider};
use lazy_static::lazy_static;
use primitive_types::U256;
lazy_static! {
pub static ref GWEI: U256 = U256::from(10).checked_pow(Gwei.as_num().into()).unwrap();
}
impl<T> wallet::Wallet<T>
where
T: key::secp256k1::ReadOnly + key::secp256k1::SignOnly + Clone,
{
#[must_use]
pub fn evm<'a, S>(
&self,
eth_signer: &'a S,
chain_rpc_url: &str,
chain_id: U256,
) -> io::Result<Evm<'a, T, S>>
where
S: ethers_signers::Signer + Clone,
S::Error: 'static,
{
let provider = Provider::<Http>::try_from(chain_rpc_url)
.map_err(|e| {
Error::new(
ErrorKind::Other,
format!("failed to create provider '{}'", e),
)
})?
.interval(Duration::from_millis(2000u64));
let escalator = GeometricGasPrice::new(5.0, 10u64, None::<u64>);
let gas_escalator_middleware =
GasEscalatorMiddleware::new(provider.clone(), escalator, Frequency::PerBlock);
let signer_middleware = SignerMiddleware::new(
gas_escalator_middleware,
eth_signer.clone().with_chain_id(chain_id.as_u64()),
);
let nonce_middleware = NonceManagerMiddleware::new(signer_middleware, eth_signer.address());
let middleware = Arc::new(nonce_middleware);
Ok(Evm::<'a, T, S> {
inner: self.clone(),
eth_signer,
chain_rpc_url: chain_rpc_url.to_string(),
provider,
middleware,
chain_id,
})
}
}
#[derive(Clone, Debug)]
pub struct Evm<'a, T, S>
where
T: key::secp256k1::ReadOnly + key::secp256k1::SignOnly + Clone,
S: ethers_signers::Signer + Clone,
S::Error: 'static,
{
pub inner: wallet::Wallet<T>,
pub eth_signer: &'a S,
pub chain_rpc_url: String,
pub provider: Provider<Http>,
pub middleware: Arc<
NonceManagerMiddleware<
SignerMiddleware<GasEscalatorMiddleware<Provider<Http>, GeometricGasPrice>, S>,
>,
>,
pub chain_id: U256,
}
impl<'a, T, S> Evm<'a, T, S>
where
T: key::secp256k1::ReadOnly + key::secp256k1::SignOnly + Clone,
S: ethers_signers::Signer + Clone,
S::Error: 'static,
{
pub async fn balance(&self) -> io::Result<U256> {
let cur_balance =
jsonrpc_client_evm::get_balance(&self.chain_rpc_url, self.inner.h160_address).await?;
Ok(cur_balance)
}
}
pub fn wei_to_gwei(wei: impl Into<U256>) -> U256 {
let wei: U256 = wei.into();
if wei.is_zero() {
U256::zero()
} else {
wei.div(*GWEI)
}
}