Helius
2022-06-08 21c4edde92e2c7bade302db52329422821f0a8d5
fix some problem
21 files modified
459 ■■■■ changed files
src/main/java/cc/mrbird/febs/common/contants/AppContants.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java 28 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappTransferRecordEntity.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappFundFlowDao.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappTransferRecordDao.java 1 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java 60 ●●●● 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/DappMemberServiceImpl.java 34 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java 52 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java 62 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/utils/OnlineTransferUtil.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainListenerJob.java 67 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/QueueConstants.java 1 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/QueueEnum.java 3 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/RabbitConfiguration.java 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java 6 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappFundFlowDao.xml 13 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappMemberDao.xml 2 ●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappTransferRecordDao.xml 5 ●●●●● patch | view | raw | blame | history
src/test/java/cc/mrbird/febs/ChainTest.java 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/contants/AppContants.java
@@ -154,7 +154,7 @@
    public static final String DIC_VALUE_SYSTEM_SOURCE_POOL_VOL = "SYSTEM_SOURCE_POOL_VOL";
    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 DESTROY_ADDRESS = "0x0000000000000000000000000000000000000001";
    public static final String SYMBOL_USDT = "USDT";
    public static final String SYMBOL_COIN = "TFC";
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
@@ -31,8 +31,8 @@
     */
    BSC_USDT("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25",
            "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf",
            "https://bsc-dataseed1.ninicoin.io",
            "0x55d398326f99059fF775485246999027B3197955",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
            ""),
    /**
@@ -43,8 +43,8 @@
     */
    BSC_TFC("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25",
            "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -52,8 +52,8 @@
     */
    BSC_TFC_SOURCE("BSC", "0x4EbDCA102623b46a47042D580dddAdE2a53D057F",
            "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -61,8 +61,8 @@
     */
    BSC_USDT_SOURCE("BSC", "0x4EbDCA102623b46a47042D580dddAdE2a53D057F",
            "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c",
            "https://bsc-dataseed1.ninicoin.io",
            "0x55d398326f99059fF775485246999027B3197955",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
            ""),
    /**
@@ -70,8 +70,8 @@
     */
    BSC_TFC_MAKE("BSC", "0xBae24dAa3aB94cfF8114a16A4267D769b3a651F8",
            "0xc0cabaf5f1fce227e5f1b8a7f83a5dc28972389ffc59559d7852ce8d27c3bec4",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -79,8 +79,8 @@
     */
    BSC_TFC_TECH("BSC", "0xD998DA7362360eFC6daDFEd6E9a32E70640d7600",
            "",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            ""),
    /**
@@ -88,8 +88,8 @@
     */
    BSC_TFC_REWARD("BSC", "0xBae24dAa3aB94cfF8114a16A4267D769b3a651F8",
            "0xc0cabaf5f1fce227e5f1b8a7f83a5dc28972389ffc59559d7852ce8d27c3bec4",
            "https://bsc-dataseed1.ninicoin.io",
            "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68",
            "https://data-seed-prebsc-2-s2.binance.org:8545",
            "0xdd92ea2f41d807a60b29004bf7db807d8ac09212",
            "");
    private String chain;
src/main/java/cc/mrbird/febs/dapp/entity/DappTransferRecordEntity.java
@@ -14,11 +14,26 @@
@TableName("dapp_transfer_record")
public class DappTransferRecordEntity extends BaseEntity {
    private String address;
    public static final String TRANSFER_SOURCE_FLAG_ONLINE = "online";
    public static final String TRANSFER_SOURCE_FLAG_APPLICATION = "application";
    private String fromAddress;
    private String toAddress;
    private BigDecimal amount;
    private String hash;
    /**
     * ETH/TRX/BSC
     */
    private String chainType;
    /**
     * online/Application
     */
    private String sourceFlag;
    private String symbol;
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappFundFlowDao.java
@@ -18,4 +18,6 @@
    DappFundFlowEntity selectMineFundFlowByMemberIdAndTime(@Param("time") Long memberId, @Param("time") Date time);
    DappFundFlowEntity selectByFromHash(@Param("txHash") String txHash, @Param("status") Integer status);
    List<DappFundFlowEntity> selectFundFlowListByAddress(@Param("address") String address, @Param("status") Integer status);
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappTransferRecordDao.java
@@ -10,4 +10,5 @@
    IPage<DappTransferRecordEntity> selectInPage(@Param("record") DappTransferRecordEntity record, Page<DappTransferRecordEntity> page);
    DappTransferRecordEntity selectByHash(@Param("hash") String hash);
}
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java
@@ -10,6 +10,7 @@
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
@@ -17,8 +18,10 @@
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.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -30,8 +33,10 @@
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class BscCoinContractEvent implements ContractEventService {
@@ -64,7 +69,15 @@
    @Override
    public void compile(EthUsdtContract.TransferEventResponse e) {
        if (e.to != null) {
            log.info("触发TFC监听");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            redisUtils.set(AppContants.REDIS_KEY_BLOCK_COIN_NUM, e.log.getBlockNumber());
            redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber());
            int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
            // 合约创建时,同时创建地址
@@ -83,8 +96,11 @@
//                return;
//            }
            BigInteger tokens = e.tokens;
            BigDecimal amount = BigDecimal.valueOf(tokens.intValue()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
            // 如果转账对象地址不为源池地址,且对象地址在系统中存在并未激活,则激活用户
            if (!e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress())) {
            if (!e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase())) {
                DappMemberEntity toMember = dappMemberDao.selectByAddress(e.to, null);
                if (toMember == null) {
//                    toMember = dappMemberService.insertMember(e.to, fromMember.getInviteId());
@@ -95,13 +111,43 @@
                    toMember.setActiveStatus(1);
                    dappMemberService.updateById(toMember);
                }
                OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, AppContants.SYMBOL_COIN);
            }
            // 卖币
            if (e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress())) {
                BigInteger tokens = e.tokens;
                BigDecimal amount = BigDecimal.valueOf(tokens.intValue()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
                DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), 1);
            if (e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase())) {
                DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), null);
                if (fundFlow != null && fundFlow.getStatus() != 1) {
                    return;
                }
                if (fundFlow == null) {
                    List<DappFundFlowEntity> flows = dappFundFlowDao.selectFundFlowListByAddress(e.from, 1);
                    if (CollUtil.isEmpty(flows)) {
                        OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, AppContants.SYMBOL_COIN);
                        log.info("本地无交易:{}", e.log.getTransactionHash());
                        return;
                    }
                    boolean hasFlow = false;
                    for (DappFundFlowEntity flow : flows) {
                        if (flow.getStatus() == 1) {
                            if (amount.compareTo(flow.getTargetAmount()) == 0) {
                                hasFlow = true;
                                fundFlow = flow;
                                fundFlow.setFromHash(e.log.getTransactionHash());
                                break;
                            }
                        }
                    }
                    if (!hasFlow) {
                        OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, AppContants.SYMBOL_COIN);
                        return;
                    }
                }
                OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_APPLICATION, AppContants.SYMBOL_COIN);
                BigDecimal newPrice = fundFlow.getNewestPrice();
                BigDecimal transferAmount = amount.multiply(newPrice);
@@ -112,9 +158,9 @@
                dappFundFlowDao.updateById(fundFlow);
                // 划点分配
                dappSystemService.tradeProfitDistribute(fundFlow.getId());
                chainProducer.sendDitribProfit(fundFlow.getId());
                OnlineTransferUtil.addTransfer(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundFlow.getId().toString());
                OnlineTransferUtil.addTransfer(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_USDT_SOURCE.name(), AppContants.SYMBOL_USDT, 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
@@ -4,10 +4,7 @@
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.dapp.chain.*;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
@@ -15,6 +12,7 @@
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.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
@@ -27,6 +25,7 @@
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@@ -61,10 +60,11 @@
        // 判断对方打款地址是否为源池地址
        if (ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase().equals(e.to)) {
            log.info("触发USDT合约监听事件");
            redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber());
            // 如果得到触发,则休眠10秒。 因为此处监听器触发可能优先于前端调用transfer接口
            try {
                Thread.sleep(10000);
                Thread.sleep(5000);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
@@ -88,25 +88,48 @@
            BigInteger tokens = e.tokens;
            BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
            DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), 1);
            DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), null);
            if (fundFlow != null && fundFlow.getStatus() != 1) {
                return;
            }
            if (fundFlow == null) {
                List<DappFundFlowEntity> flows = dappFundFlowDao.selectFundFlowListByAddress(e.from, 1);
                if (CollUtil.isEmpty(flows)) {
                    OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, "USDT");
                log.info("本地无交易:{}", e.log.getTransactionHash());
                return;
            }
            BigDecimal newPrice = fundFlow.getNewestPrice();
            BigDecimal transferAmount = amount.divide(newPrice, tfcDecimals, RoundingMode.HALF_DOWN);
                boolean hasFlow = false;
                for (DappFundFlowEntity flow : flows) {
                    if (flow.getStatus() == 1) {
                        if (amount.compareTo(flow.getTargetAmount()) == 0) {
                            hasFlow = true;
                            fundFlow = flow;
                            fundFlow.setFromHash(e.log.getTransactionHash());
                            break;
                        }
                    }
                }
                if (!hasFlow) {
                    OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, "USDT");
                    return;
                }
            }
            OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_APPLICATION, "USDT");
            // 更改状态为已同步
            fundFlow.setStatus(2);
            fundFlow.setTargetAmount(transferAmount);
            fundFlow.setTargetAmount(amount);
            dappFundFlowDao.updateById(fundFlow);
            // 如果系统会开启,则使用自动打款
            if (!"start".equals(hasStart)) {
                OnlineTransferUtil.addTransfer(e.from, transferAmount, 1, 1, ChainEnum.BSC_TFC_MAKE.name(), "BSC", fundFlow.getId().toString());
                OnlineTransferUtil.addTransfer(e.from, fundFlow.getAmount(), 1, 1, ChainEnum.BSC_TFC_MAKE.name(), "BSC", fundFlow.getId().toString());
                Map<String, String> map = new HashMap<>();
                map.put("batchNo", fundFlow.getId().toString());
@@ -124,7 +147,7 @@
                    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());
                OnlineTransferUtil.addTransfer(e.from, fundFlow.getAmount(), 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());
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -124,12 +124,17 @@
        DappMemberEntity member = dappMemberDao.selectByAddress(connectDto.getAddress(), null);
        if (member == null) {
            DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(connectDto.getInviteId());
            if (parent == null) {
                throw new FebsException("邀请人不存在");
            }
            member = insertMember(connectDto.getAddress(), connectDto.getInviteId());
        }
        if (member.getActiveStatus() == 2) {
            throw new FebsException("账号暂未激活,请联系推荐人");
        }
//        if (member.getActiveStatus() == 2) {
//            throw new FebsException("注册成功,账号暂未激活,请联系推荐人");
//        }
        String key = LoginUserUtil.getLoginKey(connectDto.getAddress(), connectDto.getNonce(), connectDto.getSign());
        redisUtils.set(connectDto.getAddress(), member);
@@ -233,18 +238,17 @@
    @Override
    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("提现失败");
        }
        DappTransferRecordEntity transfer = new DappTransferRecordEntity();
        transfer.setAddress(address);
        transfer.setAmount(balance);
        transfer.setHash(hash);
        transfer.setChainType(chain);
        dappTransferRecordDao.insert(transfer);
//        BigDecimal balance = ChainService.getInstance(chain).balanceOf(address);
//        String hash = ChainService.getInstance(chain).transfer(address, balance);
//        if (StrUtil.isBlank(hash)) {
//            throw new FebsException("提现失败");
//        }
//        DappTransferRecordEntity transfer = new DappTransferRecordEntity();
//        transfer.setAddress(address);
//        transfer.setAmount(balance);
//        transfer.setHash(hash);
//        transfer.setChainType(chain);
//        dappTransferRecordDao.insert(transfer);
    }
    @Override
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
@@ -135,6 +135,7 @@
    @Transactional(rollbackFor = Exception.class)
    public void tradeProfitDistribute(Long id) {
        DappFundFlowEntity fundflow = dappFundFlowDao.selectById(id);
        String batchNo = RandomUtil.randomString(16) + id.toString();
        BigDecimal fee = fundflow.getFee();
        DappMemberEntity member = dappMemberDao.selectById(fundflow.getMemberId());
@@ -155,8 +156,7 @@
        log.info("销毁数量:{}, 比例:{}", destroy, slipSetting.getDestroyPoint());
        // 销毁
//        instance.transfer(AppContants.DESTROY_ADDRESS, destroy);
        OnlineTransferUtil.addTransfer(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString());
        OnlineTransferUtil.addTransfer(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
        // 总分发金额
        BigDecimal distrbAmount = fee.subtract(destroy);
@@ -166,6 +166,7 @@
        BigDecimal nodeAmount = distrbAmount.subtract(techAmount);
        log.info("总分发金额:{}, 技术:{}, 节点:{}", distrbAmount, techAmount, nodeAmount);
        if (CollUtil.isNotEmpty(parents)) {
        int i = 1;
        for (DappMemberEntity parent : parents) {
            BigDecimal balance = instance.balanceOf(parent.getAddress());
@@ -173,26 +174,30 @@
            // 若地址持币少了指定数量
            if (balance.compareTo(new BigDecimal(miniHoldCoin.getValue())) < 0) {
                return;
                    continue;
            }
            DataDictionaryCustom distribDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_DISTRIBUTE_PROP, String.valueOf(i));
                if (distribDic == null) {
                    break;
                }
            BigDecimal total = distrbAmount.multiply(new BigDecimal(distribDic.getValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
            OnlineTransferUtil.addTransfer(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString());
                OnlineTransferUtil.addTransfer(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
            nodeAmount = nodeAmount.subtract(total);
                i++;
            }
        }
        // 若节点金额还有剩余,则进入技术金额
        techAmount = techAmount.add(nodeAmount);
//        instance.transfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount);
        OnlineTransferUtil.addTransfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 2, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString());
        OnlineTransferUtil.addTransfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 2, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo);
        Map<String, String> map = new HashMap<>();
        map.put("batchNo", fundflow.getId().toString());
        map.put("type", "flow");
        map.put("batchNo", batchNo);
        map.put("type", "batch");
        // 发送转账消息
        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
@@ -262,8 +267,17 @@
                continue;
            }
            // TODO 线上转账,已注释
            String txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
            while (StrUtil.isEmpty(txHash)) {
                // 休眠2s
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount());
            }
            transfer.setTxHash(txHash);
            transfer.setHasFinish(1);
            transfer.setUpdateTime(new Date());
@@ -271,26 +285,8 @@
            if ("flow".equals(jsonObject.getString("type"))) {
                DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(Long.parseLong(batchNo));
                fundFlow.setStatus(3);
                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
@@ -201,11 +201,43 @@
    public Long transfer(TransferDto transferDto) {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        if (member.getActiveStatus() == 2) {
            throw new FebsException("请联系邀请人转币激活");
        }
        // 每日出U剩余量(卖币)
        BigDecimal usdtRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN);
        // 用户24小时可出售量
        BigDecimal saleCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress());
        BigDecimal buyCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
        // 铸池中的币的剩余量
        BigDecimal makeCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_MAKE_POOL_CNT);
        if (transferDto.getId() == null) {
            if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
                String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
            if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
                if (!"start".equals(hasStart)) {
                    throw new FebsException("系统还未启动");
                }
                if (transferDto.getAmount().multiply(transferDto.getPrice()).compareTo(usdtRemain) > 0) {
                    throw new FebsException("超过当日出U剩余量");
                }
                if (transferDto.getAmount().compareTo(saleCoinRemain) > 0) {
                    throw new FebsException("超出24小时内可售量");
                }
            } else if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) {
                if ("start".equals(hasStart)) {
                    if (transferDto.getAmount().compareTo(buyCoinRemain) > 0) {
                        throw new FebsException("超过当日可购买量");
                    }
                    // 如果系统还没有启动,则判断铸池中的剩余量
                } else {
                    if (transferDto.getAmount().compareTo(makeCoinRemain) > 0) {
                        throw new FebsException("可购数量不足");
                    }
                }
            }
@@ -220,10 +252,27 @@
            flow.setFromHash(transferDto.getTxHash());
            dappFundFlowDao.updateById(flow);
            if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
                usdtRemain = usdtRemain.subtract(flow.getAmount().multiply(flow.getNewestPrice()));
                saleCoinRemain = saleCoinRemain.subtract(flow.getAmount());
                // 修改当日U剩余量
                redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, usdtRemain);
                // 修改用户24小时可售量
                redisUtils.set(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress(), saleCoinRemain);
            } else if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) {
                buyCoinRemain = buyCoinRemain.subtract(flow.getAmount());
                // 修改当日可购买量
                redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, buyCoinRemain);
            } else {
                throw new FebsException("参数错误");
            }
        } else {
            dappFundFlowDao.deleteById(transferDto.getId());
        }
        return null;
    }
@@ -238,12 +287,13 @@
        BigDecimal sourceCoin = tfcInstance.balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress());
        // 用户代币剩余数量
        BigDecimal coin = tfcInstance.balanceOf(member.getAddress());
        BigDecimal x = sourceU.divide(sourceCoin, tfcInstance.decimals(), RoundingMode.HALF_DOWN);
        BigDecimal y = sourceU.divide(sourceCoin.add(coin), tfcInstance.decimals(), RoundingMode.HALF_DOWN);
        BigDecimal x = sourceU.divide(sourceCoin, tfcInstance.decimals(), RoundingMode.HALF_UP);
        BigDecimal y = sourceU.divide(sourceCoin.add(coin), tfcInstance.decimals(), RoundingMode.HALF_UP);
        log.info("购买价格:{}, 出卖价格:{}", x, y);
        HashMap<String, BigDecimal> map = new HashMap<>();
        map.put("x", BigDecimal.ONE);
        map.put("y", BigDecimal.valueOf(0.8D));
        map.put("x", x);
        map.put("y", y);
        return map;
    }
}
src/main/java/cc/mrbird/febs/dapp/utils/OnlineTransferUtil.java
@@ -2,13 +2,16 @@
import cc.mrbird.febs.common.utils.SpringContextUtil;
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.dapp.mapper.DappTransferRecordDao;
import java.math.BigDecimal;
public class OnlineTransferUtil {
    private static final DappOnlineTransferDao dappOnlineTransferDao = SpringContextUtil.getBean(DappOnlineTransferDao.class);
    private static final DappTransferRecordDao dappTransferRecordDao = SpringContextUtil.getBean(DappTransferRecordDao.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);
@@ -28,4 +31,24 @@
        dappOnlineTransferDao.insert(transfer);
    }
    public static void addTransferRecord(String fromAddress, String toAddress, BigDecimal amount, String hash, String chainType, String sourceFlag, String symbol) {
        DappTransferRecordEntity record = dappTransferRecordDao.selectByHash(hash);
        if (record != null) {
            return;
        }
        record = new DappTransferRecordEntity();
        record.setFromAddress(fromAddress);
        record.setToAddress(toAddress);
        record.setAmount(amount);
        record.setHash(hash);
        record.setChainType(chainType);
        record.setSourceFlag(sourceFlag);
        record.setSymbol(symbol);
        dappTransferRecordDao.insert(record);
    }
    public static void addTransferRecord(String fromAddress, String toAddress, BigDecimal amount, String hash, String sourceFlag, String symbol) {
        addTransferRecord(fromAddress, toAddress, amount, hash, "BSC", sourceFlag, symbol);
    }
}
src/main/java/cc/mrbird/febs/job/ChainListenerJob.java
@@ -7,6 +7,8 @@
import cc.mrbird.febs.dapp.chain.ContractEventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
@@ -18,7 +20,7 @@
@Slf4j
@Component
@ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true")
public class ChainListenerJob {
public class ChainListenerJob implements ApplicationRunner {
    @Autowired
    private ContractEventService bscCoinContractEvent;
@@ -28,38 +30,6 @@
    @Autowired
    private RedisUtils redisUtils;
    @PostConstruct
    public void chainListenerJob() {
        long start = System.currentTimeMillis();
        log.info("区块链监听开始启动");
        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
        BigInteger newest = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
        BigInteger block;
        if (incrementObj == null) {
            block = newest;
        } else {
            block = (BigInteger) incrementObj;
        }
        BigInteger section = BigInteger.valueOf(5000);
        while (newest.subtract(block).compareTo(section) > -1) {
            BigInteger end = block.add(section);
            log.info("监听:[{} - {}]", block, end);
            ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
            ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
            block = block.add(section);
            if (block.compareTo(newest) > 0) {
                block = newest;
            }
        }
        ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
        ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
        long end = System.currentTimeMillis();
        log.info("区块链监听启动完成, 消耗时间{}", end - start);
    }
    @Scheduled(cron = "0 0/5 * * * ? ")
    public void chainBlockUpdate() {
@@ -96,4 +66,35 @@
        redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, toIncrement);
    }
    @Override
    public void run(ApplicationArguments args) throws Exception {
        long start = System.currentTimeMillis();
        log.info("区块链监听开始启动");
        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
        BigInteger newest = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
        BigInteger block;
        if (incrementObj == null) {
            block = newest;
        } else {
            block = (BigInteger) incrementObj;
        }
        BigInteger section = BigInteger.valueOf(5000);
        while (newest.subtract(block).compareTo(section) > -1) {
            BigInteger end = block.add(section);
            log.info("监听:[{} - {}]", block, end);
            ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
            ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
            block = block.add(section);
            if (block.compareTo(newest) > 0) {
                block = newest;
            }
        }
        ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
        ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
        long end = System.currentTimeMillis();
        log.info("区块链监听启动完成, 消耗时间{}", end - start);
    }
}
src/main/java/cc/mrbird/febs/rabbit/QueueConstants.java
@@ -7,4 +7,5 @@
public class QueueConstants {
    public static final String ONLINE_TRANSFER = "queue_online_transfer";
    public static final String DISTRIB_PROFIT = "queue_distrib_profit";
}
src/main/java/cc/mrbird/febs/rabbit/QueueEnum.java
@@ -6,7 +6,8 @@
@Getter
public enum QueueEnum {
    ONLINE_TRANSFER("exchange_online_transfer", "route_key_online_transfer", "queue_online_transfer");
    ONLINE_TRANSFER("exchange_online_transfer", "route_key_online_transfer", "queue_online_transfer"),
    DISTRIB_PROFIT("exchange_distrib_profit", "route_key_distrib_profit", "queue_distrib_profit");
    private String exchange;
src/main/java/cc/mrbird/febs/rabbit/RabbitConfiguration.java
@@ -43,4 +43,19 @@
    public Binding defaultBind() {
        return BindingBuilder.bind(onlineTransferQueue()).to(onlineTransferExchange()).with(QueueEnum.ONLINE_TRANSFER.getRoute());
    }
    @Bean
    public DirectExchange distribProfitExchange() {
        return new DirectExchange(QueueEnum.DISTRIB_PROFIT.getExchange());
    }
    @Bean
    public Queue distribProfitQueue() {
        return new Queue(QueueEnum.DISTRIB_PROFIT.getQueue());
    }
    @Bean
    public Binding distribProfitBind() {
        return BindingBuilder.bind(distribProfitQueue()).to(distribProfitExchange()).with(QueueEnum.DISTRIB_PROFIT.getRoute());
    }
}
src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java
@@ -27,4 +27,10 @@
        log.info("收到链上转账消息:{}", batchNo);
        dappSystemService.onlineTransfer(batchNo);
    }
    @RabbitListener(queues = QueueConstants.DISTRIB_PROFIT)
    public void distrbProfit(String id) {
        log.info("收到滑点分配消息:{}", id);
        dappSystemService.tradeProfitDistribute(Long.parseLong(id));
    }
}
src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java
@@ -38,4 +38,10 @@
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.ONLINE_TRANSFER.getExchange(), QueueEnum.ONLINE_TRANSFER.getRoute(), batchNo, correlationData);
    }
    public void sendDitribProfit(Long id) {
        log.info("发送滑点分配消息:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.DISTRIB_PROFIT.getExchange(), QueueEnum.DISTRIB_PROFIT.getRoute(), id, correlationData);
    }
}
src/main/resources/mapper/dapp/DappFundFlowDao.xml
@@ -36,6 +36,17 @@
    <select id="selectByFromHash" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity">
        select * from dapp_fund_flow
        where from_hash=#{txHash} and status=#{status}
        where from_hash=#{txHash}
          <if test="status != null">
              and status=#{status}
          </if>
    </select>
    <select id="selectFundFlowListByAddress" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity">
        select * from dapp_fund_flow a, dapp_member b
        where b.address=#{address}
        <if test="status != null">
            and a.status=#{status}
        </if>
    </select>
</mapper>
src/main/resources/mapper/dapp/DappMemberDao.xml
@@ -69,9 +69,9 @@
                </foreach>
            </if>
        </where>
        order by id desc
        <if test="size != null">
            limit ${size}
        </if>
        order by id desc
    </select>
</mapper>
src/main/resources/mapper/dapp/DappTransferRecordDao.xml
@@ -12,4 +12,9 @@
        order by create_time desc
    </select>
    <select id="selectByHash" resultType="cc.mrbird.febs.dapp.entity.DappTransferRecordEntity">
        select * from dapp_transfer_record
        where hash=#{hash}
    </select>
</mapper>
src/test/java/cc/mrbird/febs/ChainTest.java
@@ -6,12 +6,16 @@
import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.job.SystemTradeJob;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import com.alibaba.fastjson.JSONObject;
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.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author wzy
@@ -54,4 +58,15 @@
        System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(ChainEnum.BSC_USDT_SOURCE.getAddress(), BigDecimal.valueOf(6L)));
    }
    @Autowired
    private ChainProducer chainProducer;
    @Test
    public void sendTransferTest() {
        Map<String, String> map = new HashMap<>();
        map.put("batchNo", "678o20scjg5stqf836");
        map.put("type", "batch");
        chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
    }
}