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