From acf0e1696da79bc7fd73f6356182a172a0adaad8 Mon Sep 17 00:00:00 2001 From: zainali5120 <512061637@qq.com> Date: Mon, 11 Jan 2021 22:59:55 +0800 Subject: [PATCH] TRC20版本提交 --- src/main/java/com/xcong/excoin/modules/blackchain/service/TrxUsdtUpdateService.java | 255 +++++++++++++++++ src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java | 19 + src/main/java/com/xcong/excoin/modules/blackchain/service/Trc20Service.java | 94 +++++- src/main/java/com/xcong/excoin/rabbit/consumer/UsdtUpdateConsumer.java | 36 ++ src/main/resources/mapper/member/MemberCoinAddressDao.xml | 16 + src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java | 13 src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java | 124 +++----- lib/abi-0.4.0.jar | 0 src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java | 5 src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinAddressDao.java | 1 pom.xml | 46 ++ src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java | 28 + src/main/java/com/xcong/excoin/modules/blackchain/service/TransformUtil.java | 215 ++++++++++++++ src/main/java/com/xcong/excoin/modules/blackchain/model/EthUsdtChargeDto.java | 6 lib/tron-sdk.jar | 0 lib/client-0.4.0.jar | 0 lib/utils-0.4.0.jar | 0 src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtErc20UpdateService.java | 1 18 files changed, 747 insertions(+), 112 deletions(-) diff --git a/lib/abi-0.4.0.jar b/lib/abi-0.4.0.jar new file mode 100644 index 0000000..cf65d8d --- /dev/null +++ b/lib/abi-0.4.0.jar Binary files differ diff --git a/lib/client-0.4.0.jar b/lib/client-0.4.0.jar new file mode 100644 index 0000000..4785a17 --- /dev/null +++ b/lib/client-0.4.0.jar Binary files differ diff --git a/lib/tron-sdk.jar b/lib/tron-sdk.jar new file mode 100644 index 0000000..fc1364a --- /dev/null +++ b/lib/tron-sdk.jar Binary files differ diff --git a/lib/utils-0.4.0.jar b/lib/utils-0.4.0.jar new file mode 100644 index 0000000..a8175ab --- /dev/null +++ b/lib/utils-0.4.0.jar Binary files differ diff --git a/pom.xml b/pom.xml index c565c51..2abae36 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ </properties> <dependencies> - + <dependency> <groupId>ripple</groupId> <artifactId>ripple</artifactId> @@ -50,6 +50,38 @@ <version>1.0.0-SNAPSHOT</version> <scope>system</scope> <systemPath>${basedir}/lib/taobao-sdk-java.jar</systemPath> + </dependency> + + <dependency> + <groupId>tron-sdk</groupId> + <artifactId>tron-sdk</artifactId> + <version>0.0.1</version> + <scope>system</scope> + <systemPath>${basedir}/lib/tron-sdk.jar</systemPath> + </dependency> + + <dependency> + <groupId>com.github.ki5fpl.tronj</groupId> + <artifactId>abi</artifactId> + <version>0.4.0</version> + <scope>system</scope> + <systemPath>${basedir}/lib/abi-0.4.0.jar</systemPath> + </dependency> + + <dependency> + <groupId>com.github.ki5fpl.tronj</groupId> + <artifactId>client</artifactId> + <version>0.4.0</version> + <scope>system</scope> + <systemPath>${basedir}/lib/client-0.4.0.jar</systemPath> + </dependency> + + <dependency> + <groupId>com.github.ki5fpl.tronj</groupId> + <artifactId>utils</artifactId> + <version>0.4.0</version> + <scope>system</scope> + <systemPath>${basedir}/lib/utils-0.4.0.jar</systemPath> </dependency> <dependency> @@ -82,11 +114,11 @@ <artifactId>spring-boot-starter-websocket</artifactId> </dependency> -<!-- <dependency>--> -<!-- <groupId>org.springframework.security</groupId>--> -<!-- <artifactId>spring-security-test</artifactId>--> -<!-- <scope>test</scope>--> -<!-- </dependency>--> + <!-- <dependency>--> + <!-- <groupId>org.springframework.security</groupId>--> + <!-- <artifactId>spring-security-test</artifactId>--> + <!-- <scope>test</scope>--> + <!-- </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> @@ -139,7 +171,7 @@ <artifactId>mysql-connector-java</artifactId> <version>${mysql-driver.version}</version> </dependency> - + <dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> diff --git a/src/main/java/com/xcong/excoin/modules/blackchain/model/EthUsdtChargeDto.java b/src/main/java/com/xcong/excoin/modules/blackchain/model/EthUsdtChargeDto.java index 8d07d27..2def102 100644 --- a/src/main/java/com/xcong/excoin/modules/blackchain/model/EthUsdtChargeDto.java +++ b/src/main/java/com/xcong/excoin/modules/blackchain/model/EthUsdtChargeDto.java @@ -13,6 +13,12 @@ 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() { } diff --git a/src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java b/src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java index 73054d1..6bba54c 100644 --- a/src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java +++ b/src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java @@ -161,7 +161,7 @@ memberMapper.insert(coinAddress); } - } else { + } else if ("ERC20".equals(lable)) { MemberCoinAddressEntity ethAddress2 = memberMapper.selectBlockAddress(Long.parseLong(mId), "ETH"); if (ethAddress2 != null) { address = ethAddress2.getAddress(); @@ -182,8 +182,15 @@ coinAddress.setLabel(uuid); memberMapper.insert(coinAddress); } - // 发送新增的地址到监听集合 - usdtUpdateProducer.sendAddressMsg(address); + // 发送新增的地址到监听集合 + usdtUpdateProducer.sendAddressMsg(address+","+"ERC20"); + } else if ("TRC20".equals(lable)) { + Map<String, String> usdtMap = Trc20Service.createAddress(); + address = usdtMap.get("address"); + key = usdtMap.get("privateKey"); + map.put("address", address); + // 发送新增的地址到监听集合 + usdtUpdateProducer.sendAddressMsg(address+","+"TRC20"); } break; case "ROC": diff --git a/src/main/java/com/xcong/excoin/modules/blackchain/service/TransformUtil.java b/src/main/java/com/xcong/excoin/modules/blackchain/service/TransformUtil.java new file mode 100644 index 0000000..3b3d2be --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/blackchain/service/TransformUtil.java @@ -0,0 +1,215 @@ +package com.xcong.excoin.modules.blackchain.service; + +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/com/xcong/excoin/modules/blackchain/service/Trc20Service.java b/src/main/java/com/xcong/excoin/modules/blackchain/service/Trc20Service.java index 21d2215..06c0811 100644 --- a/src/main/java/com/xcong/excoin/modules/blackchain/service/Trc20Service.java +++ b/src/main/java/com/xcong/excoin/modules/blackchain/service/Trc20Service.java @@ -2,9 +2,19 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.sunlight.tronsdk.TrxService; +import com.sunlight.tronsdk.transaction.TransactionResult; import com.xcong.excoin.modules.blackchain.model.Trc20TransactionsData; import com.xcong.excoin.modules.blackchain.model.Trc20TransactionsResult; +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.List; import java.util.Map; @@ -16,31 +26,81 @@ private final static String FULL_NODE_URL = "https://api.trongrid.io"; - public static Map<String,String> createAddress(){ - String url ="https://api.trongrid.io/wallet/generateaddress"; - // {privateKey=ed0bae6e49fa4dd8a622fe77baa0d6e4077155b28ed6637870745c6da3cf372e, address=THeRNk25ps69fzqhN6tZ4Ecxur3RvDNDtY, hexAddress=4154336ea2a3a26be8a722053ee26c61e3f7f3e0ec} - String s = HttpUtil.get(url); - return JSONObject.parseObject(s,Map.class); + public final static String TRX_PRIVATE_KEY = "ea176fff7ba171154aed643321d1f9ba239e128124d8ffa5d075575ef3b58f81"; + public final static String TRX_ADDRESS = "TPSPfAZ8UG9WiXDNX6SbYHNpX46oLV6xAs"; + public final static String POOL_ADDRESS = "TPSPfAZ8UG9WiXDNX6SbYHNpX46oLV6xAs"; + + + /** + * 创建用户钱包地址 + **/ + 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; } /** - * - * @param address - * @param time 2020-09-07T00:00 - * @return + * 转TRX + * @param sendPrivateKey + * @param receiveAddress + * @param amount */ - public static List<Trc20TransactionsData> getAddressTransactions(String address,String time) { - String url = "https://api.trongrid.io/v1/accounts/"+address+"/transactions/trc20?only_confirmed=true&only_to=true&min_timestamp="+time+"&contract_address=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"; - //String url = "https://api.trongrid.io/v1/accounts/"+address+"/transactions/trc20?limit=100&contract_address=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t&only_confirmed=true"; - String s = HttpUtil.get(url); - Trc20TransactionsResult trc20TransactionsResult = JSONObject.parseObject(s, Trc20TransactionsResult.class); - if (trc20TransactionsResult.isSuccess()) { - return trc20TransactionsResult.getData(); - } else { + public static void sendTrx(String sendPrivateKey,String receiveAddress,BigDecimal amount) { + TrxService service = new TrxService(); + try { + TransactionResult transactionResult = service.testSendTrxTransaction(sendPrivateKey, receiveAddress, amount); + } 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); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static BigDecimal getTrxBalance(String address){ + TrxService service = new TrxService(); + try { + BigDecimal trxBalanceTest = service.getTrxBalanceTest(address); + 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); + 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/com/xcong/excoin/modules/blackchain/service/TrxUsdtUpdateService.java b/src/main/java/com/xcong/excoin/modules/blackchain/service/TrxUsdtUpdateService.java new file mode 100644 index 0000000..ae26ea8 --- /dev/null +++ b/src/main/java/com/xcong/excoin/modules/blackchain/service/TrxUsdtUpdateService.java @@ -0,0 +1,255 @@ +package com.xcong.excoin.modules.blackchain.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.xcong.excoin.common.enumerates.CoinTypeEnum; +import com.xcong.excoin.modules.blackchain.model.EthUsdtChargeDto; +import com.xcong.excoin.modules.member.dao.MemberCoinAddressDao; +import com.xcong.excoin.modules.member.entity.MemberCoinAddressEntity; +import com.xcong.excoin.rabbit.producer.UsdtUpdateProducer; +import com.xcong.excoin.utils.RedisUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@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"; + + @Resource + private UsdtUpdateProducer usdtUpdateProducer; + + @Resource + private MemberCoinAddressDao memberCoinAddressDao; + + @Resource + RedisUtils redisUtils; + + public void monitorCoinListener() { + 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; + } + Object trc20BlockNum = redisUtils.get("USDT_TRC20_BLOCK_NUM"); + Long blockNum = (Long) trc20BlockNum; + // http 请求 + // httpTransactionInfo(addressList, 26599313L); + //httpTransactionInfo(addressList, 26603621L); + httpTransactionInfo(addressList, blockNum); + redisUtils.set("USDT_TRC20_BLOCK_NUM", (blockNum + 1L)); + } + + private void httpTransactionInfo(List<String> addressList, Long num) { + String transactionInfoByBlockNum = getTransactionInfoByBlockNum(BigInteger.valueOf(num)); + if (StringUtils.isBlank(transactionInfoByBlockNum)) { + return; + } + JSONArray parseArray = JSON.parseArray(transactionInfoByBlockNum); + if (parseArray.size() > 0) { + for (Object e : parseArray) { + try { + String txId = JSON.parseObject(e.toString()).getString("id"); + //判断 数据库 txId 有 就不用往下继续了 + JSONObject parseObject = JSON.parseObject(getTransactionById(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(); + } + } + } + } + + + 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(); + } + + + /** + * 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) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity<String> request = new HttpEntity<>(param); + ResponseEntity<String> result = restTemplate.postForEntity(url, request, String.class); +// System.out.println("url:" + url + ",param:" + param + ",result:" + result.getBody()); + return result; + } + + 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)) { + System.out.println("存在本地的地址:" + address); + // 金额 + // 发送消息队列 + EthUsdtChargeDto dto = new EthUsdtChargeDto(address, txId, amount); + dto.setSymbol(EthUsdtChargeDto.Symbol.USDT_TRC20); + usdtUpdateProducer.sendMsg(JSONObject.toJSONString(dto)); + System.out.println("===to_address:" + to_address + "===amount:" + amount); + } + } + + } + + public boolean poolByAddress(String address) { + // 首先查询trx余额 + BigDecimal trxBalance = Trc20Service.getTrxBalance(address); + if (trxBalance == null) { + return false; + } + if (trxBalance.compareTo(new BigDecimal(1)) < 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); + return true; + } else { + Trc20Service.sendTrx(Trc20Service.TRX_PRIVATE_KEY, address, new BigDecimal(1)); + // 将这个地址记录,后续同步 TODO + 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 false; + } +} diff --git a/src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtErc20UpdateService.java b/src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtErc20UpdateService.java index f7665f8..4373dc0 100644 --- a/src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtErc20UpdateService.java +++ b/src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtErc20UpdateService.java @@ -105,6 +105,7 @@ 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){ diff --git a/src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java b/src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java index 5113425..8c3ba52 100644 --- a/src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java +++ b/src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java @@ -17,7 +17,10 @@ public void updateXrp(); - public void updateTrc20(); + /** + * 更新 + */ + public void updateTrc20(EthUsdtChargeDto dto); public void updateRoc(RocTransferDetail transferDetail); diff --git a/src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java b/src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java index 27f1f82..cd147d8 100644 --- a/src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java +++ b/src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java @@ -411,78 +411,46 @@ } @Override - public void updateTrc20() { - // 首先去查redis上的上次同步时间 - Object lastUpdateTime = redisUtils.get(trc20_update_key); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm"); - String start = null; - if (lastUpdateTime == null) { - // 没有 说明是第一次同步 此时从第一天开始同步2020 0905开始 - start = "2020-09-05'T'00:00"; - } else { - // 有上次时间 - start = lastUpdateTime.toString(); - } - - // 去查询上次同步时间后的所有记录 - //Trc20Service.getAddressTransactions() - // 写入本次更新时间 - String updateTime = format.format(new Date()); - redisUtils.set(trc20_update_key, updateTime); + 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"); - if (CollectionUtils.isNotEmpty(addressList)) { - Map<String, Object> hashParam = new HashMap<>(); - for (MemberCoinAddressEntity coinAddressEntity : addressList) { - String address = coinAddressEntity.getAddress(); - List<Trc20TransactionsData> addressTransactions = Trc20Service.getAddressTransactions(address, start); - if (CollectionUtils.isNotEmpty(addressTransactions)) { - for (Trc20TransactionsData trc20TransactionsData : addressTransactions) { - String transactionId = trc20TransactionsData.getTransaction_id(); - String value = trc20TransactionsData.getValue(); - // 本次转账金额 - BigDecimal amount = new BigDecimal(value).divide(new BigDecimal("1000000")); - // 校验token是否为trc20USD - if (trc20TransactionsData.getToken_info() != null && trc20TransactionsData.getToken_info().containsKey("address")) { - String tokenTrc = trc20TransactionsData.getToken_info().get("address").toString(); - if (!"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t".equals(tokenTrc)) { - continue; - } - } else { - continue; - } - // 校验hash是否已同步过 - hashParam.put("hash", transactionId); - List<MemberCoinChargeEntity> memberCoinChargeEntities = memberCoinChargeDao.selectByMap(hashParam); - if (CollectionUtils.isNotEmpty(memberCoinChargeEntities)) { - // 若已同步过 - continue; - } - // 添加钱包余额 - // 用户ID - Long memberId = coinAddressEntity.getMemberId(); - MemberWalletCoinEntity 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, transactionId); - LogRecordUtils.insertMemberAccountMoneyChange(memberId, "转入", amount, CoinTypeEnum.USDT.name(), 1, 1); - - ThreadPoolUtils.sendDingTalk(5); - MemberEntity member = memberDao.selectById(memberId); - if (StrUtil.isNotBlank(member.getPhone())) { - //String amountEos = amount + "XRP"; - Sms106Send.sendRechargeMsg(member.getPhone(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo); - } else { - SubMailSend.sendRechargeMail(member.getEmail(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo); - } - - } - } - } + //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(); + // 查询钱包 并更新 + MemberWalletCoinEntity 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); + MemberEntity member = memberDao.selectById(memberId); + if (StrUtil.isNotBlank(member.getPhone())) { + //String amountEos = amount + "XRP"; + Sms106Send.sendRechargeMsg(member.getPhone(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo); + } else { + SubMailSend.sendRechargeMail(member.getEmail(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo); + } + } + @Override public void updateRoc(RocTransferDetail transferDetail) { @@ -546,17 +514,17 @@ String address = ethUsdtChargeDto.getAddress(); String hash = ethUsdtChargeDto.getHash(); // hash没有用过 - Map<String,Object> param = new HashMap<>(); - param.put("hash",hash); - param.put("address",address); + Map<String, Object> param = new HashMap<>(); + param.put("hash", hash); + param.put("address", address); List<MemberCoinChargeEntity> memberCoinChargeEntities = memberCoinChargeDao.selectByMap(param); - if(CollectionUtils.isNotEmpty(memberCoinChargeEntities)){ + if (CollectionUtils.isNotEmpty(memberCoinChargeEntities)) { return; } // 校验这个交易是否成功 - EthService ethService = new EthService(); + EthService ethService = new EthService(); boolean b = ethService.checkTransferResult(hash); - if(!b){ + if (!b) { log.info("#USDT假充值:{}#", hash); return; } @@ -587,10 +555,10 @@ } else { SubMailSend.sendRechargeMail(member.getEmail(), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN), orderNo); } - // 同步 - try{ - usdtEthService.pollByAddress(address,balance); - }catch (Exception e){ + // 同步 + try { + usdtEthService.pollByAddress(address, balance); + } catch (Exception e) { } diff --git a/src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinAddressDao.java b/src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinAddressDao.java index baf9016..edc6552 100644 --- a/src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinAddressDao.java +++ b/src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinAddressDao.java @@ -16,6 +16,7 @@ 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); diff --git a/src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java b/src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java index f91418b..2f78ecc 100644 --- a/src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java +++ b/src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java @@ -1,11 +1,18 @@ package com.xcong.excoin.quartz.job; +import com.xcong.excoin.common.enumerates.CoinTypeEnum; +import com.xcong.excoin.modules.blackchain.service.TrxUsdtUpdateService; import com.xcong.excoin.modules.coin.service.BlockCoinService; +import com.xcong.excoin.modules.member.dao.MemberCoinAddressDao; +import com.xcong.excoin.modules.member.entity.MemberCoinAddressEntity; +import com.xcong.excoin.utils.RedisUtils; +import org.apache.commons.collections.CollectionUtils; 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.List; /** * 链上币种同步任务 @@ -20,14 +27,18 @@ @Resource private BlockCoinService blockCoinService; + @Resource + private TrxUsdtUpdateService trxUsdtUpdateService; + + /** * ETH_USDT 同步 */ - //@Scheduled(cron = "0 0/10 * * * ? ") -// public void ethUsdtUpdate() { -// blockCoinService.updateEthUsdt(); -// } + @Scheduled(cron = "0/3 * * * * ? ") + public void usdtTc20Update() { + trxUsdtUpdateService.monitorCoinListener(); + } /** * eth 同步 diff --git a/src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java b/src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java index f0d22e5..16711d9 100644 --- a/src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java +++ b/src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java @@ -1,12 +1,17 @@ package com.xcong.excoin.quartz.job; +import com.xcong.excoin.modules.blackchain.service.TrxUsdtUpdateService; import com.xcong.excoin.modules.blackchain.service.UsdtEthService; +import com.xcong.excoin.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; 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.ArrayList; +import java.util.List; import java.util.concurrent.ExecutionException; /** @@ -23,6 +28,12 @@ @Resource private UsdtEthService usdtEthService; + + @Resource + private RedisUtils redisUtils; + + @Resource + private TrxUsdtUpdateService trxUsdtUpdateService; /** * usdt 归集 @@ -52,4 +63,21 @@ log.info("#ETH归集错误#", e); } } + + @Scheduled(cron = "0 1/5 * * * ? ") + public void poolUsdtTrc20() { + Object trc20_pool = redisUtils.get("TRC20_POOL"); + if(trc20_pool==null){ + return; + } + List<String> list = (List)trc20_pool; + List<String> needPoll = new ArrayList<>(); + for(String address: list){ + boolean b = trxUsdtUpdateService.poolByAddress(address); + if(!b){ + needPoll.add(address); + } + } + redisUtils.set("TRC20_POOL",needPoll); + } } diff --git a/src/main/java/com/xcong/excoin/rabbit/consumer/UsdtUpdateConsumer.java b/src/main/java/com/xcong/excoin/rabbit/consumer/UsdtUpdateConsumer.java index 62c25c7..7c762db 100644 --- a/src/main/java/com/xcong/excoin/rabbit/consumer/UsdtUpdateConsumer.java +++ b/src/main/java/com/xcong/excoin/rabbit/consumer/UsdtUpdateConsumer.java @@ -3,14 +3,18 @@ import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.configurations.RabbitMqConfig; import com.xcong.excoin.modules.blackchain.model.EthUsdtChargeDto; +import com.xcong.excoin.modules.blackchain.service.Trc20Service; +import com.xcong.excoin.modules.blackchain.service.TrxUsdtUpdateService; import com.xcong.excoin.modules.blackchain.service.UsdtErc20UpdateService; import com.xcong.excoin.modules.coin.service.BlockCoinService; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.math.BigDecimal; /** * @author wzy @@ -25,20 +29,48 @@ @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); // 更新这个用户的余额 - blockCoinService.updateEthUsdtNew(ethUsdtChargeDto); + if(EthUsdtChargeDto.Symbol.USDT_ERC20.equals(ethUsdtChargeDto.getSymbol())){ + blockCoinService.updateEthUsdtNew(ethUsdtChargeDto); + } + 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) { if(!UsdtErc20UpdateService.ALL_ADDRESS_LIST.contains(content)){ log.debug("#添加新地址---->{}#", content); - UsdtErc20UpdateService.ALL_ADDRESS_LIST.add(content); + if(StringUtils.isBlank(content)){ + return; + } + String[] split = content.split(","); + if(split.length<2){ + return; + } + String address = split[0]; + String tag = split[1]; + if("ERC20".equals(tag)){ + UsdtErc20UpdateService.ALL_ADDRESS_LIST.add(address); + } + if("TRC20".equals(tag)){ + TrxUsdtUpdateService.addressList.add(address); + // 此时还需要给这个地址转账用于激活及后续手续费 + Trc20Service.sendTrx(Trc20Service.TRX_PRIVATE_KEY,address,new BigDecimal(1)); + } + } } } diff --git a/src/main/resources/mapper/member/MemberCoinAddressDao.xml b/src/main/resources/mapper/member/MemberCoinAddressDao.xml index 0dc07a9..6132e7c 100644 --- a/src/main/resources/mapper/member/MemberCoinAddressDao.xml +++ b/src/main/resources/mapper/member/MemberCoinAddressDao.xml @@ -50,6 +50,22 @@ </if> </where> </select> + <select id="selectCoinAddressByAddressAndSymbolTag" resultType="com.xcong.excoin.modules.member.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="com.xcong.excoin.modules.member.entity.MemberCoinAddressEntity"> select * from member_coin_address -- Gitblit v1.9.1