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";
}