Skip to main content

Transfer funds between accounts in a transaction

You can get started with the Developer Quickstart to rapidly generate local blockchain networks.

This tutorial shows you how to transfer funds (ETH) between accounts in a transaction.

Prerequisites

Use eth_sendSignedTransaction

The simplest way to transfer funds between externally-owned accounts is using eth_sendSignedTransaction. This example uses eth_sendSignedTransaction and one of the test accounts to transfer funds to a newly created account.

Do not use the test accounts on Ethereum Mainnet or any production network

The private key is publicly displayed, which means the account is not secure.

Before making the transaction, check the balances of both accounts to verify the funds transfer after the transaction.

const web3 = new Web3(host);
// Pre-seeded account with 90000 ETH
const privateKeyA =
"0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3";
const accountA = web3.eth.accounts.privateKeyToAccount(privateKeyA);
var accountABalance = web3.utils.fromWei(
await web3.eth.getBalance(accountA.address),
);
console.log("Account A has balance of: " + accountABalance);

// Create a new account to transfer ETH to
var accountB = web3.eth.accounts.create();
var accountBBalance = web3.utils.fromWei(
await web3.eth.getBalance(accountB.address),
);
console.log("Account B has balance of: " + accountBBalance);

Use the test account address (Account A) for the from parameter, the recipient account address (Account B) for the to parameter, and the amount of ETH to transfer between accounts for the value parameter. Sign the transaction with Account A's private key and send it using eth_sendSignedTransaction.

// Send some ETH from A to B
const rawTxOptions = {
nonce: web3.utils.numberToHex(
await web3.eth.getTransactionCount(accountA.address),
),
from: accountA.address,
to: accountB.address,
value: "0x100", // Amount of ETH to transfer
gasPrice: "0x0", // ETH per unit of gas
gasLimit: "0x24A22", // Max number of gas units the tx is allowed to use
};
console.log("Creating transaction...");
const tx = new Tx(rawTxOptions);
console.log("Signing transaction...");
tx.sign(Buffer.from(accountA.privateKey.substring(2), "hex"));
console.log("Sending transaction...");
var serializedTx = tx.serialize();
const pTx = await web3.eth.sendSignedTransaction(
"0x" + serializedTx.toString("hex").toString("hex"),
);
console.log("tx transactionHash: " + pTx.transactionHash);

Once it completes, you can see the updated balances.

// After the transaction, there should be some ETH transferred
var accountABalance = await getAccountBalance(host, accountA);
console.log("Account A has an updated balance of: " + accountABalance);
var accountBBalance = await getAccountBalance(host, accountB);
console.log("Account B has an updatedbalance of: " + accountBBalance);
}

A full example can be found in the Developer Quickstart.

Use eth_sendTransaction

An alternative to using eth_sendSignedTransaction is eth_sendTransaction. However, Hyperledger Besu does not support the eth_sendTransaction API call and keeps account management separate for stronger security. Instead, Besu uses EthSigner to make the eth_sendTransaction API call.

An example can be found in the Developer Quickstart where the RPC node is paired with EthSigner. Refer to the EthSigner documentation configuration details.

Use eth_sendTransaction similarly to using eth_sendSignedTransaction (without the signing step which is done by EthSigner):

const web3 = new Web3(host);
// Pre-seeded account with 90000 ETH
const privateKeyA = "0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3";
const accountA = web3.eth.accounts.privateKeyToAccount(privateKeyA);
var accountABalance = web3.utils.fromWei(await web3.eth.getBalance(accountA.address));
console.log("Account A has balance of: " + accountABalance);

// Create a new account to transfer ETH to
var accountB = web3.eth.accounts.create();
var accountBBalance = web3.utils.fromWei(await web3.eth.getBalance(accountB.address));
console.log("Account B has balance of: " + accountBBalance);

// Send some ETH from A to B
const txOptions = {
from: accountA.address,
to: accountB.address,
value: "0x100", // Amount of ETH to transfer
gasPrice: "0x0", // ETH per unit of gas
gasLimit: "0x24A22" // Max number of gas units the tx is allowed to use
};
console.log("Creating transaction...");
const pTx = await web3.eth.sendTransaction(txOptions);
console.log("tx transactionHash: " + pTx.transactionHash);

// After the transaction, there should be some ETH transferred
var accountABalance = await getAccountBalance(host, accountA);
console.log("Account A has an updated balance of: " + accountABalance);
var accountBBalance = await getAccountBalance(host, accountB);
console.log("Account B has an updatedbalance of: " + accountBBalance);
}