How to Transfer ETH Using Web3j: A Developer’s Guide

·

Transferring Ether (ETH) between Ethereum addresses is one of the most fundamental operations in blockchain development. Whether you're building decentralized applications (dApps), managing smart contracts, or integrating wallet functionality, understanding how to programmatically send ETH using Web3j is essential.

This guide walks you through the core concepts and practical implementation steps for sending ETH using the Web3j library in Java. We’ll cover basic transfers, EIP-1559 transaction support, nonce handling, gas management, and how to retrieve transaction and block data—ensuring your application remains compatible with modern Ethereum standards.


Core Requirements for Sending Ether

To transfer ETH from one address to another, two key parameters are required:

At its simplest, a raw transaction can be constructed like this:

BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
    <nonce>, <gasPrice>, <gasLimit>, <toAddress>, value);

While this approach gives you full control over transaction construction, it requires manual management of nonces, gas estimation, and confirmation polling—increasing complexity and potential for errors.

👉 Discover how to streamline blockchain interactions with powerful tools


Recommended Method: Using the Transfer Class

For most use cases, Web3j provides the Transfer utility class, which simplifies the entire process by automatically handling:

Here’s how to send ETH using the Transfer class:

Web3j web3 = Web3j.build(new HttpService()); // Connects to localhost:8545 by default
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");

TransactionReceipt transactionReceipt = Transfer.sendFunds(
    web3,
    credentials,
    "0x recipient-address-here ",
    BigDecimal.valueOf(1.0),
    Convert.Unit.ETHER
).send();

This method abstracts away low-level details while maintaining reliability and compatibility with existing Ethereum networks.


Supporting EIP-1559 Transactions

Since the London hard fork, Ethereum has adopted EIP-1559, which introduced a new transaction pricing mechanism that includes base fees and priority fees. To ensure your transactions are efficient and cost-effective, use sendFundsEIP1559():

TransactionReceipt transactionReceipt = Transfer.sendFundsEIP1559(
    web3,
    credentials,
    "0x recipient-address-here ",               // Destination address
    BigDecimal.ONE,                             // Value in ETH
    Convert.Unit.ETHER,                         // Unit
    BigInteger.valueOf(8_000_000),              // Gas limit
    BigInteger.valueOf(3_000_000_000L),         // Max priority fee per gas (tip)
    BigInteger.valueOf(50_000_000_000L)         // Max fee per gas (cap)
).send();

EIP-1559 transactions provide better predictability and reduce overpayment on gas during network congestion.

Accessing Transaction Details

Once a transaction is confirmed, you can extract important metadata from the TransactionReceipt:

transactionReceipt.getType();               // Returns 2 for EIP-1559 transactions
transactionReceipt.getEffectiveGasPrice();  // Actual price paid per gas unit

These fields help monitor transaction behavior and optimize future sends.


Retrieving Block Data with Web3j

Understanding block-level data is crucial for tracking network activity and validating transactions. With Web3j, you can fetch blocks by number or hash and access new EIP-1559 fields such as baseFeePerGas.

Get Block by Number

EthBlock.Block block = web3j.ethGetBlockByNumber(
    DefaultBlockParameter.valueOf("latest"),
    true // Return full transaction objects
).send().getBlock();

block.getBaseFeePerGas(); // Available post-London fork

Other Block Retrieval Options

You can also retrieve blocks and uncles using various methods:

// By block hash
EthBlock.Block block = web3j.ethGetBlockByHash("0x...", true).send().getBlock();

// Uncle blocks by hash and index
EthBlock.Block uncle = web3j.ethGetUncleByBlockHashAndIndex(
    "0x...", BigInteger.valueOf(0)).send().getBlock();

// Uncle by block number and index
EthBlock.Block uncleNum = web3j.ethGetUncleByBlockNumberAndIndex(
    DefaultBlockParameter.valueOf("latest"), BigInteger.valueOf(0)).send().getBlock();

These functions are useful for advanced analytics, consensus monitoring, or syncing historical data.


Fetching Individual Transactions

Web3j allows precise access to individual transactions via multiple query methods:

// By transaction hash
EthTransaction ethTransaction = web3j.ethGetTransactionByHash("0x...")
    .send();

// By block hash and transaction index
EthTransaction ethTransaction = web3j.ethGetTransactionByBlockHashAndIndex(
    "0x...", BigInteger.valueOf(0)).send();

// By block number and index
EthTransaction ethTransaction = web3j.ethGetTransactionByBlockNumberAndIndex(
    DefaultBlockParameter.valueOf("latest"), BigInteger.valueOf(0)).send();

Each returned object contains sender, receiver, value, gas details, and transaction type—enabling deep inspection of on-chain activity.

👉 Explore seamless blockchain integration with developer-friendly tools


Frequently Asked Questions

Q: What is Web3j used for?

A: Web3j is a lightweight Java library for integrating with Ethereum nodes. It enables developers to send transactions, interact with smart contracts, read blockchain data, and manage wallets directly from Java or Android applications.

Q: Do I need to manually handle nonces when using Transfer.sendFunds()?

A: No. The Transfer class automatically retrieves the current nonce from the network and increments it appropriately, reducing the risk of replay attacks or failed transactions due to incorrect nonce values.

Q: How does EIP-1559 improve ETH transfers?

A: EIP-1559 introduces a base fee that gets burned and a priority fee (tip) paid to miners. This model stabilizes transaction pricing, improves predictability, and prevents overpayment during high demand periods.

Q: Can I use Web3j to interact with other EVM-compatible chains?

A: Yes. Web3j works with any Ethereum Virtual Machine (EVM)-compatible blockchain such as Binance Smart Chain, Polygon, Arbitrum, and Avalanche—provided you connect to a valid node endpoint.

Q: Is sending raw transactions safe?

A: Raw transactions offer fine-grained control but require careful handling of gas limits, prices, and nonces. For most developers, using higher-level abstractions like the Transfer class is safer and less error-prone.

Q: How do I check if an ETH transfer succeeded?

A: Always inspect the TransactionReceipt. If getStatus().equals("0x1") or isStatusOK() returns true (depending on client version), the transaction was successful. Also verify getBlockNumber() is not null.


Final Thoughts

Programmatically transferring ETH using Web3j is both powerful and straightforward when leveraging built-in utilities like the Transfer class. By supporting both legacy and EIP-1559 transactions, Web3j ensures your applications remain up-to-date with Ethereum’s evolving standards.

Whether you're building backend services, mobile wallets, or enterprise blockchain solutions, mastering these fundamentals lays the foundation for robust, scalable development.

👉 Start building smarter with advanced blockchain APIs today