package cc.mrbird.febs.dapp.service.impl; import cc.mrbird.febs.common.configure.i18n.MessageSourceUtils; import cc.mrbird.febs.common.contants.AppContants; import cc.mrbird.febs.common.entity.QueryRequest; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.common.utils.FebsUtil; import cc.mrbird.febs.common.utils.LoginUserUtil; 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.ContractChainService; import cc.mrbird.febs.dapp.dto.*; import cc.mrbird.febs.dapp.entity.*; import cc.mrbird.febs.dapp.mapper.*; import cc.mrbird.febs.dapp.service.DappSystemService; import cc.mrbird.febs.dapp.service.DappWalletService; import cc.mrbird.febs.dapp.utils.BoxUtil; import cc.mrbird.febs.dapp.vo.ActiveNftListVo; import cc.mrbird.febs.dapp.vo.WalletInfoVo; import cc.mrbird.febs.rabbit.producer.ChainProducer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; /** * @author * @date 2022-03-18 **/ @Slf4j @Service @RequiredArgsConstructor public class DappWalletServiceImpl implements DappWalletService { private final DappMemberDao dappMemberDao; private final DappWalletMineDao dappWalletMineDao; private final DappWalletCoinDao dappWalletCoinDao; private final DappFundFlowDao dappFundFlowDao; private final DappAccountMoneyChangeDao dappAccountMoneyChangeDao; private final RedisUtils redisUtils; private final DataDictionaryCustomMapper dataDictionaryCustomMapper; private final DappSystemService dappSystemService; private final DappNftActivationDao dappNftActivationDao; private final ChainProducer chainProducer; @Override public WalletInfoVo walletInfo() { DappMemberEntity member = LoginUserUtil.getAppUser(); DappMemberEntity memberInfo = dappMemberDao.selectById(member.getId()); WalletInfoVo walletInfo = new WalletInfoVo(); List direct = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 1); DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); walletInfo.setDirectCnt(direct.size()); walletInfo.setInviteId(member.getInviteId()); walletInfo.setBalance(walletCoin.getAvailableAmount()); walletInfo.setHasBuy(memberInfo.getActiveStatus()); walletInfo.setOutCnt(1); walletInfo.setProfit(BigDecimal.TEN); return walletInfo; } @Override @Transactional(rollbackFor = Exception.class) public void change(WalletOperateDto walletOperateDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); BigDecimal ethUsdtPrice = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_ETH_NEW_PRICE); DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId()); if (walletOperateDto.getAmount().compareTo(walletMine.getAvailableAmount()) > 0) { throw new FebsException("可用金额不足"); } DappFundFlowEntity fund = new DappFundFlowEntity(member.getId(), walletOperateDto.getAmount(), AppContants.MONEY_TYPE_CHANGE, null, null); dappFundFlowDao.insert(fund); BigDecimal preEthAmount = walletMine.getAvailableAmount(); // TODO 并发加悲观锁 // 更新eth金额 walletMine.setAvailableAmount(walletMine.getAvailableAmount().subtract(walletOperateDto.getAmount())); dappWalletMineDao.updateById(walletMine); DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); BigDecimal preUsdtAmount = walletCoin.getAvailableAmount(); // 更新usdt金额 BigDecimal usdt = walletOperateDto.getAmount().multiply(ethUsdtPrice); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().add(usdt)); walletCoin.setTotalAmount(walletCoin.getTotalAmount().add(usdt)); dappWalletCoinDao.updateById(walletCoin); DappAccountMoneyChangeEntity ethChange = new DappAccountMoneyChangeEntity(member.getId(), preEthAmount, walletOperateDto.getAmount(), walletMine.getAvailableAmount(), "ETH兑换USDT-ETH, 兑换价格为:" + ethUsdtPrice, AppContants.MONEY_TYPE_CHANGE); DappAccountMoneyChangeEntity usdtChange = new DappAccountMoneyChangeEntity(member.getId(), preUsdtAmount, usdt, walletCoin.getAvailableAmount(), "ETH兑换USDT-USDT, 兑换价格为:" + ethUsdtPrice, AppContants.MONEY_TYPE_CHANGE); dappAccountMoneyChangeDao.insert(ethChange); dappAccountMoneyChangeDao.insert(usdtChange); } @Override @Transactional(rollbackFor = Exception.class) public void withdraw(WalletOperateDto walletOperateDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); List fundFlows = dappFundFlowDao.selectListForMemberAndDay(member.getId(), 2); if (CollUtil.isNotEmpty(fundFlows)) { throw new FebsException("一天只能提现一次"); } DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); if (walletOperateDto.getAmount().compareTo(walletCoin.getAvailableAmount()) > 0) { throw new FebsException("可用金额不足"); } Integer fee = (Integer) redisUtils.get(AppContants.REDIS_KEY_CHANGE_FEE); //TODO 并发加悲观锁 BigDecimal preAmount = walletCoin.getAvailableAmount(); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().subtract(walletOperateDto.getAmount())); walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().add(walletOperateDto.getAmount())); dappWalletCoinDao.updateById(walletCoin); DappFundFlowEntity fund = new DappFundFlowEntity(member.getId(), walletOperateDto.getAmount(), AppContants.MONEY_TYPE_WITHDRAWAL, 1, new BigDecimal(fee)); dappFundFlowDao.insert(fund); DappAccountMoneyChangeEntity usdtChange = new DappAccountMoneyChangeEntity(member.getId(), preAmount, walletOperateDto.getAmount(), walletCoin.getAvailableAmount(), "USDT申请提现", AppContants.MONEY_TYPE_WITHDRAWAL); dappAccountMoneyChangeDao.insert(usdtChange); } @Override public List recordInPage(RecordInPageDto recordInPageDto) { Page page = new Page<>(recordInPageDto.getPageNum(), recordInPageDto.getPageSize()); DappMemberEntity member = LoginUserUtil.getAppUser(); DappFundFlowEntity dappFundFlowEntity = new DappFundFlowEntity(); if (recordInPageDto.getType() != null && recordInPageDto.getType() != 0) { dappFundFlowEntity.setType(recordInPageDto.getType()); } dappFundFlowEntity.setMemberId(member.getId()); dappFundFlowEntity.setStatus(2); IPage records = dappFundFlowDao.selectInPage(page, dappFundFlowEntity); return records.getRecords(); } @Override public IPage fundFlowInPage(DappFundFlowEntity dappFundFlowEntity, QueryRequest request) { Page page = new Page<>(request.getPageNum(), request.getPageSize()); return dappFundFlowDao.selectInPage(page, dappFundFlowEntity); } @Override @Transactional(rollbackFor = Exception.class) public void withdrawAgreeOrNot(Long id, int type) { DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(id); if (fundFlow == null) { throw new FebsException("数据不存在"); } DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(fundFlow.getMemberId()); if (type == 1) { walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().subtract(fundFlow.getAmount())); walletCoin.setTotalAmount(walletCoin.getTotalAmount().subtract(fundFlow.getAmount())); fundFlow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_AGREE); } else if (type == 2) { BigDecimal preAmount = walletCoin.getAvailableAmount(); walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().subtract(fundFlow.getAmount())); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().add(fundFlow.getAmount())); DappAccountMoneyChangeEntity accountMoneyChange = new DappAccountMoneyChangeEntity(walletCoin.getMemberId(), preAmount, fundFlow.getAmount(), walletCoin.getAvailableAmount(), "提现申请被驳回", 2); fundFlow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_DISAGREE); dappAccountMoneyChangeDao.insert(accountMoneyChange); } else { throw new FebsException("参数错误"); } dappWalletCoinDao.updateById(walletCoin); dappFundFlowDao.updateById(fundFlow); } @Override public IPage walletCoinInPage(DappWalletCoinEntity walletCoin, QueryRequest request) { Page page = new Page<>(request.getPageNum(), request.getPageSize()); return dappWalletCoinDao.selectInPage(walletCoin, page); } @Override public IPage walletMineInPage(DappWalletMineEntity walletMine, QueryRequest request) { Page page = new Page<>(request.getPageNum(), request.getPageSize()); return dappWalletMineDao.selectInPage(walletMine, page); } @Override public IPage accountMoneyChangeInPage(DappAccountMoneyChangeEntity change, QueryRequest request) { Page page = new Page<>(request.getPageNum(), request.getPageSize()); return dappAccountMoneyChangeDao.selectInPage(change, page); } @Override public Long transfer(TransferDto transferDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); member = dappMemberDao.selectById(member.getId()); if (member.getActiveStatus() == 1) { throw new FebsException("Do not repeat purchase"); } if (transferDto.getBuyType() == 1) { DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); if (transferDto.getAmount().compareTo(walletCoin.getAvailableAmount()) > 0) { throw new FebsException("Balance Not Enough"); } walletCoin.setTotalAmount(walletCoin.getTotalAmount().subtract(transferDto.getAmount())); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().subtract(transferDto.getAmount())); dappWalletCoinDao.updateById(walletCoin); DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount(), 1, 2, transferDto.getFee(), transferDto.getTxHash()); dappFundFlowDao.insert(fundFlow); chainProducer.sendAchieveTreeMsg(member.getId()); } else { if (transferDto.getId() == null) { DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount(), 1, 1, transferDto.getFee(), transferDto.getTxHash()); dappFundFlowDao.insert(fundFlow); return fundFlow.getId(); } if ("success".equals(transferDto.getFlag())) { DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId()); flow.setFromHash(transferDto.getTxHash()); dappFundFlowDao.updateById(flow); } else { DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId()); if (flow.getStatus() == 1) { dappFundFlowDao.deleteById(transferDto.getId()); } } } return null; } @Override public Map calPrice(PriceDto priceDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); if (!dappSystemService.systemHasStart()) { HashMap map = new HashMap<>(); map.put("x", new BigDecimal("0.05")); map.put("y", new BigDecimal("0.05")); return map; } ContractChainService tfcInstance = ChainService.getInstance(ChainEnum.BSC_TFC.name()); // u剩余数量 BigDecimal sourceU = ChainService.getInstance(ChainEnum.BSC_USDT.name()).balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress()); // 源池代币剩余数量 BigDecimal sourceCoin = tfcInstance.balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress()); // 用户卖出数量 BigDecimal coin = priceDto.getAmount(); BigDecimal x = sourceU.divide(sourceCoin, tfcInstance.decimals(), RoundingMode.HALF_UP); BigDecimal y = sourceU.divide(sourceCoin.add(coin), tfcInstance.decimals(), RoundingMode.HALF_UP); log.info("购买价格:{}, 出卖价格:{}", x, y); HashMap map = new HashMap<>(); map.put("x", x); map.put("y", y); return map; } @Override public ActiveNftListVo boxSurprise() { DappMemberEntity member = LoginUserUtil.getAppUser(); DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); if (walletCoin.getBoxCnt() < 1) { throw new FebsException(MessageSourceUtils.getString("box_surprise_001")); } walletCoin.setBoxCnt(walletCoin.getBoxCnt() - 1); dappWalletCoinDao.updateById(walletCoin); BoxUtil.Box box = BoxUtil.openBox(); // DappFundFlowEntity boxFundFlow = new DappFundFlowEntity(member.getId(), new BigDecimal(box.getIndex()), 6, 2, BigDecimal.ZERO); // dappFundFlowDao.insert(boxFundFlow); // // new Thread(() -> { // try { // int count = box.getIndex(); // while (count > 0) { // ChainService.getInstance(ChainEnum.BSC_NFT_SDC.name()).safeMintNFT(member.getAddress()); // Thread.sleep(5000); // count--; // } // } catch (Exception e) { // e.printStackTrace(); // log.error("发放卡牌错误", e); // } // }).start(); Date time = new Date(); Date expire = DateUtil.offset(time, DateField.HOUR, 2); DappNftActivation nftActivation = new DappNftActivation(); nftActivation.setMemberId(member.getId()); nftActivation.setCount(box.getIndex()); nftActivation.setOpenTime(time); nftActivation.setExpireTime(expire); nftActivation.setStatus(1); dappNftActivationDao.insert(nftActivation); ActiveNftListVo nft = new ActiveNftListVo(); nft.setCount(box.getIndex()); nft.setId(nftActivation.getId()); nft.setRemain(DateUtil.between(time, expire, DateUnit.SECOND)); return nft; } @Override @Transactional(rollbackFor = Exception.class) public synchronized void activeNft(ActiveDto activeDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); DappNftActivation nftActive = dappNftActivationDao.selectById(activeDto.getId()); if (nftActive == null) { throw new FebsException(MessageSourceUtils.getString("nft_active_003")); } if (nftActive.getCount() < activeDto.getCount()) { throw new FebsException(MessageSourceUtils.getString("nft_active_004")); } if (DateUtil.between(new Date(), nftActive.getExpireTime(), DateUnit.SECOND) < 0) { throw new FebsException(MessageSourceUtils.getString("nft_active_005")); } if (nftActive.getStatus() != 1) { throw new FebsException(MessageSourceUtils.getString("nft_active_001")); } PriceDto priceDto = new PriceDto(); priceDto.setAmount(BigDecimal.ZERO); Map price = calPrice(priceDto); DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), new BigDecimal(activeDto.getCount()), 8, 1, BigDecimal.ZERO, activeDto.getTxHash()); fundFlow.setTargetAmount(price.get("x").multiply(new BigDecimal(activeDto.getCount()))); fundFlow.setNewestPrice(AppContants.NFT_ACTIVE_PRICE.multiply(BigDecimal.valueOf(nftActive.getCount()))); dappFundFlowDao.insert(fundFlow); int count = nftActive.getCount() - activeDto.getCount(); if (count == 0) { nftActive.setStatus(3); } nftActive.setCount(count); nftActive.setHash(activeDto.getTxHash()); dappNftActivationDao.updateById(nftActive); } @Override public List findUnActiveNftList() { DappMemberEntity member = LoginUserUtil.getAppUser(); List list = new ArrayList<>(); UpdateWrapper query = new UpdateWrapper<>(); query.eq("status", 1); query.eq("member_id", member.getId()); query.ge("expire_time", new Date()); List nftActivations = dappNftActivationDao.selectList(query); if (CollUtil.isEmpty(nftActivations)) { return list; } Date now = new Date(); nftActivations.forEach(nft -> { ActiveNftListVo nftVo = new ActiveNftListVo(); nftVo.setId(nft.getId()); nftVo.setRemain(DateUtil.between(now, nft.getExpireTime(), DateUnit.SECOND, false)); nftVo.setCount(nft.getCount()); list.add(nftVo); }); return list; } @Override public void withdraw(WithdrawDto withdrawDto) { } }