Ethereum Android Wallet Development Series: Retrieving ETH and Token Balances

ยท

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:

Understanding Ethereum Networks

Supported Networks

Ethereum operates across several networks:

  1. Mainnet: Production network with real value (PoW consensus)
  2. Ropsten: Testnet with PoW consensus
  3. Kovan: Testnet with PoA consensus (Parity-only)
  4. Rinkeby: Testnet with PoA consensus (Geth-only)
  5. 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

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:

  1. User adds tokens via UI
  2. RealmTokenSource persists the association
  3. TokenRepository fetches tokens via this sequence:
TokensViewModel โ†’ FetchTokensInteract โ†’ TokenRepository โ†’ TokenLocalSource โ†’ TokensViewModel

Using Ethplorer API

For Mainnet, the wallet uses Ethplorer's getAddressInfo endpoint:

/getAddressInfo/0xaccount?apiKey=freekey

Note the 2-second rate limit for free tier access.

Implementing Balance Checks

ETH Balance Retrieval

  1. Initialize Web3j instance:

    web3j = Web3j.build(new HttpService(networkInfo.rpcServerUrl));
  2. Call balance method:

    BigDecimal balance = new BigDecimal(web3j
        .ethGetBalance(walletAddress, DefaultBlockParameterName.LATEST)
        .send()
        .getBalance());

Token Balance Retrieval

  1. Construct balanceOf call:

    Function function = new Function(
        "balanceOf",
        Collections.singletonList(new Address(owner)),
        Collections.singletonList(new TypeReference<Uint256>() {}));
  2. 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

  1. Cache balance results to minimize RPC calls
  2. Implement error handling for network issues
  3. Use batch requests when checking multiple token balances
  4. Consider implementing balance change subscriptions via WebSocket

References

For further learning, visit our blockchain Q&A forum where experts answer development questions.