Skip to content

Commit

Permalink
Use config params & refactor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Dzejkop committed Dec 22, 2023
1 parent 91bb3c3 commit b5b2a5a
Show file tree
Hide file tree
Showing 11 changed files with 228 additions and 191 deletions.
22 changes: 22 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ pub struct TxSitterConfig {
#[serde(with = "humantime_serde")]
pub escalation_interval: Duration,

#[serde(with = "humantime_serde", default = "default_soft_reorg_interval")]
pub soft_reorg_interval: Duration,

#[serde(with = "humantime_serde", default = "default_hard_reorg_interval")]
pub hard_reorg_interval: Duration,

#[serde(default)]
pub datadog_enabled: bool,

Expand All @@ -28,6 +34,14 @@ pub struct TxSitterConfig {
pub predefined: Option<Predefined>,
}

const fn default_soft_reorg_interval() -> Duration {
Duration::from_secs(60)
}

const fn default_hard_reorg_interval() -> Duration {
Duration::from_secs(60 * 60)
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Predefined {
Expand Down Expand Up @@ -148,6 +162,8 @@ mod tests {
const WITH_DB_CONNECTION_STRING: &str = indoc! {r#"
[service]
escalation_interval = "1h"
soft_reorg_interval = "1m"
hard_reorg_interval = "1h"
datadog_enabled = false
statsd_enabled = false
Expand All @@ -165,6 +181,8 @@ mod tests {
const WITH_DB_PARTS: &str = indoc! {r#"
[service]
escalation_interval = "1h"
soft_reorg_interval = "1m"
hard_reorg_interval = "1h"
datadog_enabled = false
statsd_enabled = false
Expand All @@ -188,6 +206,8 @@ mod tests {
let config = Config {
service: TxSitterConfig {
escalation_interval: Duration::from_secs(60 * 60),
soft_reorg_interval: default_soft_reorg_interval(),
hard_reorg_interval: default_hard_reorg_interval(),
datadog_enabled: false,
statsd_enabled: false,
predefined: None,
Expand All @@ -214,6 +234,8 @@ mod tests {
let config = Config {
service: TxSitterConfig {
escalation_interval: Duration::from_secs(60 * 60),
soft_reorg_interval: default_soft_reorg_interval(),
hard_reorg_interval: default_hard_reorg_interval(),
datadog_enabled: false,
statsd_enabled: false,
predefined: None,
Expand Down
15 changes: 2 additions & 13 deletions src/tasks/handle_reorgs.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
use std::sync::Arc;
use std::time::Duration;

use crate::app::App;

// TODO: Make this configurable
const TIME_BETWEEN_HARD_REORGS_SECONDS: i64 = 60 * 60; // Once every hour
const TIME_BETWEEN_SOFT_REORGS_SECONDS: i64 = 60; // Once every minute

pub async fn handle_hard_reorgs(app: Arc<App>) -> eyre::Result<()> {
loop {
tracing::info!("Handling hard reorgs");
Expand All @@ -17,10 +12,7 @@ pub async fn handle_hard_reorgs(app: Arc<App>) -> eyre::Result<()> {
tracing::info!(id = tx, "Tx hard reorged");
}

tokio::time::sleep(Duration::from_secs(
TIME_BETWEEN_HARD_REORGS_SECONDS as u64,
))
.await;
tokio::time::sleep(app.config.service.hard_reorg_interval).await;
}
}

Expand All @@ -34,9 +26,6 @@ pub async fn handle_soft_reorgs(app: Arc<App>) -> eyre::Result<()> {
tracing::info!(id = tx, "Tx soft reorged");
}

tokio::time::sleep(Duration::from_secs(
TIME_BETWEEN_SOFT_REORGS_SECONDS as u64,
))
.await;
tokio::time::sleep(app.config.service.soft_reorg_interval).await;
}
}
67 changes: 67 additions & 0 deletions tests/common/anvil_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::time::Duration;

use ethers::providers::Middleware;
use ethers::types::{Eip1559TransactionRequest, U256};
use ethers::utils::{Anvil, AnvilInstance};

use super::prelude::{
setup_middleware, DEFAULT_ANVIL_ACCOUNT, DEFAULT_ANVIL_BLOCK_TIME,
SECONDARY_ANVIL_PRIVATE_KEY,
};

#[derive(Debug, Clone, Default)]
pub struct AnvilBuilder {
pub block_time: Option<u64>,
pub port: Option<u16>,
}

impl AnvilBuilder {
pub fn block_time(mut self, block_time: u64) -> Self {
self.block_time = Some(block_time);
self
}

pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}

pub async fn spawn(self) -> eyre::Result<AnvilInstance> {
let mut anvil = Anvil::new();

let block_time = if let Some(block_time) = self.block_time {
block_time
} else {
DEFAULT_ANVIL_BLOCK_TIME
};
anvil = anvil.block_time(block_time);

if let Some(port) = self.port {
anvil = anvil.port(port);
}

let anvil = anvil.spawn();

let middleware =
setup_middleware(anvil.endpoint(), SECONDARY_ANVIL_PRIVATE_KEY)
.await?;

// Wait for the chain to start and produce at least one block
tokio::time::sleep(Duration::from_secs(block_time)).await;

// We need to seed some transactions so we can get fee estimates on the first block
middleware
.send_transaction(
Eip1559TransactionRequest {
to: Some(DEFAULT_ANVIL_ACCOUNT.into()),
value: Some(U256::from(100u64)),
..Default::default()
},
None,
)
.await?
.await?;

Ok(anvil)
}
}
131 changes: 15 additions & 116 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,43 @@
#![allow(dead_code)] // Needed because this module is imported as module by many test crates

use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use std::time::Duration;

use ethers::core::k256::ecdsa::SigningKey;
use ethers::middleware::SignerMiddleware;
use ethers::providers::{Http, Middleware, Provider};
use ethers::signers::{LocalWallet, Signer};
use ethers::types::{Address, Eip1559TransactionRequest, H160, U256};
use ethers::utils::{Anvil, AnvilInstance};
use ethers::types::{Address, H160};
use postgres_docker_utils::DockerContainerGuard;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;
use tx_sitter::client::TxSitterClient;
use tx_sitter::config::{
Config, DatabaseConfig, KeysConfig, LocalKeysConfig, Predefined,
PredefinedNetwork, PredefinedRelayer, ServerConfig, TxSitterConfig,
};
use tx_sitter::service::Service;

pub type AppMiddleware = SignerMiddleware<Arc<Provider<Http>>, LocalWallet>;

mod anvil_builder;
mod service_builder;

pub use self::anvil_builder::AnvilBuilder;
pub use self::service_builder::ServiceBuilder;

#[allow(unused_imports)]
pub mod prelude {
pub use std::time::Duration;

pub use ethers::prelude::{Http, Provider};
pub use ethers::providers::Middleware;
pub use ethers::types::{Eip1559TransactionRequest, U256};
pub use ethers::types::{Eip1559TransactionRequest, H256, U256};
pub use ethers::utils::parse_units;
pub use futures::stream::FuturesUnordered;
pub use futures::StreamExt;
pub use tx_sitter::api_key::ApiKey;
pub use tx_sitter::client::TxSitterClient;
pub use tx_sitter::server::routes::relayer::{
CreateRelayerRequest, CreateRelayerResponse,
CreateApiKeyResponse, CreateRelayerRequest, CreateRelayerResponse,
};
pub use tx_sitter::server::routes::transaction::SendTxRequest;
pub use url::Url;

pub use super::*;
}
Expand All @@ -60,63 +63,6 @@ pub const DEFAULT_ANVIL_BLOCK_TIME: u64 = 2;

pub const DEFAULT_RELAYER_ID: &str = "1b908a34-5dc1-4d2d-a146-5eb46e975830";

#[derive(Debug, Clone, Default)]
pub struct AnvilBuilder {
pub block_time: Option<u64>,
pub port: Option<u16>,
}

impl AnvilBuilder {
pub fn block_time(mut self, block_time: u64) -> Self {
self.block_time = Some(block_time);
self
}

pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}

pub async fn spawn(self) -> eyre::Result<AnvilInstance> {
let mut anvil = Anvil::new();

let block_time = if let Some(block_time) = self.block_time {
block_time
} else {
DEFAULT_ANVIL_BLOCK_TIME
};
anvil = anvil.block_time(block_time);

if let Some(port) = self.port {
anvil = anvil.port(port);
}

let anvil = anvil.spawn();

let middleware =
setup_middleware(anvil.endpoint(), SECONDARY_ANVIL_PRIVATE_KEY)
.await?;

// Wait for the chain to start and produce at least one block
tokio::time::sleep(Duration::from_secs(block_time)).await;

// We need to seed some transactions so we can get fee estimates on the first block
middleware
.send_transaction(
Eip1559TransactionRequest {
to: Some(DEFAULT_ANVIL_ACCOUNT.into()),
value: Some(U256::from(100u64)),
..Default::default()
},
None,
)
.await?
.await?;

Ok(anvil)
}
}

pub fn setup_tracing() {
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer().pretty().compact())
Expand All @@ -137,53 +83,6 @@ pub async fn setup_db() -> eyre::Result<(String, DockerContainerGuard)> {
Ok((url, db_container))
}

pub async fn setup_service(
anvil: &AnvilInstance,
db_connection_url: &str,
escalation_interval: Duration,
) -> eyre::Result<(Service, TxSitterClient)> {
let anvil_private_key = hex::encode(DEFAULT_ANVIL_PRIVATE_KEY);

let config = Config {
service: TxSitterConfig {
escalation_interval,
datadog_enabled: false,
statsd_enabled: false,
predefined: Some(Predefined {
network: PredefinedNetwork {
chain_id: DEFAULT_ANVIL_CHAIN_ID,
name: "Anvil".to_string(),
http_rpc: anvil.endpoint(),
ws_rpc: anvil.ws_endpoint(),
},
relayer: PredefinedRelayer {
name: "Anvil".to_string(),
id: DEFAULT_RELAYER_ID.to_string(),
key_id: anvil_private_key,
chain_id: DEFAULT_ANVIL_CHAIN_ID,
},
}),
},
server: ServerConfig {
host: SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::new(127, 0, 0, 1),
0,
)),
username: None,
password: None,
},
database: DatabaseConfig::connection_string(db_connection_url),
keys: KeysConfig::Local(LocalKeysConfig::default()),
};

let service = Service::new(config).await?;

let client =
TxSitterClient::new(format!("http://{}", service.local_addr()));

Ok((service, client))
}

pub async fn setup_middleware(
rpc_url: impl AsRef<str>,
private_key: &[u8],
Expand Down
Loading

0 comments on commit b5b2a5a

Please sign in to comment.