0

Our app needs to detect and create a charging order asap whenever a user charges an amount of ETH/USDT(ERC20).

Due to the limit of infura API, we decided to set up our own ETH nodes and use JAVA to periodically check each address. When the balance increases, we will create a charging order with newblance-oldbalance.

But there are several issues: 1.The ETH nodes we own may crash or not fully synchronized so the latest balance is not accurate. 2.There are a lot addresses to scan and check each balance every time so it consumes too much CPU and resources.

Is there any better solution on this?

public BigDecimal balanceOf(String address) {
    BigDecimal bigDecimal = new BigDecimal("-1");

    Integer factor = 18;
    String contract = 0xXXXXXXXXX;

    try {
        Function function = new Function(
                "balanceOf",
                Collections.singletonList(new Address(address)),  // Solidity Types in smart contract functions
                Collections.singletonList(new TypeReference<Uint256>() {
                })
        );

        String encodedFunction = FunctionEncoder.encode(function);
        org.web3j.protocol.core.methods.response.EthCall response = getWeb3j().ethCall(
                Transaction.createEthCallTransaction(address, contract, encodedFunction),
                DefaultBlockParameterName.LATEST)
                .sendAsync().get(10, TimeUnit.SECONDS);

        String balance = response.getValue();

        if (StringUtility.isBlank(balance) || StringUtility.isBlank(balance.substring(2))) {
            return bigDecimal;
        }

        bigDecimal = Convert.fromWei(String.valueOf(Numeric.toBigInt(balance)), getEthUnit(factor));
    } catch (Exception e) {
        
    }
    return bigDecimal.setScale(6, BigDecimal.ROUND_HALF_UP);
}



public String getBalance(String address) {
    try {
        String balance = "0";
        BigDecimal bigDecimal = BigDecimal.ZERO;
        BigInteger prevNonce = BigInteger.ZERO;

        CryptoBalance cryptoBalance = CryptonBalanceAccessor.findBalanceByAddress(address);
        if (cryptoBalance != null) {
            balance = cryptoBalance.getBalance();
            prevNonce = new BigInteger(cryptoBalance.getNonce());
        }

        BigInteger latestNonce = getLatestNonce(address);
        if (!connect() || !isSynchronized(latestNonce, prevNonce)) {
            return balance;
        }

        for (int i = 0; i < 3; i++) {
            bigDecimal = balanceOf(address);
            if (bigDecimal.doubleValue() >= 0) {
                break;
            }
        }
        if (bigDecimal.doubleValue() < 0) {
            return balance;
        }

        Double walletBalance = Double.valueOf(balance);
        Double blockBalance = bigDecimal.doubleValue();


        if (blockBalance == walletBalance) {
            return balance;
        }
        COOSPayUtility.updateDigitalCoinBalance(address, Double.toString(blockBalance), latestNonce.toString(), "");
        if (walletBalance < blockBalance) {
        }
        return Double.toString(blockBalance);
    }
    catch (Exception e) {
        
    }
    return "0";
}
0
  1. The ETH nodes we own may crash or not fully synchronized so the latest balance is not accurate

You can use the etherescan API on opposite with infura API. Self-hosted node never works as expected.

I have a module to query two source at time and compare results.

  1. There are a lot addresses to scan and check each balance every time so it consumes too much CPU and resources.

Dont check addresses it cost too much resources instead check new mined block in order to find out if there are any transactions related to your addresses.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.