This guide continues our Ethereum Android wallet development series, focusing on retrieving account balances for both ETH and ERC20 tokens.
Recap
In the previous installment, we introduced the TokensViewModel to decouple UI from data handling. Let's revisit its structure:
public class TokensViewModel extends ViewModel {
private final MutableLiveData<ETHWallet> defaultWallet;
private final MutableLiveData<NetworkInfo> defaultNetwork;
private final MutableLiveData<Token[]> tokens;
private final MutableLiveData<Ticker> prices;
}Key components:
tokens: Array of tokens owned by the accountdefaultNetwork: Current active blockchain networkprices: Exchange rate data (covered later)
Understanding Ethereum Networks
Supported Networks
Ethereum operates across several networks:
- Mainnet: Production network with real value (PoW consensus)
- Ropsten: Testnet with PoW consensus
- Kovan: Testnet with PoA consensus (Parity-only)
- Rinkeby: Testnet with PoA consensus (Geth-only)
- Goerli: Cross-client testnet for Eth2.0 preparation
๐ Explore network differences
NetworkInfo Class
The wallet represents networks through this structure:
public class NetworkInfo {
public final String name; // Network identifier (e.g., "mainnet")
public final String symbol; // "ETH"
public final String rpcServerUrl; // Node RPC endpoint
public final String backendUrl; // Transaction history service
public final String etherscanUrl;
public final int chainId;
public final boolean isMainNetwork;
}Determining Active Network
The wallet stores the user-selected network in SharedPreferences, then matches it against the NETWORKS array in EthereumNetworkRepository.java.
Balance Retrieval Fundamentals
Ethereum Account Model
- ETH balances are stored in the account's
balancefield, retrievable viaeth_getBalanceRPC call - Token balances are stored in smart contracts, accessible through
balanceOf(address)calls
Token Class Structure
The wallet unifies ETH and tokens through this class:
public class Token {
public final TokenInfo tokenInfo;
public final String balance; // Token amount
public String value; // Fiat equivalent
}
public class TokenInfo {
public final String address; // Contract address
public final String name;
public final String symbol; // Token symbol (e.g., "USDT")
public final int decimals; // Token precision
}Retrieving Account Assets
Associating Tokens
Token associations per account are stored in Realm database files. The process involves:
- User adds tokens via UI
RealmTokenSourcepersists the associationTokenRepositoryfetches tokens via this sequence:
TokensViewModel โ FetchTokensInteract โ TokenRepository โ TokenLocalSource โ TokensViewModelUsing Ethplorer API
For Mainnet, the wallet uses Ethplorer's getAddressInfo endpoint:
/getAddressInfo/0xaccount?apiKey=freekeyNote the 2-second rate limit for free tier access.
Implementing Balance Checks
ETH Balance Retrieval
Initialize Web3j instance:
web3j = Web3j.build(new HttpService(networkInfo.rpcServerUrl));Call balance method:
BigDecimal balance = new BigDecimal(web3j .ethGetBalance(walletAddress, DefaultBlockParameterName.LATEST) .send() .getBalance());
Token Balance Retrieval
Construct balanceOf call:
Function function = new Function( "balanceOf", Collections.singletonList(new Address(owner)), Collections.singletonList(new TypeReference<Uint256>() {}));Execute contract call:
String encodedFunction = FunctionEncoder.encode(function); EthCall response = web3j.ethCall( Transaction.createEthCallTransaction(walletAddress, contractAddress, encodedFunction), DefaultBlockParameterName.LATEST).send();
Balance Formatting
Convert raw balances to user-friendly formats:
BigDecimal decimalDivisor = new BigDecimal(Math.pow(10, decimals));
String displayBalance = balance.divide(decimalDivisor)
.setScale(4, RoundingMode.CEILING)
.toPlainString();๐ Advanced balance handling techniques
FAQ Section
Q: Why does my testnet ETH balance show as zero?
A: Testnet ETH must be obtained through faucets - each test network has its own faucet system.
Q: How often should I refresh balances?
A: For active accounts, refresh every 15-30 seconds. For passive monitoring, every 5-10 minutes is sufficient.
Q: Why don't some tokens appear automatically?
A: The wallet only shows tokens you've manually added through the UI or that appear in transactions.
Best Practices
- Cache balance results to minimize RPC calls
- Implement error handling for network issues
- Use batch requests when checking multiple token balances
- Consider implementing balance change subscriptions via WebSocket
References
For further learning, visit our blockchain Q&A forum where experts answer development questions.