Helius
2022-06-07 6562e04677044d4c15ee303d922bfeabe56320fb
test and fix some bugs
13 files modified
2 files added
334 ■■■■ changed files
src/main/java/cc/mrbird/febs/common/contants/AppContants.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java 39 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java 56 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappFundFlowEntity.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappOnlineTransferEntity.java 34 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java 45 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java 54 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/utils/OnlineTransferUtil.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainListenerJob.java 3 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/RedisLinkHoldJob.java 23 ●●●●● patch | view | raw | blame | history
src/main/resources/application-dev.yml 8 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappOnlineTransferDao.xml 2 ●●● patch | view | raw | blame | history
src/test/java/cc/mrbird/febs/ChainTest.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/contants/AppContants.java
@@ -142,6 +142,8 @@
    public static final String REDIS_KEY_BLOCK_ETH_NEWEST_NUM = "BLOCK_ETH_NEWEST_NUM";
    public static final String REDIS_KEY_BLOCK_ETH_INCREMENT_NUM = "BLOCK_ETH_INCREMENT_NUM";
    public static final String REDIS_KEY_MAKE_POOL_CNT = "MAKE_POOL_CNT";
    public static final String DIC_TYPE_DISTRIBUTE_PROP = "DISTRIBUTE_PROP";
    public static final String DIC_TYPE_SYSTEM_SETTING = "SYSTEM_SETTING";
@@ -153,4 +155,7 @@
    public static final String DIC_VALUE_SYSTEM_NODE_CNT_LIMIT = "SYSTEM_NODE_CNT_LIMIT";
    public static final String DESTROY_ADDRESS = "0x0000000000000000000000000000000000000000";
    public static final String SYMBOL_USDT = "USDT";
    public static final String SYMBOL_COIN = "TFC";
}
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
@@ -29,30 +29,31 @@
     * 0x55d398326f99059fF775485246999027B3197955
     * 测试链 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd
     */
    BSC_USDT("BSC", "0x971c09aA9735EB98459B17EC8b48932D24CbB931",
            "0x5f38d0e63157f535fc21f89ea13ec3cd245691c20795c1d2cb60233b3ba7bb47",
            "https://bsc-dataseed1.ninicoin.io",
            "0x55d398326f99059fF775485246999027B3197955",
    BSC_USDT("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25",
            "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
            ""),
    /**
     * 币安链 代币合约
     * 测试链 0xdd92ea2f41d807a60b29004bf7db807d8ac09212
     *
     * 正式 0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68 https://bsc-dataseed1.ninicoin.io
     *
     */
    BSC_TFC("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25",
            "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
     * 源池币
     */
    BSC_TFC_SOURCE("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25",
            "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
    BSC_TFC_SOURCE("BSC", "0x4EbDCA102623b46a47042D580dddAdE2a53D057F",
            "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -60,8 +61,8 @@
     */
    BSC_USDT_SOURCE("BSC", "0x4EbDCA102623b46a47042D580dddAdE2a53D057F",
            "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c",
            "https://bsc-dataseed1.ninicoin.io",
            "0x55d398326f99059fF775485246999027B3197955",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
            ""),
    /**
@@ -69,8 +70,8 @@
     */
    BSC_TFC_MAKE("BSC", "0xBae24dAa3aB94cfF8114a16A4267D769b3a651F8",
            "0xc0cabaf5f1fce227e5f1b8a7f83a5dc28972389ffc59559d7852ce8d27c3bec4",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -78,8 +79,8 @@
     */
    BSC_TFC_TECH("BSC", "0xD998DA7362360eFC6daDFEd6E9a32E70640d7600",
            "",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -87,8 +88,8 @@
     */
    BSC_TFC_REWARD("BSC", "0xBae24dAa3aB94cfF8114a16A4267D769b3a651F8",
            "0xc0cabaf5f1fce227e5f1b8a7f83a5dc28972389ffc59559d7852ce8d27c3bec4",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-1-s3.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            "");
    private String chain;
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
@@ -27,10 +27,7 @@
import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -210,7 +207,7 @@
    @Override
    public String transfer(String address, BigDecimal amount) {
        try {
            return tokenTransferFrom(privateKey, address, ownerAddress, amount.toPlainString());
            return tokenTransfer(privateKey, ownerAddress, address, amount.toPlainString());
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
            return "";
@@ -220,7 +217,7 @@
    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"));
        BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
        amount = amountPow.toPlainString();
        if (amount.contains(".")) {
            amount = amount.substring(0, amount.lastIndexOf("."));
@@ -229,12 +226,53 @@
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(toAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
                .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>() {
                }));
@@ -289,9 +327,9 @@
        if (send != null) {
            return Numeric.decodeQuantity(send.getResult());
        } else {
            throw new NullPointerException();
        }
        return new BigInteger("1");
    }
}
src/main/java/cc/mrbird/febs/dapp/entity/DappFundFlowEntity.java
@@ -19,6 +19,10 @@
    public static final int WITHDRAW_STATUS_AGREE = 2;
    public static final int WITHDRAW_STATUS_DISAGREE = 3;
    public static final int TYPE_BUY = 1;
    public static final int TYPE_SALE = 2;
    public DappFundFlowEntity() {}
    public DappFundFlowEntity(Long memberId, BigDecimal amount, Integer type, Integer status, BigDecimal fee) {
src/main/java/cc/mrbird/febs/dapp/entity/DappOnlineTransferEntity.java
@@ -10,23 +10,23 @@
@TableName("dapp_online_transfer")
public class DappOnlineTransferEntity extends BaseEntity {
    public DappOnlineTransferEntity() {}
    public DappOnlineTransferEntity(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String batchNo) {
        new DappOnlineTransferEntity(address, amount, type, targetType, symbol, fromType, "BSC", batchNo);
    }
    public DappOnlineTransferEntity(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String chain, String batchNo) {
        this.address = address;
        this.amount = amount;
        this.type = type;
        this.targetType = targetType;
        this.symbol = symbol;
        this.chain = chain;
        this.batchNo = batchNo;
        this.fromType = fromType;
        this.hasFinish = 2;
    }
//    public DappOnlineTransferEntity() {}
//
//    public DappOnlineTransferEntity(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String batchNo) {
//        new DappOnlineTransferEntity(address, amount, type, targetType, symbol, fromType, "BSC", batchNo);
//    }
//
//    public DappOnlineTransferEntity(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String chain, String batchNo) {
//        this.address = address;
//        this.amount = amount;
//        this.type = type;
//        this.targetType = targetType;
//        this.symbol = symbol;
//        this.chain = chain;
//        this.batchNo = batchNo;
//        this.fromType = fromType;
//        this.hasFinish = 2;
//    }
    private String address;
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java
@@ -15,6 +15,7 @@
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
@@ -113,8 +114,7 @@
                // 划点分配
                dappSystemService.tradeProfitDistribute(fundFlow.getId());
                DappOnlineTransferEntity record = new DappOnlineTransferEntity(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), "USDT", fundFlow.getId().toString());
                dappOnlineTransferDao.insert(record);
                OnlineTransferUtil.addTransfer(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundFlow.getId().toString());
                Map<String, String> map = new HashMap<>();
                map.put("batchNo", fundFlow.getId().toString());
src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java
@@ -13,6 +13,7 @@
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
@@ -58,7 +59,16 @@
        redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.log.getBlockNumber());
        // 判断对方打款地址是否为源池地址
        if (ChainEnum.BSC_TFC_SOURCE.getAddress().equals(e.to)) {
        if (ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase().equals(e.to)) {
            log.info("触发USDT合约监听事件");
            // 如果得到触发,则休眠10秒。 因为此处监听器触发可能优先于前端调用transfer接口
            try {
                Thread.sleep(10000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            ContractChainService sourceUsdtInstance = ChainService.getInstance(ChainEnum.BSC_USDT.name());
            int decimals = sourceUsdtInstance.decimals();
            int tfcDecimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
@@ -77,8 +87,13 @@
            String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
            BigInteger tokens = e.tokens;
            BigDecimal amount = BigDecimal.valueOf(tokens.intValue()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
            BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
            DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), 1);
            if (fundFlow == null) {
                log.info("本地无交易:{}", e.log.getTransactionHash());
                return;
            }
            BigDecimal newPrice = fundFlow.getNewestPrice();
            BigDecimal transferAmount = amount.divide(newPrice, tfcDecimals, RoundingMode.HALF_DOWN);
@@ -91,8 +106,7 @@
            // 如果系统会开启,则使用自动打款
            if (!"start".equals(hasStart)) {
                DappOnlineTransferEntity bsc = new DappOnlineTransferEntity(e.from, transferAmount, 1, 1, ChainEnum.BSC_TFC_MAKE.name(), "BSC", fundFlow.getId().toString());
                dappOnlineTransferDao.insert(bsc);
                OnlineTransferUtil.addTransfer(e.from, transferAmount, 1, 1, ChainEnum.BSC_TFC_MAKE.name(), "BSC", fundFlow.getId().toString());
                Map<String, String> map = new HashMap<>();
                map.put("batchNo", fundFlow.getId().toString());
@@ -100,15 +114,24 @@
                // 发送转账消息
                chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
            }
            DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_START_TARGET);
            BigDecimal target = new BigDecimal(dic.getValue());
                DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_START_TARGET);
                BigDecimal target = new BigDecimal(dic.getValue());
            // 若源池中的USDT达到或超过8万U,则启动整个系统
            BigDecimal balance = sourceUsdtInstance.balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
            if (target.compareTo(balance) < 1) {
                redisUtils.set(AppContants.SYSTEM_START_FLAG, "start");
                // 若源池中的USDT达到或超过8万U,则启动整个系统
                BigDecimal balance = sourceUsdtInstance.balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
                if (target.compareTo(balance) < 1) {
                    redisUtils.set(AppContants.SYSTEM_START_FLAG, "start");
                }
            } else {
                OnlineTransferUtil.addTransfer(e.from, transferAmount, 1, 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundFlow.getId().toString());
                Map<String, String> map = new HashMap<>();
                map.put("batchNo", fundFlow.getId().toString());
                map.put("type", "flow");
                // 发送转账消息
                chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
            }
        }
    }
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
@@ -10,6 +10,7 @@
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.dapp.vo.RedisTransferPoolVo;
import cc.mrbird.febs.dapp.vo.SlipSettingVo;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
@@ -75,6 +76,27 @@
        DappMemberEntity member = LoginUserUtil.getAppUser();
        SystemDto system = new SystemDto();
        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
        // 启动未启动
        if (!"start".equals(hasStart)) {
            system.setFeeRatio(BigDecimal.TEN);
            system.setUsdtRemain(BigDecimal.ZERO);
            system.setUsdtTotal(BigDecimal.ZERO);
            system.setSaleRemain(BigDecimal.ZERO);
            system.setSaleTotal(BigDecimal.ZERO);
            Object makePoolObj = redisUtils.get(AppContants.REDIS_KEY_MAKE_POOL_CNT);
            BigDecimal balance;
            if (makePoolObj == null) {
                balance = ChainService.getInstance(ChainEnum.BSC_TFC_MAKE.name()).balanceOf(ChainEnum.BSC_TFC_MAKE.getAddress());
                redisUtils.set(AppContants.REDIS_KEY_MAKE_POOL_CNT, balance);
            } else {
                balance = (BigDecimal) makePoolObj;
            }
            system.setBuyRemain(balance);
            system.setBuyTotal(balance);
            return system;
        }
        RedisTransferPoolVo transferPool = (RedisTransferPoolVo) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL);
        BigDecimal poolRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
@@ -134,8 +156,7 @@
        // 销毁
//        instance.transfer(AppContants.DESTROY_ADDRESS, destroy);
        DappOnlineTransferEntity destroyRecord = new DappOnlineTransferEntity(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), "TFC", fundflow.getId().toString());
        dappOnlineTransferDao.insert(destroyRecord);
        OnlineTransferUtil.addTransfer(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString());
        // 总分发金额
        BigDecimal distrbAmount = fee.subtract(destroy);
@@ -158,8 +179,7 @@
            DataDictionaryCustom distribDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_DISTRIBUTE_PROP, String.valueOf(i));
            BigDecimal total = distrbAmount.multiply(new BigDecimal(distribDic.getValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
            DappOnlineTransferEntity distribRecord = new DappOnlineTransferEntity(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), "TFC", fundflow.getId().toString());
            dappOnlineTransferDao.insert(distribRecord);
            OnlineTransferUtil.addTransfer(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString());
            nodeAmount = nodeAmount.subtract(total);
        }
@@ -168,8 +188,7 @@
        techAmount = techAmount.add(nodeAmount);
//        instance.transfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount);
        DappOnlineTransferEntity techRecord = new DappOnlineTransferEntity(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 2, ChainEnum.BSC_TFC_SOURCE.name(), "TFC", fundflow.getId().toString());
        dappOnlineTransferDao.insert(techRecord);
        OnlineTransferUtil.addTransfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 2, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString());
        Map<String, String> map = new HashMap<>();
        map.put("batchNo", fundflow.getId().toString());
@@ -217,8 +236,7 @@
                continue;
            }
            DappOnlineTransferEntity tfc = new DappOnlineTransferEntity(member.getAddress(), mine, 3, 1, "TFC", ChainEnum.BSC_TFC.name(), batchNo);
            dappOnlineTransferDao.insert(tfc);
            OnlineTransferUtil.addTransfer(member.getAddress(), mine, 3, 1, ChainEnum.BSC_TFC.name(), AppContants.SYMBOL_COIN, batchNo);
        }
        Map<String, String> map = new HashMap<>();
@@ -245,8 +263,8 @@
            }
            // TODO 线上转账,已注释
//            String txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
//            transfer.setTxHash(txHash);
            String txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
            transfer.setTxHash(txHash);
            transfer.setHasFinish(1);
            transfer.setUpdateTime(new Date());
            dappOnlineTransferDao.updateById(transfer);
@@ -255,11 +273,25 @@
                DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(Long.parseLong(batchNo));
                fundFlow.setStatus(3);
//                fundFlow.setToHash(txHash);
                fundFlow.setToHash(txHash);
                dappFundFlowDao.updateById(fundFlow);
            }
            // 修改剩余量
            if (AppContants.SYMBOL_COIN.equals(transfer.getSymbol())) {
                BigDecimal poolRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
                redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, poolRemain.subtract(transfer.getAmount()));
            } else {
                BigDecimal usdtRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN);
                usdtRemain = usdtRemain.subtract(transfer.getAmount());
                if (usdtRemain.compareTo(BigDecimal.ZERO) < 0) {
                    usdtRemain = BigDecimal.ZERO;
                }
                redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, usdtRemain);
            }
        }
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
@@ -204,6 +204,13 @@
//        ChainService.getInstance(ChainEnum.BSC_USDT_SOURCE.name()).balanceOf(member.getAddress());
//        ChainService.getInstance(ChainEnum.BSC_TFC_SOURCE.name()).balanceOf(member.getAddress());
        if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
            String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
            if (!"start".equals(hasStart)) {
                throw new FebsException("系统还未启动");
            }
        }
        DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount(), transferDto.getType(), 1, transferDto.getFee(), transferDto.getTxHash());
        fundFlow.setNewestPrice(transferDto.getPrice());
        dappFundFlowDao.insert(fundFlow);
src/main/java/cc/mrbird/febs/dapp/utils/OnlineTransferUtil.java
New file
@@ -0,0 +1,31 @@
package cc.mrbird.febs.dapp.utils;
import cc.mrbird.febs.common.utils.SpringContextUtil;
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import java.math.BigDecimal;
public class OnlineTransferUtil {
    private static final DappOnlineTransferDao dappOnlineTransferDao = SpringContextUtil.getBean(DappOnlineTransferDao.class);
    public static void addTransfer(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String batchNo) {
         addTransfer(address, amount, type, targetType, fromType, symbol, "BSC", batchNo);
    }
    public static void addTransfer(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String chain, String batchNo) {
        DappOnlineTransferEntity transfer = new DappOnlineTransferEntity();
        transfer.setAddress(address);
        transfer.setAmount(amount);
        transfer.setType(type);
        transfer.setTargetType(targetType);
        transfer.setFromType(fromType);
        transfer.setSymbol(symbol);
        transfer.setChain(chain);
        transfer.setBatchNo(batchNo);
        transfer.setHasFinish(2);
        dappOnlineTransferDao.insert(transfer);
    }
}
src/main/java/cc/mrbird/febs/job/ChainListenerJob.java
@@ -63,6 +63,7 @@
    @Scheduled(cron = "0 0/5 * * * ? ")
    public void chainBlockUpdate() {
        log.info("最新区块更新");
        BigInteger blockNumber = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
        redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM, blockNumber);
@@ -86,7 +87,7 @@
            BigInteger incrementBlock = (BigInteger) incrementObj;
            // 最新区块小于增加区块
            if (newestBlock.compareTo(incrementBlock) < 0) {
            if (newestBlock.compareTo(incrementBlock) <= 0) {
                return;
            }
            toIncrement = incrementBlock.add(BigInteger.ONE);
src/main/java/cc/mrbird/febs/job/RedisLinkHoldJob.java
New file
@@ -0,0 +1,23 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * @author wzy
 * @date 2022-06-07
 **/
@Component
public class RedisLinkHoldJob {
    @Autowired
    private RedisUtils redisUtils;
    @Scheduled(cron = "0/1 * * * * ?")
    public void redisLinkHold() {
        redisUtils.set("redis_link_hold", 1);
    }
}
src/main/resources/application-dev.yml
@@ -2,7 +2,7 @@
  datasource:
    dynamic:
      # 是否开启 SQL日志输出,生产环境建议关闭,有性能损耗
      p6spy: false
      p6spy: true
      hikari:
        connection-timeout: 30000
        max-lifetime: 1800000
@@ -22,7 +22,7 @@
  redis:
    # Redis数据库索引(默认为 0)
    database: 0
    database: 6
    # Redis服务器地址
    host: 120.27.238.55
    # Redis服务器连接端口
@@ -49,5 +49,5 @@
    publisher-confirm-type: correlated
system:
  online-transfer: false
  chain-listener: false
  online-transfer: true
  chain-listener: true
src/main/resources/mapper/dapp/DappOnlineTransferDao.xml
@@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao">
    <select id="selectByBatchNo" resultType="cc.mrbird.febs.dapp.entity.DappTransferRecordEntity">
    <select id="selectByBatchNo" resultType="cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity">
        select * from dapp_online_transfer
        where batch_no=#{batchNo}
    </select>
src/test/java/cc/mrbird/febs/ChainTest.java
@@ -3,10 +3,15 @@
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractChainService;
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.job.SystemTradeJob;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
import java.util.List;
/**
 * @author wzy
@@ -35,4 +40,18 @@
    public void sourceUsdtTest() {
        systemTradeJob.sourcePoolUsdtOutLimit();
    }
    @Test
    public void poolTest() {
        systemTradeJob.transferPoolVol();
    }
    @Autowired
    private DappOnlineTransferDao dappOnlineTransferDao;
    @Test
    public void transferTest() {
        System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(ChainEnum.BSC_USDT_SOURCE.getAddress(), BigDecimal.valueOf(6L)));
    }
}