Working with Ethereum: A Comprehensive Guide to Blockchain Interactions

ยท

Understanding Account Nonce in Ethereum

Every Ethereum transaction requires a nonce - a sequential number that prevents double-spending. Here's how to retrieve it programmatically:

public static BigInteger getNonce(Web3j web3j, String addr) {
    try {
        EthGetTransactionCount getNonce = web3j.ethGetTransactionCount(
            addr,
            DefaultBlockParameterName.PENDING
        ).send();
        return getNonce.getTransactionCount();
    } catch (IOException e) {
        throw new RuntimeException("Network error occurred");
    }
}

Checking ETH Balances

To check an account's Ether balance:

public static BigDecimal getBalance(Web3j web3j, String address) {
    try {
        EthGetBalance balanceResponse = web3j.ethGetBalance(
            address, 
            DefaultBlockParameterName.LATEST
        ).send();
        return Convert.fromWei(
            new BigDecimal(balanceResponse.getBalance()),
            Convert.Unit.ETHER
        );
    } catch (IOException e) {
        throw new RuntimeException("Balance check failed");
    }
}

Retrieving Token Balances

Method 1: Direct Contract Interaction

public static BigInteger getTokenBalance(Web3j web3j, String fromAddress, String contractAddress) {
    Function function = new Function(
        "balanceOf",
        Collections.singletonList(new Address(fromAddress)),
        Collections.singletonList(new TypeReference<Uint256>() {})
    );
    
    String encodedFunction = FunctionEncoder.encode(function);
    Transaction transaction = Transaction.createEthCallTransaction(
        fromAddress, 
        contractAddress, 
        encodedFunction
    );

    try {
        EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
        List<Type> results = FunctionReturnDecoder.decode(
            response.getValue(), 
            function.getOutputParameters()
        );
        return (BigInteger) results.get(0).getValue();
    } catch (IOException e) {
        throw new RuntimeException("Token balance check failed");
    }
}

Method 2: Using Etherscan API

For mainnet tokens only:

String tokenBalanceUrl = "https://api.etherscan.io/api?module=account"
    + "&action=tokenbalance"
    + "&contractaddress=TOKEN_CONTRACT_ADDRESS"
    + "&address=ACCOUNT_ADDRESS"
    + "&tag=latest"
    + "&apikey=YOUR_API_KEY";

String result = HttpRequest.sendGet(tokenBalanceUrl);
TokenBalanceResult balanceResult = JSON.parseObject(result, TokenBalanceResult.class);
BigDecimal tokenCount = new BigDecimal(balanceResult.getResult())
    .divide(BigDecimal.TEN.pow(TOKEN_DECIMALS));

Constructing Ethereum Transactions

ETH Transfer Transaction

Transaction transaction = Transaction.createEtherTransaction(
    fromAddr, 
    nonce, 
    gasPrice, 
    gasLimit, 
    toAddr, 
    value
);

Smart Contract Function Call

Transaction transaction = Transaction.createFunctionCallTransaction(
    fromAddr, 
    nonce, 
    gasPrice, 
    gasLimit, 
    contractAddr, 
    funcABI
);

Estimating Gas Costs

public static BigInteger estimateGas(Web3j web3j, Transaction transaction) {
    try {
        EthEstimateGas estimate = web3j.ethEstimateGas(transaction).send();
        return estimate.getAmountUsed();
    } catch (IOException e) {
        throw new RuntimeException("Gas estimation failed");
    }
}

๐Ÿ‘‰ Want to learn advanced gas optimization techniques?

Executing ETH Transfers

public static String transferETH(Web3j web3j, Credentials credentials, String toAddr, BigDecimal amount) {
    BigInteger nonce = getNonce(web3j, credentials.getAddress());
    BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger();
    
    Transaction transaction = Transaction.createEtherTransaction(
        credentials.getAddress(),
        nonce,
        gasPrice,
        gasLimit,
        toAddr,
        value
    );

    return signAndSend(web3j, credentials, transaction);
}

Transferring Token Assets

public static String transferToken(Web3j web3j, Credentials credentials, String toAddr, String contractAddr, BigDecimal amount) {
    Function function = new Function(
        "transfer",
        Arrays.asList(
            new Address(toAddr),
            new Uint256(amount.scaleByPowerOfTen(18).toBigInteger())
        ),
        Collections.emptyList()
    );

    String encodedFunction = FunctionEncoder.encode(function);
    BigInteger nonce = getNonce(web3j, credentials.getAddress());
    
    Transaction transaction = Transaction.createFunctionCallTransaction(
        credentials.getAddress(),
        nonce,
        gasPrice,
        gasLimit,
        contractAddr,
        encodedFunction
    );

    return signAndSend(web3j, credentials, transaction);
}

Transaction Signing and Submission

public static String signAndSend(Web3j web3j, Credentials credentials, Transaction transaction) {
    byte chainId = 1; // Mainnet
    RawTransaction rawTransaction = RawTransaction.createTransaction(
        transaction.getNonce(),
        transaction.getGasPrice(),
        transaction.getGasLimit(),
        transaction.getTo(),
        transaction.getValue(),
        transaction.getData()
    );

    byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, chainId, credentials);
    String hexValue = Numeric.toHexString(signedMessage);

    try {
        EthSendTransaction response = web3j.ethSendRawTransaction(hexValue).send();
        return response.getTransactionHash();
    } catch (IOException e) {
        throw new RuntimeException("Transaction submission failed");
    }
}

Dynamic Gas Pricing Strategies

For time-sensitive transactions, consider dynamic gas pricing:

// Using EthGasStation API
String gasStationUrl = "https://ethgasstation.info/json/ethgasAPI.json";
String response = HttpRequest.sendGet(gasStationUrl, "");
GasPriceData gasData = JSON.parseObject(response, GasPriceData.class);

// Convert to wei
BigInteger averageGasPrice = gasData.getAverage().multiply(BigInteger.TEN.pow(8));
BigInteger fastGasPrice = gasData.getFast().multiply(BigInteger.TEN.pow(8));

๐Ÿ‘‰ Explore more blockchain development resources

FAQ Section

What is a nonce in Ethereum?

A nonce is a sequentially incrementing number used in Ethereum transactions to ensure each transaction is unique and to prevent replay attacks.

How can I speed up my Ethereum transaction?

You can increase the gas price (priority fee) to incentivize miners to include your transaction in the next block.

What's the difference between ETH transfer and token transfer?

ETH transfers are native currency transfers, while token transfers involve calling smart contract functions to move ERC-20 tokens.

How do I estimate the right gas limit?

For simple ETH transfers, 21,000 gas is standard. For contract interactions, use the ethEstimateGas RPC call.

What happens if I set the wrong gas price?

Too low: Your transaction may take hours/days to process or get stuck. Too high: You'll overpay for transaction processing.

Can I cancel a pending transaction?

Yes, by sending a new transaction with the same nonce and higher gas price, with zero value to your own address.