Skip to content

Commit 7188a09

Browse files
authored
feat: integration test (#36)
1 parent e25bdfd commit 7188a09

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ name = "builder"
1717
name = "zenith-builder-example"
1818
path = "bin/builder.rs"
1919

20+
[[bin]]
21+
name = "integration-test"
22+
path = "bin/submit_transaction.rs"
23+
2024
[dependencies]
2125
zenith-types = { git = "https://github.com/init4tech/zenith-rs", tag = "v0.10.1" }
2226

bin/submit_transaction.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use alloy::{
2+
network::{EthereumWallet, TransactionBuilder},
3+
providers::{Provider as _, ProviderBuilder, WalletProvider},
4+
rpc::types::eth::TransactionRequest,
5+
signers::aws::AwsSigner,
6+
};
7+
use alloy_primitives::Address;
8+
use aws_config::BehaviorVersion;
9+
use builder::config::{load_address, load_string, load_u64, load_url, Provider};
10+
use metrics::histogram;
11+
use metrics_exporter_prometheus::PrometheusBuilder;
12+
use std::time::Instant;
13+
14+
#[tokio::main]
15+
async fn main() {
16+
tracing_subscriber::fmt::try_init().unwrap();
17+
18+
tracing::trace!("installing metrics collector");
19+
PrometheusBuilder::new().install().expect("failed to install prometheus exporter");
20+
21+
tracing::trace!("connecting to provider");
22+
let (provider, recipient_address, sleep_time) = connect_from_config().await;
23+
24+
loop {
25+
tracing::debug!("attempting transaction");
26+
send_transaction(provider.clone(), recipient_address).await;
27+
28+
tracing::debug!(sleep_time, "sleeping");
29+
tokio::time::sleep(tokio::time::Duration::from_secs(sleep_time)).await;
30+
}
31+
}
32+
33+
async fn send_transaction(provider: Provider, recipient_address: Address) {
34+
// construct simple transaction to send ETH to a recipient
35+
let tx = TransactionRequest::default()
36+
.with_from(provider.default_signer_address())
37+
.with_to(recipient_address)
38+
.with_value(alloy_primitives::U256::from(1))
39+
.with_gas_limit(30_000);
40+
41+
// start timer to measure how long it takes to mine the transaction
42+
let dispatch_start_time: Instant = Instant::now();
43+
44+
// dispatch the transaction
45+
tracing::debug!("dispatching transaction");
46+
let result = provider.send_transaction(tx).await.unwrap();
47+
48+
// wait for the transaction to mine
49+
let receipt = result.get_receipt().await.unwrap();
50+
51+
// record metrics for how long it took to mine the transaction
52+
let mine_time = dispatch_start_time.elapsed().as_secs();
53+
tracing::debug!(success = receipt.status(), mine_time, "transaction mined");
54+
histogram!("integration.tx_mine_time").record(mine_time as f64);
55+
}
56+
57+
async fn connect_from_config() -> (Provider, Address, u64) {
58+
// load signer config values from .env
59+
let rpc_url = load_url("RPC_URL").unwrap();
60+
let chain_id = load_u64("CHAIN_ID").unwrap();
61+
let kms_key_id = load_string("AWS_KMS_KEY_ID").unwrap();
62+
// load transaction sending config value from .env
63+
let recipient_address: Address = load_address("RECIPIENT_ADDRESS").unwrap();
64+
let sleep_time = load_u64("SLEEP_TIME").unwrap();
65+
66+
// connect signer & provider
67+
let config = aws_config::load_defaults(BehaviorVersion::latest()).await;
68+
let client = aws_sdk_kms::Client::new(&config);
69+
let signer = AwsSigner::new(client, kms_key_id.to_string(), Some(chain_id)).await.unwrap();
70+
71+
let provider = ProviderBuilder::new()
72+
.with_recommended_fillers()
73+
.wallet(EthereumWallet::from(signer))
74+
.on_builtin(&rpc_url)
75+
.await
76+
.unwrap();
77+
78+
(provider, recipient_address, sleep_time)
79+
}

src/config.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,15 +228,15 @@ impl BuilderConfig {
228228
}
229229
}
230230

231-
fn load_string(key: &str) -> Result<String, ConfigError> {
231+
pub fn load_string(key: &str) -> Result<String, ConfigError> {
232232
env::var(key).map_err(|_| ConfigError::missing(key))
233233
}
234234

235235
fn load_string_option(key: &str) -> Option<String> {
236236
load_string(key).ok()
237237
}
238238

239-
fn load_u64(key: &str) -> Result<u64, ConfigError> {
239+
pub fn load_u64(key: &str) -> Result<u64, ConfigError> {
240240
let val = load_string(key)?;
241241
val.parse::<u64>().map_err(Into::into)
242242
}
@@ -246,11 +246,11 @@ fn load_u16(key: &str) -> Result<u16, ConfigError> {
246246
val.parse::<u16>().map_err(Into::into)
247247
}
248248

249-
fn load_url(key: &str) -> Result<Cow<'static, str>, ConfigError> {
249+
pub fn load_url(key: &str) -> Result<Cow<'static, str>, ConfigError> {
250250
load_string(key).map_err(Into::into).map(Into::into)
251251
}
252252

253-
fn load_address(key: &str) -> Result<Address, ConfigError> {
253+
pub fn load_address(key: &str) -> Result<Address, ConfigError> {
254254
let address = load_string(key)?;
255255
Address::from_str(&address).map_err(Into::into)
256256
}

0 commit comments

Comments
 (0)