#!/bin/bash # Enhanced Live MEV Bot Activity Monitor # Comprehensive monitoring with error tracking, health metrics, and statistics # Color codes GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' PURPLE='\033[0;35m' BOLD='\033[1m' NC='\033[0m' # Configuration LOG_FILE="${1:-logs/mev_bot.log}" UPDATE_INTERVAL=10 # Stats update interval in opportunities ALERT_ERROR_THRESHOLD=50 # Alert when errors exceed this # Check if log file exists if [[ ! -f "$LOG_FILE" ]]; then echo -e "${RED}Error: Log file not found: $LOG_FILE${NC}" echo "Usage: $0 [log-file]" echo "Example: $0 logs/mev_bot.log" exit 1 fi # Initialize counters declare -A STATS=( # Opportunities ["opportunities_total"]=0 ["opportunities_executable"]=0 ["opportunities_rejected"]=0 # Executions ["executions_attempted"]=0 ["executions_successful"]=0 ["executions_failed"]=0 ["flash_loans_initiated"]=0 ["transactions_submitted"]=0 # Errors ["errors_total"]=0 ["errors_parsing"]=0 ["errors_rpc"]=0 ["errors_validation"]=0 ["errors_zero_address"]=0 ["errors_timeout"]=0 ["errors_connection"]=0 ["errors_rate_limit"]=0 # Processing ["blocks_processed"]=0 ["transactions_analyzed"]=0 ["swap_events_detected"]=0 ["dex_transactions"]=0 # Performance ["gas_estimations"]=0 ["pool_queries"]=0 ["price_checks"]=0 ) # Track recent activity for rate calculations declare -a RECENT_OPPORTUNITIES=() declare -a RECENT_ERRORS=() START_TIME=$(date +%s) LAST_ACTIVITY=$(date +%s) # Function to calculate rates calculate_rate() { local count=$1 local elapsed=$(($(date +%s) - START_TIME)) if [[ $elapsed -gt 0 ]]; then echo "scale=2; $count / $elapsed * 60" | bc -l else echo "0" fi } # Function to calculate percentage calculate_percentage() { local part=$1 local total=$2 if [[ $total -gt 0 ]]; then echo "scale=1; $part * 100 / $total" | bc -l else echo "0" fi } # Function to get health status get_health_status() { local error_rate=$(calculate_percentage ${STATS["errors_total"]} $((${STATS["opportunities_total"]} + ${STATS["errors_total"]}))) local error_rate_int=${error_rate%.*} if [[ $error_rate_int -lt 5 ]]; then echo -e "${GREEN}EXCELLENT${NC}" elif [[ $error_rate_int -lt 15 ]]; then echo -e "${YELLOW}GOOD${NC}" elif [[ $error_rate_int -lt 30 ]]; then echo -e "${YELLOW}DEGRADED${NC}" else echo -e "${RED}CRITICAL${NC}" fi } # Function to display header display_header() { clear echo -e "${BOLD}${PURPLE}════════════════════════════════════════════════════════════════════════${NC}" echo -e "${BOLD}${PURPLE} 🤖 MEV Bot Enhanced Live Activity Monitor${NC}" echo -e "${BOLD}${PURPLE}════════════════════════════════════════════════════════════════════════${NC}" echo "" echo -e "${CYAN}📊 Log File:${NC} $LOG_FILE" echo -e "${CYAN}💼 Bot Wallet:${NC} 0x40091653f652a259747D86d7Cbe3e2848082a051" echo -e "${CYAN}🌐 Network:${NC} Arbitrum One" echo -e "${CYAN}⏱️ Started:${NC} $(date)" echo "" echo -e "${BOLD}Monitoring:${NC}" echo -e " ${GREEN}✅${NC} Opportunities (executable & rejected)" echo -e " ${BLUE}⚡${NC} Executions (flash loans, transactions, confirmations)" echo -e " ${RED}❌${NC} Errors (parsing, RPC, validation, timeouts)" echo -e " ${CYAN}📈${NC} Performance (blocks, transactions, events)" echo -e " ${PURPLE}💊${NC} Health (success rate, error rate, uptime)" echo "" echo -e "${YELLOW}Press Ctrl+C to stop${NC}" echo -e "${PURPLE}════════════════════════════════════════════════════════════════════════${NC}" echo "" } # Function to display comprehensive stats display_stats() { local elapsed=$(($(date +%s) - START_TIME)) local hours=$((elapsed / 3600)) local minutes=$(((elapsed % 3600) / 60)) local seconds=$((elapsed % 60)) local opp_rate=$(calculate_rate ${STATS["opportunities_total"]}) local exec_rate=$(calculate_rate ${STATS["executions_attempted"]}) local error_rate_pct=$(calculate_percentage ${STATS["errors_total"]} $((${STATS["opportunities_total"]} + ${STATS["errors_total"]}))) local executable_pct=$(calculate_percentage ${STATS["opportunities_executable"]} ${STATS["opportunities_total"]}) local success_pct=$(calculate_percentage ${STATS["executions_successful"]} ${STATS["executions_attempted"]}) echo -e "${BOLD}${CYAN}╔════════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${BOLD}${CYAN}║ 📊 LIVE STATISTICS ║${NC}" echo -e "${BOLD}${CYAN}╠════════════════════════════════════════════════════════════════════════╣${NC}" # Opportunities section echo -e "${CYAN}║${NC} ${BOLD}🎯 OPPORTUNITIES${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Total: ${GREEN}${STATS["opportunities_total"]}${NC} (${opp_rate}/min) ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Executable: ${GREEN}${STATS["opportunities_executable"]}${NC} (${executable_pct}%) ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Rejected: ${YELLOW}${STATS["opportunities_rejected"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}╠════════════════════════════════════════════════════════════════════════╣${NC}" # Executions section echo -e "${CYAN}║${NC} ${BOLD}⚡ EXECUTIONS${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Attempted: ${BLUE}${STATS["executions_attempted"]}${NC} (${exec_rate}/min) ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Successful: ${GREEN}${STATS["executions_successful"]}${NC} (${success_pct}%) ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Failed: ${RED}${STATS["executions_failed"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Flash Loans: ${PURPLE}${STATS["flash_loans_initiated"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Tx Submitted:${BLUE}${STATS["transactions_submitted"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}╠════════════════════════════════════════════════════════════════════════╣${NC}" # Errors section local error_color=$RED if [[ ${STATS["errors_total"]} -lt 10 ]]; then error_color=$GREEN elif [[ ${STATS["errors_total"]} -lt 50 ]]; then error_color=$YELLOW fi echo -e "${CYAN}║${NC} ${BOLD}❌ ERRORS${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Total: ${error_color}${STATS["errors_total"]}${NC} (${error_rate_pct}% error rate) ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Parsing: ${RED}${STATS["errors_parsing"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} RPC: ${RED}${STATS["errors_rpc"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Validation: ${RED}${STATS["errors_validation"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Zero Addr: ${RED}${STATS["errors_zero_address"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Timeout: ${RED}${STATS["errors_timeout"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Connection: ${RED}${STATS["errors_connection"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Rate Limit: ${RED}${STATS["errors_rate_limit"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}╠════════════════════════════════════════════════════════════════════════╣${NC}" # Processing section echo -e "${CYAN}║${NC} ${BOLD}📈 PROCESSING${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Blocks: ${BLUE}${STATS["blocks_processed"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Transactions:${BLUE}${STATS["transactions_analyzed"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Swap Events: ${CYAN}${STATS["swap_events_detected"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} DEX Txs: ${CYAN}${STATS["dex_transactions"]}${NC} ${CYAN}║${NC}" echo -e "${CYAN}╠════════════════════════════════════════════════════════════════════════╣${NC}" # Health section local health_status=$(get_health_status) echo -e "${CYAN}║${NC} ${BOLD}💊 HEALTH${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Status: $health_status ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Uptime: ${GREEN}${hours}h ${minutes}m ${seconds}s${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Success Rate:${GREEN}${success_pct}%${NC} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} Error Rate: ${error_color}${error_rate_pct}%${NC} ${CYAN}║${NC}" echo -e "${CYAN}╚════════════════════════════════════════════════════════════════════════╝${NC}" echo "" } # Function to handle opportunity detection handle_opportunity() { local line="$1" local timestamp=$(echo "$line" | awk '{print $1, $2}') ((STATS["opportunities_total"]++)) RECENT_OPPORTUNITIES+=("$(date +%s)") if echo "$line" | grep -q "isExecutable:true"; then ((STATS["opportunities_executable"]++)) echo -e "${GREEN}[$(date +'%H:%M:%S')] ✅ EXECUTABLE OPPORTUNITY #${STATS["opportunities_executable"]}${NC}" # Extract profit if echo "$line" | grep -oP 'netProfitETH:[0-9.]+' &>/dev/null; then PROFIT=$(echo "$line" | grep -oP 'netProfitETH:[0-9.]+' | cut -d: -f2) echo -e "${GREEN} 💰 Net Profit: $PROFIT ETH${NC}" fi # Extract path if echo "$line" | grep -oP 'tokenIn:\w+' &>/dev/null; then TOKEN_IN=$(echo "$line" | grep -oP 'tokenIn:\w+' | cut -d: -f2) TOKEN_OUT=$(echo "$line" | grep -oP 'tokenOut:\w+' | cut -d: -f2) echo -e "${CYAN} 🔄 Path: $TOKEN_IN → $TOKEN_OUT${NC}" fi # Extract DEX info if echo "$line" | grep -oP 'dex:\w+' &>/dev/null; then DEX=$(echo "$line" | grep -oP 'dex:\w+' | cut -d: -f2) echo -e "${BLUE} 🏦 DEX: $DEX${NC}" fi else ((STATS["opportunities_rejected"]++)) echo -e "${YELLOW}[$(date +'%H:%M:%S')] 🎯 Opportunity #${STATS["opportunities_total"]} (rejected)${NC}" # Extract reject reason if echo "$line" | grep -oP 'rejectReason:[^]]+' &>/dev/null; then REASON=$(echo "$line" | grep -oP 'rejectReason:[^]]+' | cut -d: -f2 | head -c 70) echo -e "${RED} ❌ Reason: $REASON${NC}" fi fi } # Function to handle execution events handle_execution() { local line="$1" if echo "$line" | grep -q "Flash loan initiated"; then ((STATS["flash_loans_initiated"]++)) ((STATS["executions_attempted"]++)) echo -e "${PURPLE}[$(date +'%H:%M:%S')] ⚡ FLASH LOAN INITIATED #${STATS["flash_loans_initiated"]}${NC}" elif echo "$line" | grep -q "Transaction submitted"; then ((STATS["transactions_submitted"]++)) TXHASH=$(echo "$line" | grep -oP '0x[a-fA-F0-9]{64}' | head -1) echo -e "${GREEN}[$(date +'%H:%M:%S')] 🚀 TRANSACTION SUBMITTED${NC}" echo -e "${GREEN} 📝 TxHash: $TXHASH${NC}" echo -e "${GREEN} 🔗 Arbiscan: https://arbiscan.io/tx/$TXHASH${NC}" elif echo "$line" | grep -q "Trade confirmed\|execution successful"; then ((STATS["executions_successful"]++)) echo -e "${GREEN}[$(date +'%H:%M:%S')] ✅ TRADE CONFIRMED!${NC}" if echo "$line" | grep -oP 'Profit:.*ETH' &>/dev/null; then PROFIT=$(echo "$line" | grep -oP 'Profit:.*ETH') echo -e "${GREEN} 💰 $PROFIT${NC}" fi elif echo "$line" | grep -q "execution failed\|Trade failed"; then ((STATS["executions_failed"]++)) echo -e "${RED}[$(date +'%H:%M:%S')] ❌ EXECUTION FAILED${NC}" if echo "$line" | grep -oP 'error:.*' &>/dev/null; then ERROR=$(echo "$line" | grep -oP 'error:.*' | head -c 70) echo -e "${RED} ⚠️ $ERROR${NC}" fi elif echo "$line" | grep -q "Executing arbitrage"; then ((STATS["executions_attempted"]++)) echo -e "${BLUE}[$(date +'%H:%M:%S')] ⚡ EXECUTING ARBITRAGE #${STATS["executions_attempted"]}${NC}" fi } # Function to handle errors handle_error() { local line="$1" ((STATS["errors_total"]++)) RECENT_ERRORS+=("$(date +%s)") local error_type="GENERAL" if echo "$line" | grep -qi "parsing.*failed\|PARSING FAILED\|failed to parse"; then ((STATS["errors_parsing"]++)) error_type="PARSING" elif echo "$line" | grep -qi "rpc.*error\|rpc.*failed\|connection refused"; then ((STATS["errors_rpc"]++)) error_type="RPC" elif echo "$line" | grep -qi "validation.*failed\|invalid.*input"; then ((STATS["errors_validation"]++)) error_type="VALIDATION" elif echo "$line" | grep -qi "0x0000000000000000000000000000000000000000\|zero.*address"; then ((STATS["errors_zero_address"]++)) error_type="ZERO_ADDRESS" elif echo "$line" | grep -qi "timeout\|deadline exceeded"; then ((STATS["errors_timeout"]++)) error_type="TIMEOUT" elif echo "$line" | grep -qi "connection.*failed\|connection.*lost\|context.*canceled"; then ((STATS["errors_connection"]++)) error_type="CONNECTION" elif echo "$line" | grep -qi "rate.*limit\|too many requests\|429"; then ((STATS["errors_rate_limit"]++)) error_type="RATE_LIMIT" fi echo -e "${RED}[$(date +'%H:%M:%S')] ❌ ERROR ($error_type) #${STATS["errors_total"]}${NC}" # Extract error message local error_msg=$(echo "$line" | grep -oP 'error[=:].*' | head -c 100) if [[ -n "$error_msg" ]]; then echo -e "${RED} ⚠️ $error_msg${NC}" fi # Alert on high error count if [[ ${STATS["errors_total"]} -gt $ALERT_ERROR_THRESHOLD ]] && [[ $((${STATS["errors_total"]} % 10)) -eq 0 ]]; then echo -e "${RED}${BOLD} 🚨 ALERT: Error count exceeds threshold ($ALERT_ERROR_THRESHOLD)${NC}" fi } # Function to handle processing events handle_processing() { local line="$1" if echo "$line" | grep -qi "Block.*Processing.*transactions\|Processing block"; then ((STATS["blocks_processed"]++)) # Extract block number if echo "$line" | grep -oP 'block[=: ]+\d+' &>/dev/null; then BLOCK=$(echo "$line" | grep -oP '\d+' | head -1) echo -e "${BLUE}[$(date +'%H:%M:%S')] 📦 Block #$BLOCK processed${NC}" fi elif echo "$line" | grep -qi "DEX transactions\|Found.*DEX"; then ((STATS["dex_transactions"]++)) elif echo "$line" | grep -qi "swap.*event\|Swap detected"; then ((STATS["swap_events_detected"]++)) elif echo "$line" | grep -qi "Analyzing transaction"; then ((STATS["transactions_analyzed"]++)) fi } # Main monitoring loop main() { display_header local line_count=0 local last_stats_update=0 tail -f "$LOG_FILE" | while IFS= read -r line; do ((line_count++)) LAST_ACTIVITY=$(date +%s) # Handle different event types if echo "$line" | grep -qi "OPPORTUNITY DETECTED"; then handle_opportunity "$line" echo "" elif echo "$line" | grep -qi "ERROR\|WARN\|failed"; then handle_error "$line" echo "" elif echo "$line" | grep -qi "Flash loan\|Transaction submitted\|Trade confirmed\|execution\|Executing arbitrage"; then handle_execution "$line" echo "" elif echo "$line" | grep -qi "Block\|Processing\|DEX\|swap.*event"; then handle_processing "$line" fi # Update stats display periodically (only when count actually changes) local current_count=${STATS["opportunities_total"]} if [[ $((current_count % UPDATE_INTERVAL)) -eq 0 ]] && [[ $current_count -gt 0 ]] && [[ $current_count -ne $last_stats_update ]]; then last_stats_update=$current_count display_stats fi done } # Trap Ctrl+C for clean exit trap 'echo -e "\n${YELLOW}Monitoring stopped.${NC}"; display_stats; exit 0' SIGINT SIGTERM # Run main monitoring main