126 lines
4.3 KiB
Python
126 lines
4.3 KiB
Python
|
|
#!/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)
|