Skip to content

Commit

Permalink
refactor and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasArrachea committed Nov 13, 2024
1 parent 4ffda51 commit 5908010
Showing 1 changed file with 53 additions and 27 deletions.
80 changes: 53 additions & 27 deletions crates/chainio/txmanager/src/simple_tx_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ use alloy::primitives::U256;
use alloy::providers::{Provider, ProviderBuilder, RootProvider};
use alloy::rpc::types::eth::{TransactionInput, TransactionReceipt, TransactionRequest};
use alloy::signers::local::PrivateKeySigner;
use backoff::{future::retry, ExponentialBackoff};
use backoff::{future::retry, ExponentialBackoffBuilder};
use eigen_logging::logger::SharedLogger;
use eigen_signer::signer::Config;
use reqwest::Url;
use std::time::Duration;
use thiserror::Error;

static FALLBACK_GAS_TIP_CAP: u128 = 5_000_000_000;

pub type Transport = alloy::transports::http::Http<reqwest::Client>;

/// Possible errors raised in Tx Manager
#[derive(Error, Debug)]
#[derive(Error, Debug, PartialEq)]
pub enum TxManagerError {
#[error("signer error")]
SignerError,
Expand Down Expand Up @@ -148,31 +149,18 @@ impl SimpleTxManager {
pub async fn send_tx_with_retries(
&self,
tx: &mut TransactionRequest,
initial_interval: Duration,
max_elapsed_time: Duration,
multiplier: f64,
) -> Result<TransactionReceipt, TxManagerError> {
// Estimating gas and nonce
self.logger.debug("Estimating gas and nonce", "");

let tx = self.estimate_gas_and_nonce(tx).await.inspect_err(|err| {
self.logger
.error("Failed to estimate gas", &err.to_string())
})?;

let signer = self.create_local_signer()?;
let wallet = EthereumWallet::from(signer);

let signed_tx = tx
.build(&wallet)
.await
.inspect_err(|err| {
self.logger
.error("Failed to build and sign transaction", &err.to_string())
})
.map_err(|_| TxManagerError::SendTxError)?;

retry(ExponentialBackoff::default(), || async {
self.send_and_wait_receipt(signed_tx.clone())
.await
.map_err(|e| e.into())
let backoff_config = ExponentialBackoffBuilder::default()
.with_initial_interval(initial_interval)
.with_max_elapsed_time(Some(max_elapsed_time))
.with_multiplier(multiplier)
.build();
retry(backoff_config, || async {
let mut cloned_tx = tx.clone();
Ok(self.send_tx(&mut cloned_tx).await?)
})
.await
}
Expand Down Expand Up @@ -300,14 +288,16 @@ impl SimpleTxManager {

#[cfg(test)]
mod tests {
use super::SimpleTxManager;
use super::{SimpleTxManager, TxManagerError};
use alloy::consensus::TxLegacy;
use alloy::network::TransactionBuilder;
use alloy::primitives::{address, bytes, TxKind::Call, U256};
use alloy::rpc::types::eth::TransactionRequest;
use eigen_logging::get_test_logger;
use eigen_testing_utils::anvil::start_anvil_container;
use std::time::Duration;
use tokio;
use tokio::time::Instant;

#[tokio::test]
async fn test_send_transaction_from_legacy() {
Expand Down Expand Up @@ -369,4 +359,40 @@ mod tests {
assert!(block_number > 0);
assert_eq!(receipt.to, Some(to));
}

#[tokio::test]
async fn test_send_transaction_with_retries_returns_after_timeout() {
let rpc_url = "http://fake:8545";
let logger = get_test_logger();
let private_key =
"ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80".to_string();
let simple_tx_manager =
SimpleTxManager::new(logger, 1.0, private_key.as_str(), rpc_url).unwrap();
let to = address!("a0Ee7A142d267C1f36714E4a8F75612F20a79720");

let account_nonce = 0x69;
let mut tx = TransactionRequest::default()
.with_to(to)
.with_nonce(account_nonce)
.with_chain_id(31337)
.with_value(U256::from(100))
.with_gas_limit(21_000)
.with_max_priority_fee_per_gas(1_000_000_000)
.with_max_fee_per_gas(20_000_000_000)
.with_gas_price(21_000_000_000);
let start = Instant::now();

let result = simple_tx_manager
.send_tx_with_retries(
&mut tx,
Duration::from_millis(5),
Duration::from_secs(1),
1.0,
)
.await;
assert_eq!(result, Err(TxManagerError::SendTxError));
// substract one interval for asserting, because if the last try does not fit in the max_elapsed_time, it will not be executed
let elapsed = start.elapsed();
assert!(elapsed >= Duration::from_secs(1) - Duration::from_millis(5));
}
}

0 comments on commit 5908010

Please sign in to comment.