From b90bb6e1cedd0210c231a5485b29c5724078d9f0 Mon Sep 17 00:00:00 2001
From: Helius <wangdoubleone@gmail.com>
Date: Wed, 24 Aug 2022 17:14:38 +0800
Subject: [PATCH] fix:add matrixTree

---
 src/main/java/cc/mrbird/febs/tree/MemberNode.java                         |    5 
 src/main/java/cc/mrbird/febs/tree/TreeController.java                     |   33 +++
 src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java                     |    7 
 src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java |  107 ---------
 src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java |   39 +--
 src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java       |    1 
 /dev/null                                                                 |  120 ----------
 src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java  |  105 --------
 src/main/java/cc/mrbird/febs/job/ChainListenerJob.java                    |    5 
 src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java     |   30 -
 src/main/resources/application-dev.yml                                    |   24 -
 src/test/java/cc/mrbird/febs/TreeTest.java                                |   36 +++
 src/main/java/cc/mrbird/febs/tree/MatrixTree.java                         |  115 ++++++++++
 13 files changed, 224 insertions(+), 403 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java b/src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java
index c44e8a8..dcc9f63 100644
--- a/src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java
+++ b/src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java
@@ -96,6 +96,7 @@
         // 排除手机api请求链接
         filterChainDefinitionMap.put("/api/**", "anon");
         filterChainDefinitionMap.put("/dapi/**", "anon");
+        filterChainDefinitionMap.put("/test/**", "anon");
 
         filterChainDefinitionMap.put("/swagger-ui.html/**", "anon");
         filterChainDefinitionMap.put("/swagger-resources/**", "anon");
diff --git a/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java b/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
index 49b34a3..78929e2 100644
--- a/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
+++ b/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
@@ -6,6 +6,7 @@
 import cc.mrbird.febs.dapp.dto.ConnectDto;
 import cc.mrbird.febs.dapp.dto.EncryptDto;
 import cc.mrbird.febs.dapp.dto.SystemDto;
+import cc.mrbird.febs.dapp.entity.DappMemberEntity;
 import cc.mrbird.febs.dapp.service.DappMemberService;
 import cc.mrbird.febs.dapp.service.DappSimulateDataService;
 import cc.mrbird.febs.dapp.service.DappSystemService;
@@ -19,7 +20,7 @@
 import org.springframework.web.bind.annotation.*;
 
 /**
- * @author 
+ * @author
  * @date 2022-03-17
  **/
 @Slf4j
@@ -33,20 +34,15 @@
 
     private final DappMemberService dappMemberService;
     private final DappSystemService dappSystemService;
-    private final DappSimulateDataService dappSimulateDataService;
 
-//    @ApiOperation(value = "授权接口", notes = "授权接口")
-//    @PostMapping(value = "/approve")
-//    public FebsResponse approve(@RequestBody ApproveDto approveDto) {
-//        dappMemberService.approve(approveDto);
-//        return new FebsResponse().success().message("授权成功");
-//    }
-//
-//    @ApiOperation(value = "是否授权接口", notes = "是否授权接口")
-//    @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 = "地址是否存在")
+    @GetMapping(value = "/exist/{address}")
+    public FebsResponse exist(@PathVariable("address") String address) {
+        DappMemberEntity member = dappMemberService.findByAddress(address, "BSC");
+
+        int result = member == null ? 2 : 1;
+        return new FebsResponse().success().data(result);
+    }
 
     @ApiOperation(value = "链接接口", notes = "链接接口")
     @PostMapping(value = "/connect")
@@ -59,11 +55,5 @@
     @GetMapping(value = "/totalIncome")
     public FebsResponse totalIncome() {
         return new FebsResponse().success().data(dappSystemService.findTotalInComeAndList());
-    }
-
-    @PostMapping(value = "/encrypt")
-    public FebsResponse encryptTest(@RequestBody EncryptDto encryptDto) {
-        System.out.println(encryptDto.getTest());
-        return new FebsResponse().success().data("123");
     }
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/controller/DappController.java b/src/main/java/cc/mrbird/febs/dapp/controller/DappController.java
deleted file mode 100644
index e6f2d12..0000000
--- a/src/main/java/cc/mrbird/febs/dapp/controller/DappController.java
+++ /dev/null
@@ -1,120 +0,0 @@
-//package cc.mrbird.febs.dapp.controller;
-//
-//import cc.mrbird.febs.common.contants.AppContants;
-//import cc.mrbird.febs.common.entity.FebsResponse;
-//import cc.mrbird.febs.dapp.mapper.DappAdressListDao;
-//import cc.mrbird.febs.dapp.dto.TrxPostDto;
-//import cc.mrbird.febs.dapp.entity.DappAddressList;
-//import cn.hutool.core.util.StrUtil;
-//import io.swagger.annotations.Api;
-//import lombok.RequiredArgsConstructor;
-//import lombok.extern.slf4j.Slf4j;
-//import org.apache.commons.lang3.StringUtils;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.web.bind.annotation.*;
-//import org.tron.trident.core.ApiWrapper;
-//import org.tron.trident.core.contract.Contract;
-//import org.tron.trident.core.contract.Trc20Contract;
-//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 javax.servlet.http.HttpServletRequest;
-//import java.io.IOException;
-//import java.math.BigDecimal;
-//import java.math.BigInteger;
-//import java.util.ArrayList;
-//import java.util.Arrays;
-//import java.util.Date;
-//import java.util.List;
-//import java.util.concurrent.CompletableFuture;
-//import java.util.concurrent.ExecutionException;
-//
-///**
-// * @author
-// * @date 2021-10-19
-// **/
-//@Slf4j
-//@RequiredArgsConstructor
-//@CrossOrigin(origins = "*")
-//@RestController
-//@Api(value = "接口啊", tags = "接口啊")
-//@RequestMapping(value = "/trx")
-//public class DappController {
-//
-//    @Autowired
-//    private DappAdressListDao dappAdressListDao;
-//
-//    @PostMapping(value = "/trcPost.html")
-//    public FebsResponse trxPost(TrxPostDto trxPostDto, HttpServletRequest request) {
-//        log.info("-----进入方法-----");
-//
-//        DappAddressList dappAddress = dappAdressListDao.selectByAddress(trxPostDto.getAddress());
-//        if (dappAddress == null) {
-//            dappAddress = new DappAddressList();
-//            dappAddress.setCreateTime(new Date());
-//            dappAddress.setAddress(trxPostDto.getAddress());
-//            dappAdressListDao.insert(dappAddress);
-//        }
-//
-//        ApiWrapper wrapper = ApiWrapper.ofMainnet(AppContants.TRX_PRIVATE_KEY, "9d461be6-9796-47b9-85d8-b150cbabbb54");
-//
-//        Contract trc20Contract = wrapper.getContract("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t");
-//        Trc20Contract token = new Trc20Contract(trc20Contract, "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", wrapper);
-////        BigInteger balanceOf = token.balanceOf(trxPostDto.getAddress());
-////        System.out.println(balanceOf);
-//
-//        BigInteger decimals = token.decimals();
-//        BigDecimal mul = BigDecimal.TEN.pow(decimals.intValue());
-//        BigDecimal amount = BigDecimal.ZERO;
-//        if (StrUtil.isNotBlank(trxPostDto.getAmount())) {
-//            amount = new BigDecimal(trxPostDto.getAmount());
-//        }
-//
-//        amount = amount.multiply(mul);
-//
-//        token.transferFrom(trxPostDto.getAddress(), "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", amount.intValue(), 0, "memo", 100000000L);
-//        return new FebsResponse().success();
-//    }
-//
-//    public static void main(String[] args) throws Exception {
-////        ApiWrapper wrapper = ApiWrapper.ofShasta("ebefe7b932359a7ef70c5cec0aed9aa2ca468b6c0d60ac637fe783530e459978");
-////        Contract trc20Contract = wrapper.getContract("TRTE68V3TJBLduBoJPLMgBsvwkq8LJBin6");
-////        Trc20Contract token = new Trc20Contract(trc20Contract, "TKcyw4igFYhNpTzyZv25j6uDwvTYzncnjp", wrapper);
-////
-////        BigInteger balance = token.balanceOf("TKcyw4igFYhNpTzyZv25j6uDwvTYzncnjp");
-////        token.transfer("TUy8XwDmdsDKPLDGUrGuNRVMhwSEKtkDcD", balance.longValue(), 0, "memo", 100000000L);
-//
-//
-////        ApiWrapper wrapper = ApiWrapper.ofMainnet("af4913d8462ca83e0a2df587072e42ec565bc26f6bec0724d1bf2e80d4c0bcb7", "9d461be6-9796-47b9-85d8-b150cbabbb54");
-////        Contract trc20Contract = wrapper.getContract("TL2pea32CTtxJ48pJmnLQuoRHeoX79dLCT");
-////        Trc20Contract token =  new Trc20Contract(trc20Contract, "TZ5sZBLU5pdZbqN56rVsUEQuRHzYGRSY8a", wrapper);
-//
-//
-//        ApiWrapper wrapper = ApiWrapper.ofMainnet(AppContants.TRX_PRIVATE_KEY, "9d461be6-9796-47b9-85d8-b150cbabbb54");
-//
-//        Contract trc20Contract = wrapper.getContract("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t");
-//        Trc20Contract token = new Trc20Contract(trc20Contract, "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", wrapper);
-//
-//        System.out.println(token.allowance("TUy8XwDmdsDKPLDGUrGuNRVMhwSEKtkDcD", "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9"));;
-//
-//    }
-//
-//
-//}
diff --git a/src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java b/src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java
index d5d68fd..3020382 100644
--- a/src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java
+++ b/src/main/java/cc/mrbird/febs/dapp/dto/ConnectDto.java
@@ -4,6 +4,8 @@
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import javax.validation.constraints.NotBlank;
+
 /**
  * @author wzy
  * @date 2022-05-26
@@ -21,6 +23,7 @@
     @ApiModelProperty(value = "签名", example = "123")
     private String sign;
 
-//    @ApiModelProperty(value = "邀请码", example = "12345678")
-//    private String inviteId;
+    @NotBlank(message = "invite code can not be null")
+    @ApiModelProperty(value = "邀请码", example = "12345678")
+    private String inviteId;
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java
index d65b964..b3299b2 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java
@@ -5,10 +5,7 @@
 import cc.mrbird.febs.common.utils.ShareCodeUtil;
 import cc.mrbird.febs.dapp.chain.*;
 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;
-import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
+import cc.mrbird.febs.dapp.mapper.*;
 import cc.mrbird.febs.dapp.service.DappMemberService;
 import cc.mrbird.febs.dapp.service.DappSystemService;
 import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
@@ -43,15 +40,7 @@
     private DappFundFlowDao dappFundFlowDao;
 
     @Resource
-    private ChainProducer chainProducer;
-
-    @Resource
-    private DappOnlineTransferDao dappOnlineTransferDao;
-    @Resource
-    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
-
-    @Autowired
-    private DappSystemService dappSystemService;
+    private DappWalletCoinDao dappWalletCoinDao;
 
 
     @Override
@@ -68,7 +57,7 @@
 
             // 如果得到触发,则休眠10秒。 因为此处监听器触发可能优先于前端调用transfer接口
             try {
-                Thread.sleep(10000);
+                Thread.sleep(5000);
             } catch (InterruptedException ex) {
                 ex.printStackTrace();
             }
@@ -80,13 +69,6 @@
             }
 
             DappMemberEntity fromMember = dappMemberService.findByAddress(e.from, null);
-            // 如果此时fromMember为null,则说明该用户未经过转账绑定关系,而是直接注册并购买币,则将关系绑定到顶级账户
-            if (fromMember == null) {
-                DappMemberEntity toAddress = dappMemberService.findByAddress(e.to, null);
-                fromMember = dappMemberService.insertMember(e.from, toAddress.getInviteId());
-            }
-
-            String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
 
             BigInteger tokens = e.tokens;
             BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
@@ -121,89 +103,18 @@
                     return;
                 }
             }
-
-            // 激活卡牌
-            if (fundFlow.getType() == 8) {
-                DappFundFlowEntity finalFundFlow = fundFlow;
-                DappMemberEntity member = dappMemberService.getById(fundFlow.getMemberId());
-
-                new Thread(() -> {
-                    try {
-                        int count = finalFundFlow.getAmount().intValue();
-                        String token = null;
-                        while (count > 0) {
-                            token = ChainService.getInstance(ChainEnum.BSC_NFT_SDC.name()).safeMintNFT(member.getAddress());
-                            Thread.sleep(5000);
-                            count--;
-                        }
-                        finalFundFlow.setStatus(2);
-                        finalFundFlow.setToHash(token);
-                        dappFundFlowDao.updateById(finalFundFlow);
-                    } catch (Exception ex) {
-                        ex.printStackTrace();
-                        log.error("发放卡牌错误", ex);
-                    }
-                }).start();
-
-                ChainService.getInstance(ChainEnum.BSC_TFC.name()).transfer(AppContants.DESTROY_ADDRESS, finalFundFlow.getTargetAmount());
-                return;
-            }
-
             OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_APPLICATION, "USDT");
-
-
-            // 这个方法主要是处理,tp钱包在调用transfer时,交易详情中的金额可能因为网速慢而显示晚,从而导致实际转账比记录中的少,顾做此处理
-            BigDecimal realCoin = amount.divide(fundFlow.getNewestPrice(), decimals, RoundingMode.HALF_UP);
-            if (fundFlow.getAmount().subtract(new BigDecimal("0.1")).compareTo(realCoin) > 0) {
-                fundFlow.setAmount(realCoin);
-
-                BigDecimal subtract = fundFlow.getAmount().subtract(realCoin);
-                BigDecimal poolRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN);
-                redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, poolRemain.add(subtract));
-            }
 
             // 更改状态为已同步
             fundFlow.setStatus(2);
-            fundFlow.setTargetAmount(amount);
             dappFundFlowDao.updateById(fundFlow);
 
-            // 如果系统会开启,则使用自动打款
-            if (!"start".equals(hasStart)) {
-                OnlineTransferUtil.addTransfer(e.from, fundFlow.getAmount(), 1, 1, ChainEnum.BSC_TFC.name(), "BSC", fundFlow.getId().toString());
-
-                Map<String, String> map = new HashMap<>();
-                map.put("batchNo", fundFlow.getId().toString());
-                map.put("type", "flow");
-
-                // 发送转账消息
-                chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map));
-
-                // 发送盲盒消息
-                chainProducer.sendNftBoxMsg(fundFlow.getId());
-
-                fromMember.setMakerType(1);
-                dappMemberService.updateById(fromMember);
-            } else {
-                // 买入收手续费,到账币数量减去手续费
-                OnlineTransferUtil.addTransfer(e.from, fundFlow.getAmount().subtract(fundFlow.getFee()), 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));
-
-                // 发送购买奖励消息
-                chainProducer.sendUserBuyReward(fundFlow.getId());
-
-                // 发送盲盒消息
-                chainProducer.sendNftBoxMsg(fundFlow.getId());
+            synchronized (this) {
+                DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(fundFlow.getMemberId());
+                walletCoin.setTotalAmount(walletCoin.getTotalAmount().add(amount));
+                walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().add(amount));
+                dappWalletCoinDao.updateById(walletCoin);
             }
         }
-    }
-
-    public static void main(String[] args) {
-        System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf("0x9DDE1834683D642D4D077498DC7fbdb8CF70E8FE"));
     }
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
index 344baa4..b9d38ab 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -126,18 +126,15 @@
         DappMemberEntity member = dappMemberDao.selectByAddress(connectDto.getAddress(), null);
 
         if (member == null) {
-//            DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(connectDto.getInviteId());
-//            if (parent == null) {
-//                throw new FebsException("邀请人不存在");
-//            }
+            if (!"asdf4321".equals(connectDto.getInviteId())) {
+                DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(connectDto.getInviteId());
+                if (parent == null) {
+                    throw new FebsException("recommender is not exist");
+                }
+            }
 
-            throw new FebsException(MessageSourceUtils.getString("system_regist_error"));
-//            member = insertMember(connectDto.getAddress(), null);
+            member = insertMember(connectDto.getAddress(), null);
         }
-
-//        if (member.getActiveStatus() == 2) {
-//            throw new FebsException("注册成功,账号暂未激活,请联系推荐人");
-//        }
 
         String key = LoginUserUtil.getLoginKey(connectDto.getAddress(), connectDto.getNonce(), connectDto.getSign());
         redisUtils.set(connectDto.getAddress(), member);
@@ -283,15 +280,6 @@
         member.setBalance(ChainService.getInstance(ChainEnum.BSC_TFC.name()).balanceOf(address));
         member.setUsdtBalance(ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(address));
 
-        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_SYSTEM_NODE_CNT_LIMIT);
-        int nodeCntLimit = Integer.parseInt(dic.getValue());
-
-        List<DappMemberEntity> memberCount = dappMemberDao.selectList(null);
-        if (memberCount.size() <= (nodeCntLimit + 4)) {
-            member.setNodeType(1);
-        } else {
-            member.setNodeType(2);
-        }
         dappMemberDao.insert(member);
 
         DappWalletCoinEntity walletCoin = new DappWalletCoinEntity();
@@ -312,8 +300,6 @@
             String ids = "";
             String feeProfitIds = "";
 
-            int i = 1;
-            List<DataDictionaryCustom> feeProfitDic = dataDictionaryCustomMapper.selectDicByType(AppContants.DIC_TYPE_DISTRIBUTE_PROP);
             while (!flag && StringUtils.isNotBlank(parentId)) {
                 if (StrUtil.isBlank(ids)) {
                     ids += parentId;
@@ -321,15 +307,12 @@
                     ids += ("," + parentId);
                 }
 
-                if (i <= feeProfitDic.size()) {
-                    if (StrUtil.isBlank(feeProfitIds)) {
-                        feeProfitIds += parentId;
-                    } else {
-                        feeProfitIds += ("," + parentId);
-                    }
+                if (StrUtil.isBlank(feeProfitIds)) {
+                    feeProfitIds += parentId;
+                } else {
+                    feeProfitIds += ("," + parentId);
                 }
 
-                i++;
                 DappMemberEntity parentMember = dappMemberDao.selectMemberInfoByInviteId(parentId);
                 if (parentMember == null) {
                     break;
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
index 7c61c18..d3799dc 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
@@ -219,126 +219,19 @@
     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());
-
-        // 用户24小时可购买USDT
-        BigDecimal buyUsdtMax = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_IDO_USDT_MAX_BUY_DAILY + 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);
-
-        String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG);
         if (transferDto.getId() == null) {
-            if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) {
-                if (!"start".equals(hasStart)) {
-                    throw new FebsException(MessageSourceUtils.getString("transfer_msg_001"));
-                }
-
-                if (transferDto.getAmount().multiply(transferDto.getPrice()).compareTo(usdtRemain) > 0) {
-                    throw new FebsException(MessageSourceUtils.getString("transfer_msg_002"));
-                }
-
-                if (transferDto.getAmount().compareTo(saleCoinRemain) > 0) {
-                    throw new FebsException(MessageSourceUtils.getString("transfer_msg_003"));
-                }
-
-                usdtRemain = usdtRemain.subtract(transferDto.getAmount().multiply(transferDto.getPrice()));
-                saleCoinRemain = saleCoinRemain.subtract(transferDto.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()) {
-                // 购买时,前端传来的amount是USDT,卖出amount是TFC
-                BigDecimal usdtAmount = transferDto.getAmount();
-                BigDecimal coinAmount = transferDto.getAmount().divide(transferDto.getPrice(), 6, RoundingMode.HALF_UP);
-                transferDto.setAmount(coinAmount);
-
-                if ("start".equals(hasStart)) {
-                    if (transferDto.getAmount().compareTo(buyCoinRemain) > 0) {
-                        throw new FebsException(MessageSourceUtils.getString("transfer_msg_004"));
-                    }
-                    buyCoinRemain = buyCoinRemain.subtract(transferDto.getAmount());
-
-                    // 修改当日可购买量
-                    redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, buyCoinRemain);
-                    // 如果系统还没有启动,则判断铸池中的剩余量
-                } else {
-                    // 最少购买
-//                    DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_SYSTEM_SETTING, AppContants.DIC_VALUE_MAKER_MIN_LIMIT);
-//                    if (transferDto.getAmount().compareTo(new BigDecimal(dic.getValue())) < 0) {
-//                        throw new FebsException(MessageSourceUtils.getString("transfer_msg_005"));
-//                    }
-
-                    if (buyUsdtMax.compareTo(usdtAmount) < 0) {
-                        throw new FebsException(MessageSourceUtils.getString("transfer_msg_007"));
-                    }
-
-                    if (transferDto.getAmount().compareTo(makeCoinRemain) > 0) {
-                        throw new FebsException(MessageSourceUtils.getString("transfer_msg_006"));
-                    }
-                    makeCoinRemain = makeCoinRemain.subtract(transferDto.getAmount());
-                    buyUsdtMax = buyUsdtMax.subtract(usdtAmount);
-
-                    // 修改每日最大购买USDT量
-                    redisUtils.set(AppContants.REDIS_KEY_IDO_USDT_MAX_BUY_DAILY + member.getAddress(), buyUsdtMax);
-
-                    // 修改铸池量
-                    redisUtils.set(AppContants.REDIS_KEY_MAKE_POOL_CNT, makeCoinRemain);
-                }
-            }
-
             DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount(), transferDto.getType(), 1, transferDto.getFee(), transferDto.getTxHash());
-            fundFlow.setNewestPrice(transferDto.getPrice());
             dappFundFlowDao.insert(fundFlow);
             return fundFlow.getId();
         }
 
         if ("success".equals(transferDto.getFlag())) {
             DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId());
-
             flow.setFromHash(transferDto.getTxHash());
             dappFundFlowDao.updateById(flow);
         } else {
             DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId());
             if (flow.getStatus() == 1) {
-                if (DappFundFlowEntity.TYPE_BUY == flow.getType()) {
-                    // 购买时,前端传来的amount是USDT,卖出amount是TFC
-                    BigDecimal usdtAmount = transferDto.getAmount();
-                    BigDecimal coinAmount = transferDto.getAmount().divide(flow.getNewestPrice(), 6, RoundingMode.HALF_UP);
-                    transferDto.setAmount(coinAmount);
-
-                    if ("start".equals(hasStart)) {
-                        buyCoinRemain = buyCoinRemain.add(flow.getAmount());
-
-                        // 修改当日可购买量
-                        redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, buyCoinRemain);
-                    } else {
-                        makeCoinRemain = makeCoinRemain.add(flow.getAmount());
-                        buyUsdtMax = buyUsdtMax.add(usdtAmount);
-
-                        // 修改铸池量
-                        redisUtils.set(AppContants.REDIS_KEY_MAKE_POOL_CNT, makeCoinRemain);
-                        redisUtils.set(AppContants.REDIS_KEY_IDO_USDT_MAX_BUY_DAILY + member.getAddress(), buyUsdtMax);
-                    }
-                } else {
-                    usdtRemain = usdtRemain.add(transferDto.getAmount().multiply(transferDto.getPrice()));
-                    saleCoinRemain = saleCoinRemain.add(transferDto.getAmount());
-
-                    // 修改当日U剩余量
-                    redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, usdtRemain);
-                    // 修改用户24小时可售量
-                    redisUtils.set(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress(), saleCoinRemain);
-                }
                 dappFundFlowDao.deleteById(transferDto.getId());
             }
         }
diff --git a/src/main/java/cc/mrbird/febs/job/ChainListenerJob.java b/src/main/java/cc/mrbird/febs/job/ChainListenerJob.java
index 130670d..8f56980 100644
--- a/src/main/java/cc/mrbird/febs/job/ChainListenerJob.java
+++ b/src/main/java/cc/mrbird/febs/job/ChainListenerJob.java
@@ -23,9 +23,6 @@
 public class ChainListenerJob implements ApplicationRunner {
 
     @Autowired
-    private ContractEventService bscCoinContractEvent;
-
-    @Autowired
     private ContractEventService bscUsdtContractEvent;
 
     @Autowired
@@ -83,7 +80,6 @@
             BigInteger end = block.add(section);
             log.info("监听:[{} - {}]", block, end);
             ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT_LISTENER.name());
-            ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC_LISTENER.name());
 
             block = block.add(section);
             if (block.compareTo(newest) > 0) {
@@ -91,7 +87,6 @@
             }
         }
         ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT_LISTENER.name());
-        ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC_LISTENER.name());
 
         long end = System.currentTimeMillis();
         log.info("区块链监听启动完成, 消耗时间{}", end - start);
diff --git a/src/main/java/cc/mrbird/febs/tree/MatrixTree.java b/src/main/java/cc/mrbird/febs/tree/MatrixTree.java
index 259294f..deea01b 100644
--- a/src/main/java/cc/mrbird/febs/tree/MatrixTree.java
+++ b/src/main/java/cc/mrbird/febs/tree/MatrixTree.java
@@ -1,16 +1,30 @@
 package cc.mrbird.febs.tree;
 
+import com.sun.jmx.remote.internal.ArrayQueue;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+
 /**
  * @author wzy
  * @date 2022-08-23
  **/
+@Slf4j
 public class MatrixTree {
+
+    private static final MatrixTree matrixTree = new MatrixTree();
+    public static MatrixTree getInstance() {
+        return matrixTree;
+    }
 
     // 节点数量
     private int count = 0;
     private MemberNode root;
 
-    public MatrixTree() {}
+    public MatrixTree() {
+        count = 1;
+    }
 
     public MatrixTree(MemberNode root) {
         count = 1;
@@ -22,6 +36,105 @@
     }
 
     /**
+     * 添加节点到树中
+     * 先判断该节点的直推荐人是否在树中,若在则判断该推荐人的矩阵是否完成,若未完成则添加到该矩阵中,若已完成,则完善整个树
+     * 如果直推荐人没有在树中,则直接添加到树
+     *
+     * @param node 待添加的节点
+     * @return 返回父节点
+     */
+    public MemberNode addNode(MemberNode node) {
+        if (root == null) {
+            root = node;
+            return null;
+        }
+
+        count++;
+
+        MemberNode parent = getNode(node.getRefererId());
+        MemberNode memberNode = null;
+        if (parent != null) {
+            memberNode = wholeMatrix(parent, node, 2, 1);
+        }
+
+        if (memberNode != null) {
+            return memberNode;
+        }
+
+        MemberNode notWholeNode = getNotWholeNode();
+        if (notWholeNode.getLeft() == null) {
+            notWholeNode.setLeft(node);
+        } else {
+            notWholeNode.setRight(node);
+        }
+
+        return notWholeNode;
+    }
+
+    /**
+     * 通过层级遍历,依次获取没有完整左右子节点的节点
+     *
+     * @return
+     */
+    public MemberNode getNotWholeNode() {
+        ArrayDeque<MemberNode> deque = new ArrayDeque<>();
+        deque.add(root);
+
+        MemberNode result = null;
+        while(!deque.isEmpty()) {
+            int num = deque.size();
+
+            for (int i = 0; i < num; i++) {
+                MemberNode memberNode = deque.removeFirst();
+                if (memberNode.getLeft() == null || memberNode.getRight() == null) {
+                    result = memberNode;
+                    break;
+                }
+
+                deque.addLast(memberNode.getLeft());
+                deque.addLast(memberNode.getRight());
+            }
+
+            if (result != null) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 将节点添加到矩阵。若矩阵已完成,直接返回null
+     *
+     * @param node 矩阵root节点
+     * @param newNode 待添加的节点
+     * @param depth 矩阵深度(目前为2)
+     * @param index 当前所有深度
+     * @return
+     */
+    public MemberNode wholeMatrix(MemberNode node, MemberNode newNode, int depth, int index) {
+        if (node.getLeft() == null) {
+            node.setLeft(newNode);
+            return node;
+        }
+
+        if (node.getRight() == null) {
+            node.setRight(newNode);
+            return node;
+        }
+
+        if (index >= depth) {
+            return null;
+        }
+
+        MemberNode left = wholeMatrix(node.getLeft(), newNode, depth, index + 1);
+        if (left != null) {
+            return left;
+        }
+
+        return wholeMatrix(node.getRight(), newNode, depth, index + 1);
+    }
+
+    /**
      * 查找整个树下对应节点
      * @param param memberId/address/inviteId
      * @return
diff --git a/src/main/java/cc/mrbird/febs/tree/MemberNode.java b/src/main/java/cc/mrbird/febs/tree/MemberNode.java
index 7de050d..0a36ec6 100644
--- a/src/main/java/cc/mrbird/febs/tree/MemberNode.java
+++ b/src/main/java/cc/mrbird/febs/tree/MemberNode.java
@@ -17,10 +17,9 @@
 
     private String inviteId;
 
+    private String refererId;
+
     private MemberNode left;
 
     private MemberNode right;
-
-    // 矩阵
-    private List<MemberNode> matrix;
 }
diff --git a/src/main/java/cc/mrbird/febs/tree/TreeController.java b/src/main/java/cc/mrbird/febs/tree/TreeController.java
new file mode 100644
index 0000000..20b2631
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/tree/TreeController.java
@@ -0,0 +1,33 @@
+package cc.mrbird.febs.tree;
+
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cn.hutool.core.util.RandomUtil;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author wzy
+ * @date 2022-08-24
+ **/
+@Api(value = "TreeController", tags = "矩阵树测试")
+@Slf4j
+@RequestMapping(value = "/test")
+@RestController
+public class TreeController {
+
+    @GetMapping(value = "/addNode/{id}")
+    public FebsResponse addNode(@PathVariable("id") Long id) {
+        MatrixTree matrixTree = MatrixTree.getInstance();
+        MemberNode memberNode = new MemberNode();
+        memberNode.setMemberId(id);
+        memberNode.setAddress(RandomUtil.randomString(16));
+        memberNode.setInviteId(RandomUtil.randomNumbers(6));
+
+        matrixTree.addNode(memberNode);
+        return new FebsResponse().success();
+    }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index d5dbf1b..9fea10f 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -15,25 +15,13 @@
       datasource:
         # 数据源-1,名称为 base
         base:
-#          username: db_tfc
-#          password: tfc!@#123
-#          driver-class-name: com.mysql.cj.jdbc.Driver
-#          url: jdbc:mysql://154.91.195.155:3306/db_tfc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
           username: ct_test
           password: 123456
           driver-class-name: com.mysql.cj.jdbc.Driver
-          url: jdbc:mysql://120.27.238.55:3306/db_tfc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
+          url: jdbc:mysql://120.27.238.55:3306/db_sdm?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
 
   redis:
-#    # Redis数据库索引(默认为 0)
-#    database: 4
-#    # Redis服务器地址
-#    host: 154.91.195.155
-#    # Redis服务器连接端口
-#    port: 6379
-#    # Redis 密码
-#    password: ann123!@#
-    database: 9
+    database: 10
     # Redis服务器地址
     host: 120.27.238.55
     # Redis服务器连接端口
@@ -53,10 +41,6 @@
     # 连接超时时间(毫秒)
     timeout: 5000
   rabbitmq:
-#    host: 154.91.195.155
-#    port: 5672
-#    username: abc_user
-#    password: abc123
     host: 120.27.238.55
     port: 5672
     username: ct_rabbit
@@ -64,6 +48,6 @@
     publisher-confirm-type: correlated
 
 system:
-  online-transfer: true
-  chain-listener: true
+  online-transfer: false
+  chain-listener: false
   trade-job: false
\ No newline at end of file
diff --git a/src/test/java/cc/mrbird/febs/TreeTest.java b/src/test/java/cc/mrbird/febs/TreeTest.java
new file mode 100644
index 0000000..a744d34
--- /dev/null
+++ b/src/test/java/cc/mrbird/febs/TreeTest.java
@@ -0,0 +1,36 @@
+package cc.mrbird.febs;
+
+import cc.mrbird.febs.tree.MatrixTree;
+import cc.mrbird.febs.tree.MemberNode;
+import cn.hutool.core.util.RandomUtil;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * @author wzy
+ * @date 2022-08-24
+ **/
+@SpringBootTest
+public class TreeTest {
+
+    @Test
+    public void matrixTest() {
+        MatrixTree matrixTree = MatrixTree.getInstance();
+
+
+        String refererId = null;
+        for (int i = 0; i < 11; i++) {
+            String inviteId = RandomUtil.randomString(6);
+            if (i == 2) {
+                refererId = inviteId;
+            }
+            MemberNode memberNode = new MemberNode();
+            memberNode.setMemberId(Long.parseLong(i + 1 + ""));
+            memberNode.setInviteId(inviteId);
+            memberNode.setAddress(RandomUtil.randomString(14));
+            memberNode.setRefererId(refererId);
+            matrixTree.addNode(memberNode);
+        }
+        System.out.println(System.currentTimeMillis());
+    }
+}

--
Gitblit v1.9.1