pub mod helpers; pub mod mint; pub mod receipt; pub mod block_scanner; pub mod mempool; use clap::Parser; use std::sync::Arc; use ethers::prelude::{k256::ecdsa::SigningKey, *}; use crate::mint::Mint; use crate::mempool::loop_mempool; use crate::block_scanner::loop_blocks; use crate::helpers::{setup_signer, user_balance, wei_to_float, wei_to_gwei}; use colored::*; #[macro_export] macro_rules! timestamp_print { ($color: expr, $message: expr) => { println!( "{} {} {}", chrono::Local::now() .format("[%Y-%m-%d]") .to_string() .color($color), chrono::Local::now() .format("[%H:%M:%S]") .to_string() .color($color), $message.color($color) ); }; } pub struct Config { #[allow(dead_code)] pub http: Arc, Wallet>>, #[allow(dead_code)] pub wss: Arc>, } impl Config { pub async fn new() -> Self { let network = std::env::var("NETWORK_RPC").expect("NETWORK_RPC missing"); let provider = Provider::::try_from(network).unwrap(); let middleware = Arc::new(setup_signer(provider.clone()).await); let ws_network = std::env::var("NETWORK_WSS").expect("NETWORK_WS missing"); let ws_provider = Provider::::connect(ws_network).await.unwrap(); Self { http: middleware, wss: Arc::new(ws_provider), } } } pub async fn run() { let config = Arc::new(Config::new().await); let mint = Mint::parse(); mint.check_requirements(config.clone()).await.unwrap(); let config_clone = config.clone(); if mint.backrun { let handle_blocks = tokio::spawn(async move { loop_blocks(config_clone.http.clone()).await; }); let owner_tx = Arc::new( loop_mempool( config.wss.clone(), mint.contract) .await .unwrap()); let config_clone = config.clone(); let last_block_price = config.http.get_gas_price().await.unwrap(); let sniper_gas_price = last_block_price.as_u64() * 125 / 100; let handle = tokio::spawn(async move { let sniping_receipt = mint.sniping( config_clone, U256::from(sniper_gas_price), ).await.unwrap(); sniping_receipt }); timestamp_print!(Color::Green, format!("Owner's tx detected: {:#?}", owner_tx.hash)); timestamp_print!(Color::Blue, format!("Last block gas price: {} Gwei", wei_to_gwei(last_block_price.as_u64()))); timestamp_print!(Color::Blue, format!("Setting Sniping gas price to: {} Gwei", wei_to_gwei(sniper_gas_price))); timestamp_print!(Color::Blue, "SNIPIIIIIIIIING.".to_string()); timestamp_print!(Color::White, "Waiting for tx to be mined...".to_string()); let tx_receipt = handle.await.unwrap(); handle_blocks.abort(); let mint_receipt = receipt::Transaction::new(tx_receipt); let owner_tx_position = config.http.get_transaction_receipt(owner_tx.hash).await.unwrap().unwrap().transaction_index; timestamp_print!(Color::Blue, format!("Owner's tx position in block: {}", owner_tx_position)); mint_receipt.print(); } else { mint.trigger_timestamp().unwrap(); let last_block_price = config.http.get_gas_price().await.unwrap(); let sniper_gas_price = last_block_price.as_u64() * 125 / 100; let handle = tokio::spawn(async move { let sniping_receipt = mint.sniping( config_clone, U256::from(sniper_gas_price), ).await.unwrap(); sniping_receipt }); timestamp_print!(Color::Blue, "SNIPIIIIIIIIING.".to_string()); timestamp_print!(Color::White, "Waiting for tx to be mined...".to_string()); let tx_receipt = handle.await.unwrap(); let mint_receipt = receipt::Transaction::new(tx_receipt); mint_receipt.print(); } let balance = user_balance(config.http.clone()).await.unwrap(); timestamp_print!(Color::White, format!("Balance after mint: {} ETH", wei_to_float(balance.as_u64()))); }