Helius
2020-07-03 7a447492f1bf8ac6849166f9345f176ebad02c4b
modify
1 files added
1 files deleted
3 files modified
215 ■■■■■ changed files
src/main/java/com/xcong/excoin/modules/blackchain/UsdtEthService.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtEthService.java 160 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinChargeDao.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java 29 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/member/MemberCoinChargeDao.xml 11 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/blackchain/UsdtEthService.java
File was deleted
src/main/java/com/xcong/excoin/modules/blackchain/service/UsdtEthService.java
New file
@@ -0,0 +1,160 @@
package com.xcong.excoin.modules.blackchain.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.xcong.excoin.common.enumerates.CoinTypeEnum;
import com.xcong.excoin.modules.member.dao.MemberCoinAddressDao;
import com.xcong.excoin.modules.member.dao.MemberCoinChargeDao;
import com.xcong.excoin.modules.member.dao.MemberDao;
import com.xcong.excoin.modules.member.dao.MemberWalletCoinDao;
import com.xcong.excoin.modules.member.entity.MemberCoinAddressEntity;
import com.xcong.excoin.modules.member.entity.MemberCoinChargeEntity;
import com.xcong.excoin.modules.member.entity.MemberWalletCoinEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.ExecutionException;
/**
 * @author wzy
 * @date 2020-07-03
 **/
@Slf4j
@Component
public class UsdtEthService {
    private static final BigDecimal LIMIT = new BigDecimal("50");
    private static final BigDecimal LIMIT_ETH = new BigDecimal("0.2");
    private static final BigDecimal FEE = new BigDecimal("0.0032");
    private static final BigDecimal ETH_TR_FEE = new BigDecimal("0.0032");
    public static String ETH_FEE = "0.0032";
    public static final String TOTAL_ADDRESS = "0x067b4bE5d7B05560AE539Fc8f10597D854ae056D";
    public static final String TOTAL_PRIVATE = "1fb7288c8c88c37d6f79e9617822bffc8d3635bf2d808c5f6afdee9bb326e49c";
    @Resource
    private MemberCoinChargeDao memberCoinChargeDao;
    @Resource
    private MemberCoinAddressDao memberCoinAddressDao;
    @Resource
    private MemberWalletCoinDao memberWalletCoinDao;
    public void pool() throws ExecutionException, InterruptedException {
        List<MemberCoinChargeEntity> list = memberCoinChargeDao.selectAllBySymbolAndTag(CoinTypeEnum.USDT.name(), "ERC20", 1);
        if (CollUtil.isNotEmpty(list)) {
            EthService ethService = new EthService();
            for (MemberCoinChargeEntity coinCharge : list) {
                // 首先根据每个地址查询其是否有ETH 如果没有就充值ETH并设置1 表示初始状态 status=2(待充值)3:表示已提过
                String address = coinCharge.getAddress();
                Long memberId = coinCharge.getMemberId();
                BigDecimal lastAmount = coinCharge.getLastAmount();
                if (lastAmount == null || lastAmount.compareTo(LIMIT) < 0) {
                    continue;
                }
                BigDecimal usdt = ethService.tokenGetBalance(address);
                log.info("地址:{}, 金额:{}", address, usdt);
                if (usdt != null && usdt.compareTo(LIMIT) > 0) {
                    usdt = usdt.subtract(new BigDecimal("0.01"));
                    // 查询eth是否足够
                    BigDecimal eth = EthService.getEthBlance(address);
                    log.info("地址:{}, ETH:{}", address, eth);
                    if (eth != null && eth.compareTo(FEE) >= 0) {
                        MemberCoinAddressEntity memberCoinAddressEntity = memberCoinAddressDao.selectBlockAddressWithTag(memberId, CoinTypeEnum.USDT.name(), "ERC20");
                        if (memberCoinAddressEntity == null) {
                            continue;
                        }
                        String privateKey = memberCoinAddressEntity.getPrivateKey();
                        usdt = usdt.multiply(new BigDecimal("1000000"));
                        String usdtStr = usdt.toPlainString();
                        if (usdtStr.contains(".")) {
                            usdtStr = usdtStr.substring(0, usdtStr.lastIndexOf("."));
                        }
                        String hash = ethService.tokenSend(privateKey, address, TOTAL_ADDRESS, usdtStr);
                        log.info("归集:{}", hash);
                        if (StrUtil.isNotBlank(hash)) {
                            // 归集成功更新状态 先保存本次的hash值,待交易成功后再更新
                            coinCharge.setHash(hash);
                            memberCoinChargeDao.updateById(coinCharge);
                        }
                    } else {
                        String hash = ethService.ethSend(TOTAL_PRIVATE, TOTAL_ADDRESS, address, ETH_FEE);
                        log.info("转手续费:{}", hash);
                    }
                }
            }
        }
    }
    public void ethPool() throws ExecutionException, InterruptedException {
        List<MemberCoinChargeEntity> list = memberCoinChargeDao.selectAllBySymbolAndTag(CoinTypeEnum.ETH.name(), null, 1);
        if (CollUtil.isNotEmpty(list)) {
            EthService ethService = new EthService();
            for (MemberCoinChargeEntity coinCharge : list) {
                String address = coinCharge.getAddress();
                Long memberId = coinCharge.getMemberId();
                MemberWalletCoinEntity walletCoin = memberWalletCoinDao.selectWalletCoinBymIdAndCode(memberId, CoinTypeEnum.ETH.name());
                if (walletCoin == null) {
                    continue;
                }
                BigDecimal earlyBalance = walletCoin.getEarlyBalance();
                if (earlyBalance == null || earlyBalance.compareTo(LIMIT_ETH) < 0) {
                    continue;
                }
                BigDecimal eth = EthService.getEthBlance(address);
                if (eth != null && eth.compareTo(LIMIT_ETH) >= 0) {
                    MemberCoinAddressEntity coinAddress = memberCoinAddressDao.selectBlockAddressWithTag(memberId, CoinTypeEnum.ETH.name(), null);
                    String privateKey = coinAddress.getPrivateKey();
                    BigDecimal tr = eth.subtract(ETH_TR_FEE);
                    String hash = ethService.ethSend(privateKey, address, TOTAL_ADDRESS, tr.toPlainString());
                    if (StrUtil.isNotBlank(hash)) {
                        coinCharge.setHash(hash);
                        coinCharge.setLastAmount(new BigDecimal("0.0001"));
                        coinCharge.setStatus(3);
                        memberCoinChargeDao.updateById(coinCharge);
                    }
                }
            }
        }
    }
    /**
     * 定时查询该归集转账交易是否成功
     */
    public void usdtEthPoolCheck() {
        // 首先查询需要确认的交易
        List<MemberCoinChargeEntity> list = memberCoinChargeDao.selectAllBySymbolAndTag(CoinTypeEnum.USDT.name(), "ERC20", null);
        EthService ethService = new EthService();
        if (CollectionUtils.isNotEmpty(list)) {
            for (MemberCoinChargeEntity appeal : list) {
                String hash = appeal.getHash();
                boolean b = ethService.checkTransferResult(hash);
                if (b) {
                    appeal.setStatus(3);
                    appeal.setLastAmount(new BigDecimal("0.0001"));
                    // 表示这笔归集转账已经成功
                    // 更新状态
                    memberCoinChargeDao.updateById(appeal);
                }
            }
        }
    }
}
src/main/java/com/xcong/excoin/modules/member/dao/MemberCoinChargeDao.java
@@ -4,8 +4,12 @@
import com.xcong.excoin.modules.member.entity.MemberCoinChargeEntity;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MemberCoinChargeDao extends BaseMapper<MemberCoinChargeEntity> {
    public MemberCoinChargeEntity selectNewestChargeRecord(@Param("memberId") Long memberId, @Param("symbol") String symbol, @Param("tag") String tag);
    List<MemberCoinChargeEntity> selectAllBySymbolAndTag(@Param("symbol") String symbol, @Param("tag") String tag, @Param("status") Integer status);
}
src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java
@@ -1,8 +1,13 @@
package com.xcong.excoin.quartz.job;
import com.xcong.excoin.modules.blackchain.service.UsdtEthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;
/**
 * 归集定时任务
@@ -11,22 +16,40 @@
 * @date 2020-07-02
 **/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "app", name = "block-job", havingValue = "true")
public class NotionalPoolingJob {
    @Resource
    private UsdtEthService usdtEthService;
    /**
     * 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 * * * ? ")
    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);
        }
    }
}
src/main/resources/mapper/member/MemberCoinChargeDao.xml
@@ -12,4 +12,15 @@
        order by create_time desc limit 1
    </select>
    <select id="selectAllBySymbolAndTag" resultType="com.xcong.excoin.modules.member.entity.MemberCoinChargeEntity">
        select * from member_coin_charge
        where symbol=#{symbol}
        <if test="tag !=null and tag != ''">
            and tag = #{tag}
        </if>
        <if test="status !=null and status != ''">
            and status = #{status}
        </if>
    </select>
</mapper>