Files
explorer-monorepo/scripts/send-with-optimal-gas.sh

155 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Send Transaction with Optimal Gas Pricing
# Prevents stuck transactions by using dynamic gas pricing
# Usage: ./send-with-optimal-gas.sh <contract> <function> [args...]
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Load environment variables
if [ -f "$PROJECT_ROOT/.env" ]; then
source "$PROJECT_ROOT/.env"
elif [ -f "$PROJECT_ROOT/../.env" ]; then
source "$PROJECT_ROOT/../.env"
fi
# Configuration
RPC_URL="${RPC_URL_138:-http://192.168.11.250:8545}"
GAS_MULTIPLIER="${GAS_MULTIPLIER:-1.5}" # Use 1.5x current gas for faster inclusion
if [ -z "${PRIVATE_KEY:-}" ]; then
log_error "PRIVATE_KEY not found in .env"
exit 1
fi
# Get optimal gas price (prefer Etherscan API, fallback to RPC)
get_optimal_gas() {
# Try Etherscan API first (if available)
if [ -f "$SCRIPT_DIR/get-optimal-gas-from-api.sh" ]; then
API_GAS=$("$SCRIPT_DIR/get-optimal-gas-from-api.sh" "proposed" 2>/dev/null || echo "")
if [ -n "$API_GAS" ] && [ "$API_GAS" != "0" ]; then
# Use API gas with multiplier for faster inclusion
local optimal_gas=$(echo "scale=0; $API_GAS * $GAS_MULTIPLIER / 1" | bc 2>/dev/null || echo "$API_GAS")
echo "$optimal_gas"
return 0
fi
fi
# Fallback to RPC gas price
local current_gas=$(cast gas-price --rpc-url "$RPC_URL" 2>/dev/null || echo "1000000000")
local optimal_gas=$(echo "scale=0; $current_gas * $GAS_MULTIPLIER / 1" | bc 2>/dev/null || echo "$current_gas")
echo "$optimal_gas"
}
# Check nonce
check_nonce() {
local account="$1"
local current_nonce=$(cast nonce "$account" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
local pending_nonce=$(cast nonce "$account" --rpc-url "$RPC_URL" --pending 2>/dev/null || echo "$current_nonce")
if [ "$pending_nonce" -gt "$current_nonce" ]; then
local pending_count=$((pending_nonce - current_nonce))
log_warn "Found $pending_count pending transaction(s)"
log_info "Current nonce: $current_nonce, Pending nonce: $pending_nonce"
return 1
fi
return 0
}
# Get account address
ACCOUNT=$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || echo "")
if [ -z "$ACCOUNT" ]; then
log_error "Could not derive address from PRIVATE_KEY"
exit 1
fi
# Check nonce before sending
log_info "Checking nonce..."
if ! check_nonce "$ACCOUNT"; then
log_warn "Pending transactions detected"
log_info "Waiting 10 seconds for pending transactions..."
sleep 10
# Re-check
if ! check_nonce "$ACCOUNT"; then
log_error "Still have pending transactions"
log_info "Consider waiting longer or using higher gas price to replace"
exit 1
fi
fi
# Get optimal gas price
CURRENT_GAS=$(cast gas-price --rpc-url "$RPC_URL" 2>/dev/null || echo "1000000000")
OPTIMAL_GAS=$(get_optimal_gas)
CURRENT_GAS_GWEI=$(echo "scale=2; $CURRENT_GAS / 1000000000" | bc 2>/dev/null || echo "1")
OPTIMAL_GAS_GWEI=$(echo "scale=2; $OPTIMAL_GAS / 1000000000" | bc 2>/dev/null || echo "1.5")
log_info "Current gas price: $CURRENT_GAS_GWEI gwei"
log_info "Optimal gas price: $OPTIMAL_GAS_GWEI gwei (${GAS_MULTIPLIER}x multiplier)"
log_info ""
# Get current nonce
CURRENT_NONCE=$(cast nonce "$ACCOUNT" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
log_info "Using nonce: $CURRENT_NONCE"
log_info ""
# Build cast send command
CONTRACT="$1"
FUNCTION="$2"
shift 2
ARGS="$@"
log_info "Sending transaction..."
log_info " Contract: $CONTRACT"
log_info " Function: $FUNCTION"
log_info " Args: $ARGS"
log_info ""
# Send transaction with optimal gas
TX_OUTPUT=$(cast send "$CONTRACT" "$FUNCTION" $ARGS \
--rpc-url "$RPC_URL" \
--private-key "$PRIVATE_KEY" \
--gas-price "$OPTIMAL_GAS" \
--nonce "$CURRENT_NONCE" \
2>&1 || echo "FAILED")
if echo "$TX_OUTPUT" | grep -qE "(blockHash|transactionHash)"; then
TX_HASH=$(echo "$TX_OUTPUT" | grep -oE "(blockHash|transactionHash)[[:space:]]+0x[0-9a-fA-F]{64}" | awk '{print $2}' | head -1)
log_success "Transaction sent successfully!"
log_info " Hash: $TX_HASH"
log_info " Gas Price: $OPTIMAL_GAS_GWEI gwei"
log_info " Nonce: $CURRENT_NONCE"
exit 0
else
log_error "Transaction failed"
log_error "$TX_OUTPUT"
# Check for specific errors
if echo "$TX_OUTPUT" | grep -q "underpriced"; then
log_warn "Transaction underpriced"
log_info "Try with higher gas multiplier: GAS_MULTIPLIER=2.0 $0 $@"
elif echo "$TX_OUTPUT" | grep -q "nonce"; then
log_warn "Nonce issue detected"
log_info "Wait for pending transactions or use next nonce"
fi
exit 1
fi