Developing an Ethereum (ETH) wallet app is a pivotal step for developers entering the decentralized ecosystem. With the growing adoption of blockchain technology, creating secure and functional ETH wallets has become increasingly relevant. This guide walks you through the essential concepts, development setup, and practical implementation steps using Web3j, a powerful Java-based library ideal for both desktop and Android environments.
Understanding Ethereum and Smart Contracts
Before diving into wallet development, it's crucial to understand the core principles of Ethereum.
Ethereum is an open-source, decentralized blockchain platform with smart contract functionality. It enables developers to build and deploy applications that run without downtime, fraud, or third-party interference.
What Are Smart Contracts?
A smart contract is a self-executing program residing on the Ethereum blockchain. It has its own address and can receive transactions. When triggered by incoming data or value, the contract executes predefined logic—such as transferring tokens, updating records, or interacting with other contracts.
Unlike traditional transactions that only transfer funds, Ethereum transactions can carry additional data. This feature allows interaction with smart contracts, making them the backbone of decentralized applications (dApps).
Development Setup with Web3j
To streamline Ethereum integration in Java or Android apps, Web3j offers a robust, type-safe, and reactive solution.
Key Features of Web3j
- Full implementation of Ethereum’s JSON-RPC API via HTTP and IPC
- Native support for Ethereum wallet management
- Automatic generation of Java wrappers for Solidity smart contracts
- Reactive programming support for event filtering
- Integration with Infura, eliminating the need to run your own node
- Built-in support for ERC20 and ERC721 token standards
- Compatibility with Android and Quorum (enterprise blockchain)
Required Dependencies
For Java projects (JDK 8+):
compile 'org.web3j:core:4.5.12'For Android:
implementation 'org.web3j:core:4.2.0-android'👉 Discover how to securely manage digital assets with advanced tools
Connecting to the Ethereum Network
You can interact with the Ethereum blockchain either by running your own node or using services like Infura.
Synchronous Request Example
Web3j web3 = Web3j.build(new HttpService("https://mainnet.infura.io/v3/YOUR_PROJECT_ID"));
Web3ClientVersion version = web3.web3ClientVersion().send();
System.out.println("Client version: " + version.getWeb3ClientVersion());Asynchronous Request Example
web3.web3ClientVersion().sendAsync()
.thenAccept(result -> System.out.println(result.getWeb3ClientVersion()))
.exceptionally(e -> {
e.printStackTrace();
return null;
});Using asynchronous calls improves performance, especially in mobile applications where responsiveness is key.
Building an ETH Wallet: Practical Implementation
Now let’s implement core wallet functionalities such as account creation, import methods, balance checking, and fund transfers.
1. Generate a New Ethereum Account
Creating a new wallet involves generating a mnemonic phrase (seed), deriving a private key, and storing credentials securely.
String mnemonic = ChainUtil.genMnemonic();
ECKey ecKey = ChainUtil.genECKey(mnemonic, "m/44'/60'/0'/0/0", "");
ECKeyPair keyPair = ECKeyPair.create(ecKey.getPrivKeyBytes());
File walletDir = new File("/path/to/keystore");
String fileName = WalletUtils.generateWalletFile("your-password", keyPair, walletDir, false);
Credentials credentials = WalletUtils.loadCredentials("your-password", new File(walletDir, fileName));
String address = credentials.getAddress();
System.out.println("Address: " + address);
System.out.println("Mnemonic: " + mnemonic);
System.out.println("Private Key: " + keyPair.getPrivateKey().toString(16));This process ensures user ownership and enables recovery via the mnemonic phrase.
2. Import Wallet via Private Key
Users may want to import existing wallets using their private keys:
Credentials credentials = Credentials.create("your-private-key");
String address = credentials.getAddress();Note: While private keys allow access, they cannot be used to derive a mnemonic phrase due to cryptographic one-way functions.
3. Import Using Keystore File
Keystore files encrypt private keys with a password. Here's how to decrypt one:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
WalletFile walletFile = mapper.readValue(keystoreJson, WalletFile.class);
ECKeyPair keyPair = Wallet.decrypt("password", walletFile);
Credentials credentials = Credentials.create(keyPair);4. Import via Mnemonic Phrase
Recover a wallet using a 12- or 24-word recovery phrase:
String mnemonic = "word1,word2,...,word12";
ECKey ecKey = ChainUtil.genECKey(mnemonic, "m/44'/60'/0'/0/0", "");
// Continue as above to generate credentialsPerforming Transactions
Transfer ETH (Ether)
Sending ETH requires setting up gas price, gas limit, nonce, and signing the transaction.
BigInteger nonce = web3.ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).send().getTransactionCount();
RawTransaction rawTx = RawTransaction.createTransaction(
nonce, gasPrice, BigInteger.valueOf(21000), toAddress, value, ""
);
Credentials credentials = Credentials.create(privateKey);
byte[] signedMessage = TransactionEncoder.signMessage(rawTx, credentials);
String hexValue = Numeric.toHexString(signedMessage);
EthSendTransaction response = web3.ethSendRawTransaction(hexValue).send();
System.out.println("Transaction Hash: " + response.getTransactionHash());Transfer ERC20 Tokens
Token transfers involve calling the transfer function on the token contract:
Function function = new Function(
"transfer",
Arrays.asList(new Address(to), new Uint256(value)),
Collections.singletonList(new TypeReference<Bool>() {})
);
String data = FunctionEncoder.encode(function);
RawTransaction rawTx = RawTransaction.createTransaction(nonce, gasPrice, BigInteger.valueOf(60000), contractAddress, data);
// Sign and send as aboveGas limit is higher for token transfers due to smart contract execution.
Checking Balances
Get ETH Balance
BigInteger balanceWei = web3.ethGetBalance(address, DefaultBlockParameterName.LATEST).send().getBalance();
BigDecimal balanceEth = Convert.fromWei(balanceWei.toString(), Convert.Unit.ETHER);
System.out.println("ETH Balance: " + balanceEth);Get ERC20 Token Balance
Use eth_call to query token smart contracts:
String data = "0x70a08231000000000000000000000000" + addressNoPrefix;
Transaction tx = Transaction.createEthCallTransaction(walletAddress, tokenContract, data);
EthCall response = web3.ethCall(tx, DefaultBlockParameterName.LATEST).send();
BigInteger tokenBalance = new BigInteger(response.getValue(), 16);Common Issues and Solutions
Fixing Out-of-Memory Errors on Android
When importing heavy keystore files on Android, you may encounter OutOfMemoryError due to high scrypt parameters (n=262144). The default JVM implementation struggles under load.
Solution: Replace the default scrypt library:
implementation 'com.lambdaworks:scrypt:1.4.0'Then override the key derivation method:
derivedKey = com.lambdaworks.crypto.SCrypt.scrypt(passwordBytes, salt, n, r, p, dklen);This significantly reduces memory usage during decryption.
👉 Learn how top developers secure their blockchain applications
Frequently Asked Questions (FAQ)
Q: Can I recover my wallet without a private key?
A: Yes—using the mnemonic phrase or keystore file with password. These methods derive the private key securely without exposing it directly.
Q: Is Web3j suitable for production apps?
A: Absolutely. Web3j is widely used in enterprise and consumer applications due to its stability, active maintenance, and comprehensive feature set.
Q: How do I handle different Ethereum networks (testnet vs mainnet)?
A: Simply change the node URL (e.g., use Infura endpoints for Ropsten or Sepolia testnets). Web3j treats all EVM-compatible chains similarly.
Q: What’s the difference between gas price and gas limit?
A: Gas price is how much you’re willing to pay per unit of computation (in Gwei), while gas limit is the maximum units you allow. For simple ETH transfers, 21,000 is standard.
Q: Are mnemonic phrases secure?
A: They are cryptographically secure if generated properly and kept confidential. Never share or store them digitally in plaintext.
Final Thoughts
Building an Ethereum wallet app is accessible thanks to mature libraries like Web3j. By mastering account management, transaction handling, and balance queries, developers can create full-featured wallets for desktop or mobile platforms.
Security remains paramount—always use encrypted storage, validate inputs, and follow best practices for key management.