fix
Helius
2022-09-14 ed86dfe43e1815e6803568b137f8984735186b25
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
@@ -1,308 +1,428 @@
package cc.mrbird.febs.dapp.chain;
import cc.mrbird.febs.common.exception.FebsException;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.*;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Convert.Unit;
import org.web3j.utils.Numeric;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
 * ETH类,使用Web3j 下面为使用教程
 * https://kauri.io/article/925d923e12c543da9a0a3e617be963b4/manage-an-ethereum-account-with-java-and-web3js
 *
 * @author Administrator
 *
 */
@Slf4j
public class EthService {
   private static String ethWalletPath = "/home/javaweb/webresource/eth";
   private Web3j web3j;
   /**
    * 服务器地址
    */
   //private static final String ETH_UTL = "http://120.55.86.146:8545";
   //   private static final String ETH_UTL = "http://114.55.250.231:8545";
   private static final String ETH_UTL = "https://mainnet.infura.io/v3/f54a5887a3894ebb9425920701a97fe0";
   public EthService() {
      try {
         HttpService service = new HttpService(ETH_UTL);
         web3j = Web3j.build(service);
      } catch (Exception e) {
         log.error("连接eth网络失败", e);
      }
   }
   /**
    * 查询ETH余额
    *
    * @param address
    * @return
    */
   public static BigDecimal getEthBlance(String address) {
      Web3j web3 = Web3j.build(new HttpService(ETH_UTL));
      EthGetBalance balanceWei;
      try {
         balanceWei = web3.ethGetBalance(address, DefaultBlockParameterName.LATEST).send();
         if (balanceWei.getResult() == null) {
            return null;
         }
         BigDecimal balanceInEther = Convert.fromWei(balanceWei.getBalance().toString(), Unit.ETHER);
         return balanceInEther;
      } catch (Exception e) {
         System.out.println("ETH查询失败:" + address);
         e.printStackTrace();
      }
      return null;
   }
   /**
    * 创建ETH钱包
    *
    * @return
    */
   public static Map<String, String> createEth() {
      Map<String, String> wallet = new HashMap<String, String>();
      try {
         String walletPassword = "secr3t";
         // 文件路径
         String walletDirectory = ethWalletPath;
         String walletName = WalletUtils.generateNewWalletFile(walletPassword, new File(walletDirectory));
         System.out.println("wallet location: " + walletDirectory + "/" + walletName);
         Credentials credentials = WalletUtils.loadCredentials(walletPassword, walletDirectory + "/" + walletName);
         String accountAddress = credentials.getAddress();
         String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);
         // 钱包地址
         wallet.put("address", accountAddress);
         // 钱包私钥
         wallet.put("privateKey", privateKey);
         // 产生的钱包文件地址
         wallet.put("walletLocation", walletDirectory + "/" + walletName);
      } catch (Exception e) {
         e.printStackTrace();
      }
      return wallet;
   }
   public boolean checkTransferResult(String hash) {
      // 0xa3e6a0ccc3aac30d866a86ca9c0477dd58b7b061787ba40b16c3844803273816 交易hash
      Request<?, EthGetTransactionReceipt> ethGetTransactionReceiptRequest = web3j.ethGetTransactionReceipt(hash);
      EthGetTransactionReceipt send = null;
      try {
         send = ethGetTransactionReceiptRequest.send();
         if(send!=null){
            TransactionReceipt result = send.getResult();
            if(result!=null){
               String status = result.getStatus();
               System.out.println(status);//0x1
               if("0x1".equals(status)){
                  return true;
               }else{
                  return false;
               }
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
         return false;
      }
        return false;
   }
   public static void main(String[] args) throws IOException {
      HttpService service = new HttpService(ETH_UTL);
      Web3j build = Web3j.build(service);
      //Request<?, EthTransaction> ethTransactionRequest = build.ethGetTransactionByHash("0xa3e6a0ccc3aac30d866a86ca9c0477dd58b7b061787ba40b16c3844803273816");
      Request<?, EthGetTransactionReceipt> ethGetTransactionReceiptRequest = build.ethGetTransactionReceipt("0xa3e6a0ccc3aac30d866a86ca9c0477dd58b7b061787ba40b16c3844803273816");
      EthGetTransactionReceipt send = ethGetTransactionReceiptRequest.send();
      String status = send.getResult().getStatus();
      System.out.println(status);//0x1
//      EthTransaction send = ethTransactionRequest.send();
//      String input = send.getResult().getInput();
//      System.out.println(input);
   }
   /**
    *
    * 方法描述:获取代币余额
    *
    * @param fromAddress
    * @param
    * @param
    * @return long
    */
   public BigDecimal tokenGetBalance(String fromAddress) {
      try {
         // 合约地址
         String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
         int decimal = 6;
         String methodName = "balanceOf";
         List<Type> inputParameters = new ArrayList<>();
         List<TypeReference<?>> outputParameters = new ArrayList<>();
         Address address = new Address(fromAddress);
         inputParameters.add(address);
         TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
         };
         outputParameters.add(typeReference);
         Function function = new Function(methodName, inputParameters, outputParameters);
         String data = FunctionEncoder.encode(function);
         Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
         EthCall ethCall;
         BigInteger balanceValue = BigInteger.ZERO;
         try {
            ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
            List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
            balanceValue = (BigInteger) results.get(0).getValue();
         } catch (IOException e) {
            e.printStackTrace();
         }
         double res = new BigDecimal(balanceValue).divide(BigDecimal.valueOf(Math.pow(10, decimal)), 8, RoundingMode.HALF_DOWN).doubleValue();
         if (res > 0) {
            return new BigDecimal(res);
         }
      } catch (Exception e) {
         // logger.error("==============以太坊代币链接获取失败!");
         e.printStackTrace();
      }
      return BigDecimal.ZERO;
   }
   // USDT
   public String tokenSend(String privateKey, String fromAddress, String toAddress, String amount,String gas)
         throws InterruptedException, ExecutionException {
      // Web3j web3j = Web3j.build(new
      // HttpService("https://mainnet.infura.io/v3/882c66ebcfc141abbea22b948fa44321"));
      if(StringUtils.isBlank(gas)){
         gas="70";
      }
      String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
      Credentials credentials = Credentials.create(privateKey);
      EthGetTransactionCount ethGetTransactionCount = web3j
            .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
      BigInteger nonce = ethGetTransactionCount.getTransactionCount();
      Function function = new Function("transfer",
            Arrays.asList(new Address(toAddress), new Uint256(new BigInteger(amount))),
            Arrays.asList(new TypeReference<Type>() {
            }));
      String encodedFunction = FunctionEncoder.encode(function);
      RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
            Convert.toWei(gas, Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
            Convert.toWei("60000", Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
              // 10*80000/1000000000=0.0008 手续费
      byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
      String hexValue = Numeric.toHexString(signedMessage);
      // log.debug("transfer hexValue:" + hexValue);
      CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
      EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
      //return "hash";
      if (ethSendTransaction.hasError()) {
         // log.info("transfer error:", ethSendTransaction.getError().getMessage());
         return "";
      } else {
         String transactionHash = ethSendTransaction.getTransactionHash();
         // log.info("Transfer transactionHash:" + transactionHash);
         return transactionHash;
      }
   }
   public String ethSend(String privateKey, String fromAddress, String toAddress, String amount,String gas)
         throws InterruptedException, ExecutionException {
      // Web3j web3j = Web3j.build(new
      // HttpService("https://mainnet.infura.io/v3/882c66ebcfc141abbea22b948fa44321"));
      if(StringUtils.isBlank(gas)){
         gas="70";
      }
      Credentials credentials = Credentials.create(privateKey);
      EthGetTransactionCount ethGetTransactionCount = web3j
            .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
      BigInteger nonce = ethGetTransactionCount.getTransactionCount();
      BigInteger value = Convert.toWei(amount, Unit.ETHER).toBigInteger();
      RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce,
            Convert.toWei(gas, Unit.GWEI).toBigInteger(),
            Convert.toWei("60000", Unit.WEI).toBigInteger(), toAddress, value);
      byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
      String hexValue = Numeric.toHexString(signedMessage);
      EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
      if (ethSendTransaction.hasError()) {
         // log.info("transfer error:", ethSendTransaction.getError().getMessage());
         return "";
      } else {
         String transactionHash = ethSendTransaction.getTransactionHash();
         // log.info("Transfer transactionHash:" + transactionHash);
         return transactionHash;
      }
   }
   public BigInteger ethAllowance(String toAddress, String fromAddress) {
      String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
      String methodName = "allowance";
      List<TypeReference<?>> outputParameters = new ArrayList<>();
      TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {};
      outputParameters.add(typeReference);
      Function function = new Function(methodName,
            Arrays.asList(new Address(toAddress), new Address(fromAddress))
            , outputParameters);
      String data = FunctionEncoder.encode(function);
      Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
      EthCall ethCall = null;
      try {
         ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
         List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
         return (BigInteger) results.get(0).getValue();
      } catch (IOException e) {
         e.printStackTrace();
      }
      return BigInteger.ZERO;
   }
}
package cc.mrbird.febs.dapp.chain;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.jcajce.provider.digest.SHA3;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.*;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.*;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
 * @author wzy
 * @date 2022-04-15
 **/
public class EthService implements ContractChainService {
    private Web3j web3j;
    private String url;
    private String ownerAddress;
    private String privateKey;
    private String contractAddress;
    public EthService(String url, String address, String privateKey, String contractAddress) {
        this.url = url;
        this.ownerAddress = address;
        this.privateKey = privateKey;
        this.contractAddress = contractAddress;
        HttpService service = new HttpService(url);
        web3j = Web3j.build(service);
    }
    public static void main(String[] args) throws IOException {
        HttpService service = new HttpService("https://bsc-dataseed1.ninicoin.io");
        Web3j web3j = Web3j.build(service);
        long start = System.currentTimeMillis();
        Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
        EthBlockNumber send = request.send();
        BigInteger bigInteger = Numeric.decodeQuantity(send.getResult());
        long end = System.currentTimeMillis();
        System.out.println(end - start);
//        String address = "0x971c09aa9735eb98459b17ec8b48932d24cbb931";
//        String nonce = "0x1d5f7444107bc02e980deda39d0fce21b06c9da4233a19cb11124cb5bfefc9ec";
//        String sign = "0x8f92cee24906122e26c3cc6cbd72f851cfe2c9574aa03bf3371e5d506fbec68b2ad22bbbc19b00ed21d26ab5a6871507831e2c902d8ed8c33301addc2b57a7731b";
//
//        String result = address + ":" + nonce + ":" + sign;
//        System.out.println(Hash.sha3(result));
//        Web3Sha3 send = web3j.web3Sha3(result).send();
//        System.out.println(1);
    }
    @Override
    public BigInteger balanceOfUnDecimal(String fromAddress) {
        try {
            String methodName = "balanceOf";
            List<Type> inputParameters = new ArrayList<>();
            List<TypeReference<?>> outputParameters = new ArrayList<>();
            Address address = new Address(fromAddress);
            inputParameters.add(address);
            TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
            };
            outputParameters.add(typeReference);
            Function function = new Function(methodName, inputParameters, outputParameters);
            String data = FunctionEncoder.encode(function);
            Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
            EthCall ethCall;
            BigInteger balanceValue = BigInteger.ZERO;
            try {
                ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
                List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
                balanceValue = (BigInteger) results.get(0).getValue();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return balanceValue;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BigInteger.ZERO;
    }
    @Override
    public int decimals() {
        try {
            String methodName = "decimals";
            List<Type> inputParameters = new ArrayList<>();
            List<TypeReference<?>> outputParameters = new ArrayList<>();
            TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
            };
            outputParameters.add(typeReference);
            Function function = new Function(methodName, inputParameters, outputParameters);
            String data = FunctionEncoder.encode(function);
            Transaction transaction = Transaction.createEthCallTransaction(null, contractAddress, data);
            EthCall ethCall;
            BigInteger decimals = BigInteger.ZERO;
            try {
                ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
                List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
                decimals = (BigInteger) results.get(0).getValue();
                return decimals.intValue();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
    @Override
    public BigDecimal balanceOf(String fromAddress) {
        int decimal = decimals();
        BigInteger balanceValue = balanceOfUnDecimal(fromAddress);
        double res = new BigDecimal(balanceValue).divide(BigDecimal.valueOf(Math.pow(10, decimal)), 8, RoundingMode.HALF_DOWN).doubleValue();
        if (res > 0) {
            return new BigDecimal(res);
        }
        return BigDecimal.ZERO;
    }
    @Override
    public BigInteger allowance(String address) {
        String methodName = "allowance";
        List<TypeReference<?>> outputParameters = new ArrayList<>();
        TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
        };
        outputParameters.add(typeReference);
        Function function = new Function(methodName,
                Arrays.asList(new Address(address), new Address(ownerAddress))
                , outputParameters);
        String data = FunctionEncoder.encode(function);
        Transaction transaction = Transaction.createEthCallTransaction(ownerAddress, contractAddress, data);
        EthCall ethCall = null;
        try {
            ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
            List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
            return (BigInteger) results.get(0).getValue();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return BigInteger.ZERO;
    }
    @Override
    public boolean isAllowance(String address) {
        return allowance(address).intValue() != 0;
    }
    public String getGas() {
        String gas;
        if (url.contains("infura.io")) {
            String resp = HttpUtil.get("https://etherscan.io/autoUpdateGasTracker.ashx?sid=75f30b765180f29e2b7584b8501c9124");
            JSONObject data = JSONObject.parseObject(resp);
            gas = data.getString("avgPrice");
        } else {
            String resp = HttpUtil.get("https://gbsc.blockscan.com/gasapi.ashx?apikey=key&method=gasoracle");
            JSONObject data = JSONObject.parseObject(resp);
            gas = data.getString("FastGasPrice");
        }
        return StrUtil.isBlank(gas) ? "35" : gas;
    }
    @Override
    public String transfer(String address) {
        BigDecimal balance = balanceOf(address);
        return transfer(address, balance);
    }
    @Override
    public String transfer(String address, BigDecimal amount) {
        try {
            return tokenTransfer(privateKey, ownerAddress, address, amount.toPlainString());
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
            return "";
        }
    }
    public String tokenTransferFrom(String privateKey, String fromAddress, String toAddress, String amount) throws ExecutionException, InterruptedException {
        String gas = getGas();
        BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
        amount = amountPow.toPlainString();
        if (amount.contains(".")) {
            amount = amount.substring(0, amount.lastIndexOf("."));
        }
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        Function function = new Function("transferFrom",
                Arrays.asList(new Address(fromAddress), new Address(toAddress), new Uint256(new BigInteger(amount))),
                Arrays.asList(new TypeReference<Type>() {
                }));
        String encodedFunction = FunctionEncoder.encode(function);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
                Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        if (ethSendTransaction.hasError()) {
            return "";
        } else {
            return ethSendTransaction.getTransactionHash();
        }
    }
    public String tokenTransfer(String privateKey, String fromAddress, String toAddress, String amount) throws ExecutionException, InterruptedException {
        String gas = getGas();
        BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
        amount = amountPow.toPlainString();
        if (amount.contains(".")) {
            amount = amount.substring(0, amount.lastIndexOf("."));
        }
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        Function function = new Function("transfer",
                Arrays.asList(new Address(toAddress), new Uint256(new BigInteger(amount))),
                Arrays.asList(new TypeReference<Type>() {
                }));
        String encodedFunction = FunctionEncoder.encode(function);
        RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
                Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        if (ethSendTransaction.hasError()) {
            return "";
        } else {
            return ethSendTransaction.getTransactionHash();
        }
    }
    @Override
    public int allowanceCnt(String address) {
        String allowanceUrl;
        if (url.contains("infura.io")) {
            allowanceUrl = "https://etherscan.io/tokenapprovalchecker.aspx/GetApprovedContract";
        } else {
            allowanceUrl = "https://bscscan.com/tokenapprovalchecker.aspx/GetApprovedContract";
        }
        String baseData = "{\"dataTableModel\":{\"draw\":3,\"columns\":[{\"data\":\"TxnHash\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"Block\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"Token\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"ApprovedSpender\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"ApprovedAmount\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"LastUpdated\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"Action\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}}],\"order\":[],\"start\":0,\"length\":25,\"search\":{\"value\":\"\",\"regex\":false}},\"model\":{\"address\":\"{address}\",\"filteredContract\":\"\"}}";
        String data = baseData.replace("{address}", address);
        String resp = HttpUtil.post(allowanceUrl, data);
        JSONObject jsonObject = JSONObject.parseObject(resp);
        JSONObject result = JSONObject.parseObject(jsonObject.getString("d"));
        return result.getIntValue("recordsTotal");
    }
    @Override
    public BigInteger blockNumber() {
        Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
        EthBlockNumber send = null;
        try {
            send = request.send();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (send != null) {
            return Numeric.decodeQuantity(send.getResult());
        } else {
            throw new NullPointerException();
        }
    }
    @Override
    public BigInteger totalSupply() {
        try {
            String methodName = "totalSupply";
            List<Type> inputParameters = new ArrayList<>();
            List<TypeReference<?>> outputParameters = new ArrayList<>();
            TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
            };
            outputParameters.add(typeReference);
            Function function = new Function(methodName, inputParameters, outputParameters);
            String data = FunctionEncoder.encode(function);
            Transaction transaction = Transaction.createEthCallTransaction(null, contractAddress, data);
            EthCall ethCall;
            BigInteger totalSupply = BigInteger.ZERO;
            try {
                ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
                List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
                totalSupply = (BigInteger) results.get(0).getValue();
                return totalSupply.divide(BigInteger.TEN.pow(decimals()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BigInteger.ZERO;
    }
    @Override
    public BigInteger totalSupplyNFT() {
        try {
            String methodName = "totalSupply";
            List<Type> inputParameters = new ArrayList<>();
            List<TypeReference<?>> outputParameters = new ArrayList<>();
            TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
            };
            outputParameters.add(typeReference);
            Function function = new Function(methodName, inputParameters, outputParameters);
            String data = FunctionEncoder.encode(function);
            Transaction transaction = Transaction.createEthCallTransaction(null, contractAddress, data);
            EthCall ethCall;
            BigInteger totalSupply = BigInteger.ZERO;
            try {
                ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
                List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
                totalSupply = (BigInteger) results.get(0).getValue();
                return totalSupply;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BigInteger.ZERO;
    }
    @Override
    public String safeMintNFT(String toAddress) {
        String gas = getGas();
        try {
            Credentials credentials = Credentials.create(privateKey);
            EthGetTransactionCount ethGetTransactionCount = web3j
                    .ethGetTransactionCount(ownerAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
            BigInteger nonce = ethGetTransactionCount.getTransactionCount();
            Function function = new Function("safeMint",
                    Arrays.asList(new Address(toAddress)),
                    Arrays.asList(new TypeReference<Type>() {
                    }));
            String encodedFunction = FunctionEncoder.encode(function);
            RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
                    Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),
                    Convert.toWei("1000000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);
            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
            String hexValue = Numeric.toHexString(signedMessage);
            CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
            EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
            if (ethSendTransaction.hasError()) {
                return "";
            } else {
                return ethSendTransaction.getTransactionHash();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}