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.enumerate.DataDictionaryEnum; import cc.mrbird.febs.dapp.mapper.*; 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 cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; 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 DappNftActivationDao dappNftActivationDao; private final MemberCoinWithdrawDao memberCoinWithdrawDao; private final ChainProducer chainProducer; private final DappSystemDao dappSystemDao; private final DappSystemProfitDao dappSystemProfitDao; @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, 1); DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId()); DappMineDataEntity mineData = dappSystemDao.selectMineDataForOne(); walletInfo.setDirectCnt(direct.size()); walletInfo.setInviteId(member.getActiveStatus() == 1 ? member.getInviteId() : "-"); walletInfo.setBalance(walletCoin.getAvailableAmount()); walletInfo.setHasBuy(memberInfo.getActiveStatus()); walletInfo.setOutCnt(memberInfo.getOutCnt()); walletInfo.setProfit(dappFundFlowDao.selectProfitAmountByMemberId(member.getId())); walletInfo.setTfcBalance(walletMine.getAvailableAmount()); walletInfo.setSafePool(mineData.getSafePool()); walletInfo.setAccountType(memberInfo.getAccountType()); DappSystemProfit dappSystemProfit = dappSystemProfitDao.selectByMemberIdAndState(memberInfo.getId(),DappSystemProfit.STATE_IN); walletInfo.setSystemProfitId(ObjectUtil.isEmpty(dappSystemProfit) ? 0L : dappSystemProfit.getId()); BigDecimal directProfit = dappFundFlowDao.selectSumAmountByMemberIdAndTypeAndStatus(memberInfo.getId(),3,2); walletInfo.setDirectProfit(directProfit); BigDecimal levelProfit = dappFundFlowDao.selectSumAmountByMemberIdAndTypeAndStatus(memberInfo.getId(),4,2); walletInfo.setLevelProfit(levelProfit); BigDecimal luckyProfit = dappFundFlowDao.selectSumAmountByMemberIdAndTypeAndStatus(memberInfo.getId(),7,2); walletInfo.setLuckyProfit(luckyProfit); // //获取当前是第几轮队列 // String redisKey = "QUEUE_COUNT"; // String memberOutCount = redisUtils.getString(redisKey); // DataDictionaryCustom queueCountSet = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.QUEUE_COUNT.getType(), DataDictionaryEnum.QUEUE_COUNT.getCode()); // String queueCount = queueCountSet.getValue(); // if(StrUtil.isBlank(memberOutCount)){ // redisUtils.set(redisKey,queueCount,0L); // memberOutCount = queueCount; // } // //出局条件的人数 // /** // * 初始大小 5+4*0 // * 1 1,2,3,4,5 1出局 5+4*0 // * 2 2,3,4,5,1(复投),7,8,9,10 2出局 5+4*1 // * 3 3,4,5,1(复投),7,8,9,10,2(复投),12,13,14,15 3出局 5+4*2 // * 4 4,5,1(复投),7,8,9,10,2(复投),12,13,14,15,3(复投),17,18,19,20 4出局 5+4*3 // */ // Integer memberCount = Integer.parseInt(memberOutCount) * 4 + 5; // //判断当前是否符合出局条件 // QueryWrapper objectQueryWrapper = new QueryWrapper<>(); // objectQueryWrapper.eq("state",DappSystemProfit.STATE_IN); // //实际投资人数 // Integer selectCount = dappSystemProfitDao.selectCount(objectQueryWrapper); // BigDecimal memberRunPercent = BigDecimal.ZERO; // List dappSystemProfits = dappSystemProfitDao.selectDappSysstemProfitByState(DappSystemProfit.STATE_IN); // if(CollUtil.isEmpty(dappSystemProfits)){ // walletInfo.setRunPercent(memberRunPercent); // } // // for(int i=0;i 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 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); } /** * // 第一次{amount: val, fee: 0, txHash: '', type: 1, buyType: 2} *       // 成功{type: 1, txHash: result.transactionHash, id: res.data, flag: 'success', buyType: 2} *       // 失败{type: 1, id: res.data, flag: 'fail', buyType: 2} */ @Override public Long transfer(TransferDto transferDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); // DappMemberEntity member = dappMemberDao.selectById(transferDto.getMemberId()); String upgrade = redisUtils.getString("APP_UPGRADE"); if ("upgrade".equals(upgrade)) { throw new FebsException("功能升级中"); } if (transferDto.getType() != 2) { 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"); } updateWalletCoinWithLock(transferDto.getAmount(), member.getId(), 2); DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount().negate(), 1, 2, transferDto.getFee(), transferDto.getTxHash()); dappFundFlowDao.insert(fundFlow); chainProducer.sendAchieveTreeMsg(member.getId()); } else { int type = 1; // 1-认购 2-充值tfc if (transferDto.getType() == 2) { type = 6; } if (transferDto.getId() == null) { DappFundFlowEntity fundFlowOld = dappFundFlowDao.selectBymemberIdAndType(member.getId(),type); if(ObjectUtil.isNotEmpty(fundFlowOld)){ //网络问题导致第二次提交前,未成功就关闭了页面 if (fundFlowOld.getStatus() == 1 && StrUtil.isEmpty(fundFlowOld.getFromHash())) { dappFundFlowDao.deleteById(transferDto.getId()); } throw new FebsException("Refresh and try again"); } DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), transferDto.getAmount(), type, 1, transferDto.getFee(), transferDto.getTxHash()); dappFundFlowDao.insert(fundFlow); return fundFlow.getId(); } if ("success".equals(transferDto.getFlag())) { DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId()); if(DappFundFlowEntity.WITHDRAW_STATUS_AGREE == flow.getStatus()){ throw new FebsException("Do not repeat purchase"); } //是否已经加入动能 DappSystemProfit dappSystemProfitIng = dappSystemProfitDao.selectByMemberIdAndState(member.getId(), DappSystemProfit.STATE_IN); if(ObjectUtil.isNotEmpty(dappSystemProfitIng)){ throw new FebsException("Do not repeat purchase"); } //插入一条会员入列记录,即加入动能队列 DappSystemProfit dappSystemProfit = new DappSystemProfit(member.getId(), flow.getAmount()); dappSystemProfitDao.insert(dappSystemProfit); flow.setFromHash(transferDto.getTxHash()); flow.setSystemProfitId(dappSystemProfit.getId()); flow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_AGREE); dappFundFlowDao.updateById(flow); //升级成为Agent dappMemberDao.updateMemberAccountType(DataDictionaryEnum.AGENT.getCode(),member.getId()); dappMemberDao.updateMemberActiveStatus(1,member.getId()); //直接拿走0.05个BNB放入技术方 DataDictionaryCustom systemProfit = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.SYSTEM_PROFIT.getType(), DataDictionaryEnum.SYSTEM_PROFIT.getCode()); String systemProfitStr = StrUtil.isEmpty(systemProfit.getValue()) ? "0.05" : systemProfit.getValue(); DappFundFlowEntity systemProfitFlow = new DappFundFlowEntity(1L, new BigDecimal(systemProfitStr), 2, 1, BigDecimal.ZERO, null,dappSystemProfit.getId()); dappFundFlowDao.insert(systemProfitFlow); //发送转币消息 // chainProducer.sendBnbTransferMsg(systemProfitFlow.getId()); //直接返利30%给直接上级 DappMemberEntity dappMemberEntity = dappMemberDao.selectById(member.getId()); String refererId = dappMemberEntity.getRefererId(); DappMemberEntity refererMember = dappMemberDao.selectMemberInfoByInviteId(refererId); DataDictionaryCustom directProfitSet = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.DIRECT_PROFIT.getType(), DataDictionaryEnum.DIRECT_PROFIT.getCode()); BigDecimal directProfitStr = new BigDecimal(StrUtil.isEmpty(directProfitSet.getValue()) ? "0.3" : directProfitSet.getValue()); BigDecimal subtract = transferDto.getAmount().subtract(new BigDecimal(systemProfitStr)); BigDecimal directProfit = subtract.multiply(directProfitStr).setScale(6,BigDecimal.ROUND_DOWN); DappFundFlowEntity fundFlow = new DappFundFlowEntity(refererMember.getId(), directProfit, 3, 1, BigDecimal.ZERO, null,dappSystemProfit.getId()); dappFundFlowDao.insert(fundFlow); //发送转币消息 chainProducer.sendBnbTransferMsg(fundFlow.getId()); //层级奖励30% chainProducer.sendLevelProfitMsg(dappSystemProfit.getId()); //发送一个消息,计算当前是否有人可以出局 chainProducer.sendMemberOutMsg(dappSystemProfit.getId()); } else { DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId()); if (flow.getStatus() == 1) { dappFundFlowDao.deleteById(transferDto.getId()); } } } return null; } @Override public BigDecimal calPrice(PriceDto priceDto) { // String priceStr = redisUtils.getString(AppContants.REDIS_KEY_TFC_NEW_PRICE); DataDictionaryCustom symbolPrice = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.SYMBOL_PRICE.getType(), DataDictionaryEnum.SYMBOL_PRICE.getCode()); DataDictionaryCustom serviceFeeDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.WITHDRAW_SERVICE_FEE.getType(), DataDictionaryEnum.WITHDRAW_SERVICE_FEE.getCode()); BigDecimal amount = priceDto.getAmount(); if (priceDto.getAmount() == null) { amount = BigDecimal.ZERO; } return amount.multiply(new BigDecimal(serviceFeeDic.getValue()).divide(BigDecimal.valueOf(100), 8, RoundingMode.HALF_DOWN)).divide(new BigDecimal(symbolPrice.getValue()), 2, RoundingMode.HALF_UP); } @Override @Transactional(rollbackFor = Exception.class) public void withdraw(WithdrawDto withdrawDto) { DappMemberEntity member = LoginUserUtil.getAppUser(); DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); if (walletCoin.getAvailableAmount().compareTo(withdrawDto.getAmount()) < 0) { throw new FebsException("Balance Not Enough"); } DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId()); if (walletMine.getAvailableAmount().compareTo(withdrawDto.getFee()) < 0) { throw new FebsException("DMD Not Enough"); } updateWalletCoinWithLock(withdrawDto.getAmount(), member.getId(), 2); updateWalletMineWithLock(withdrawDto.getFee(), member.getId(), 2); DappFundFlowEntity feeFlow = new DappFundFlowEntity(member.getId(), withdrawDto.getFee().negate(), 7, 2, null, null); dappFundFlowDao.insert(feeFlow); DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), withdrawDto.getAmount().negate(), 5, 2, withdrawDto.getFee(), null); dappFundFlowDao.insert(fundFlow); MemberCoinWithdrawEntity memberCoinWithdraw = new MemberCoinWithdrawEntity(); memberCoinWithdraw.setMemberId(member.getId()); memberCoinWithdraw.setAddress(member.getAddress()); memberCoinWithdraw.setAmount(withdrawDto.getAmount()); memberCoinWithdraw.setFeeAmount(withdrawDto.getFee()); memberCoinWithdraw.setStatus(MemberCoinWithdrawEntity.STATUS_YES); memberCoinWithdraw.setSymbol("USDT"); memberCoinWithdraw.setFlowId(fundFlow.getId()); memberCoinWithdrawDao.insert(memberCoinWithdraw); String hash = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(member.getAddress(), withdrawDto.getAmount()); fundFlow.setToHash(hash); dappFundFlowDao.updateById(fundFlow); chainProducer.sendFeeDistributeMsg(fundFlow.getId()); // Map map = new HashMap<>(); // map.put("fee", withdrawDto.getFee()); // map.put("address", ChainEnum.BSC_TFC_FEE.getAddress()); // map.put("flow", feeFlow.getId()); // chainProducer.sendTfcFee(JSONObject.toJSONString(map)); } @Override public void updateWalletCoinWithLock(BigDecimal amount, Long memberId, int type) { boolean isSuccess = false; while(!isSuccess) { DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(memberId); // 加 if (type == 1) { walletCoin.setTotalAmount(walletCoin.getTotalAmount().add(amount)); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().add(amount)); // 减 } else { if (amount.compareTo(walletCoin.getAvailableAmount()) > 0) { throw new FebsException("Balance Not Enough"); } walletCoin.setTotalAmount(walletCoin.getTotalAmount().subtract(amount)); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().subtract(amount)); } int i = dappWalletCoinDao.updateWithLock(walletCoin); if (i > 0) { isSuccess = true; } } } @Override public void updateWalletMineWithLock(BigDecimal amount, Long memberId, int type) { boolean isSuccess = false; while(!isSuccess) { DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(memberId); if (type == 1) { walletMine.setTotalAmount(walletMine.getTotalAmount().add(amount)); walletMine.setAvailableAmount(walletMine.getAvailableAmount().add(amount)); } else { if (amount.compareTo(walletMine.getAvailableAmount()) > 0) { throw new FebsException("DMD Not Enough"); } walletMine.setTotalAmount(walletMine.getTotalAmount().subtract(amount)); walletMine.setAvailableAmount(walletMine.getAvailableAmount().subtract(amount)); } int i = dappWalletMineDao.updateWithLock(walletMine); if (i > 0) { isSuccess = true; } } } @Override public void addFrozenAmountWithLock(BigDecimal amount, Long memberId) { boolean isSuccess = false; while(!isSuccess) { DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(memberId); walletCoin.setTotalAmount(walletCoin.getTotalAmount().add(amount)); walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().add(amount)); int i = dappWalletCoinDao.updateWithLock(walletCoin); if (i > 0) { isSuccess = true; DappFundFlowEntity frozenAmount = new DappFundFlowEntity(memberId, amount, 9, 2, null, null); dappFundFlowDao.insert(frozenAmount); } } } @Override public void releaseFrozenAmountWithLock(Long memberId) { boolean isSuccess = false; while(!isSuccess) { DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(memberId); if (walletCoin.getFrozenAmount().compareTo(BigDecimal.ZERO) <= 0) { return; } BigDecimal frozen = walletCoin.getFrozenAmount(); walletCoin.setAvailableAmount(walletCoin.getAvailableAmount().add(frozen)); walletCoin.setFrozenAmount(walletCoin.getFrozenAmount().subtract(frozen)); int i = dappWalletCoinDao.updateWithLock(walletCoin); if (i > 0) { isSuccess = true; DappFundFlowEntity releaseFrozen = new DappFundFlowEntity(memberId, frozen, 10, 2, null, null); dappFundFlowDao.insert(releaseFrozen); DappFundFlowEntity releaseFrozenNegate = new DappFundFlowEntity(memberId, frozen.negate(), 9, 2, null, null); dappFundFlowDao.insert(releaseFrozenNegate); } } } @Override public DappWalletCoinEntity findByMemberId(Long memberId) { return dappWalletCoinDao.selectByMemberId(memberId); } @Override public void transferAgain(TransferDto transferDto) { Long memberId = transferDto.getMemberId(); DappMemberEntity member = dappMemberDao.selectById(memberId); String upgrade = redisUtils.getString("APP_UPGRADE"); if ("upgrade".equals(upgrade)) { throw new FebsException("功能升级中"); } if ("success".equals(transferDto.getFlag())) { //是否已经加入动能 DappSystemProfit dappSystemProfitIng = dappSystemProfitDao.selectByMemberIdAndState(member.getId(), DappSystemProfit.STATE_IN); if(ObjectUtil.isNotEmpty(dappSystemProfitIng)){ return; } //插入一条会员入列记录,即加入动能队列 DappSystemProfit dappSystemProfit = new DappSystemProfit(member.getId(), transferDto.getAmount()); dappSystemProfitDao.insert(dappSystemProfit); DappFundFlowEntity flow = dappFundFlowDao.selectById(transferDto.getId()); flow.setFromHash(transferDto.getTxHash()); flow.setSystemProfitId(dappSystemProfit.getId()); flow.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_AGREE); dappFundFlowDao.updateById(flow); //直接拿走0.05个BNB放入技术方 DataDictionaryCustom systemProfit = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.SYSTEM_PROFIT.getType(), DataDictionaryEnum.SYSTEM_PROFIT.getCode()); String systemProfitStr = StrUtil.isEmpty(systemProfit.getValue()) ? "0.05" : systemProfit.getValue(); DappFundFlowEntity systemProfitFlow = new DappFundFlowEntity(1L, new BigDecimal(systemProfitStr), 2, 1, BigDecimal.ZERO, null,dappSystemProfit.getId()); dappFundFlowDao.insert(systemProfitFlow); //发送转币消息 chainProducer.sendBnbTransferMsg(systemProfitFlow.getId()); //直接返利30%给直接上级 DappMemberEntity dappMemberEntity = dappMemberDao.selectById(member.getId()); String refererId = dappMemberEntity.getRefererId(); DappMemberEntity refererMember = dappMemberDao.selectMemberInfoByInviteId(refererId); DataDictionaryCustom directProfitSet = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.DIRECT_PROFIT.getType(), DataDictionaryEnum.DIRECT_PROFIT.getCode()); BigDecimal directProfitStr = new BigDecimal(StrUtil.isEmpty(directProfitSet.getValue()) ? "0.3" : directProfitSet.getValue()); BigDecimal directProfit = (transferDto.getAmount().subtract(new BigDecimal(systemProfitStr))).multiply(directProfitStr).setScale(6,BigDecimal.ROUND_DOWN); DappFundFlowEntity fundFlow = new DappFundFlowEntity(refererMember.getId(), directProfit, 3, 1, BigDecimal.ZERO, null,dappSystemProfit.getId()); dappFundFlowDao.insert(fundFlow); //发送转币消息 chainProducer.sendBnbTransferMsg(fundFlow.getId()); //层级奖励30% chainProducer.sendLevelProfitMsg(dappSystemProfit.getId()); //发送一个消息,计算当前是否有人可以出局 chainProducer.sendMemberOutMsg(dappSystemProfit.getId()); } } }