From 218df35e1e8b89447fe7d3c1ca6f3a29f8f89755 Mon Sep 17 00:00:00 2001
From: xiaoyong931011 <15274802129@163.com>
Date: Sat, 31 Dec 2022 02:02:58 +0800
Subject: [PATCH] 20221227 充值归集
---
src/main/java/cc/mrbird/febs/mall/chain/job/ChainListenerJob.java | 88 ++++
src/main/java/cc/mrbird/febs/mall/chain/service/ChainService.java | 185 +++++++++
src/test/java/cc/mrbird/febs/ProfitTest.java | 25 +
src/main/java/cc/mrbird/febs/mall/service/impl/BlockSeriveImpl.java | 1
src/main/java/cc/mrbird/febs/mall/chain/service/UsdtErc20UpdateService.java | 2
src/main/java/cc/mrbird/febs/mall/chain/service/ContractEventService.java | 6
pom.xml | 5
src/main/java/cc/mrbird/febs/mall/chain/service/BscUsdtContractEvent.java | 138 +++++++
src/main/java/cc/mrbird/febs/mall/chain/service/BlockCoinServiceImpl.java | 12
src/main/java/cc/mrbird/febs/mall/chain/service/ContractChainService.java | 31 +
src/main/java/cc/mrbird/febs/mall/chain/enums/ChainEnum.java | 54 ++
src/main/java/cc/mrbird/febs/mall/chain/service/BaseCoinService.java | 135 +++++++
src/main/java/cc/mrbird/febs/common/utils/AppContants.java | 3
src/main/java/cc/mrbird/febs/mall/chain/enums/EthService.java | 433 ++++++++++++++++++++++
src/main/java/cc/mrbird/febs/mall/chain/service/EthService.java | 10
15 files changed, 1,114 insertions(+), 14 deletions(-)
diff --git a/pom.xml b/pom.xml
index dd93c07..ebdbe02 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,11 @@
</properties>
<dependencies>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-websocket</artifactId>
+ </dependency>
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
diff --git a/src/main/java/cc/mrbird/febs/common/utils/AppContants.java b/src/main/java/cc/mrbird/febs/common/utils/AppContants.java
index 79d69c3..0374bd5 100644
--- a/src/main/java/cc/mrbird/febs/common/utils/AppContants.java
+++ b/src/main/java/cc/mrbird/febs/common/utils/AppContants.java
@@ -67,5 +67,8 @@
public static final String AGENT_LEVEL = "AGENT_LEVEL";
public static final String AGENT_LEVEL_REQUIRE = "AGENT_LEVEL_REQUIRE";
+ public static final String REDIS_KEY_BLOCK_USDT_NUM = "BLOCK_USDT_NUM";
+ public static final String REDIS_KEY_BLOCK_ETH_INCREMENT_NUM = "BLOCK_ETH_INCREMENT_NUM";
+ public static final String REDIS_KEY_BLOCK_ETH_NEWEST_NUM = "BLOCK_ETH_NEWEST_NUM";
}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/enums/ChainEnum.java b/src/main/java/cc/mrbird/febs/mall/chain/enums/ChainEnum.java
new file mode 100644
index 0000000..c1353cb
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/enums/ChainEnum.java
@@ -0,0 +1,54 @@
+package cc.mrbird.febs.mall.chain.enums;
+
+import lombok.Getter;
+
+/**
+ * 链类型
+ */
+@Getter
+public enum ChainEnum {
+
+ /**
+ * 币安 usdt合约
+ * 0x55d398326f99059fF775485246999027B3197955
+ * 测试链 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd
+ */
+ BSC_USDT("BSC", "0x7FC948E091C4b71fC063cE59B8Dad1062B1c5065",
+ "0xbf6f11f5689961d5351375bebbae751de0d0d5c2e2095c1017368485dc909ff8",
+ "https://bsc-dataseed1.ninicoin.io",
+ "0x55d398326f99059fF775485246999027B3197955",
+ "");
+
+
+ private String chain;
+
+ private String address;
+
+ private String privateKey;
+
+ private String url;
+
+ private String contractAddress;
+
+ private String apiKey;
+
+ ChainEnum(String chain, String address, String privateKey, String url, String contractAddress, String apiKey) {
+ this.chain = chain;
+ this.address = address;
+ this.privateKey = privateKey;
+ this.url = url;
+ this.contractAddress = contractAddress;
+ this.apiKey = apiKey;
+ }
+
+ public static ChainEnum getValueByName(String name) {
+ ChainEnum[] values = values();
+ for (ChainEnum value : values) {
+ if (value.name().equals(name)) {
+ return value;
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/enums/EthService.java b/src/main/java/cc/mrbird/febs/mall/chain/enums/EthService.java
new file mode 100644
index 0000000..4cbecc8
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/enums/EthService.java
@@ -0,0 +1,433 @@
+package cc.mrbird.febs.mall.chain.enums;
+
+import cc.mrbird.febs.mall.chain.service.ContractChainService;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONObject;
+import org.web3j.abi.FunctionEncoder;
+import org.web3j.abi.FunctionReturnDecoder;
+import org.web3j.abi.TypeReference;
+import org.web3j.abi.datatypes.Address;
+import org.web3j.abi.datatypes.Function;
+import org.web3j.abi.datatypes.Type;
+import org.web3j.abi.datatypes.generated.Uint256;
+import org.web3j.crypto.Credentials;
+import org.web3j.crypto.RawTransaction;
+import org.web3j.crypto.TransactionEncoder;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.DefaultBlockParameterName;
+import org.web3j.protocol.core.Request;
+import org.web3j.protocol.core.methods.request.Transaction;
+import org.web3j.protocol.core.methods.response.EthBlockNumber;
+import org.web3j.protocol.core.methods.response.EthCall;
+import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
+import org.web3j.protocol.core.methods.response.EthSendTransaction;
+import org.web3j.protocol.http.HttpService;
+import org.web3j.utils.Convert;
+import org.web3j.utils.Numeric;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * @author wzy
+ * @date 2022-04-15
+ **/
+public class EthService implements ContractChainService {
+
+ private Web3j web3j;
+ private String url;
+ private String ownerAddress;
+ private String privateKey;
+ private String contractAddress;
+
+ public EthService(String url, String address, String privateKey, String contractAddress) {
+ this.url = url;
+ this.ownerAddress = address;
+ this.privateKey = privateKey;
+ this.contractAddress = contractAddress;
+
+ HttpService service = new HttpService(url);
+ web3j = Web3j.build(service);
+ }
+
+ public static void main(String[] args) throws IOException {
+ HttpService service = new HttpService("https://bsc-dataseed1.ninicoin.io");
+ Web3j web3j = Web3j.build(service);
+ long start = System.currentTimeMillis();
+ Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
+ EthBlockNumber send = request.send();
+ BigInteger bigInteger = Numeric.decodeQuantity(send.getResult());
+ long end = System.currentTimeMillis();
+ System.out.println(end - start);
+
+// String address = "0x971c09aa9735eb98459b17ec8b48932d24cbb931";
+// String nonce = "0x1d5f7444107bc02e980deda39d0fce21b06c9da4233a19cb11124cb5bfefc9ec";
+// String sign = "0x8f92cee24906122e26c3cc6cbd72f851cfe2c9574aa03bf3371e5d506fbec68b2ad22bbbc19b00ed21d26ab5a6871507831e2c902d8ed8c33301addc2b57a7731b";
+//
+// String result = address + ":" + nonce + ":" + sign;
+// System.out.println(Hash.sha3(result));
+
+
+// Web3Sha3 send = web3j.web3Sha3(result).send();
+// System.out.println(1);
+ }
+
+ @Override
+ public BigInteger balanceOfUnDecimal(String fromAddress) {
+ try {
+ String methodName = "balanceOf";
+ List<Type> inputParameters = new ArrayList<>();
+ List<TypeReference<?>> outputParameters = new ArrayList<>();
+ Address address = new Address(fromAddress);
+ inputParameters.add(address);
+ TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
+ };
+ outputParameters.add(typeReference);
+ Function function = new Function(methodName, inputParameters, outputParameters);
+ String data = FunctionEncoder.encode(function);
+ Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
+
+ EthCall ethCall;
+ BigInteger balanceValue = BigInteger.ZERO;
+ try {
+ ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
+ List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
+ balanceValue = (BigInteger) results.get(0).getValue();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return balanceValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return BigInteger.ZERO;
+ }
+
+ @Override
+ public int decimals() {
+ try {
+ String methodName = "decimals";
+ List<Type> inputParameters = new ArrayList<>();
+ List<TypeReference<?>> outputParameters = new ArrayList<>();
+ TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
+ };
+ outputParameters.add(typeReference);
+ Function function = new Function(methodName, inputParameters, outputParameters);
+ String data = FunctionEncoder.encode(function);
+ Transaction transaction = Transaction.createEthCallTransaction(null, contractAddress, data);
+
+ EthCall ethCall;
+ BigInteger decimals = BigInteger.ZERO;
+ try {
+ ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
+ List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
+ decimals = (BigInteger) results.get(0).getValue();
+ return decimals.intValue();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ @Override
+ public BigDecimal balanceOf(String fromAddress) {
+ int decimal = decimals();
+ BigInteger balanceValue = balanceOfUnDecimal(fromAddress);
+
+ double res = new BigDecimal(balanceValue).divide(BigDecimal.valueOf(Math.pow(10, decimal)), 8, RoundingMode.HALF_DOWN).doubleValue();
+ if (res > 0) {
+ return new BigDecimal(res);
+ }
+
+ return BigDecimal.ZERO;
+ }
+
+ @Override
+ public BigInteger allowance(String address) {
+ String methodName = "allowance";
+ List<TypeReference<?>> outputParameters = new ArrayList<>();
+ TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
+ };
+ outputParameters.add(typeReference);
+
+ Function function = new Function(methodName,
+ Arrays.asList(new Address(address), new Address(ownerAddress))
+ , outputParameters);
+ String data = FunctionEncoder.encode(function);
+ Transaction transaction = Transaction.createEthCallTransaction(ownerAddress, contractAddress, data);
+
+ EthCall ethCall = null;
+ try {
+ ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
+ List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
+ return (BigInteger) results.get(0).getValue();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return BigInteger.ZERO;
+ }
+
+ @Override
+ public boolean isAllowance(String address) {
+ return allowance(address).intValue() != 0;
+ }
+
+ public String getGas() {
+ String gas;
+ if (url.contains("infura.io")) {
+ String resp = HttpUtil.get("https://etherscan.io/autoUpdateGasTracker.ashx?sid=75f30b765180f29e2b7584b8501c9124");
+ JSONObject data = JSONObject.parseObject(resp);
+ gas = data.getString("avgPrice");
+ } else {
+ String resp = HttpUtil.get("https://gbsc.blockscan.com/gasapi.ashx?apikey=key&method=gasoracle");
+ JSONObject data = JSONObject.parseObject(resp);
+ gas = data.getString("FastGasPrice");
+ }
+ return StrUtil.isBlank(gas) ? "35" : gas;
+ }
+
+ @Override
+ public String transfer(String address) {
+ BigDecimal balance = balanceOf(address);
+
+ return transfer(address, balance);
+ }
+
+ @Override
+ public String transfer(String address, BigDecimal amount) {
+ try {
+ return tokenTransfer(privateKey, ownerAddress, address, amount.toPlainString());
+ } catch (ExecutionException | InterruptedException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ public String tokenTransferFrom(String privateKey, String fromAddress, String toAddress, String amount) throws ExecutionException, InterruptedException {
+ String gas = getGas();
+
+ BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
+ amount = amountPow.toPlainString();
+ if (amount.contains(".")) {
+ amount = amount.substring(0, amount.lastIndexOf("."));
+ }
+
+ Credentials credentials = Credentials.create(privateKey);
+
+ EthGetTransactionCount ethGetTransactionCount = web3j
+ .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
+
+ BigInteger nonce = ethGetTransactionCount.getTransactionCount();
+
+ Function function = new Function("transferFrom",
+ Arrays.asList(new Address(fromAddress), new Address(toAddress), new Uint256(new BigInteger(amount))),
+ Arrays.asList(new TypeReference<Type>() {
+ }));
+
+ String encodedFunction = FunctionEncoder.encode(function);
+
+ RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
+ Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
+ Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
+
+ byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
+ String hexValue = Numeric.toHexString(signedMessage);
+
+ CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
+ EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
+
+
+ if (ethSendTransaction.hasError()) {
+ return "";
+ } else {
+ return ethSendTransaction.getTransactionHash();
+ }
+ }
+
+ public String tokenTransfer(String privateKey, String fromAddress, String toAddress, String amount) throws ExecutionException, InterruptedException {
+ String gas = getGas();
+
+ BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
+ amount = amountPow.toPlainString();
+ if (amount.contains(".")) {
+ amount = amount.substring(0, amount.lastIndexOf("."));
+ }
+
+ Credentials credentials = Credentials.create(privateKey);
+
+ EthGetTransactionCount ethGetTransactionCount = web3j
+ .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
+
+ BigInteger nonce = ethGetTransactionCount.getTransactionCount();
+
+ Function function = new Function("transfer",
+ Arrays.asList(new Address(toAddress), new Uint256(new BigInteger(amount))),
+ Arrays.asList(new TypeReference<Type>() {
+ }));
+
+ String encodedFunction = FunctionEncoder.encode(function);
+
+ RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
+ Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
+ Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
+
+ byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
+ String hexValue = Numeric.toHexString(signedMessage);
+
+ CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
+ EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
+
+
+ if (ethSendTransaction.hasError()) {
+ return "";
+ } else {
+ return ethSendTransaction.getTransactionHash();
+ }
+ }
+
+ @Override
+ public int allowanceCnt(String address) {
+ String allowanceUrl;
+ if (url.contains("infura.io")) {
+ allowanceUrl = "https://etherscan.io/tokenapprovalchecker.aspx/GetApprovedContract";
+ } else {
+ allowanceUrl = "https://bscscan.com/tokenapprovalchecker.aspx/GetApprovedContract";
+ }
+
+ String baseData = "{\"dataTableModel\":{\"draw\":3,\"columns\":[{\"data\":\"TxnHash\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"Block\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"Token\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"ApprovedSpender\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"ApprovedAmount\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"LastUpdated\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}},{\"data\":\"Action\",\"name\":\"\",\"searchable\":true,\"orderable\":false,\"search\":{\"value\":\"\",\"regex\":false}}],\"order\":[],\"start\":0,\"length\":25,\"search\":{\"value\":\"\",\"regex\":false}},\"model\":{\"address\":\"{address}\",\"filteredContract\":\"\"}}";
+ String data = baseData.replace("{address}", address);
+
+ String resp = HttpUtil.post(allowanceUrl, data);
+
+ JSONObject jsonObject = JSONObject.parseObject(resp);
+ JSONObject result = JSONObject.parseObject(jsonObject.getString("d"));
+ return result.getIntValue("recordsTotal");
+ }
+
+ @Override
+ public BigInteger blockNumber() {
+ Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
+ EthBlockNumber send = null;
+ try {
+ send = request.send();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ if (send != null) {
+ return Numeric.decodeQuantity(send.getResult());
+ } else {
+ throw new NullPointerException();
+ }
+ }
+
+ @Override
+ public BigInteger totalSupply() {
+ try {
+ String methodName = "totalSupply";
+ List<Type> inputParameters = new ArrayList<>();
+ List<TypeReference<?>> outputParameters = new ArrayList<>();
+ TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
+ };
+ outputParameters.add(typeReference);
+ Function function = new Function(methodName, inputParameters, outputParameters);
+ String data = FunctionEncoder.encode(function);
+ Transaction transaction = Transaction.createEthCallTransaction(null, contractAddress, data);
+
+ EthCall ethCall;
+ BigInteger totalSupply = BigInteger.ZERO;
+ try {
+ ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
+ List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
+ totalSupply = (BigInteger) results.get(0).getValue();
+ return totalSupply.divide(BigInteger.TEN.pow(decimals()));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return BigInteger.ZERO;
+ }
+
+ @Override
+ public BigInteger totalSupplyNFT() {
+ try {
+ String methodName = "totalSupply";
+ List<Type> inputParameters = new ArrayList<>();
+ List<TypeReference<?>> outputParameters = new ArrayList<>();
+ TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
+ };
+ outputParameters.add(typeReference);
+ Function function = new Function(methodName, inputParameters, outputParameters);
+ String data = FunctionEncoder.encode(function);
+ Transaction transaction = Transaction.createEthCallTransaction(null, contractAddress, data);
+
+ EthCall ethCall;
+ BigInteger totalSupply = BigInteger.ZERO;
+ try {
+ ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
+ List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
+ totalSupply = (BigInteger) results.get(0).getValue();
+ return totalSupply;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return BigInteger.ZERO;
+ }
+
+ @Override
+ public String safeMintNFT(String toAddress) {
+ String gas = getGas();
+
+ try {
+ Credentials credentials = Credentials.create(privateKey);
+ EthGetTransactionCount ethGetTransactionCount = web3j
+ .ethGetTransactionCount(ownerAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
+ BigInteger nonce = ethGetTransactionCount.getTransactionCount();
+ Function function = new Function("safeMint",
+ Arrays.asList(new Address(toAddress)),
+ Arrays.asList(new TypeReference<Type>() {
+ }));
+
+ String encodedFunction = FunctionEncoder.encode(function);
+ RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
+ Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),
+ Convert.toWei("1000000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);
+
+ byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
+ String hexValue = Numeric.toHexString(signedMessage);
+
+ CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
+ EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
+
+ if (ethSendTransaction.hasError()) {
+ return "";
+ } else {
+ return ethSendTransaction.getTransactionHash();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/job/ChainListenerJob.java b/src/main/java/cc/mrbird/febs/mall/chain/job/ChainListenerJob.java
new file mode 100644
index 0000000..b6ad5c3
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/job/ChainListenerJob.java
@@ -0,0 +1,88 @@
+package cc.mrbird.febs.mall.chain.job;
+
+import cc.mrbird.febs.common.utils.AppContants;
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.mall.chain.enums.ChainEnum;
+import cc.mrbird.febs.mall.chain.service.BaseCoinService;
+import cc.mrbird.febs.mall.chain.service.BscUsdtContractEvent;
+import cc.mrbird.febs.mall.chain.service.ChainService;
+import cc.mrbird.febs.mall.chain.service.ContractEventService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.math.BigInteger;
+
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true")
+public class ChainListenerJob implements ApplicationRunner {
+
+ @Autowired
+ private ContractEventService bscUsdtContractEvent;
+
+ @Autowired
+ private RedisUtils redisUtils;
+
+ @Autowired
+ private BaseCoinService baseCoinService;
+
+ @Scheduled(cron = "0 0/5 * * * ? ")
+ public void chainBlockUpdate() {
+ BigInteger blockNumber = ChainService.getInstance(ChainEnum.BSC_USDT.name()).blockNumber();
+
+ redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM, blockNumber);
+ }
+
+ @Scheduled(cron = "0/2 * * * * ? ")
+ public void chainIncrementBlock() {
+ Object newestBlockObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_NEWEST_NUM);
+ BigInteger newestBlock;
+ if (newestBlockObj == null) {
+ newestBlock = ChainService.getInstance(ChainEnum.BSC_USDT.name()).blockNumber();
+ } else {
+ newestBlock = (BigInteger) newestBlockObj;
+ }
+
+ Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
+ BigInteger toIncrement;
+ if (incrementObj == null) {
+ toIncrement = newestBlock;
+ } else {
+ BigInteger incrementBlock = (BigInteger) incrementObj;
+
+ // 最新区块小于增加区块
+ if (newestBlock.compareTo(incrementBlock) <= 0) {
+ return;
+ }
+ toIncrement = incrementBlock.add(BigInteger.ONE);
+ }
+
+ redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, toIncrement);
+ }
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ long start = System.currentTimeMillis();
+ log.info("区块链监听开始启动");
+ Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
+ BigInteger newest = ChainService.getInstance(ChainEnum.BSC_USDT.name()).blockNumber();
+ BigInteger block;
+ if (incrementObj == null) {
+ block = newest;
+ } else {
+ block = (BigInteger) incrementObj;
+ }
+
+
+// ChainService.wssBaseCoinEventListener(block, baseCoinService);
+// ChainService.wssBaseCoinEventListener(block, bscUsdtContractEvent);
+ ChainService.wssContractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
+ long end = System.currentTimeMillis();
+ log.info("区块链监听启动完成, 消耗时间{}", end - start);
+ }
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/BaseCoinService.java b/src/main/java/cc/mrbird/febs/mall/chain/service/BaseCoinService.java
new file mode 100644
index 0000000..0f7332c
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/BaseCoinService.java
@@ -0,0 +1,135 @@
+package cc.mrbird.febs.mall.chain.service;
+
+import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
+import cc.mrbird.febs.common.enumerates.MallMoneyFlowTypeEnum;
+import cc.mrbird.febs.common.utils.AppContants;
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.mall.chain.enums.ChainEnum;
+import cc.mrbird.febs.mall.chain.enums.CoinTypeEnum;
+import cc.mrbird.febs.mall.entity.MallMemberWallet;
+import cc.mrbird.febs.mall.entity.MallMoneyFlow;
+import cc.mrbird.febs.mall.entity.MemberCoinAddressEntity;
+import cc.mrbird.febs.mall.entity.MemberCoinChargeEntity;
+import cc.mrbird.febs.mall.mapper.MallMemberWalletMapper;
+import cc.mrbird.febs.mall.mapper.MemberCoinAddressDao;
+import cc.mrbird.febs.mall.mapper.MemberCoinChargeDao;
+import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.stereotype.Service;
+import org.web3j.protocol.core.methods.response.Transaction;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service
+public class BaseCoinService {
+
+ @Resource
+ private RedisUtils redisUtils;
+ @Resource
+ private MemberCoinChargeDao memberCoinChargeDao;
+ @Resource
+ private MemberCoinAddressDao memberCoinAddressDao;
+ @Resource
+ private MallMemberWalletMapper mallMemberWalletMapper;
+ @Resource
+ private IMallMoneyFlowService mallMoneyFlowService;
+
+ public void compile(Transaction e) {
+ if (e.getTo() == null) {
+ return;
+ }
+
+ redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.getBlockNumber());
+
+ String address = e.getTo();
+ String hash = e.getHash();
+ MemberCoinAddressEntity coinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbol(address, CoinTypeEnum.USDT.toString());
+ if (coinAddressEntity == null) {
+ return;
+ }
+ // 判断对方打款地址是否为源池地址
+ if(ObjectUtil.isNotEmpty(coinAddressEntity)){
+// if (ChainEnum.BSC_USDT.getAddress().toLowerCase().equals(e.to)) {
+ log.info("触发USDT合约监听事件");
+ redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.getBlockNumber());
+ // hash没有用过
+ Map<String, Object> param = new HashMap<>();
+ param.put("hash", hash);
+ param.put("address", address);
+ List<MemberCoinChargeEntity> memberCoinChargeEntities = memberCoinChargeDao.selectByMap(param);
+ if (CollectionUtils.isNotEmpty(memberCoinChargeEntities)) {
+ return;
+ }
+
+// MemberCoinAddressEntity coinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbol(address, CoinTypeEnum.USDT.toString());
+// if (coinAddressEntity == null) {
+// return;
+// }
+ Long memberId = coinAddressEntity.getMemberId();
+ BigDecimal amount = new BigDecimal(e.getValue()).divide(BigDecimal.TEN.pow(18), 8, RoundingMode.HALF_DOWN);
+ BigDecimal balance = amount;
+ if (balance != null && balance.compareTo(new BigDecimal("0.1")) > 0) {
+ balance = balance.setScale(8, RoundingMode.CEILING);
+ BigDecimal early = BigDecimal.ZERO;
+ // 查询钱包 并更新
+ MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(memberId);
+ if (mallMemberWallet == null) {
+ return;
+ }
+
+ mallMemberWalletMapper.updateBlockBalanceById(mallMemberWallet.getId(), balance);
+
+ String orderNo = insertCoinCharge(address, memberId, balance, CoinTypeEnum.USDT.name(), "ERC20", BigDecimal.ZERO, hash);
+ // 插入财务记录
+
+ Long chargeFlowId = mallMoneyFlowService.addMoneyFlow(
+ memberId,
+ orderNo,
+ balance.setScale(4, BigDecimal.ROUND_DOWN),
+ MallMoneyFlowTypeEnum.CHARGE.getCode(),
+ MallMoneyFlow.STATUS_SUCCESS,
+ MallMoneyFlow.IS_RETURN_Y,
+ memberId,
+ FlowTypeEnum.BALANCE.getValue(),
+ MallMoneyFlowTypeEnum.CHARGE.getName()
+ );
+ // 同步
+// BigDecimal bigDecimal = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(e.to);
+
+ }
+
+
+ }
+ }
+ 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;
+ }
+ private String generateNo() {
+ // 生成订单号
+ Long timestamp = System.currentTimeMillis();
+ // 随机数
+ int random = (int) (Math.random() * 10);
+ return String.valueOf(timestamp).substring(2) + random;
+ }
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/BlockCoinServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/chain/service/BlockCoinServiceImpl.java
index 0660317..be364b5 100644
--- a/src/main/java/cc/mrbird/febs/mall/chain/service/BlockCoinServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/BlockCoinServiceImpl.java
@@ -114,12 +114,12 @@
return;
}
// 校验这个交易是否成功
- EthService ethService = new EthService();
- boolean b = ethService.checkTransferResult(hash);
- if (!b) {
- log.info("#USDT假充值:{}#", hash);
- return;
- }
+// EthService ethService = new EthService();
+// boolean b = ethService.checkTransferResult(hash);
+// if (!b) {
+// log.info("#USDT假充值:{}#", hash);
+// return;
+// }
MemberCoinAddressEntity coinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbol(address, CoinTypeEnum.USDT.toString());
if (coinAddressEntity == null) {
return;
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/BscUsdtContractEvent.java b/src/main/java/cc/mrbird/febs/mall/chain/service/BscUsdtContractEvent.java
new file mode 100644
index 0000000..fcffcac
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/BscUsdtContractEvent.java
@@ -0,0 +1,138 @@
+package cc.mrbird.febs.mall.chain.service;
+
+import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
+import cc.mrbird.febs.common.enumerates.MallMoneyFlowTypeEnum;
+import cc.mrbird.febs.common.utils.AppContants;
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.mall.chain.enums.ChainEnum;
+import cc.mrbird.febs.mall.chain.enums.CoinTypeEnum;
+import cc.mrbird.febs.mall.entity.MallMemberWallet;
+import cc.mrbird.febs.mall.entity.MallMoneyFlow;
+import cc.mrbird.febs.mall.entity.MemberCoinAddressEntity;
+import cc.mrbird.febs.mall.entity.MemberCoinChargeEntity;
+import cc.mrbird.febs.mall.mapper.MallMemberWalletMapper;
+import cc.mrbird.febs.mall.mapper.MemberCoinAddressDao;
+import cc.mrbird.febs.mall.mapper.MemberCoinChargeDao;
+import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Service
+public class BscUsdtContractEvent implements ContractEventService {
+
+ @Resource
+ private RedisUtils redisUtils;
+ @Resource
+ private MemberCoinChargeDao memberCoinChargeDao;
+ @Resource
+ private MemberCoinAddressDao memberCoinAddressDao;
+ @Resource
+ private MallMemberWalletMapper mallMemberWalletMapper;
+ @Resource
+ private IMallMoneyFlowService mallMoneyFlowService;
+
+ @Override
+ public void compile(EthUsdtContract.TransferEventResponse e) {
+ if (e.to == null) {
+ return;
+ }
+
+ redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.log.getBlockNumber());
+
+ String address = e.to;
+ String hash = e.log.getTransactionHash();
+ MemberCoinAddressEntity coinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbol(address, CoinTypeEnum.USDT.toString());
+ if (coinAddressEntity == null) {
+ return;
+ }
+ // 判断对方打款地址是否为源池地址
+ if(ObjectUtil.isNotEmpty(coinAddressEntity)){
+// if (ChainEnum.BSC_USDT.getAddress().toLowerCase().equals(e.to)) {
+ log.info("触发USDT合约监听事件");
+ redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber());
+ // hash没有用过
+ Map<String, Object> param = new HashMap<>();
+ param.put("hash", hash);
+ param.put("address", address);
+ List<MemberCoinChargeEntity> memberCoinChargeEntities = memberCoinChargeDao.selectByMap(param);
+ if (CollectionUtils.isNotEmpty(memberCoinChargeEntities)) {
+ return;
+ }
+
+// MemberCoinAddressEntity coinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbol(address, CoinTypeEnum.USDT.toString());
+// if (coinAddressEntity == null) {
+// return;
+// }
+ Long memberId = coinAddressEntity.getMemberId();
+ ContractChainService sourceUsdtInstance = ChainService.getInstance(ChainEnum.BSC_USDT.name());
+ int decimals = sourceUsdtInstance.decimals();
+ BigInteger tokens = e.tokens;
+ BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
+ BigDecimal balance = amount;
+ if (balance != null && balance.compareTo(new BigDecimal("0.1")) > 0) {
+ balance = balance.setScale(8, RoundingMode.CEILING);
+ BigDecimal early = BigDecimal.ZERO;
+ // 查询钱包 并更新
+ MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(memberId);
+ if (mallMemberWallet == null) {
+ return;
+ }
+
+ mallMemberWalletMapper.updateBlockBalanceById(mallMemberWallet.getId(), balance);
+
+ String orderNo = insertCoinCharge(address, memberId, balance, CoinTypeEnum.USDT.name(), "ERC20", BigDecimal.ZERO, hash);
+ // 插入财务记录
+
+ Long chargeFlowId = mallMoneyFlowService.addMoneyFlow(
+ memberId,
+ orderNo,
+ balance.setScale(4, BigDecimal.ROUND_DOWN),
+ MallMoneyFlowTypeEnum.CHARGE.getCode(),
+ MallMoneyFlow.STATUS_SUCCESS,
+ MallMoneyFlow.IS_RETURN_Y,
+ memberId,
+ FlowTypeEnum.BALANCE.getValue(),
+ MallMoneyFlowTypeEnum.CHARGE.getName()
+ );
+ // 同步
+// BigDecimal bigDecimal = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(e.to);
+
+ }
+
+
+ }
+ }
+ 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;
+ }
+ private String generateNo() {
+ // 生成订单号
+ Long timestamp = System.currentTimeMillis();
+ // 随机数
+ int random = (int) (Math.random() * 10);
+ return String.valueOf(timestamp).substring(2) + random;
+ }
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/ChainService.java b/src/main/java/cc/mrbird/febs/mall/chain/service/ChainService.java
new file mode 100644
index 0000000..732ec34
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/ChainService.java
@@ -0,0 +1,185 @@
+package cc.mrbird.febs.mall.chain.service;
+
+import cc.mrbird.febs.common.exception.FebsException;
+import cc.mrbird.febs.mall.chain.enums.ChainEnum;
+import cc.mrbird.febs.mall.chain.enums.EthService;
+import io.reactivex.Flowable;
+import io.reactivex.disposables.Disposable;
+import lombok.extern.slf4j.Slf4j;
+import org.web3j.crypto.Credentials;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.DefaultBlockParameter;
+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.protocol.websocket.WebSocketClient;
+import org.web3j.protocol.websocket.WebSocketService;
+import org.web3j.tx.gas.StaticGasProvider;
+
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author
+ * @date 2022-03-23
+ **/
+@Slf4j
+public class ChainService {
+ private final static Map<String, ContractChainService> contractMap = new HashMap<>();
+
+ static {
+ for (ChainEnum chain : ChainEnum.values()) {
+ contractMap.put(chain.name(), new EthService(chain.getUrl(), chain.getAddress(), chain.getPrivateKey(), chain.getContractAddress()));
+ }
+ }
+
+ private ChainService() {
+ }
+
+ public final static ChainService INSTANCE = new ChainService();
+
+ public static ContractChainService getInstance(String chainType) {
+ ContractChainService contract = contractMap.get(chainType);
+ if (contract == null) {
+ throw new FebsException("参数错误");
+ }
+
+ return contract;
+ }
+
+ /**
+ * 监听合约事件
+ *
+ * @param startBlock 开始区块
+ */
+ public static void contractEventListener(BigInteger startBlock, ContractEventService event, String type) {
+ contractEventListener(startBlock, null, event, type);
+ }
+
+ public static void contractEventListener(BigInteger startBlock, BigInteger endBlock, ContractEventService event, String type) {
+ ChainEnum chain = ChainEnum.getValueByName(type);
+ assert chain != null;
+
+ EthUsdtContract contract = contract(chain.getPrivateKey(), chain.getContractAddress(), chain.getUrl());
+ EthFilter filter = getFilter(startBlock, endBlock, chain.getContractAddress());
+
+ Flowable<EthUsdtContract.TransferEventResponse> eventFlowable = contract.transferEventFlowable(filter);
+ eventFlowable.subscribe(e -> {
+ event.compile(e);
+ }, error -> {
+ log.error("合约监听启动报错", error);
+ });
+ }
+
+ public static void wssContractEventListener(BigInteger startBlock, ContractEventService event, String type) {
+ WebSocketService ws = null;
+ WebSocketClient webSocketClient = null;
+ Web3j web3j = null;
+
+ try {
+ webSocketClient = new WebSocketClient(new URI("wss://bsc-mainnet.nodereal.io/ws/v1/78074065950e4915aef4f12b6f357d16"));
+ ws = new WebSocketService(webSocketClient, true);
+ ws.connect();
+ web3j = Web3j.build(ws);
+ ChainEnum chain = ChainEnum.getValueByName(type);
+ assert chain != null;
+
+ EthUsdtContract ethUsdtContract = wssContract(chain.getPrivateKey(), chain.getContractAddress(), web3j);
+ EthFilter filter = getFilter(startBlock, startBlock, chain.getContractAddress());
+
+
+ Flowable<EthUsdtContract.TransferEventResponse> eventFlowable = ethUsdtContract.transferEventFlowable(filter);
+ Disposable subscribe = eventFlowable.subscribe(event::compile, error -> {
+ log.error("币安监听异常", error);
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+
+
+ public static void wssBaseCoinEventListener(BigInteger startBlock, BaseCoinService event) {
+ WebSocketService ws = null;
+ WebSocketClient webSocketClient = null;
+ Web3j web3j = null;
+
+ try {
+ webSocketClient = new WebSocketClient(new URI("wss://bsc-mainnet.nodereal.io/ws/v1/78074065950e4915aef4f12b6f357d16"));
+ ws = new WebSocketService(webSocketClient, true);
+ ws.connect();
+ web3j = Web3j.build(ws);
+
+ Disposable subscribe = web3j.replayPastAndFutureTransactionsFlowable(new DefaultBlockParameterNumber(startBlock)).subscribe(event::compile, error ->{
+ log.error("监听链上异常", error);
+ });
+ }catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ private static EthUsdtContract contract(String privateKey, String contractAddress, String url) {
+ Credentials credentials = Credentials.create(privateKey);
+ HttpService httpService = new HttpService(url);
+// httpService.addHeader("Authorization", "Bearer " + Base64.encode("tfc:tfc123".getBytes()));
+// httpService.addHeader("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJwdWJsaWMiLCJleHAiOjE2NTk5MzcxOTAsImp0aSI6IjRiMjNkYTVjLWRlZWEtNDYzNi04YjMwLWNmMmZmMjVkM2NlYyIsImlhdCI6MTY1OTkzMzU5MCwiaXNzIjoiQW5rciIsIm5iZiI6MTY1OTkzMzU5MCwic3ViIjoiZmNiNjY0YjItOGEwNC00N2E5LTg3ZjMtNTJhMjE2ODVlMzEzIn0.YfEwvDByU2MGHywsblZpEmKMIbjv4cWYkn5CaFglXY0TSANzd2pCSbIe40yU_R9_nV6xZeE8Uk74jJOdd_QvMpFyUgo-MMNWZP6uiEaYvK_K3tlpk5yzeZq9D4ruWaq8rFKggr-iaRGzu6coRSAOFv2prWll3a7NdEbmkM-y5Y85xYD6g1N-TPIpE_Y-_-WPf3JUavk744kG8YyHhGvAmk2IL0N2xePfC6CHesdJhwvmJJXzr_53dbPwit1y5KljS0iTZz3mGTML2bq4hGaEHbQxeY2fBpZOSm8sPMz-zB9IVJQKzH5-DXlPKz01mJ9XiBJlubfHsN72RdqFD-O2Tw");
+ return EthUsdtContract.load(contractAddress,
+ Web3j.build(httpService),
+ credentials,
+ new StaticGasProvider(BigInteger.valueOf(4500000L), BigInteger.valueOf(200000L)));
+ }
+
+ private static EthUsdtContract wssContract(String privateKey, String contractAddress, Web3j web3j) {
+ Credentials credentials = Credentials.create(privateKey);
+// httpService.addHeader("Authorization", "Bearer " + Base64.encode("tfc:tfc123".getBytes()));
+// httpService.addHeader("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJwdWJsaWMiLCJleHAiOjE2NTk5MzcxOTAsImp0aSI6IjRiMjNkYTVjLWRlZWEtNDYzNi04YjMwLWNmMmZmMjVkM2NlYyIsImlhdCI6MTY1OTkzMzU5MCwiaXNzIjoiQW5rciIsIm5iZiI6MTY1OTkzMzU5MCwic3ViIjoiZmNiNjY0YjItOGEwNC00N2E5LTg3ZjMtNTJhMjE2ODVlMzEzIn0.YfEwvDByU2MGHywsblZpEmKMIbjv4cWYkn5CaFglXY0TSANzd2pCSbIe40yU_R9_nV6xZeE8Uk74jJOdd_QvMpFyUgo-MMNWZP6uiEaYvK_K3tlpk5yzeZq9D4ruWaq8rFKggr-iaRGzu6coRSAOFv2prWll3a7NdEbmkM-y5Y85xYD6g1N-TPIpE_Y-_-WPf3JUavk744kG8YyHhGvAmk2IL0N2xePfC6CHesdJhwvmJJXzr_53dbPwit1y5KljS0iTZz3mGTML2bq4hGaEHbQxeY2fBpZOSm8sPMz-zB9IVJQKzH5-DXlPKz01mJ9XiBJlubfHsN72RdqFD-O2Tw");
+ return EthUsdtContract.load(contractAddress,
+ web3j,
+ credentials,
+ new StaticGasProvider(BigInteger.valueOf(4500000L), BigInteger.valueOf(200000L)));
+ }
+
+ private static EthFilter getFilter(BigInteger startBlock, String contractAddress) {
+ return getFilter(startBlock, null, contractAddress);
+ }
+
+ private static EthFilter getFilter(BigInteger startBlock, BigInteger endBlock, String contractAddress) {
+ DefaultBlockParameter startParameterName = null;
+ DefaultBlockParameter endParameterName = null;
+ if (startBlock != null) {
+ startParameterName = new DefaultBlockParameterNumber(startBlock);
+ } else {
+ startParameterName = DefaultBlockParameterName.EARLIEST;
+ }
+
+ if (endBlock != null) {
+ endParameterName = new DefaultBlockParameterNumber(endBlock);
+ } else {
+ endParameterName = DefaultBlockParameterName.LATEST;
+ }
+
+ return new EthFilter(startParameterName, endParameterName, contractAddress);
+ }
+
+ public static void main(String[] args) {
+// ChainEnum chain = ChainEnum.getValueByName(ChainEnum.BSC_TFC.name());
+// assert chain != null;
+//
+// EthUsdtContract contract = contract(chain.getPrivateKey(), chain.getContractAddress(), chain.getUrl());
+// EthFilter filter = getFilter(new BigInteger("18097238"), chain.getContractAddress());
+//
+// contract.transferEventFlowable(filter).subscribe(e -> {
+// System.out.println(1);
+// }, error -> {
+// log.error("--->", error);
+// });
+
+// System.out.println(ChainService.getInstance(ChainEnum.BSC_TFC.name()).totalSupply());
+ }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/ContractChainService.java b/src/main/java/cc/mrbird/febs/mall/chain/service/ContractChainService.java
new file mode 100644
index 0000000..076e23c
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/ContractChainService.java
@@ -0,0 +1,31 @@
+package cc.mrbird.febs.mall.chain.service;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public interface ContractChainService {
+
+ BigInteger balanceOfUnDecimal(String address);
+
+ BigDecimal balanceOf(String address);
+
+ BigInteger allowance(String address);
+
+ boolean isAllowance(String address);
+
+ String transfer(String address);
+
+ String transfer(String address, BigDecimal amount);
+
+ int allowanceCnt(String address);
+
+ int decimals();
+
+ BigInteger blockNumber();
+
+ BigInteger totalSupply();
+
+ BigInteger totalSupplyNFT();
+
+ String safeMintNFT(String address);
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/ContractEventService.java b/src/main/java/cc/mrbird/febs/mall/chain/service/ContractEventService.java
new file mode 100644
index 0000000..fdd40df
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/ContractEventService.java
@@ -0,0 +1,6 @@
+package cc.mrbird.febs.mall.chain.service;
+
+public interface ContractEventService {
+
+ void compile(EthUsdtContract.TransferEventResponse e);
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/EthService.java b/src/main/java/cc/mrbird/febs/mall/chain/service/EthService.java
index 5faeb20..a4f1f82 100644
--- a/src/main/java/cc/mrbird/febs/mall/chain/service/EthService.java
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/EthService.java
@@ -33,7 +33,7 @@
/**
* ETH类,使用Web3j 下面为使用教程
* https://kauri.io/article/925d923e12c543da9a0a3e617be963b4/manage-an-ethereum-account-with-java-and-web3js
- *
+ *
* @author Administrator
*
*/
@@ -66,7 +66,7 @@
/**
* 查询ETH余额
- *
+ *
* @param address
* @return
*/
@@ -90,7 +90,7 @@
/**
* 创建ETH钱包
- *
+ *
* @return
*/
public static Map<String, String> createEth() {
@@ -163,9 +163,9 @@
}
/**
- *
+ *
* 方法描述:获取代币余额
- *
+ *
* @param fromAddress
* @param
* @param
diff --git a/src/main/java/cc/mrbird/febs/mall/chain/service/UsdtErc20UpdateService.java b/src/main/java/cc/mrbird/febs/mall/chain/service/UsdtErc20UpdateService.java
index b41ae0e..c7af807 100644
--- a/src/main/java/cc/mrbird/febs/mall/chain/service/UsdtErc20UpdateService.java
+++ b/src/main/java/cc/mrbird/febs/mall/chain/service/UsdtErc20UpdateService.java
@@ -93,7 +93,7 @@
Credentials credentials = Credentials.create(privateKey);
EthUsdtContract contract = EthUsdtContract.load(contractAddr, getInstance(), credentials, getStaticGasProvider());
- EthFilter filter = getFilter(blockNum,null,contractAddr);
+ EthFilter filter = getFilter(blockNum,blockNum,contractAddr);
Map<String,BigInteger> map = new HashMap<String,BigInteger>();
map.put("blockNum",blockNum);
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/BlockSeriveImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/BlockSeriveImpl.java
index 32a0c24..16370ec 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/BlockSeriveImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/BlockSeriveImpl.java
@@ -3,7 +3,6 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.mall.chain.service.EthService;
-import cc.mrbird.febs.mall.chain.service.Trc20Service;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.entity.MemberCoinAddressEntity;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
diff --git a/src/test/java/cc/mrbird/febs/ProfitTest.java b/src/test/java/cc/mrbird/febs/ProfitTest.java
index b770871..31e6bb5 100644
--- a/src/test/java/cc/mrbird/febs/ProfitTest.java
+++ b/src/test/java/cc/mrbird/febs/ProfitTest.java
@@ -6,6 +6,11 @@
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.MallUtils;
+import cc.mrbird.febs.common.utils.RedisUtils;
+import cc.mrbird.febs.mall.chain.enums.ChainEnum;
+import cc.mrbird.febs.mall.chain.service.BaseCoinService;
+import cc.mrbird.febs.mall.chain.service.ChainService;
+import cc.mrbird.febs.mall.chain.service.ContractEventService;
import cc.mrbird.febs.mall.chain.service.UsdtErc20UpdateService;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.*;
@@ -29,6 +34,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -414,12 +420,29 @@
//
+ @Autowired
+ private ContractEventService bscUsdtContractEvent;
+
+ @Autowired
+ private BaseCoinService baseCoinService;
+ @Autowired
+ private RedisUtils redisUtils;
@Resource
private UsdtErc20UpdateService usdtErc20UpdateService;
@Test
public void scorePool(){
- usdtErc20UpdateService.updateUsdt();
+ long start = System.currentTimeMillis();
+ Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM);
+ BigInteger newest = ChainService.getInstance(ChainEnum.BSC_USDT.name()).blockNumber();
+ BigInteger block;
+ if (incrementObj == null) {
+ block = newest;
+ } else {
+ block = (BigInteger) incrementObj;
+ }
+// ChainService.wssBaseCoinEventListener(BigInteger.valueOf(24317595), baseCoinService);
+ ChainService.wssContractEventListener(BigInteger.valueOf(24317595), bscUsdtContractEvent, ChainEnum.BSC_USDT.name());
}
//
// @Test
--
Gitblit v1.9.1