#!/usr/bin/env node /** * 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: * node example-send-signed-transaction.js * * Example: * node example-send-signed-transaction.js http://192.168.11.250:8545 0x 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 0.01 */ const https = require('https'); const http = require('http'); const { ethers } = require('ethers'); // Parse command line arguments const args = process.argv.slice(2); if (args.length < 4) { console.error('Usage: node example-send-signed-transaction.js '); console.error(''); console.error('Example:'); console.error(' node example-send-signed-transaction.js http://192.168.11.250:8545 0x 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb 0.01'); process.exit(1); } const [rpcUrl, privateKey, toAddress, amountEth] = args; async function sendSignedTransaction() { try { console.log('=== Besu Signed Transaction Example ===\n'); // 1. Create wallet from private key console.log('1. Creating wallet from private key...'); const wallet = new ethers.Wallet(privateKey); console.log(` Address: ${wallet.address}\n`); // 2. Connect to RPC provider console.log('2. Connecting to RPC node...'); const provider = new ethers.providers.JsonRpcProvider(rpcUrl); // Verify connection const network = await provider.getNetwork(); console.log(` Chain ID: ${network.chainId}`); const balance = await provider.getBalance(wallet.address); console.log(` Balance: ${ethers.utils.formatEther(balance)} ETH\n`); if (balance.lt(ethers.utils.parseEther(amountEth))) { console.error(`❌ Insufficient balance. Need ${amountEth} ETH, have ${ethers.utils.formatEther(balance)} ETH`); process.exit(1); } // 3. Get current gas price console.log('3. Getting gas price...'); const gasPrice = await provider.getGasPrice(); console.log(` Gas Price: ${ethers.utils.formatUnits(gasPrice, 'gwei')} gwei\n`); // 4. Get nonce console.log('4. Getting transaction count (nonce)...'); const nonce = await provider.getTransactionCount(wallet.address, 'pending'); console.log(` Nonce: ${nonce}\n`); // 5. Create transaction console.log('5. Creating transaction...'); const tx = { to: toAddress, value: ethers.utils.parseEther(amountEth), gasLimit: 21000, // Standard transfer gasPrice: gasPrice, nonce: nonce, chainId: network.chainId }; console.log(` To: ${tx.to}`); console.log(` Value: ${amountEth} ETH`); console.log(` Gas Limit: ${tx.gasLimit}`); console.log(` Gas Price: ${ethers.utils.formatUnits(tx.gasPrice, 'gwei')} gwei`); console.log(` Nonce: ${tx.nonce}`); console.log(` Chain ID: ${tx.chainId}\n`); // 6. Sign transaction console.log('6. Signing transaction...'); const signedTx = await wallet.signTransaction(tx); console.log(` Signed transaction length: ${signedTx.length} characters\n`); // 7. Send signed transaction via eth_sendRawTransaction console.log('7. Sending signed transaction via eth_sendRawTransaction...'); const txResponse = await provider.sendTransaction(signedTx); console.log(` ✅ Transaction hash: ${txResponse.hash}\n`); // 8. Wait for transaction to be mined console.log('8. Waiting for transaction to be mined...'); const receipt = await txResponse.wait(); if (receipt.status === 1) { console.log(` ✅ Transaction successful!`); console.log(` Block: ${receipt.blockNumber}`); console.log(` Gas Used: ${receipt.gasUsed.toString()}`); } else { console.log(` ❌ Transaction failed (status: ${receipt.status})`); } console.log('\n=== Transaction Complete ==='); } catch (error) { console.error('\n❌ Error:', error.message); if (error.message.includes('eth_sendTransaction')) { console.error('\n⚠️ This error occurs if you try to use eth_sendTransaction.'); console.error(' Besu requires eth_sendRawTransaction with signed transactions.'); } else if (error.message.includes('insufficient funds')) { console.error('\n⚠️ Insufficient balance for this transaction.'); } else if (error.message.includes('nonce')) { console.error('\n⚠️ Nonce error - transaction may already be pending.'); } process.exit(1); } } // Run the example sendSignedTransaction();