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