KKSU
2024-05-16 c268540881fe493bc40e76ba82793a63c0897c91
滑点监控
7 files modified
1 files added
300 ■■■■ changed files
src/main/java/cc/mrbird/febs/dapp/chain/ChainService.java 49 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ContractEventService.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappHdRecord.java 1 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java 53 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java 17 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainHuadianRunner.java 63 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/GiveMeMoneyJob.java 107 ●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/banner/coinPrice.html 6 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ChainService.java
@@ -1,35 +1,21 @@
package cc.mrbird.febs.dapp.chain;
import cc.mrbird.febs.common.exception.FebsException;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.data.repository.query.ParameterOutOfBoundsException;
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.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.gas.StaticGasProvider;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.rmi.activation.UnknownObjectException;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -139,6 +125,41 @@
    }
    public static void huadianEventListener(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)
                .doOnError(throwable ->
                        log.error("合约事件监听发生错误: " + throwable.getMessage(), throwable)) // 更具体的错误日志记录
                .retryWhen(errors -> {
                    AtomicInteger counter = new AtomicInteger();
                    return errors.takeWhile(e -> counter.getAndIncrement() != 3)
                       .flatMap(e -> {
                        System.out.println("delay retry by " + counter.get() + " second(s)");
                        return Flowable.timer(counter.get(), TimeUnit.SECONDS);
                    });
                })
                .subscribeOn(Schedulers.io()); // 指定subscribe操作在IO线程中执行,避免阻塞主线程
        eventFlowable.subscribe(
                e -> {
                    try {
                        event.huadian(e); // 处理事件
                    } catch (Exception ex) {
                        // 处理事件时可能出现的异常
                        log.error("处理合约事件时出错", ex);
                    }
                },
                Throwable::printStackTrace, // 打印错误堆栈,或者可以替换为更具体的错误处理逻辑
                () -> log.info("合约事件监听已完成") // 在Flowable完成时执行的逻辑,如记录日志等
        );
    }
    private static EthUsdtContract contract(String privateKey, String contractAddress, String url) {
        Credentials credentials = Credentials.create(privateKey);
src/main/java/cc/mrbird/febs/dapp/chain/ContractEventService.java
@@ -4,4 +4,8 @@
    void compile(EthUsdtContract.TransferEventResponse e);
    void coinReward(EthUsdtContract.CoinRewardEventResponse e);
    void huadian(EthUsdtContract.TransferEventResponse e);
}
src/main/java/cc/mrbird/febs/dapp/entity/DappHdRecord.java
@@ -16,6 +16,7 @@
    private BigDecimal usdtAmount;//滑点累计
    private BigDecimal coinEvery;//币量新增
    private BigDecimal coinAmount;//币量累计
    private String transactionHash;//币量累计
    @TableField(exist = false)
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java
@@ -1,18 +1,15 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractEventService;
import cc.mrbird.febs.dapp.chain.EthUsdtContract;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappMemberFundMapper;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
@@ -23,7 +20,6 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -35,6 +31,7 @@
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@Slf4j
@@ -63,6 +60,9 @@
    @Resource
    private ChainProducer chainProducer;
    @Resource
    private DappHdRecordMapper dappHdRecordMapper;
    public static void main(String[] args) {
        System.out.println(Numeric.toBigInt("0x12e4e85"));
@@ -242,4 +242,45 @@
            log.info("本地交易:{},amount-{},price-{}", e.adr,amount,price);
        }
    }
    @Override
    public void huadian(EthUsdtContract.TransferEventResponse e) {
        log.info("滑点奖励");
        if (e.to == null) {
            return;
        }
        String address = e.to;
        String transactionHash = e.log.getTransactionHash();
        List<DappHdRecord> transaction_hash = dappHdRecordMapper.selectList(new QueryWrapper<DappHdRecord>().eq("transaction_hash", transactionHash));
        if(ObjectUtil.isNotEmpty(transaction_hash)){
            return;
        }
        if(!address.toUpperCase(Locale.ROOT).equals("0x1Ea392645f816BF15f1Fc87728eA010585bAAE7D".toUpperCase())){
            return;
        }
        //获取滑点钱包的余额
        BigDecimal coinPrice = ChainService.getInstance(ChainEnum.BSC_GFA.name()).getPrice("0x1Ea392645f816BF15f1Fc87728eA010585bAAE7D").setScale(8,BigDecimal.ROUND_DOWN);
        //更新此刻的USDT数量
        String existToken = redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue());
        if (StrUtil.isNotBlank(existToken)) {
            redisUtils.del(existToken);
        }
        int decimals = ChainService.getInstance(ChainEnum.BSC_GFA.name()).decimals();
        BigDecimal amount = new BigDecimal(e.tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN).setScale(8,BigDecimal.ROUND_DOWN);
        //获取这个时刻的滑点入账数量
        BigDecimal multiply = coinPrice.multiply(amount).multiply(new BigDecimal("0.97")).setScale(8,BigDecimal.ROUND_DOWN);
        //更新这个时间段的滑点数量
        redisUtils.set(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue(), multiply, 0);
        //生成一条记录
        DappHdRecord dappHdRecordAdd = new DappHdRecord();
        dappHdRecordAdd.setPrice(coinPrice);
        dappHdRecordAdd.setUsdtEvery(multiply);
        dappHdRecordAdd.setCoinEvery(amount);
        dappHdRecordAdd.setCoinAmount(BigDecimal.ZERO);
        dappHdRecordAdd.setTransactionHash(transactionHash);
        dappHdRecordMapper.insert(dappHdRecordAdd);
        dappSystemService.tradeProfitDistribute(1L);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java
@@ -2,11 +2,11 @@
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.dapp.chain.*;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.DappMemberService;
@@ -14,10 +14,8 @@
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -167,6 +165,15 @@
        log.info("本地无交易USDT:{}", e.log.getTransactionHash());
    }
    @Override
    public void huadian(EthUsdtContract.TransferEventResponse e) {
        if (e.to == null) {
            return;
        }
        log.info("本地无交易USDT:{}", e.log.getTransactionHash());
    }
    public static void main(String[] args) {
        System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf("0x9DDE1834683D642D4D077498DC7fbdb8CF70E8FE"));
    }
src/main/java/cc/mrbird/febs/job/ChainHuadianRunner.java
New file
@@ -0,0 +1,63 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.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.stereotype.Component;
import java.math.BigInteger;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true")
public class ChainHuadianRunner implements ApplicationRunner {
    @Autowired
    private ContractEventService bscCoinContractEvent;
    @Autowired
    private RedisUtils redisUtils;
    @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_GFA.name()).blockNumber();
//        Object incrementObj = BigInteger.valueOf(39780699);
//        BigInteger newest = BigInteger.valueOf(39780739);
        BigInteger block;
        if (incrementObj == null) {
            block = newest;
        } else {
            block = (BigInteger) incrementObj;
        }
        BigInteger section = BigInteger.valueOf(5000);
        log.info("监听:[{} - {} - {}]", newest,block,newest.subtract(block).compareTo(section) > -1);
        while (newest.subtract(block).compareTo(section) > -1) {
            BigInteger end = block.add(section);
            log.info("监听:[{} - {}]", block, end);
            ChainService.huadianEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_GFA.name());
            block = block.add(section);
            if (block.compareTo(newest) > 0) {
                block = newest;
            }
        }
        ChainService.huadianEventListener(block, null, bscCoinContractEvent, ChainEnum.BSC_GFA.name());
        long end = System.currentTimeMillis();
        log.info("区块链滑点启动完成, 消耗时间{}", end - start);
    }
}
src/main/java/cc/mrbird/febs/job/GiveMeMoneyJob.java
@@ -1,19 +1,13 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.common.enumerates.DataDicEnum;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.entity.DappAchieve;
import cc.mrbird.febs.dapp.entity.DappHdRecord;
import cc.mrbird.febs.dapp.mapper.DappAchieveMapper;
import cc.mrbird.febs.dapp.mapper.DappHdRecordMapper;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -21,7 +15,6 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@@ -74,55 +67,55 @@
    /**
     * 每日定时零点计算滑点
     */
    @Scheduled(cron = "0 0/5 * * * ? ")
    public void mineJob() {
        /**
         * 定时器循环计算每个时间跨度内增加的滑点数量
         */
        log.info("滑点奖励");
        //获取滑点钱包的余额
        BigDecimal coinCnt = ChainService.getInstance(ChainEnum.BSC_GFA.name()).balanceOf("0x1Ea392645f816BF15f1Fc87728eA010585bAAE7D").setScale(8,BigDecimal.ROUND_DOWN);
        BigDecimal coinPrice = ChainService.getInstance(ChainEnum.BSC_GFA.name()).getPrice("0x1Ea392645f816BF15f1Fc87728eA010585bAAE7D").setScale(8,BigDecimal.ROUND_DOWN);
        if(new BigDecimal("10").compareTo(coinCnt) >= 0){
            return;
        }
//        BigDecimal coinCnt = ChainService.getInstance(ChainEnum.BSC_GFA.name()).balanceOf("0xF6b06A30196aA5E318232a3b61319eab0FD4A3bF").setScale(8,BigDecimal.ROUND_DOWN);
//        BigDecimal coinPrice = ChainService.getInstance(ChainEnum.BSC_GFA.name()).getPrice("0xF6b06A30196aA5E318232a3b61319eab0FD4A3bF").setScale(8,BigDecimal.ROUND_DOWN);
        //获取上一时刻的数据
        BigDecimal coinAmountOld =BigDecimal.ZERO;
        DappHdRecord dappHdRecord = dappHdRecordMapper.selectNewRecord();
        if(ObjectUtil.isNotEmpty(dappHdRecord)){
            coinAmountOld = dappHdRecord.getCoinAmount();
        }
        //更新此刻的USDT数量
        String existToken = redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue());
        if (StrUtil.isNotBlank(existToken)) {
            redisUtils.del(existToken);
        }
        //这个时间段的新增余额
        //此刻的余额-上一次账户的余额 = 这个时间段的新增余额
        BigDecimal subtract = coinCnt.subtract(coinCnt).setScale(0,BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(subtract) >= 0){
            return;
        }
        //获取这个时刻的滑点入账数量
        BigDecimal multiply = coinPrice.multiply(subtract).multiply(new BigDecimal("0.97")).setScale(8,BigDecimal.ROUND_DOWN);
        //更新这个时间段的滑点数量
        redisUtils.set(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue(), multiply, 0);
        //生成一条记录
        DappHdRecord dappHdRecordAdd = new DappHdRecord();
        dappHdRecordAdd.setPrice(coinPrice);
        dappHdRecordAdd.setUsdtEvery(multiply);
        dappHdRecordAdd.setCoinEvery(subtract);
        dappHdRecordAdd.setCoinAmount(coinCnt);
        dappHdRecordMapper.insert(dappHdRecordAdd);
        dappSystemService.tradeProfitDistribute(1L);
    }
//    @Scheduled(cron = "0 0/5 * * * ? ")
//    public void mineJob() {
//        /**
//         * 定时器循环计算每个时间跨度内增加的滑点数量
//         */
//        log.info("滑点奖励");
//        //获取滑点钱包的余额
//        BigDecimal coinCnt = ChainService.getInstance(ChainEnum.BSC_GFA.name()).balanceOf("0x1Ea392645f816BF15f1Fc87728eA010585bAAE7D").setScale(8,BigDecimal.ROUND_DOWN);
//        BigDecimal coinPrice = ChainService.getInstance(ChainEnum.BSC_GFA.name()).getPrice("0x1Ea392645f816BF15f1Fc87728eA010585bAAE7D").setScale(8,BigDecimal.ROUND_DOWN);
//
//        if(new BigDecimal("10").compareTo(coinCnt) >= 0){
//            return;
//        }
//
////        BigDecimal coinCnt = ChainService.getInstance(ChainEnum.BSC_GFA.name()).balanceOf("0xF6b06A30196aA5E318232a3b61319eab0FD4A3bF").setScale(8,BigDecimal.ROUND_DOWN);
////        BigDecimal coinPrice = ChainService.getInstance(ChainEnum.BSC_GFA.name()).getPrice("0xF6b06A30196aA5E318232a3b61319eab0FD4A3bF").setScale(8,BigDecimal.ROUND_DOWN);
//
//        //获取上一时刻的数据
//        BigDecimal coinAmountOld =BigDecimal.ZERO;
//        DappHdRecord dappHdRecord = dappHdRecordMapper.selectNewRecord();
//        if(ObjectUtil.isNotEmpty(dappHdRecord)){
//            coinAmountOld = dappHdRecord.getCoinAmount();
//        }
//
//        //更新此刻的USDT数量
//        String existToken = redisUtils.getString(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue());
//        if (StrUtil.isNotBlank(existToken)) {
//            redisUtils.del(existToken);
//        }
//        //这个时间段的新增余额
//        //此刻的余额-上一次账户的余额 = 这个时间段的新增余额
//        BigDecimal subtract = coinCnt.subtract(coinCnt).setScale(0,BigDecimal.ROUND_DOWN);
//
//        if(BigDecimal.ZERO.compareTo(subtract) >= 0){
//            return;
//        }
//        //获取这个时刻的滑点入账数量
//        BigDecimal multiply = coinPrice.multiply(subtract).multiply(new BigDecimal("0.97")).setScale(8,BigDecimal.ROUND_DOWN);
//        //更新这个时间段的滑点数量
//        redisUtils.set(DataDicEnum.GFA_HUA_DIAN_WALLET_USDT_AMOUNT.getValue(), multiply, 0);
//
//        //生成一条记录
//        DappHdRecord dappHdRecordAdd = new DappHdRecord();
//        dappHdRecordAdd.setPrice(coinPrice);
//        dappHdRecordAdd.setUsdtEvery(multiply);
//        dappHdRecordAdd.setCoinEvery(subtract);
//        dappHdRecordAdd.setCoinAmount(coinCnt);
//        dappHdRecordMapper.insert(dappHdRecordAdd);
//        dappSystemService.tradeProfitDistribute(1L);
//    }
}
src/main/resources/templates/febs/views/modules/banner/coinPrice.html
@@ -132,10 +132,10 @@
                url: ctx + 'admin/banner/hdRecord',
                cols: [[
                    {field: 'id', title: '', minWidth: 10,align:'left',totalRowText:"合计"},
                    {field: 'coinAmount', title: '滑点累计币量', minWidth: 120,align:'center', totalRow:true},
                    {field: 'coinEvery', title: '新增滑点', minWidth: 120,align:'center', totalRow:true},
                    {field: 'transactionHash', title: '交易HASH', minWidth: 300,align:'left'},
                    {field: 'coinEvery', title: '滑点', minWidth: 120,align:'center', totalRow:true},
                    {field: 'price', title: '价格', minWidth: 120,align:'center', totalRow:true},
                    {field: 'usdtEvery', title: '新增USDT', minWidth: 120,align:'center', totalRow:true},
                    {field: 'usdtEvery', title: '滑点USDT', minWidth: 120,align:'center', totalRow:true},
                    {field: 'createTime', title: '时间', minWidth: 120,align:'center'},
                ]]
            });