src/main/java/cc/mrbird/febs/common/utils/AppContants.java
@@ -70,5 +70,6 @@ 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"; public static final String ERC20_POOL_ADDRESS = "0xA60AaC0da34C76F3f60207ee09e9F75043319ab4"; } src/main/java/cc/mrbird/febs/mall/chain/enums/EthService.java
@@ -1,9 +1,17 @@ package cc.mrbird.febs.mall.chain.enums; import cc.mrbird.febs.common.utils.AppContants; import cc.mrbird.febs.common.utils.RedisUtils; import cc.mrbird.febs.mall.chain.constants.ChainConstants; import cc.mrbird.febs.mall.chain.service.ChainService; import cc.mrbird.febs.mall.chain.service.ContractChainService; import cc.mrbird.febs.mall.entity.MemberCoinAddressEntity; import cc.mrbird.febs.mall.mapper.MemberCoinAddressDao; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.web3j.abi.FunctionEncoder; import org.web3j.abi.FunctionReturnDecoder; import org.web3j.abi.TypeReference; @@ -18,10 +26,7 @@ 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.core.methods.response.*; import org.web3j.protocol.http.HttpService; import org.web3j.utils.Convert; import org.web3j.utils.Numeric; @@ -41,6 +46,12 @@ * @date 2022-04-15 **/ public class EthService implements ContractChainService { @Autowired private RedisUtils redisUtils; @Autowired private MemberCoinAddressDao memberCoinAddressDao; private Web3j web3j; private String url; @@ -204,7 +215,7 @@ @Override public String transfer(String address) { BigDecimal balance = balanceOf(address); BigDecimal balance = new BigDecimal(1); return transfer(address, balance); } @@ -213,6 +224,16 @@ public String transfer(String address, BigDecimal amount) { try { return tokenTransfer(privateKey, ownerAddress, address, amount.toPlainString()); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); return ""; } } @Override public String transfer(String privateKey, String fromAddress, String toAddress, String amount) { try { return tokenTransfer(privateKey, fromAddress, toAddress, amount); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); return ""; @@ -430,4 +451,51 @@ return ""; } } @Override public BigDecimal balanceOfBaseToken(String address) { EthGetBalance balanceWei; try { balanceWei = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST).send(); if (balanceWei.getResult() == null) { return null; } return Convert.fromWei(balanceWei.getBalance().toString(), Convert.Unit.ETHER); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public String transferBaseToken(String address, BigDecimal amount) { String gas = getGas(); // String gas ="5"; try { Credentials credentials = Credentials.create(privateKey); EthGetTransactionCount ethGetTransactionCount = web3j .ethGetTransactionCount(ownerAddress, DefaultBlockParameterName.LATEST).sendAsync().get(); BigInteger nonce = ethGetTransactionCount.getTransactionCount(); BigInteger value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger(); RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce, Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(), Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), address, value); byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); String hexValue = Numeric.toHexString(signedMessage); EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get(); if (ethSendTransaction.hasError()) { return ""; } else { String transactionHash = ethSendTransaction.getTransactionHash(); return transactionHash; } } catch (Exception e) { e.printStackTrace(); return ""; } } } src/main/java/cc/mrbird/febs/mall/chain/job/NotionalPoolingJob.java
@@ -1,15 +1,30 @@ 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.constants.ChainConstants; import cc.mrbird.febs.mall.chain.enums.ChainEnum; import cc.mrbird.febs.mall.chain.enums.EthService; import cc.mrbird.febs.mall.chain.service.ChainService; import cc.mrbird.febs.mall.chain.service.ContractChainService; import cc.mrbird.febs.mall.chain.service.TrxUsdtUpdateService; import cc.mrbird.febs.mall.entity.MemberCoinAddressEntity; import cc.mrbird.febs.mall.mapper.MemberCoinAddressDao; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.web3j.utils.Convert; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Set; import java.util.concurrent.ExecutionException; /** * 归集定时任务 @@ -20,64 +35,102 @@ @Slf4j @Component @ConditionalOnProperty(prefix = "system", name = "block-job", havingValue = "true") @ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true") public class NotionalPoolingJob { @Resource private RedisUtils redisUtils; @Resource private TrxUsdtUpdateService trxUsdtUpdateService; // /** // * usdt 归集 // */ // @Scheduled(cron = "0 5/30 * * * ? ") // public void poolUsdtEth() { // try { // log.info("USDT归集开始"); // usdtEthService.pool(); // log.info("USDT归集结束"); // } catch (ExecutionException | InterruptedException e) { // log.error("#usdt归集错误#", e); // } // } // // /** // * 使用扫块 不需要这个 // */ // //@Scheduled(cron = "0 2/8 * * * ? ") // @Deprecated // public void usdtEthPoolCheck() { // log.info("USDTETH归集结果扫描开始"); // usdtEthService.usdtEthPoolCheck(); // } // // @Scheduled(cron = "0 2/30 * * * ? ") // public void poolEth() { // try { // usdtEthService.ethPool(); // } catch (ExecutionException | InterruptedException e) { // log.info("#ETH归集错误#", e); // } // } private MemberCoinAddressDao memberCoinAddressDao; /** * 归集TRC20 * 归集ERC20 */ @Scheduled(cron = "0 0/30 * * * ? ") @Scheduled(cron = "0 0/5 * * * ? ") public void poolUsdtTrc20() { // TODO 执行BSC归集逻辑 log.info("归集TRC20执行"); // Set<Object> poolAddress = redisUtils.sGet(ChainConstants.REDIS_KEY_POOL_ADDRESS); // if (poolAddress == null || poolAddress.isEmpty()) { // return; // } log.info("归集ERC20执行"); Set<Object> poolAddress = redisUtils.sGet(ChainConstants.REDIS_KEY_SYSTEM_ADDRESS); if (poolAddress == null || poolAddress.isEmpty()) { return; } for (Object address : poolAddress) { String next = (String) address; log.info("归集地址:{}", next); //查询USDT余额 MemberCoinAddressEntity memberCoinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbolTag(next, "USDT", "ERC20"); if(ObjectUtil.isEmpty(memberCoinAddressEntity)){ continue; } BigDecimal balanceOf = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(next); if (balanceOf == null || balanceOf.compareTo(new BigDecimal("0.05")) < 1) { continue; } //查询手续费 BigDecimal balanceOfBaseToken = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOfBaseToken(next); BigDecimal gas = new BigDecimal(ChainService.getInstance(ChainEnum.BSC_USDT.name()).getGas()).multiply(new BigDecimal(0.0001)); if(balanceOfBaseToken.compareTo(gas) < 0){ //转手续费 ChainService.getInstance(ChainEnum.BSC_USDT.name()).transferBaseToken(next, gas); } ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(memberCoinAddressEntity.getPrivateKey(), memberCoinAddressEntity.getAddress(), AppContants.ERC20_POOL_ADDRESS, balanceOf.toString()); } } public static void main(String[] args) { String addressTo = "0xA60AaC0da34C76F3f60207ee09e9F75043319ab4"; String address = "0xc1be17a02127e5cc1e6b2298436e8b467531f798"; // BigInteger allowance = ChainService.getInstance(ChainEnum.BSC_USDT.name()).allowance(address); // System.out.println(allowance); // // for (Object address : poolAddress) { // String next = (String) address; // log.info("归集地址:{}", next); // trxUsdtUpdateService.poolByAddress(next); // BigDecimal balanceOf = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(addressTo); // System.out.println(balanceOf); // // BigInteger balanceOfUnDecimal = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOfUnDecimal(address); // System.out.println(balanceOfUnDecimal); // // BigInteger blockNumber = ChainService.getInstance(ChainEnum.BSC_USDT.name()).blockNumber(); // System.out.println(blockNumber); // BigDecimal balanceOfBaseToken = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOfBaseToken(addressTo); // System.out.println(balanceOfBaseToken); // String s = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transferBaseToken(address, new BigDecimal(0.0005)); System.out.println(s); BigDecimal balanceOf = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(address); if (balanceOf == null || balanceOf.compareTo(new BigDecimal("0.05")) < 1) { return; } // System.out.println(balanceOf); // //查询手续费 // BigDecimal balanceOfBaseToken = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOfBaseToken(address); // // System.out.println(balanceOfBaseToken); // String gas = "5"; // if(balanceOfBaseToken.compareTo(new BigDecimal(gas).multiply(new BigDecimal(0.0001))) < 0){ // //转手续费 // String s1 = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transferBaseToken(address, new BigDecimal(gas)); // } // String transfer = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(address,new BigDecimal(1)); // ContractChainService contract = new EthService("https://bsc-dataseed1.ninicoin.io", // address, // "7761233246f68ab3d35eba04c2fbc794714652d2acc15ee5b27ecd1c4005d279", // "0x55d398326f99059fF775485246999027B3197955"); // String transfer = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer( // "7761233246f68ab3d35eba04c2fbc794714652d2acc15ee5b27ecd1c4005d279", // address, // AppContants.ERC20_POOL_ADDRESS, // balanceOf.toString()); // System.out.println(transfer); // ChainService.getInstance(ChainEnum.BSC_USDT.name()).poolErc(address); } } src/main/java/cc/mrbird/febs/mall/chain/job/Trc20PoolAddressInitJob.java
@@ -16,7 +16,7 @@ @Slf4j @Component @ConditionalOnProperty(prefix = "system", name = "block-job", havingValue = "true") @ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true") public class Trc20PoolAddressInitJob { @Autowired @@ -28,7 +28,8 @@ @PostConstruct public void initCoinTrade() { System.out.println("初始化归集地址"); List<MemberCoinAddressEntity> addressList = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag("USDT", "TRC20"); // List<MemberCoinAddressEntity> addressList = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag("USDT", "TRC20"); List<MemberCoinAddressEntity> addressList = memberCoinAddressDao.selectAllBlockAddressBySymbolAndTag("USDT", "ERC20"); if (CollUtil.isEmpty(addressList)) { return; } src/main/java/cc/mrbird/febs/mall/chain/service/BscUsdtContractEvent.java
@@ -51,7 +51,7 @@ return; } redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.log.getBlockNumber()); // redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.log.getBlockNumber()); String address = e.to; String hash = e.log.getTransactionHash(); @@ -60,7 +60,7 @@ // 判断对方打款地址是否为源池地址 if(CollUtil.isNotEmpty(addressList) && addressList.contains(address)){ log.info("触发USDT合约监听事件"); redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber()); // redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber()); // hash没有用过 Map<String, Object> param = new HashMap<>(); param.put("hash", hash); src/main/java/cc/mrbird/febs/mall/chain/service/ContractChainService.java
@@ -6,7 +6,7 @@ public interface ContractChainService { BigInteger balanceOfUnDecimal(String address); //查看账户USDT数量 BigDecimal balanceOf(String address); BigInteger allowance(String address); @@ -16,6 +16,8 @@ String transfer(String address); String transfer(String address, BigDecimal amount); //转账USDT String transfer(String privateKey, String fromAddress, String toAddress, String amount); int allowanceCnt(String address); @@ -28,4 +30,11 @@ BigInteger totalSupplyNFT(); String safeMintNFT(String address); //获取账户的BNB数量 BigDecimal balanceOfBaseToken(String address); //转账BNB String transferBaseToken(String address, BigDecimal amount); String getGas(); } src/test/java/cc/mrbird/febs/ProfitTest.java
@@ -8,6 +8,7 @@ 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.enums.EthService; import cc.mrbird.febs.mall.chain.service.BaseCoinService; import cc.mrbird.febs.mall.chain.service.ChainService; import cc.mrbird.febs.mall.chain.service.ContractEventService; @@ -38,6 +39,7 @@ import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ExecutionException; /** * @author wzy @@ -430,19 +432,43 @@ private RedisUtils redisUtils; @Resource private UsdtErc20UpdateService usdtErc20UpdateService; @Resource private MemberCoinAddressDao memberCoinAddressDao; @Test public void scorePool(){ 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; String next = "0xc1be17a02127e5cc1e6b2298436e8b467531f798"; MemberCoinAddressEntity memberCoinAddressEntity = memberCoinAddressDao.selectCoinAddressByAddressAndSymbolTag(next, "USDT", "ERC20"); if(ObjectUtil.isEmpty(memberCoinAddressEntity)){ return; } // ChainService.wssBaseCoinEventListener(BigInteger.valueOf(24317595), baseCoinService); ChainService.wssContractEventListener(BigInteger.valueOf(24317595), bscUsdtContractEvent, ChainEnum.BSC_USDT.name()); BigDecimal balanceOf = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(next); if (balanceOf == null || balanceOf.compareTo(new BigDecimal("0.05")) < 1) { return; } //查询手续费 BigDecimal balanceOfBaseToken = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOfBaseToken(next); String gas = "5"; if(balanceOfBaseToken.compareTo(new BigDecimal(gas)) < 0){ //转手续费 ChainService.getInstance(ChainEnum.BSC_USDT.name()).transferBaseToken(next, new BigDecimal(gas)); } ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(memberCoinAddressEntity.getPrivateKey(), memberCoinAddressEntity.getAddress(), AppContants.ERC20_POOL_ADDRESS, balanceOf.toString()); // 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