From 2da3b45c4fccd0b1ff0108931da544c410bcc97f Mon Sep 17 00:00:00 2001
From: wzy <wzy19931122ai@163.com>
Date: Fri, 21 Oct 2022 23:06:44 +0800
Subject: [PATCH] 添加充值逻辑

---
 src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java           |   10 
 src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinService.java             |   13 
 src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java        |    2 
 src/main/java/cc/mrbird/febs/rabbit/consumer/UsdtUpdateConsumer.java      |   84 ++
 src/main/java/cc/mrbird/febs/dapp/chain/TransformUtil.java                |  215 +++++
 src/main/java/cc/mrbird/febs/dapp/service/impl/BlockSeriveImpl.java       |   95 ++
 src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java |    1 
 src/main/resources/application-prod.yml                                   |    7 
 src/main/java/cc/mrbird/febs/dapp/enumerate/CoinTypeEnum.java             |   10 
 src/main/java/cc/mrbird/febs/rabbit/producer/UsdtUpdateProducer.java      |   52 +
 src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinAddressEntity.java     |   55 +
 src/main/java/cc/mrbird/febs/job/BlockCoinUpdateJob.java                  |   93 ++
 src/main/java/cc/mrbird/febs/dapp/service/BlockSerive.java                |    9 
 src/main/resources/application-dev.yml                                    |    3 
 src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinAddressDao.java        |   28 
 src/main/java/cc/mrbird/febs/dapp/chain/Trc20Service.java                 |  105 ++
 src/main/java/cc/mrbird/febs/dapp/chain/UsdtErc20UpdateService.java       |  132 +++
 src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinChargeEntity.java      |   36 
 src/main/java/cc/mrbird/febs/rabbit/RabbitMqConfig.java                   |  511 +++++++++++++
 src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinServiceImpl.java         |  124 +++
 src/main/java/cc/mrbird/febs/dapp/chain/TrxUsdtUpdateService.java         |  377 ++++++++++
 src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinChargeDao.java         |   20 
 src/main/resources/application-test.yml                                   |    1 
 src/main/java/cc/mrbird/febs/dapp/chain/entity/EthUsdtChargeDto.java      |   31 
 src/main/resources/mapper/dapp/MemberCoinChargeDao.xml                    |   32 
 src/main/resources/mapper/dapp/MemberCoinAddressDao.xml                   |  107 ++
 src/main/resources/mapper/dapp/DappWalletCoinDao.xml                      |   41 +
 27 files changed, 2,190 insertions(+), 4 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinService.java b/src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinService.java
new file mode 100644
index 0000000..c740163
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinService.java
@@ -0,0 +1,13 @@
+package cc.mrbird.febs.dapp.chain;
+
+
+import cc.mrbird.febs.dapp.chain.entity.EthUsdtChargeDto;
+
+public interface BlockCoinService {
+
+    /**
+     *  更新
+     */
+    public void updateTrc20(EthUsdtChargeDto dto);
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinServiceImpl.java b/src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinServiceImpl.java
new file mode 100644
index 0000000..5df7181
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/BlockCoinServiceImpl.java
@@ -0,0 +1,124 @@
+package cc.mrbird.febs.dapp.chain;
+
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.dapp.chain.entity.EthUsdtChargeDto;
+import cc.mrbird.febs.dapp.entity.DappMemberEntity;
+import cc.mrbird.febs.dapp.entity.DappWalletCoinEntity;
+import cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity;
+import cc.mrbird.febs.dapp.entity.MemberCoinChargeEntity;
+import cc.mrbird.febs.dapp.enumerate.CoinTypeEnum;
+import cc.mrbird.febs.dapp.mapper.DappMemberDao;
+import cc.mrbird.febs.dapp.mapper.DappWalletCoinDao;
+import cc.mrbird.febs.dapp.mapper.MemberCoinAddressDao;
+import cc.mrbird.febs.dapp.mapper.MemberCoinChargeDao;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2020-07-02
+ **/
+@Slf4j
+@Service
+public class BlockCoinServiceImpl implements BlockCoinService {
+
+    @Resource
+    private MemberCoinAddressDao memberCoinAddressDao;
+    @Resource
+    private DappMemberDao memberDao;
+    @Resource
+    private MemberCoinChargeDao memberCoinChargeDao;
+    @Resource
+    private DappWalletCoinDao memberWalletCoinDao;
+
+    private final static String EOS_SEQ_KEY = "eos_seq_key";
+
+    private final static String xrp_update_key = "xrp_update_key";
+
+    private final static String trc20_update_key = "trc20_update_key";
+
+
+    @Override
+    public void updateTrc20(EthUsdtChargeDto dto) {
+        String address = dto.getAddress();
+        BigDecimal amount = dto.getBalance();
+        String hash = dto.getHash();
+        // 判断有无
+        //List<MemberCoinAddressEntity> addressList = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag(CoinTypeEnum.USDT.name(), "TRC20");
+        Map<String, Object> hashParam = new HashMap<>();
+        // 校验hash是否已同步过
+        hashParam.put("hash", hash);
+        List<MemberCoinChargeEntity> memberCoinChargeEntities = memberCoinChargeDao.selectByMap(hashParam);
+        if (CollectionUtils.isNotEmpty(memberCoinChargeEntities)) {
+            // 若已同步过
+            return;
+        }
+        // 添加钱包余额
+        // 用户ID
+        MemberCoinAddressEntity memberCoinAddress = memberCoinAddressDao.selectCoinAddressByAddressAndSymbolTag(address, CoinTypeEnum.USDT.name(),"TRC20");
+        if (memberCoinAddress == null) {
+            return;
+        }
+        Long memberId = memberCoinAddress.getMemberId();
+        // 查询钱包 并更新
+        DappWalletCoinEntity memberWalletCoinEntity = memberWalletCoinDao.selectWalletCoinBymIdAndCode(memberId, CoinTypeEnum.USDT.name());
+        memberWalletCoinDao.updateBlockBalance(memberWalletCoinEntity.getId(), amount, BigDecimal.ZERO, 0);
+        // 添加冲币记录
+        String orderNo = insertCoinCharge(address, memberId, amount, CoinTypeEnum.USDT.name(), "TRC20", BigDecimal.ZERO, hash);
+//        LogRecordUtils.insertMemberAccountMoneyChange(memberId, "转入", amount, CoinTypeEnum.USDT.name(), 1, 1);
+
+//        ThreadPoolUtils.sendDingTalk(5);
+//        DappMemberEntity member = memberDao.selectById(memberId);
+//        if (StrUtil.isNotBlank(member.getPhone())) {
+//            //String amountEos = amount + "XRP";
+//            ZzSmsSend.sendRechargeMsg(member.getPhone(), new Date(), amount+"U", orderNo);
+//        } else {
+//            SubMailSend.sendRechargeMail(member.getEmail(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo);
+//        }
+
+
+    }
+
+
+    private String generateNo() {
+        // 生成订单号
+        Long timestamp = System.currentTimeMillis();
+        // 随机数
+        int random = (int) (Math.random() * 10);
+        return String.valueOf(timestamp).substring(2) + random;
+    }
+
+    public String insertCoinCharge(String address, Long memberId, BigDecimal newBalance, String symbol, String tag, BigDecimal lastAmount, String hash) {
+        MemberCoinChargeEntity memberCoinChargeEntity = new MemberCoinChargeEntity();
+        memberCoinChargeEntity.setAddress(address);
+        memberCoinChargeEntity.setMemberId(memberId);
+        memberCoinChargeEntity.setAmount(newBalance);
+        memberCoinChargeEntity.setSymbol(symbol);
+        memberCoinChargeEntity.setTag(tag);
+        memberCoinChargeEntity.setStatus(1);
+        memberCoinChargeEntity.setLastAmount(lastAmount);
+        memberCoinChargeEntity.setHash(hash);
+        String orderNo = generateNo();
+        memberCoinChargeEntity.setOrderCode(orderNo);
+        memberCoinChargeDao.insert(memberCoinChargeEntity);
+        return orderNo;
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/TransformUtil.java b/src/main/java/cc/mrbird/febs/dapp/chain/TransformUtil.java
new file mode 100644
index 0000000..bdc4fa5
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/TransformUtil.java
@@ -0,0 +1,215 @@
+package cc.mrbird.febs.dapp.chain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Auther: little liu
+ * @Date: 2020/09/03/16:03
+ * @Description:
+ */
+public class TransformUtil {
+
+
+    /**
+     * 长度不够前面补0
+     *
+     * @param str
+     * @param strLength
+     * @return
+     */
+    public static String addZeroForNum(String str, int strLength) {
+        int strLen = str.length();
+        if (strLen < strLength) {
+            while (strLen < strLength) {
+                StringBuffer sb = new StringBuffer();
+                sb.append("0").append(str);// 左补0
+                // sb.append(str).append("0");//右补0
+                str = sb.toString();
+                strLen = str.length();
+            }
+        }
+        return str;
+    }
+
+    public static String delZeroForNum(String str) {
+        return str.replaceAll("^(0+)", "");
+    }
+
+    public static String getSeqNumByLong(Long l, int bitCount) {
+        return String.format("%0" + bitCount + "d", l);
+    }
+
+
+    /**
+     * 字符串转换为16进制字符串
+     *
+     * @param s
+     * @return
+     */
+    public static String stringToHexString(String s) {
+        String str = "";
+        for (int i = 0; i < s.length(); i++) {
+            int ch = s.charAt(i);
+            String s4 = Integer.toHexString(ch);
+            str = str + s4;
+        }
+        return str;
+    }
+
+    /**
+     * 16进制字符串转换为字符串
+     *
+     * @param s
+     * @return
+     */
+    public static String hexStringToString(String s) {
+        if (s == null || s.equals("")) {
+            return null;
+        }
+        s = s.replace(" ", "");
+        byte[] baKeyword = new byte[s.length() / 2];
+        for (int i = 0; i < baKeyword.length; i++) {
+            try {
+                baKeyword[i] = (byte) (0xff & Integer.parseInt(
+                        s.substring(i * 2, i * 2 + 2), 16));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        try {
+            s = new String(baKeyword, "gbk");
+            new String();
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+        return s;
+    }
+
+    /**
+     * 16进制表示的字符串转换为字节数组
+     *
+     * @param s 16进制表示的字符串
+     * @return byte[] 字节数组
+     */
+    public static byte[] hexStringToByteArray(String s) {
+        int len = s.length();
+        byte[] b = new byte[len / 2];
+        for (int i = 0; i < len; i += 2) {
+            // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节
+            b[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character
+                    .digit(s.charAt(i + 1), 16));
+        }
+        return b;
+    }
+
+    /**
+     * byte数组转16进制字符串
+     *
+     * @param bArray
+     * @return
+     */
+    public static final String bytesToHexString(byte[] bArray) {
+        StringBuffer sb = new StringBuffer(bArray.length);
+        String sTemp;
+        for (int i = 0; i < bArray.length; i++) {
+            sTemp = Integer.toHexString(0xFF & bArray[i]);
+            if (sTemp.length() < 2)
+                sb.append(0);
+            sb.append(sTemp.toUpperCase());
+        }
+        return sb.toString();
+    }
+
+
+    /**
+     * @param: [hex]
+     * @return: int
+     * @description: 按位计算,位值乘权重
+     */
+    public static int hexToDecimal(String hex) {
+        int outcome = 0;
+        for (int i = 0; i < hex.length(); i++) {
+            char hexChar = hex.charAt(i);
+            outcome = outcome * 16 + charToDecimal(hexChar);
+        }
+        return outcome;
+    }
+
+    /**
+     * @param: [c]
+     * @return: int
+     * @description:将字符转化为数字
+     */
+    public static int charToDecimal(char c) {
+        if (c >= 'A' && c <= 'F')
+            return 10 + c - 'A';
+        else
+            return c - '0';
+    }
+
+
+
+
+    /**
+     * 把原始字符串分割成指定长度的字符串列表
+     *
+     * @param inputString
+     *            原始字符串
+     * @param length
+     *            指定长度
+     * @return
+     */
+    public static List<String> getStrList(String inputString, int length) {
+        int size = inputString.length() / length;
+        if (inputString.length() % length != 0) {
+            size += 1;
+        }
+        return getStrList(inputString, length, size);
+    }
+
+    /**
+     * 把原始字符串分割成指定长度的字符串列表
+     *
+     * @param inputString
+     *            原始字符串
+     * @param length
+     *            指定长度
+     * @param size
+     *            指定列表大小
+     * @return
+     */
+    public static List<String> getStrList(String inputString, int length,
+                                          int size) {
+        List<String> list = new ArrayList<String>();
+        for (int index = 0; index < size; index++) {
+            String childStr = substring(inputString, index * length,
+                    (index + 1) * length);
+            list.add(childStr);
+        }
+        return list;
+    }
+
+    /**
+     * 分割字符串,如果开始位置大于字符串长度,返回空
+     *
+     * @param str
+     *            原始字符串
+     * @param f
+     *            开始位置
+     * @param t
+     *            结束位置
+     * @return
+     */
+    public static String substring(String str, int f, int t) {
+        if (f > str.length())
+            return null;
+        if (t > str.length()) {
+            return str.substring(f, str.length());
+        } else {
+            return str.substring(f, t);
+        }
+    }
+
+}
+
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/Trc20Service.java b/src/main/java/cc/mrbird/febs/dapp/chain/Trc20Service.java
new file mode 100644
index 0000000..fa6a7c4
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/Trc20Service.java
@@ -0,0 +1,105 @@
+package cc.mrbird.febs.dapp.chain;
+
+import com.sunlight.tronsdk.TrxService;
+import com.sunlight.tronsdk.transaction.TransactionResult;
+import org.apache.commons.codec.binary.Hex;
+import org.tron.common.crypto.SignInterface;
+import org.tron.common.crypto.SignUtils;
+import org.tron.common.utils.ByteArray;
+import org.tron.common.utils.Utils;
+import org.tron.walletserver.WalletApi;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * TRC20 服务类
+ * https://cn.developers.tron.network/reference
+ */
+public class Trc20Service {
+
+    private final static String FULL_NODE_URL = "https://api.trongrid.io";
+
+    public final static String TRX_PRIVATE_KEY = "a932e4cc6fd9e4932da90e8dd0c6b2bdbfcdfb54de1ce6b68d854cc9b3c95653";
+    public final static String TRX_ADDRESS = "TJD7nWCAiTiiRoqh7TDjc6wL72YwBi2ef5";
+    public final static String POOL_ADDRESS = "TXBQCyHDmHTauN3nUixjiQT6fK7pvUeKAM";
+
+    public final static String API_KEY="a7b0c96a-cfcd-474d-88c5-75c6277fedbf";
+
+
+    /**
+     * 创建用户钱包地址
+     **/
+    public static  Map<String,String> createAddress() {
+//        String url = http + "/wallet/generateaddress";
+        SignInterface sign = SignUtils.getGeneratedRandomSign(Utils.getRandom(), true);
+        byte[] priKey = sign.getPrivateKey();
+        byte[] address = sign.getAddress();
+        String priKeyStr = Hex.encodeHexString(priKey);
+        String base58check = WalletApi.encode58Check(address);
+        String hexString = ByteArray.toHexString(address);
+        Map<String,String> jsonAddress = new HashMap<>();
+        jsonAddress.put("address", base58check);
+        jsonAddress.put("hexAddress", hexString);
+        jsonAddress.put("privateKey", priKeyStr);
+        return jsonAddress;
+    }
+
+    /**
+     *  转TRX
+     * @param sendPrivateKey
+     * @param receiveAddress
+     * @param amount
+     */
+    public static void sendTrx(String sendPrivateKey,String receiveAddress,BigDecimal amount) {
+        TrxService service  = new TrxService();
+        try {
+            TransactionResult transactionResult = service.testSendTrxTransaction(sendPrivateKey, receiveAddress, amount,API_KEY);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     *  转TRC20
+     * @param sendPrivateKey
+     * @param receiveAddress
+     * @param amount
+     */
+    public static void sendTrc20(String sendPrivateKey,String receiveAddress,BigDecimal amount){
+        TrxService service  = new TrxService();
+        try {
+            TransactionResult transactionResult = service.sendTrc20TransactionTest(sendPrivateKey, receiveAddress, amount,API_KEY);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static BigDecimal getTrxBalance(String address){
+        TrxService service  = new TrxService();
+        try {
+            BigDecimal trxBalanceTest = service.getTrxBalanceTest(address,API_KEY);
+            return trxBalanceTest;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static BigDecimal getTrc20Balance(String address){
+        TrxService service  = new TrxService();
+        try {
+            BigDecimal trxBalanceTest = service.trc20BalanceOfTest(address,API_KEY);
+            return trxBalanceTest;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+    public static void main(String[] args) {
+        System.out.println(createAddress());
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/TrxUsdtUpdateService.java b/src/main/java/cc/mrbird/febs/dapp/chain/TrxUsdtUpdateService.java
new file mode 100644
index 0000000..0a0cbab
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/TrxUsdtUpdateService.java
@@ -0,0 +1,377 @@
+package cc.mrbird.febs.dapp.chain;
+
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.dapp.chain.entity.EthUsdtChargeDto;
+import cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity;
+import cc.mrbird.febs.dapp.enumerate.CoinTypeEnum;
+import cc.mrbird.febs.dapp.mapper.MemberCoinAddressDao;
+import cc.mrbird.febs.rabbit.producer.UsdtUpdateProducer;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.*;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+import org.tron.common.utils.ByteArray;
+import org.tron.walletserver.WalletApi;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.*;
+
+/**
+ * TRX TRC20服务类
+ */
+@Slf4j
+@Service
+public class TrxUsdtUpdateService {
+
+    public static List<String> addressList = new ArrayList<>();
+    private static String http = "https://api.trongrid.io";
+
+    private static String TRC20_CONTRACT_ADDRESS = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t";
+
+    /**
+     * 手续费
+     */
+    private final static BigDecimal TRX_FEE = new BigDecimal("10");
+
+    @Resource
+    private UsdtUpdateProducer usdtUpdateProducer;
+
+    @Resource
+    private MemberCoinAddressDao memberCoinAddressDao;
+
+    @Resource
+    RedisUtils redisUtils;
+
+    /**
+     * 扫块 同步充值USDT-TRC20和TRX
+     */
+    public void monitorCoinListener(Long blockNum) {
+        if (CollectionUtils.isEmpty(addressList)) {
+            List<MemberCoinAddressEntity> coinAddressList = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag(CoinTypeEnum.USDT.name(), "TRC20");
+            if (CollectionUtils.isNotEmpty(coinAddressList)) {
+                coinAddressList.forEach(e -> {
+                    addressList.add(e.getAddress());
+                });
+            }
+        }
+        if (CollectionUtils.isEmpty(addressList)) {
+            return;
+        }
+
+
+        //  解析区块
+        httpTransactionInfo(addressList, blockNum);
+
+    }
+
+    /**
+     * 解析区块数据 同步用户充值
+     *
+     * @param addressList
+     * @param num
+     */
+    private void httpTransactionInfo(List<String> addressList, Long num) {
+        // 查询详情,包含了所有交易信息
+        String transactionInfoByBlockNum = getblockbynum(BigInteger.valueOf(num));
+        if (StringUtils.isBlank(transactionInfoByBlockNum)) {
+            return;
+        }
+//        log.info("--->{}, {}", num, System.currentTimeMillis());
+        // 不用等到扫完再累加 只要进来就加 还有一个条件是必须查询出区块再加 否则当区块超过实际区块
+//        redisUtils.set("USDT_TRC20_BLOCK_NUM", (num + 1L));
+        JSONArray parseArray = JSON.parseObject(transactionInfoByBlockNum).getJSONArray("transactions");
+        if (parseArray != null && parseArray.size() > 0) {
+            for (Object e : parseArray) {
+                try {
+//                    String txId = JSON.parseObject(e.toString()).getString("id");
+//                    String contract_address = JSON.parseObject(e.toString()).getString("contract_address");
+//                    if(!"41a614f803b6fd780986a42c78ec9c7f77e6ded13c".equals(contract_address)){
+//                        continue;
+//                    }
+                    //判断 数据库 txId 有 就不用往下继续了
+                    JSONObject parseObject = JSON.parseObject(e.toString());
+                    String txId = parseObject.getString("txID");
+                    String contractRet = parseObject.getJSONArray("ret").getJSONObject(0).getString("contractRet");
+                    //交易成功
+                    if ("SUCCESS".equals(contractRet)) {
+                        String type = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getString("type");
+                        if ("TriggerSmartContract".equals(type)) {
+                            //合约地址转账
+                            triggerSmartContract(addressList, txId, parseObject);
+
+                        } else if ("TransferContract".equals(type)) {
+                            //trx 转账
+                            //transferContract(parseObject);
+                        }
+                    }
+                } catch (Exception exception) {
+                    exception.printStackTrace();
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 比对本地地址 同步TRX充值
+     *
+     * @param parseObject
+     */
+    private void transferContract(JSONObject parseObject) {
+        //数量
+        BigDecimal amount = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getJSONObject("parameter").getJSONObject("value").getBigDecimal("amount");
+
+        //调用者地址
+        String owner_address = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getJSONObject("parameter").getJSONObject("value").getString("owner_address");
+        owner_address = WalletApi.encode58Check(ByteArray.fromHexString(owner_address));
+
+        //转入地址
+        String to_address = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getJSONObject("parameter").getJSONObject("value").getString("to_address");
+        to_address = WalletApi.encode58Check(ByteArray.fromHexString(to_address));
+
+        amount = amount.divide(new BigDecimal(1 + TransformUtil.getSeqNumByLong(0L, 6)));
+
+    }
+
+    /**
+     * 获取特定区块的所有交易 Info 信息
+     *
+     * @param num 区块
+     * @return
+     */
+    public static String getTransactionInfoByBlockNum(BigInteger num) {
+        String url = http + "/wallet/gettransactioninfobyblocknum";
+        Map<String, Object> map = new HashMap<>();
+        map.put("num", num);
+        String param = JSON.toJSONString(map);
+        return postForEntity(url, param).getBody();
+    }
+
+    /**
+     * 获取特定区块的所有交易 Info 信息
+     *
+     * @param num 区块
+     * @return
+     */
+    public static String getblockbynum(BigInteger num) {
+        String url = http + "/wallet/getblockbynum";
+        Map<String, Object> map = new HashMap<>();
+        map.put("num", num);
+        String param = JSON.toJSONString(map);
+//        return postForEntity(url, param).getBody();
+        return postForEntityHuTool(url, param).body();
+    }
+
+
+    /**
+     * https://cn.developers.tron.network/docs/%E4%BA%A4%E6%98%9311#%E4%BA%A4%E6%98%93%E7%A1%AE%E8%AE%A4%E6%96%B9%E6%B3%95
+     * 按交易哈希查询交易
+     *
+     * @param txId 交易id
+     * @return
+     */
+    public static String getTransactionById(String txId) {
+        // String url = walletSolidityHttp + "/walletsolidity/gettransactionbyid";
+        String url = http + "/wallet/gettransactionbyid";
+        Map<String, Object> map = new HashMap<>();
+        map.put("value", txId);
+        String param = JSON.toJSONString(map);
+        return postForEntity(url, param).getBody();
+    }
+
+    /**
+     * 执行 post 请求
+     *
+     * @param url   url
+     * @param param 请求参数
+     * @return
+     */
+    private static ResponseEntity<String> postForEntity(String url, String param) {
+        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+        factory.setConnectTimeout(20000);
+        factory.setReadTimeout(20000);
+        RestTemplate restTemplate = new RestTemplate(factory);
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        headers.set("TRON-PRO-API-KEY", Trc20Service.API_KEY);
+        HttpEntity<String> request = new HttpEntity<>(param, headers);
+        ResponseEntity<String> result = restTemplate.postForEntity(url, request, String.class);
+//        System.out.println("url:" + url + ",param:" + param + ",result:" + result.getBody());
+        return result;
+    }
+
+    private static HttpResponse postForEntityHuTool(String url, String param) {
+        System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
+        return HttpUtil.createPost(url).body(param)
+                .timeout(20000).contentType("application/json")
+                .header("TRON-PRO-API-KEY", Trc20Service.API_KEY)
+                .execute();
+    }
+
+    /**
+     * 比对本地地址 同步充值USDT-TRC20
+     *
+     * @param addressList
+     * @param txId
+     * @param parseObject
+     */
+    private void triggerSmartContract(List<String> addressList, String txId, JSONObject parseObject) {
+        //方法参数
+        String data = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getJSONObject("parameter").getJSONObject("value").getString("data");
+        // 调用者地址
+        String owner_address = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getJSONObject("parameter").getJSONObject("value").getString("owner_address");
+        owner_address = WalletApi.encode58Check(ByteArray.fromHexString(owner_address));
+        //System.out.println("owner_address:"+owner_address);
+        // 合约地址
+        String contract_address = parseObject.getJSONObject("raw_data").getJSONArray("contract").getJSONObject(0).getJSONObject("parameter").getJSONObject("value").getString("contract_address");
+        contract_address = WalletApi.encode58Check(ByteArray.fromHexString(contract_address));
+
+        String dataStr = data.substring(8);
+        List<String> strList = TransformUtil.getStrList(dataStr, 64);
+        //System.out.println(strList);
+        if (strList.size() != 2) {
+            return;
+        }
+
+        String to_address = TransformUtil.delZeroForNum(strList.get(0));
+
+        if (!to_address.startsWith("41")) {
+            to_address = "41" + to_address;
+        }
+
+        to_address = WalletApi.encode58Check(ByteArray.fromHexString(to_address));
+        //System.out.println("to_address:"+to_address);
+        String amountStr = TransformUtil.delZeroForNum(strList.get(1));
+
+        if (amountStr.length() > 0) {
+            amountStr = new BigInteger(amountStr, 16).toString(10);
+        }
+
+        BigDecimal amount = BigDecimal.ZERO;
+        //相匹配的合约地址
+        if (!TRC20_CONTRACT_ADDRESS.equals(contract_address)) {
+            return;
+        }
+
+        //币种
+        if (StringUtils.isNotEmpty(amountStr)) {
+            amount = new BigDecimal(amountStr).divide(new BigDecimal(1 + TransformUtil.getSeqNumByLong(0L, 6)));
+        }
+        for (String address : addressList) {
+            if (address.equals(to_address)) {
+                log.info("存在本地的地址:" + address);
+                // 金额
+                // 发送消息队列
+                EthUsdtChargeDto dto = new EthUsdtChargeDto(address, txId, amount);
+                dto.setSymbol(EthUsdtChargeDto.Symbol.USDT_TRC20);
+                usdtUpdateProducer.sendMsg(JSONObject.toJSONString(dto));
+                log.info("===to_address:" + to_address + "===amount:" + amount);
+            }
+        }
+
+    }
+
+    /**
+     * 根据地址归集USDT-TRC20
+     *
+     * @param address
+     * @return
+     */
+    public boolean poolByAddress(String address) {
+        // 首先查询trx余额
+        BigDecimal trxBalance = Trc20Service.getTrxBalance(address);
+        if (trxBalance == null) {
+            return false;
+        }
+        if (trxBalance.compareTo(TRX_FEE) >= 0) {
+            // 转
+            BigDecimal trc20Balance = Trc20Service.getTrc20Balance(address);
+            if (trc20Balance == null) {
+                return false;
+            }
+            MemberCoinAddressEntity coinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbolTag(address, "USDT", "TRC20");
+            if (coinAddressEntity == null) {
+                return false;
+            }
+            Trc20Service.sendTrc20(coinAddressEntity.getPrivateKey(), Trc20Service.POOL_ADDRESS, trc20Balance);
+            // 需要将存在redis的待归集地址删除
+            Object trc20_pool = redisUtils.get("TRC20_POOL");
+            if (trc20_pool != null) {
+                List<String> poolList = (List) trc20_pool;
+                Iterator<String> iterator = poolList.iterator();
+                while (iterator.hasNext()) {
+                    String next = iterator.next();
+                    if (address.equals(next)) {
+                        iterator.remove();
+                    }
+                }
+                if (CollectionUtils.isEmpty(poolList)) {
+                    redisUtils.del("TRC20_POOL");
+                } else {
+                    redisUtils.set("TRC20_POOL", poolList);
+                }
+            }
+            return true;
+        } else {
+            Trc20Service.sendTrx(Trc20Service.TRX_PRIVATE_KEY, address, TRX_FEE);
+            // 将这个地址记录,后续同步
+            Object trc20_pool = redisUtils.get("TRC20_POOL");
+            List<String> poolList = new ArrayList<>();
+            if (trc20_pool != null) {
+                poolList = (List) trc20_pool;
+            }
+            poolList.add(address);
+            redisUtils.set("TRC20_POOL", poolList);
+            return true;
+        }
+    }
+
+    // https://api.trongrid.io/wallet/getnowblock
+
+    /**
+     * 获取最新区块
+     *
+     * @return
+     */
+    public long getnowblock() {
+        String url = http + "/wallet/getnowblock";
+        RestTemplate restTemplate = new RestTemplate();
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        headers.set("TRON-PRO-API-KEY", Trc20Service.API_KEY);
+        HttpEntity<String> request = new HttpEntity<>(headers);
+        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, request, String.class);
+        String forObject = exchange.getBody();
+        //System.out.println(forObject);
+        // String forObject = restTemplate.getForObject(url, String.class);
+        String number = JSON.parseObject(forObject).getJSONObject("block_header").getJSONObject("raw_data").getString("number");
+        return Long.valueOf(number);
+    }
+
+    /**
+     *  从tronscan.io查询最新区块
+     *  {"whole_block_count":29625671,"whole_pay":3392835760,"last_day_pay":460432,"last_day_block_count":28777}
+     * @return
+     */
+    public  Long getnowblockFromTronScan() {
+        String roundNum = Math.random() + "";
+        String url = "https://apiasia.tronscan.io:5566/api/block/statistic?randomNum=" + roundNum;
+        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+        factory.setConnectTimeout(20000);
+        factory.setReadTimeout(20000);
+        RestTemplate restTemplate = new RestTemplate(factory);
+        String forObject = restTemplate.getForObject(url, String.class);
+        String wholeBlockCount = JSON.parseObject(forObject).getString("whole_block_count");
+        return Long.valueOf(wholeBlockCount);
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/UsdtErc20UpdateService.java b/src/main/java/cc/mrbird/febs/dapp/chain/UsdtErc20UpdateService.java
new file mode 100644
index 0000000..ff8f2ba
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/UsdtErc20UpdateService.java
@@ -0,0 +1,132 @@
+package cc.mrbird.febs.dapp.chain;
+
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.dapp.chain.entity.EthUsdtChargeDto;
+import cc.mrbird.febs.dapp.enumerate.CoinTypeEnum;
+import cc.mrbird.febs.dapp.mapper.MemberCoinAddressDao;
+import cc.mrbird.febs.rabbit.producer.UsdtUpdateProducer;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.stereotype.Service;
+import org.web3j.crypto.Credentials;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.DefaultBlockParameterName;
+import org.web3j.protocol.core.DefaultBlockParameterNumber;
+import org.web3j.protocol.core.methods.request.EthFilter;
+import org.web3j.protocol.http.HttpService;
+import org.web3j.tx.gas.StaticGasProvider;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class UsdtErc20UpdateService {
+
+    @Resource
+    private UsdtUpdateProducer usdtUpdateProducer;
+
+    @Resource
+    private MemberCoinAddressDao coinWalletDao;
+
+    public final static List<String> ALL_ADDRESS_LIST = new ArrayList<>();
+
+    public final static String ETH_USDT_BLOCK_NUM = "ETH_USDT_BLOCK_NUM";
+
+    private final static BigDecimal DIVIDE_USDT = new BigDecimal("1000000");
+
+    private static Web3j web3;
+
+    private static Web3j getInstance() {
+        if (web3 == null) {
+            HttpService httpService = new HttpService(blockchainNode);
+            web3 = Web3j.build(httpService);
+        }
+        return web3;
+    }
+
+    public static  BigInteger GAS_PRICE = BigInteger.valueOf(45000000000L);
+    //public static final BigInteger GAS_LIMIT = BigInteger.valueOf(4300000L);
+    public static final BigInteger GAS_LIMIT = BigInteger.valueOf(2000000L);
+    private static StaticGasProvider getStaticGasProvider(){
+        return new StaticGasProvider(GAS_PRICE,GAS_LIMIT);
+    }
+
+    private static Web3j getInstanceScope() {
+
+        HttpService httpService = new HttpService(blockchainNode);
+        return Web3j.build(httpService);
+    }
+
+    //private static String blockchainNode = "http://114.55.250.231:8545";
+    private static String blockchainNode = "http://120.55.86.146:8545";
+
+    private static String contractAddr = "0xdac17f958d2ee523a2206206994597c13d831ec7";
+
+
+    // 操作账号
+    private static String privateKey = "4576fafdd215f52051c60e04618ef8997fbc5cee8413d3b34d210e296e6e9a3d";
+
+
+    @Resource
+    private RedisUtils redisUtils;
+
+
+    public void updateUsdt(){
+        // 首先查询所有的钱包地址
+        List<String> tdCoinWallets = coinWalletDao.selectAllSymbolAddress(CoinTypeEnum.USDT.toString(),"ERC20");
+        if(tdCoinWallets!=null){
+            ALL_ADDRESS_LIST.addAll(tdCoinWallets);
+        }
+        // 获取最新区块
+        String string = redisUtils.getString(ETH_USDT_BLOCK_NUM);
+        if(string==null){
+            string = "11957825";
+        }
+        BigInteger blockNum = new BigInteger(string);
+        Credentials credentials = Credentials.create(privateKey);
+        EthUsdtContract contract = EthUsdtContract.load(contractAddr, getInstance(), credentials, getStaticGasProvider());
+        EthFilter filter = getFilter(blockNum);
+        Map<String,BigInteger> map = new HashMap<String,BigInteger>();
+        map.put("blockNum",blockNum);
+        contract.transferEventFlowable(filter).subscribe(e->{
+            if(e!=null && StrUtil.isNotBlank(e.to) &&  e.log.getBlockNumber()!=null){
+                String transactionHash = e.log.getTransactionHash();
+                BigInteger blockNumber1 = e.log.getBlockNumber();
+                String toAddress = e.to;
+                BigInteger tokenBalance = e.tokens;
+                if(ALL_ADDRESS_LIST.contains(toAddress)){
+                    System.out.println("存在本地的地址:"+toAddress);
+                    // 金额
+                    BigDecimal divide = new BigDecimal(tokenBalance.toString()).divide(DIVIDE_USDT);
+                    // 发送消息队列
+                    EthUsdtChargeDto dto = new EthUsdtChargeDto(toAddress,transactionHash,divide);
+                    dto.setSymbol(EthUsdtChargeDto.Symbol.USDT_ERC20);
+                    usdtUpdateProducer.sendMsg(JSONObject.toJSONString(dto));
+                }
+                if(map.get("blockNum").compareTo(blockNumber1)!=0){
+                    redisUtils.set(ETH_USDT_BLOCK_NUM,blockNumber1.toString());
+                    map.put("blockNum",blockNumber1);
+                }
+            }
+        });
+
+    }
+
+
+    private static EthFilter getFilter(BigInteger startBlock) {
+        if (startBlock != null) {
+            EthFilter filter = new EthFilter(new DefaultBlockParameterNumber(startBlock),
+                    DefaultBlockParameterName.LATEST, contractAddr);
+            return filter;
+        } else {
+            return new EthFilter(DefaultBlockParameterName.EARLIEST,
+                    DefaultBlockParameterName.LATEST, contractAddr);
+        }
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/entity/EthUsdtChargeDto.java b/src/main/java/cc/mrbird/febs/dapp/chain/entity/EthUsdtChargeDto.java
new file mode 100644
index 0000000..b9fd2fd
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/entity/EthUsdtChargeDto.java
@@ -0,0 +1,31 @@
+package cc.mrbird.febs.dapp.chain.entity;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ *  充值扫块dto
+ */
+@Data
+public class EthUsdtChargeDto {
+
+    private String address;
+    private String hash;
+    private BigDecimal balance;
+    private String symbol;
+
+    public interface Symbol{
+        String USDT_ERC20 = "USDT_ERC20";
+        String USDT_TRC20 = "USDT_TRC20";
+    }
+
+    public EthUsdtChargeDto() {
+    }
+
+    public EthUsdtChargeDto(String address, String hash, BigDecimal balance) {
+        this.address = address;
+        this.hash = hash;
+        this.balance = balance;
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java b/src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java
index 55d298b..9bac033 100644
--- a/src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java
+++ b/src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java
@@ -30,4 +30,6 @@
      * 盲盒数量
      */
     private Integer boxCnt;
+
+    private String walletCode;
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinAddressEntity.java b/src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinAddressEntity.java
new file mode 100644
index 0000000..6947db5
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinAddressEntity.java
@@ -0,0 +1,55 @@
+package cc.mrbird.febs.dapp.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 会员币地址
+ * @author Administrator
+ *
+ */
+@Data
+@TableName("member_coin_address")
+public class MemberCoinAddressEntity extends BaseEntity {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	/**
+     * 会员ID
+     */
+    private Long memberId;
+    /**
+     * 地址
+     */
+    private String address;
+    /**
+     * 私钥
+     */
+    private String privateKey;
+    /**
+     * 币种
+     */
+    private String symbol;
+    /**
+     * 是否是本平台地址1:是  0:否
+     */
+    private String isBiyict;
+    public static final String IS_BIYICT_YES = "1";
+    public static final String IS_BIYICT_NO = "2";
+    /**
+     * 
+     */
+    private String label;
+    /**
+     * 
+     */
+    private String tag;
+    /**
+     * 币种ID
+     */
+    private Long symbolscoinId;
+    
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinChargeEntity.java b/src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinChargeEntity.java
new file mode 100644
index 0000000..7d99bfd
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/entity/MemberCoinChargeEntity.java
@@ -0,0 +1,36 @@
+package cc.mrbird.febs.dapp.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wzy
+ * @date 2020-07-02
+ **/
+@Data
+@TableName("member_coin_charge")
+public class MemberCoinChargeEntity extends BaseEntity {
+
+    private Long memberId;
+
+    private String certificate;
+
+    private BigDecimal amount;
+
+    private BigDecimal lastAmount;
+
+    private int status;
+
+    private String symbol;
+
+    private String address;
+
+    private String tag;
+
+    private String hash;
+
+    private String orderCode;
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/enumerate/CoinTypeEnum.java b/src/main/java/cc/mrbird/febs/dapp/enumerate/CoinTypeEnum.java
new file mode 100644
index 0000000..75a09fb
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/enumerate/CoinTypeEnum.java
@@ -0,0 +1,10 @@
+package cc.mrbird.febs.dapp.enumerate;
+
+/**
+ * 币种枚举数据
+ *
+ * @author wzy
+ */
+public enum CoinTypeEnum {
+    USDT, BTC, ETH, LTC, EOS, XRP, BCH, ETC
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java b/src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java
index 996d6cb..0e3399b 100644
--- a/src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java
+++ b/src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java
@@ -23,4 +23,14 @@
     Integer addTotalAndaddAvailableById(@Param("id") Long id, @Param("balance")  BigDecimal amount);
 
     Integer delAvailableDelTotalById(@Param("id") Long id, @Param("balance")  BigDecimal amount);
+
+    DappWalletCoinEntity selectWalletCoinBymIdAndCode(@Param("memberId") Long memberId, @Param("walletCode") String walletCode);
+
+    int updateFrozenBalance(@Param("memberId") Long memberId, @Param("id") Long id, @Param("amount") BigDecimal amount);
+
+    int subFrozenBalance(@Param("memberId") Long memberId, @Param("id") Long id, @Param("amount") BigDecimal amount);
+
+    int updateBlockBalance(@Param("id") Long id, @Param("availableBalance") BigDecimal availableBalance, @Param("earlyBalance") BigDecimal earlyBalance, @Param("blockNumber") Integer blockNumber);
+
+    int reduceFrozenBalance(@Param("id") Long id, @Param("amount") BigDecimal amount);
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinAddressDao.java b/src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinAddressDao.java
new file mode 100644
index 0000000..00d9687
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinAddressDao.java
@@ -0,0 +1,28 @@
+package cc.mrbird.febs.dapp.mapper;
+
+import cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface MemberCoinAddressDao extends BaseMapper<MemberCoinAddressEntity> {
+
+    MemberCoinAddressEntity selectAddressByMemberIdAndSymbol(Long memberId, String symbol);
+
+    MemberCoinAddressEntity selectBlockAddressWithTag(@Param("memberId") Long memberId, @Param("symbol") String symbol, @Param("tag") String tag);
+
+    MemberCoinAddressEntity selectBlockAddress(@Param("memberId") Long memberId, @Param("symbol") String symbol);
+
+    MemberCoinAddressEntity selectCoinAddressByAddressAndSymbol(@Param("address") String address, @Param("symbol") String symbol);
+    MemberCoinAddressEntity selectCoinAddressByAddressAndSymbolTag(@Param("address") String address, @Param("symbol") String symbol,@Param("tag") String tag);
+
+    List<MemberCoinAddressEntity> selectCoinAddressListByMap(@Param("symbol") String symbol, @Param("memberId") Long memberId);
+
+    List<MemberCoinAddressEntity> selectAllBlockAddressBySymbolAndTag(@Param("symbol") String symbol, @Param("tag") String tag);
+
+    List<MemberCoinAddressEntity> selectAllBlockAddressBySymbol(@Param("symbol") String symbol);
+
+    List<String> selectAllSymbolAddress(@Param("symbol")String symbol,@Param("tag") String tag);
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinChargeDao.java b/src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinChargeDao.java
new file mode 100644
index 0000000..29b7be8
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/mapper/MemberCoinChargeDao.java
@@ -0,0 +1,20 @@
+package cc.mrbird.febs.dapp.mapper;
+
+import cc.mrbird.febs.dapp.entity.MemberCoinChargeEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface MemberCoinChargeDao extends BaseMapper<MemberCoinChargeEntity> {
+
+    public MemberCoinChargeEntity selectNewestChargeRecord(@Param("memberId") Long memberId, @Param("symbol") String symbol, @Param("tag") String tag);
+
+    List<MemberCoinChargeEntity> selectAllBySymbolAndTag(@Param("symbol") String symbol, @Param("tag") String tag, @Param("status") Integer status);
+
+	public IPage<MemberCoinChargeEntity> findMemberCoinChargeInPage(Page<MemberCoinChargeEntity> page,
+			@Param("record")MemberCoinChargeEntity memberCoinChargeEntity);
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/BlockSerive.java b/src/main/java/cc/mrbird/febs/dapp/service/BlockSerive.java
new file mode 100644
index 0000000..d6bfccb
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/service/BlockSerive.java
@@ -0,0 +1,9 @@
+package cc.mrbird.febs.dapp.service;
+
+import cc.mrbird.febs.common.entity.FebsResponse;
+
+public interface BlockSerive {
+
+	FebsResponse findBlockAddress(String symbol, String lable);
+
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/BlockSeriveImpl.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/BlockSeriveImpl.java
new file mode 100644
index 0000000..5151795
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/BlockSeriveImpl.java
@@ -0,0 +1,95 @@
+package cc.mrbird.febs.dapp.service.impl;
+
+import cc.mrbird.febs.common.configure.i18n.MessageSourceUtils;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.utils.LoginUserUtil;
+import cc.mrbird.febs.dapp.chain.Trc20Service;
+import cc.mrbird.febs.dapp.entity.DappMemberEntity;
+import cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity;
+import cc.mrbird.febs.dapp.mapper.DappMemberDao;
+import cc.mrbird.febs.dapp.mapper.MemberCoinAddressDao;
+import cc.mrbird.febs.dapp.service.BlockSerive;
+import cc.mrbird.febs.rabbit.producer.UsdtUpdateProducer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Service
+public class BlockSeriveImpl implements BlockSerive {
+
+    @Resource
+    DappMemberDao memberDao;
+
+    @Resource
+    MemberCoinAddressDao memberMapper;
+
+    @Resource
+    private UsdtUpdateProducer usdtUpdateProducer;
+
+    @Override
+    public FebsResponse findBlockAddress(String symbol, String lable) {
+        //获取用户ID
+        String mId = LoginUserUtil.getAppUser().getId().toString();
+        DappMemberEntity member = memberDao.selectById(mId);
+        if (member == null) {
+            return new FebsResponse().fail().message(MessageSourceUtils.getString("member_service_0003"));
+        }
+        if(StringUtils.isBlank(lable)){
+            //lable = "ERC20";
+            lable = "TRC20";
+        }
+
+        FebsResponse result = new FebsResponse();
+        try {
+            Map<String, String> map = new HashMap<String, String>();
+            MemberCoinAddressEntity memberCoinAddress = new MemberCoinAddressEntity();
+
+            if ("USDT".equals(symbol)) {
+                memberCoinAddress = memberMapper.selectBlockAddressWithTag(Long.parseLong(mId), symbol, lable);
+            } else {
+                memberCoinAddress = memberMapper.selectBlockAddress(Long.parseLong(mId), symbol);
+            }
+
+            if (memberCoinAddress != null) {
+                map.put("address", memberCoinAddress.getAddress());
+                map.put("lable", memberCoinAddress.getLabel());
+                result.data(map);
+            } else {
+                String address = "";
+                String key = "";
+                String uuid = member.getInviteId();
+
+                Map<String, String> usdtMap = Trc20Service.createAddress();
+                address = usdtMap.get("address");
+                key = usdtMap.get("privateKey");
+                map.put("address", address);
+
+                // 发送新增的地址到监听集合
+                usdtUpdateProducer.sendAddressMsg(address+","+"TRC20");
+
+                MemberCoinAddressEntity coinAddress = new MemberCoinAddressEntity();
+                coinAddress.setAddress(address);
+                coinAddress.setIsBiyict(MemberCoinAddressEntity.IS_BIYICT_YES);
+                coinAddress.setMemberId(Long.parseLong(mId));
+                coinAddress.setPrivateKey(key);
+                coinAddress.setSymbol(symbol);
+                coinAddress.setLabel(uuid);
+                if (symbol.equals("USDT")) {
+                    coinAddress.setTag(lable);
+                }
+
+                memberMapper.insert(coinAddress);
+                result.data(map);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+}
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 27cfbc5..c4010fc 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
@@ -447,6 +447,7 @@
         dappWalletCoinEntity.setAvailableAmount(AppContants.INIT_MONEY);
         dappWalletCoinEntity.setFrozenAmount(AppContants.INIT_MONEY);
         dappWalletCoinEntity.setTotalAmount(AppContants.INIT_MONEY);
+        dappWalletCoinEntity.setWalletCode("USDT");
         dappWalletCoinDao.insert(dappWalletCoinEntity);
 
         return new FebsResponse().success().message(MessageSourceUtils.getString("register_err_006"));
diff --git a/src/main/java/cc/mrbird/febs/job/BlockCoinUpdateJob.java b/src/main/java/cc/mrbird/febs/job/BlockCoinUpdateJob.java
new file mode 100644
index 0000000..99f9b28
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/job/BlockCoinUpdateJob.java
@@ -0,0 +1,93 @@
+package cc.mrbird.febs.job;
+
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.dapp.chain.BlockCoinService;
+import cc.mrbird.febs.dapp.chain.TrxUsdtUpdateService;
+import cc.mrbird.febs.rabbit.producer.UsdtUpdateProducer;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * 链上币种同步任务
+ *
+ * @author wzy
+ * @date 2020-07-02
+ **/
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "system", name = "block-job", havingValue = "true")
+public class BlockCoinUpdateJob {
+
+    @Resource
+    private BlockCoinService blockCoinService;
+
+    @Resource
+    private TrxUsdtUpdateService trxUsdtUpdateService;
+
+    @Resource
+    RedisUtils redisUtils;
+
+    @Autowired
+    private UsdtUpdateProducer usdtUpdateProducer;
+
+
+    public static ConcurrentLinkedQueue<Long> TRC_BLOCK = new ConcurrentLinkedQueue<>();
+
+    /**
+     * TRC20_USDT 同步
+     */
+    @Scheduled(cron = "0/2 * * * * ? ")
+//    @Async
+    public void usdtTc20Update() {
+        // 波场3秒出一个块
+        Long blocnNum = TRC_BLOCK.poll();
+        if (blocnNum == null) {
+            return;
+        }
+        usdtUpdateProducer.sendTrc20BlockMsg(blocnNum.toString());
+        redisUtils.set("USDT_TRC20_CURRENT_BLOCK_NUM", blocnNum);
+//        try {
+//            trxUsdtUpdateService.monitorCoinListener(blocnNum);
+//        } catch (RestClientException | HttpException e) {
+//            //  此时是连接问题 这个块需要重新扫描
+//            log.info("查询区块超时:" + blocnNum);
+//            TRC_BLOCK.add(blocnNum);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+
+    }
+
+    @Scheduled(cron = "0 0/1 * * * ? ")
+    public void usdtTc20UpdateQueue() {
+        // 查询最新区块号
+        long getnowblock = trxUsdtUpdateService.getnowblockFromTronScan() - 25;
+        // 拿到redis里最新区块
+        Object trc20BlockNum = redisUtils.get("USDT_TRC20_BLOCK_NUM");
+        if (trc20BlockNum == null) {
+            // 没有则取最新的块
+            trc20BlockNum = getnowblock;
+            redisUtils.set("USDT_TRC20_BLOCK_NUM", getnowblock);
+        }
+        Long blockNum = Long.valueOf(trc20BlockNum.toString());
+        if (getnowblock <= blockNum) {
+            // 如果当前区块比最新已确认区块还大,则不继续执行
+            return;
+        }
+        // 得到最新区块和当前区块的差值
+        Long diff = getnowblock-blockNum;
+        for(long i=1;i<=diff;i++){
+            blockNum++;
+            TRC_BLOCK.add(blockNum);
+        }
+        // 将最新的最大区块放入redis
+        redisUtils.set("USDT_TRC20_BLOCK_NUM", blockNum);
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/rabbit/RabbitMqConfig.java b/src/main/java/cc/mrbird/febs/rabbit/RabbitMqConfig.java
new file mode 100644
index 0000000..bdaf0c5
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/rabbit/RabbitMqConfig.java
@@ -0,0 +1,511 @@
+package cc.mrbird.febs.rabbit;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2020-05-25
+ **/
+@Configuration
+public class RabbitMqConfig {
+
+    public static final String EXCHANGE_ONE = "biue-exchange-one";
+
+    public static final String QUEUE_TEST = "test-queue";
+
+    public static final String ROUTING_KEY_TEST = "test-routingKey";
+
+    public static final String EXCHANGE_A = "biue-exchange-A";
+
+
+    public static final String EXCHANGE_USDT_UPDATE = "exchange_usdt_update";
+
+    public static final String QUEUE_USDT_UPDATE = "queue_usdt_update";
+
+    public static final String ROUTING_KEY_USDT_UPDATE = "routing_key_usdt_update";
+
+    public static final String EXCHANGE_USDT_ADDRESS = "exchange_usdt_address";
+
+    public static final String QUEUE_USDT_ADDRESS= "queue_usdt_address";
+
+    public static final String ROUTING_KEY_USDT_ADDRESS = "routing_key_usdt_address";
+
+
+    /**
+     * 撮合交易
+     */
+    public static final String EXCHANGE_B = "biue-exchange-B";
+
+
+    // 开多止盈队列
+    public static final String QUEUE_MOREPRO = "QUEUE_MOREPRO_NEW";
+    // 开空止盈队列
+    public static final String QUEUE_LESSPRO = "QUEUE_LESSPRO_NEW";
+    // 开多止损队列
+    public static final String QUEUE_MORELOSS = "QUEUE_MORELOSS_NEW";
+    // 开空止损队列
+    public static final String QUEUE_LESSLOSS = "QUEUE_LESSLOSS_NEW";
+
+    // 限价委托
+    public static final String QUEUE_LIMIT = "QUEUE_LIMIT_NEW";
+
+    // 委托平仓
+    public static final String QUEUE_LIMIT_CLOSE = "QUEUE_LIMIT_CLOSE_NEW";
+
+    // 爆仓队列
+    public static final String QUEUE_COINOUT = "QUEUE_COINOUT_NEW";
+
+    //价格操作
+    public static final String QUEUE_PRICEOPERATE = "QUEUE_PRICEOPERATE_NEW";
+
+    // 平仓队列
+    public static final String QUEUE_CLOSETRADE = "QUEUE_CLOSETRADE_NEW";
+
+    // 全仓爆仓
+    public static final String QUEUE_WHOLE_BOMB = "QUEUE_WHOLE_BOMB_NEW";
+
+    // 全仓价格操作
+    public static final String QUEUE_WHOLE_PRICE = "QUEUE_WHOLE_PRCE";
+
+    // 跟单下单
+    public static final String QUEUE_FOLLOW_ORDER = "QUEUE_FOLLOW_ORDER";
+
+    public static final String ROUTINGKEY_FOLLOW_ORDER = "ROUTINGKEY_FOLLOW_ORDER";
+
+    // 跟单调整保证金
+    public static final String QUEUE_FOLLOW_CHANGE_BOND = "QUEUE_FOLLOW_CHANGE_BOND";
+
+    public static final String ROUTINGKEY_FOLLOW_CHANGE_BOND = "ROUTINGKEY_FOLLOW_CHANGE_BOND";
+
+    // 开多止盈路由键
+    public static final String ROUTINGKEY_MOREPRO = "ROUTINGKEY_MOREPRO";
+    // 开空止盈路由
+    public static final String ROUTINGKEY_LESSPRO = "ROUTINGKEY_LESSPRO";
+    // 开多止损路由
+    public static final String ROUTINGKEY_MORELOSS = "ROUTINGKEY_MORELOSS";
+    // 开空止损路由
+    public static final String ROUTINGKEY_LESSLOSS = "ROUTINGKEY_LESSLOSS";
+    // 限价委托
+    public static final String ROUTINGKEY_LIMIT = "ROUTINGKEY_LIMIT";
+
+    // 爆仓路由
+    public static final String ROUTINGKEY_COINOUT = "ROUTINGKEY_COINOUT";
+
+
+    // 价格操作
+    public static final String ROUTINGKEY_PRICEOPERATE = "ROUTINGKEY_PRICEOPERATE";
+    // 平仓路由
+    public static final String ROUTINGKEY_CLOSETRADE = "ROUTINGKEY_CLOSETRADE";
+
+    // 委托平仓
+    public static final String ROUTINGKEY_LIMIT_CLOSE = "ROUTINGKEY_LIMIT_CLOSE";
+
+    // 全仓爆仓
+    public static final String ROUTINGKEY_WHOLE_BOMB = "ROUTINGKEY_WHOLE_BOMB";
+
+    // 全仓价格操作
+    public static final String ROUTINGKEY_WHOLE_PRICE = "ROUTINGKEY_WHOLE_PRICE";
+
+    public static final String ROUTINGKEY_MARKET_BUSSINESS = "ROUTINGKEY_MARKET_BUSSINESS";
+
+    public static final String QUEUE_MARKET_BUSSINESS = "QUEUE_MARKET_BUSSINESS";
+
+    public static final String ROUTING_KEY_DELAY = "route.delay";
+    public static final String QUEUE_DELAY = "queue.delay";
+    public static final String EXCHANGE_DELAY = "exchange.delay";
+
+    public static final String QUEUE_MSG_HISTORY = "queue_msg_history";
+    public static final String ROUTING_KEY_MSG_HISTORY = "routing_key_msg_history";
+
+    public static final String QUEUE_TRC20_BLOCK = "QUEUE_TRC20_BLOCK";
+    public static final String ROUTING_TRC20_BLOCK = "ROUTING_TRC20_BLOCK";
+
+
+    public static final String QUEUE_ORDER_RETURN = "QUEUE_ORDER_RETURN";
+    public static final String ROUTING_ORDER_RETURN = "ROUTING_ORDER_RETURN";
+
+    @Resource
+    private ConnectionFactory connectionFactory;
+
+//    @Bean
+//    public ConnectionFactory connectionFactory() {
+//        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(customRabbitProperties.getHost(), customRabbitProperties.getPort());
+//        connectionFactory.setUsername(customRabbitProperties.getUsername());
+//        connectionFactory.setPassword(customRabbitProperties.getPassword());
+//        connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
+//        return connectionFactory;
+//    }
+
+    @Bean
+    public DirectExchange defaultExchange() {
+        return new DirectExchange(EXCHANGE_ONE);
+    }
+
+    @Bean
+    public DirectExchange delayExchange() {
+        return new DirectExchange(EXCHANGE_DELAY);
+    }
+
+    @Bean
+    public Queue delayQueue() {
+        Map<String, Object> params = new HashMap<>();
+        // x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称,
+        params.put("x-dead-letter-exchange", EXCHANGE_DELAY);
+        // x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称。
+        params.put("x-dead-letter-routing-key", ROUTING_KEY_DELAY);
+//        params.put("x-message-ttl", 6000);
+        return new Queue(QUEUE_DELAY, true, false, false, params);
+    }
+
+    @Bean
+    public Binding delayBinding() {
+        return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(ROUTING_KEY_DELAY);
+    }
+
+    @Bean
+    public Queue marketBussinessQueue() {
+        return new Queue(QUEUE_MARKET_BUSSINESS);
+    }
+
+    @Bean
+    public Binding marketBussinessBinding() {
+        return BindingBuilder.bind(marketBussinessQueue()).to(defaultExchange()).with(ROUTINGKEY_MARKET_BUSSINESS);
+    }
+
+    @Bean
+    public Queue msgHistoryQueue() {
+        return new Queue(QUEUE_MSG_HISTORY);
+    }
+
+    @Bean
+    public Binding msgHistoryBinding() {
+        return BindingBuilder.bind(msgHistoryQueue()).to(defaultExchange()).with(ROUTING_KEY_MSG_HISTORY);
+    }
+
+    @Bean
+    public Queue orderReturnQueue() {
+        return new Queue(QUEUE_ORDER_RETURN);
+    }
+
+    @Bean
+    public Binding orderReturnBinding() {
+        return BindingBuilder.bind(orderReturnQueue()).to(defaultExchange()).with(ROUTING_ORDER_RETURN);
+    }
+
+
+    @Bean
+    public Queue trc20Queue() {
+        return new Queue(QUEUE_TRC20_BLOCK);
+    }
+
+    @Bean
+    public Binding trc20Binding() {
+        return BindingBuilder.bind(trc20Queue()).to(defaultExchange()).with(ROUTING_TRC20_BLOCK);
+    }
+
+
+    @Bean
+    public Queue testQueue() {
+        return new Queue(QUEUE_TEST, true);
+    }
+
+    @Bean
+    public Binding binding() {
+        return BindingBuilder.bind(testQueue()).to(defaultExchange()).with(ROUTING_KEY_TEST);
+    }
+
+
+   @Bean
+    public DirectExchange usdtUpdateExchange() {
+        return new DirectExchange(EXCHANGE_USDT_UPDATE);
+    }
+
+
+    @Bean
+    public Queue usdtUpdateQueue() {
+        return new Queue(QUEUE_USDT_UPDATE, true);
+    }
+
+    @Bean
+    public Binding usdtUpdatebinding() {
+        return BindingBuilder.bind(usdtUpdateQueue()).to(usdtUpdateExchange()).with(ROUTING_KEY_USDT_UPDATE);
+    }
+
+    @Bean
+    public DirectExchange usdtAddressExchange() {
+        return new DirectExchange(EXCHANGE_USDT_ADDRESS);
+    }
+
+
+    @Bean
+    public Queue usdtAddressQueue() {
+        return new Queue(QUEUE_USDT_ADDRESS, true);
+    }
+
+    @Bean
+    public Binding usdtAddressbinding() {
+        return BindingBuilder.bind(usdtAddressQueue()).to(usdtAddressExchange()).with(ROUTING_KEY_USDT_ADDRESS);
+    }
+
+
+    /**
+     * 交换器A 可以继续添加交换器B C
+     *
+     * @return
+     */
+    @Bean
+    public DirectExchange orderExchange() {
+        return new DirectExchange(EXCHANGE_A);
+    }
+
+
+    /**
+     * 开多止盈队列
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueMorePro() {
+        // 定义一个名称为QUEUE_A,持久化的队列
+        return new Queue(QUEUE_MOREPRO, true);
+    }
+
+    /**
+     * 开空止盈队列
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueLessPro() {
+        // 定义一个名称为QUEUE_A,持久化的队列
+        return new Queue(QUEUE_LESSPRO, true);
+    }
+
+    /**
+     * 开多止损
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueMoreLoss() {
+        // 定义一个名称为QUEUE_A,持久化的队列
+        return new Queue(QUEUE_MORELOSS, true);
+    }
+
+    /**
+     * 开空止损
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueLessLoss() {
+        // 定义一个名称为QUEUE_A,持久化的队列
+        return new Queue(QUEUE_LESSLOSS, true);
+    }
+
+    /**
+     * 限价委托
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueLimit() {
+        return new Queue(QUEUE_LIMIT, true);
+    }
+
+    /**
+     * 委托平仓
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueLimitClose() {
+        return new Queue(QUEUE_LIMIT_CLOSE, true);
+    }
+
+
+    /**
+     * 爆仓
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueCoinout() {
+        return new Queue(QUEUE_COINOUT, true);
+    }
+
+    /**
+     * 价格操作
+     *
+     * @return
+     */
+    @Bean
+    public Queue queuePriceoperate() {
+        return new Queue(QUEUE_PRICEOPERATE, true);
+    }
+
+    /**
+     * 价格操作
+     *
+     * @return
+     */
+    @Bean
+    public Queue queueCloseTrade() {
+        return new Queue(QUEUE_CLOSETRADE, true);
+    }
+
+    @Bean
+    public Queue queueWholePrice() {
+        return new Queue(QUEUE_WHOLE_PRICE, true);
+    }
+    /**
+     * 全仓爆仓
+     * @return
+     */
+    @Bean
+    public Queue queueWholeBomb() {
+        return new Queue(QUEUE_WHOLE_BOMB, true);
+    }
+
+    @Bean
+    public Queue queueFollowOrder() {
+        return new Queue(QUEUE_FOLLOW_ORDER, true);
+    }
+
+    @Bean
+    public Queue queueFollowChangeBond() {
+        return new Queue(QUEUE_FOLLOW_CHANGE_BOND, true);
+    }
+
+    @Bean
+    public Binding bindingFollowChangeBond() {
+        return BindingBuilder.bind(queueFollowChangeBond()).to(orderExchange()).with(ROUTINGKEY_FOLLOW_CHANGE_BOND);
+    }
+
+    @Bean
+    public Binding bindingFollowOrder() {
+        return BindingBuilder.bind(queueFollowOrder()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_FOLLOW_ORDER);
+    }
+
+
+    @Bean
+    public Binding bindingWholePrice() {
+        return BindingBuilder.bind(queueWholePrice()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_WHOLE_PRICE);
+    }
+
+    /**
+     * 开多止盈
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingMroPro() {
+        return BindingBuilder.bind(queueMorePro()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_MOREPRO);
+    }
+
+    /**
+     * 开空止盈
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingLessPro() {
+        return BindingBuilder.bind(queueLessPro()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_LESSPRO);
+    }
+
+    /**
+     * 开多止损
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingMroLoss() {
+        return BindingBuilder.bind(queueMoreLoss()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_MORELOSS);
+    }
+
+    /**
+     * 开空止损
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingLessLoss() {
+        return BindingBuilder.bind(queueLessLoss()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_LESSLOSS);
+    }
+
+
+    /**
+     * 委托
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingLimit() {
+        return BindingBuilder.bind(queueLimit()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_LIMIT);
+    }
+
+    /**
+     * 委托平仓
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingLimitClose() {
+        return BindingBuilder.bind(queueLimitClose()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_LIMIT_CLOSE);
+    }
+
+    /**
+     * 爆仓
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingCoinout() {
+        return BindingBuilder.bind(queueCoinout()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_COINOUT);
+    }
+
+
+    /**
+     * 价格操作
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingPriceoperate() {
+        return BindingBuilder.bind(queuePriceoperate()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_PRICEOPERATE);
+    }
+
+    /**
+     * 平仓绑定
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingCloseTrade() {
+        return BindingBuilder.bind(queueCloseTrade()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_CLOSETRADE);
+    }
+
+    /**
+     * 全仓爆仓绑定
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingWholeBomb() {
+        return BindingBuilder.bind(queueWholeBomb()).to(orderExchange()).with(RabbitMqConfig.ROUTINGKEY_WHOLE_BOMB);
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/rabbit/consumer/UsdtUpdateConsumer.java b/src/main/java/cc/mrbird/febs/rabbit/consumer/UsdtUpdateConsumer.java
new file mode 100644
index 0000000..aef580f
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/rabbit/consumer/UsdtUpdateConsumer.java
@@ -0,0 +1,84 @@
+package cc.mrbird.febs.rabbit.consumer;
+
+import cc.mrbird.febs.dapp.chain.BlockCoinService;
+import cc.mrbird.febs.dapp.chain.Trc20Service;
+import cc.mrbird.febs.dapp.chain.TrxUsdtUpdateService;
+import cc.mrbird.febs.dapp.chain.UsdtErc20UpdateService;
+import cc.mrbird.febs.dapp.chain.entity.EthUsdtChargeDto;
+import cc.mrbird.febs.job.BlockCoinUpdateJob;
+import cc.mrbird.febs.rabbit.RabbitMqConfig;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpException;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestClientException;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+
+
+/**
+ * @author wzy
+ * @date 2020-05-25
+ **/
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "system", name = "block-job", havingValue = "true")
+public class UsdtUpdateConsumer {
+
+
+    @Resource
+    private BlockCoinService blockCoinService;
+
+    @Resource
+    TrxUsdtUpdateService trxUsdtUpdateService;
+
+    @RabbitListener(queues = RabbitMqConfig.QUEUE_USDT_UPDATE)
+    public void doSomething(String content) {
+        log.info("#USDT同步---->{}#", content);
+        EthUsdtChargeDto ethUsdtChargeDto = JSONObject.parseObject(content, EthUsdtChargeDto.class);
+
+        if(EthUsdtChargeDto.Symbol.USDT_TRC20.equals(ethUsdtChargeDto.getSymbol())){
+            blockCoinService.updateTrc20(ethUsdtChargeDto);
+            // 同步完直接归集
+            trxUsdtUpdateService.poolByAddress(ethUsdtChargeDto.getAddress());
+        }
+
+    }
+
+    @RabbitListener(queues = RabbitMqConfig.QUEUE_USDT_ADDRESS)
+    public void addUsdtAddress(String content) {
+        log.info("#添加新地址---->{}#", content);
+        if(StrUtil.isBlank(content)){
+            return;
+        }
+        String[] split = content.split(",");
+        if(split.length<2){
+            return;
+        }
+        String address = split[0];
+        String tag = split[1];
+        if("TRC20".equals(tag)){
+            TrxUsdtUpdateService.addressList.add(address);
+            // 此时还需要给这个地址转账用于激活及后续手续费
+            Trc20Service.sendTrx(Trc20Service.TRX_PRIVATE_KEY,address,new BigDecimal(10));
+        }
+    }
+
+    @RabbitListener(queues = RabbitMqConfig.QUEUE_TRC20_BLOCK)
+    public void trc20BlockMsg(String content) {
+        Long blocnNum = Long.parseLong(content);
+        try {
+            trxUsdtUpdateService.monitorCoinListener(blocnNum);
+        } catch (RestClientException | HttpException e) {
+            //  此时是连接问题 这个块需要重新扫描
+            log.info("查询区块超时:" + blocnNum);
+            BlockCoinUpdateJob.TRC_BLOCK.add(blocnNum);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/rabbit/producer/UsdtUpdateProducer.java b/src/main/java/cc/mrbird/febs/rabbit/producer/UsdtUpdateProducer.java
new file mode 100644
index 0000000..a256eda
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/rabbit/producer/UsdtUpdateProducer.java
@@ -0,0 +1,52 @@
+package cc.mrbird.febs.rabbit.producer;
+
+import cc.mrbird.febs.rabbit.RabbitMqConfig;
+import cn.hutool.core.util.IdUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author wzy
+ * @date 2020-05-25
+ **/
+@Slf4j
+@Component
+public class UsdtUpdateProducer implements RabbitTemplate.ConfirmCallback {
+
+    private RabbitTemplate rabbitTemplate;
+
+    @Autowired
+    public UsdtUpdateProducer(RabbitTemplate rabbitTemplate) {
+        this.rabbitTemplate = rabbitTemplate;
+        rabbitTemplate.setConfirmCallback(this);
+    }
+
+    public void sendMsg(String content) {
+        CorrelationData correlationData = new CorrelationData(IdUtil.simpleUUID());
+        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_USDT_UPDATE, RabbitMqConfig.ROUTING_KEY_USDT_UPDATE, content, correlationData);
+    }
+
+    public void sendAddressMsg(String content) {
+        CorrelationData correlationData = new CorrelationData(IdUtil.simpleUUID());
+        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_USDT_ADDRESS, RabbitMqConfig.ROUTING_KEY_USDT_ADDRESS, content, correlationData);
+    }
+
+    public void sendTrc20BlockMsg(String content) {
+        CorrelationData correlationData = new CorrelationData(IdUtil.simpleUUID());
+        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_ONE, RabbitMqConfig.ROUTING_TRC20_BLOCK, content, correlationData);
+    }
+
+
+    @Override
+    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
+//        log.info("#----->{}#", correlationData);
+        if (ack) {
+//            log.info("success");
+        } else {
+            log.info("--->{}", cause);
+        }
+    }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 6e584b0..bd3b5cd 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -66,4 +66,5 @@
 system:
   online-transfer: false
   chain-listener: false
-  trade-job: fales
\ No newline at end of file
+  trade-job: false
+  block-job: false
\ No newline at end of file
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index 0cb6db4..13d25e4 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -53,6 +53,7 @@
     time-zone: GMT+8
 
 system:
-  online-transfer: true
-  chain-listener: true
-  trade-job: true
\ No newline at end of file
+  online-transfer: false
+  chain-listener: false
+  trade-job: true
+  block-job: true
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index 4ad4281..06e8926 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -52,3 +52,4 @@
   online-transfer: false
   chain-listener: false
   trade-job: false
+  block-job: false
diff --git a/src/main/resources/mapper/dapp/DappWalletCoinDao.xml b/src/main/resources/mapper/dapp/DappWalletCoinDao.xml
index 885c20f..b3fe6f7 100644
--- a/src/main/resources/mapper/dapp/DappWalletCoinDao.xml
+++ b/src/main/resources/mapper/dapp/DappWalletCoinDao.xml
@@ -68,4 +68,45 @@
               id = #{id}
            and total_amount - #{balance} <![CDATA[ >= ]]> 0
     </update>
+
+
+    <select id="selectWalletCoinBymIdAndCode" resultType="cc.mrbird.febs.dapp.entity.DappWalletCoinEntity">
+        select * from member_wallet_coin where member_id = #{memberId} and wallet_code = #{walletCode}
+    </select>
+
+    <update id="updateFrozenBalance" parameterType="map">
+        UPDATE member_wallet_coin
+        SET available_balance = available_balance - #{amount},
+            frozen_balance = frozen_balance + #{amount}
+        WHERE
+            id = #{id}
+          AND member_id = #{memberId}
+    </update>
+
+    <update id="subFrozenBalance" parameterType="map">
+        UPDATE member_wallet_coin
+        SET available_balance = available_balance + #{amount},
+            frozen_balance = frozen_balance - #{amount}
+        WHERE
+            id = #{id}
+          AND member_id = #{memberId}
+    </update>
+
+
+    <update id="updateBlockBalance">
+        update member_wallet_coin
+        set
+            available_balance = IFNULL(available_balance, 0) + #{availableBalance},
+            total_balance = IFNULL(total_balance, 0) + #{availableBalance},
+            early_balance = IFNULL(early_balance, 0) + #{earlyBalance},
+            block_number  = IFNULL(block_number, 0) + #{blockNumber}
+        where id=#{id}
+    </update>
+
+    <update id="reduceFrozenBalance">
+        update member_wallet_coin
+        set frozen_balance = frozen_balance - #{amount},
+            total_balance = total_balance - #{amount}
+        where id=#{id}
+    </update>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/dapp/MemberCoinAddressDao.xml b/src/main/resources/mapper/dapp/MemberCoinAddressDao.xml
new file mode 100644
index 0000000..8ff7871
--- /dev/null
+++ b/src/main/resources/mapper/dapp/MemberCoinAddressDao.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!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.MemberCoinAddressDao">
+
+	<select id="selectAddressByMemberIdAndSymbol" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+        select * from member_coin_address where member_id=#{memberId} and symbol = #{symbol}
+    </select>
+    
+	<select id="selectBlockAddressWithTag" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select *
+		  from member_coin_address 
+		 <where>
+		 is_biyict = 1
+	 		<if test="memberId != null  and  memberId  != ''">
+	 			 and member_id = #{memberId}
+	 		</if>
+			 <if test="symbol != null  and  symbol  != ''">
+				 and symbol = #{symbol}
+			 </if>
+			 <if test="tag != null  and  tag  != ''">
+				 and tag = #{tag}
+			 </if>
+		 </where>
+	</select>
+	
+	<select id="selectBlockAddress" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select * 
+		  from member_coin_address 
+		 <where>
+		 is_biyict = 1
+	 		<if test="memberId != null  and  memberId  != ''">
+	 			 and member_id = #{memberId}
+	 		</if>
+			 <if test="symbol != null  and  symbol  != ''">
+				 and symbol = #{symbol}
+			 </if>
+		 </where>
+	</select>
+
+	<select id="selectCoinAddressByAddressAndSymbol" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select *
+		  from member_coin_address
+		 <where>
+		 is_biyict = 1
+			 <if test="symbol != null  and  symbol  != ''">
+				 and symbol = #{symbol}
+			 </if>
+			 <if test="address != null  and  address  != ''">
+				 and address = #{address}
+			 </if>
+		 </where>
+	</select>
+	<select id="selectCoinAddressByAddressAndSymbolTag" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select *
+		  from member_coin_address
+		 <where>
+		 is_biyict = 1
+			 <if test="symbol != null  and  symbol  != ''">
+				 and symbol = #{symbol}
+			 </if>
+			 <if test="address != null  and  address  != ''">
+				 and address = #{address}
+			 </if>
+			 <if test="tag != null  and  tag  != ''">
+				 and tag = #{tag}
+			 </if>
+		 </where>
+	</select>
+
+	<select id="selectCoinAddressListByMap" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select *  from member_coin_address 
+		 <where>
+		 is_biyict = 2
+		  and symbolscoin_id IS NOT NULL
+	 		<if test="memberId != null  and  memberId  != ''">
+	 			 and member_id = #{memberId}
+	 		</if>
+			 <if test="symbol != null  and  symbol  != ''">
+				 and symbol = #{symbol}
+			 </if>
+		 </where>
+	</select>
+
+
+	<select id="selectAllBlockAddressBySymbolAndTag" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select * from member_coin_address
+		where is_biyict = 1
+		<if test="symbol != null  and  symbol  != ''">
+			and symbol = #{symbol}
+		</if>
+		<if test="tag != null  and  tag  != ''">
+			and tag = #{tag}
+		</if>
+	</select>
+
+	<select id="selectAllBlockAddressBySymbol" resultType="cc.mrbird.febs.dapp.entity.MemberCoinAddressEntity">
+		select * from member_coin_address
+		where symbol=#{symbol}
+	</select>
+
+	<select id="selectAllSymbolAddress" resultType="string" parameterType="map">
+		select address from member_coin_address where symbol =#{symbol}
+		<if test="tag!=null and tag !=''">
+			and tag = #{tag}
+		</if>
+	</select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/dapp/MemberCoinChargeDao.xml b/src/main/resources/mapper/dapp/MemberCoinChargeDao.xml
new file mode 100644
index 0000000..db21548
--- /dev/null
+++ b/src/main/resources/mapper/dapp/MemberCoinChargeDao.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!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.MemberCoinChargeDao">
+
+	<select id="findMemberCoinChargeInPage" resultType="cc.mrbird.febs.dapp.entity.MemberCoinChargeEntity">
+		select * from member_coin_charge
+		where member_id=#{record.memberId}
+		order by create_time desc 
+	</select>
+	
+	<select id="selectNewestChargeRecord" resultType="cc.mrbird.febs.dapp.entity.MemberCoinChargeEntity">
+		select * from member_coin_charge
+		where member_id=#{memberId}
+		and symbol=#{symbol}
+		<if test="tag !=null and tag != ''">
+			and tag = #{tag}
+		</if>
+		order by create_time desc limit 1
+	</select>
+
+	<select id="selectAllBySymbolAndTag" resultType="cc.mrbird.febs.dapp.entity.MemberCoinChargeEntity">
+		select * from member_coin_charge
+		where symbol=#{symbol}
+		<if test="tag !=null and tag != ''">
+			and tag = #{tag}
+		</if>
+		<if test="status !=null and status != ''">
+			and status = #{status}
+		</if>
+	</select>
+
+</mapper>
\ No newline at end of file

--
Gitblit v1.9.1