#!/usr/bin/env python3
"""
Example: How to Send Signed Transactions to Besu RPC Nodes

This script demonstrates the correct way to send transactions to Besu,
which requires eth_sendRawTransaction instead of eth_sendTransaction.

Usage:
    python3 example-send-signed-transaction.py <rpc_url> <private_key> <to_address> <amount_eth>

Example:
    python3 example-send-signed-transaction.py http://192.168.11.250:8545 0x<private_key> 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 0.01
"""

import sys
import json
from web3 import Web3
from eth_account import Account

def send_signed_transaction(rpc_url, private_key, to_address, amount_eth):
    """Send a signed transaction to Besu RPC node"""
    
    print("=== Besu Signed Transaction Example ===\n")
    
    # 1. Connect to RPC
    print("1. Connecting to RPC node...")
    w3 = Web3(Web3.HTTPProvider(rpc_url))
    
    if not w3.isConnected():
        print(f"   ❌ Failed to connect to {rpc_url}")
        sys.exit(1)
    
    chain_id = w3.eth.chain_id
    print(f"   Chain ID: {chain_id}\n")
    
    # 2. Create account from private key
    print("2. Creating account from private key...")
    account = Account.from_key(private_key)
    print(f"   Address: {account.address}\n")
    
    # 3. Check balance
    print("3. Checking balance...")
    balance = w3.eth.get_balance(account.address)
    balance_eth = Web3.fromWei(balance, 'ether')
    print(f"   Balance: {balance_eth} ETH\n")
    
    amount_wei = Web3.toWei(float(amount_eth), 'ether')
    if balance < amount_wei:
        print(f"   ❌ Insufficient balance. Need {amount_eth} ETH, have {balance_eth} ETH")
        sys.exit(1)
    
    # 4. Get gas price
    print("4. Getting gas price...")
    gas_price = w3.eth.gas_price
    gas_price_gwei = Web3.fromWei(gas_price, 'gwei')
    print(f"   Gas Price: {gas_price_gwei} gwei\n")
    
    # 5. Get nonce
    print("5. Getting transaction count (nonce)...")
    nonce = w3.eth.get_transaction_count(account.address, 'pending')
    print(f"   Nonce: {nonce}\n")
    
    # 6. Build transaction
    print("6. Building transaction...")
    transaction = {
        'to': to_address,
        'value': amount_wei,
        'gas': 21000,  # Standard transfer
        'gasPrice': gas_price,
        'nonce': nonce,
        'chainId': chain_id
    }
    
    print(f"   To: {transaction['to']}")
    print(f"   Value: {amount_eth} ETH")
    print(f"   Gas: {transaction['gas']}")
    print(f"   Gas Price: {gas_price_gwei} gwei")
    print(f"   Nonce: {transaction['nonce']}")
    print(f"   Chain ID: {transaction['chainId']}\n")
    
    # 7. Sign transaction
    print("7. Signing transaction...")
    signed_txn = account.sign_transaction(transaction)
    print(f"   ✅ Transaction signed\n")
    
    # 8. Send signed transaction via eth_sendRawTransaction
    print("8. Sending signed transaction via eth_sendRawTransaction...")
    try:
        tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
        print(f"   ✅ Transaction hash: {tx_hash.hex()}\n")
    except Exception as e:
        print(f"   ❌ Error sending transaction: {e}")
        sys.exit(1)
    
    # 9. Wait for transaction receipt
    print("9. Waiting for transaction to be mined...")
    try:
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
        
        if receipt.status == 1:
            print(f"   ✅ Transaction successful!")
            print(f"   Block: {receipt.blockNumber}")
            print(f"   Gas Used: {receipt.gasUsed}")
        else:
            print(f"   ❌ Transaction failed (status: {receipt.status})")
    except Exception as e:
        print(f"   ⚠️  Error waiting for receipt: {e}")
        print(f"   Transaction hash: {tx_hash.hex()}")
    
    print("\n=== Transaction Complete ===")

if __name__ == "__main__":
    if len(sys.argv) < 5:
        print("Usage: python3 example-send-signed-transaction.py <rpc_url> <private_key> <to_address> <amount_eth>")
        print("")
        print("Example:")
        print("  python3 example-send-signed-transaction.py http://192.168.11.250:8545 0x<private_key> 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 0.01")
        sys.exit(1)
    
    rpc_url = sys.argv[1]
    private_key = sys.argv[2]
    to_address = sys.argv[3]
    amount_eth = sys.argv[4]
    
    send_signed_transaction(rpc_url, private_key, to_address, amount_eth)
