| | |
| | | public static final String DIC_VALUE_SYSTEM_SOURCE_POOL_VOL = "SYSTEM_SOURCE_POOL_VOL";
|
| | | public static final String DIC_VALUE_SYSTEM_NODE_CNT_LIMIT = "SYSTEM_NODE_CNT_LIMIT";
|
| | |
|
| | | public static final String DESTROY_ADDRESS = "0x0000000000000000000000000000000000000000";
|
| | | public static final String DESTROY_ADDRESS = "0x0000000000000000000000000000000000000001";
|
| | |
|
| | | public static final String SYMBOL_USDT = "USDT";
|
| | | public static final String SYMBOL_COIN = "TFC";
|
| | |
| | | */ |
| | | BSC_USDT("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25", |
| | | "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x55d398326f99059fF775485246999027B3197955", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd", |
| | | ""), |
| | | |
| | | /** |
| | |
| | | */ |
| | | BSC_TFC("BSC", "0x977a9ddfb965a9a3416fa72ca7f91c4949c18f25", |
| | | "0xefe98e00cd227b6322e892c82fcbd8eadf119c3188b7e574bc624f65405d61bf", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0xdd92ea2f41d807a60b29004bf7db807d8ac09212", |
| | | ""), |
| | | |
| | | /** |
| | |
| | | */ |
| | | BSC_TFC_SOURCE("BSC", "0x4EbDCA102623b46a47042D580dddAdE2a53D057F", |
| | | "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0xdd92ea2f41d807a60b29004bf7db807d8ac09212", |
| | | ""), |
| | | |
| | | /** |
| | |
| | | */ |
| | | BSC_USDT_SOURCE("BSC", "0x4EbDCA102623b46a47042D580dddAdE2a53D057F", |
| | | "0x81c2c02d0c106c1e32ab060a37f6eb279c0649c30ea5cc1c4951e6a8dd4e963c", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x55d398326f99059fF775485246999027B3197955", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd", |
| | | ""), |
| | | |
| | | /** |
| | |
| | | */ |
| | | BSC_TFC_MAKE("BSC", "0xBae24dAa3aB94cfF8114a16A4267D769b3a651F8", |
| | | "0xc0cabaf5f1fce227e5f1b8a7f83a5dc28972389ffc59559d7852ce8d27c3bec4", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0xdd92ea2f41d807a60b29004bf7db807d8ac09212", |
| | | ""), |
| | | |
| | | /** |
| | |
| | | */ |
| | | BSC_TFC_TECH("BSC", "0xD998DA7362360eFC6daDFEd6E9a32E70640d7600", |
| | | "", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0xdd92ea2f41d807a60b29004bf7db807d8ac09212", |
| | | ""), |
| | | |
| | | /** |
| | |
| | | */ |
| | | BSC_TFC_REWARD("BSC", "0xBae24dAa3aB94cfF8114a16A4267D769b3a651F8", |
| | | "0xc0cabaf5f1fce227e5f1b8a7f83a5dc28972389ffc59559d7852ce8d27c3bec4", |
| | | "https://bsc-dataseed1.ninicoin.io", |
| | | "0x6c6835e60e7dBaD7a60112a6371271e8eb79ee68", |
| | | "https://data-seed-prebsc-2-s2.binance.org:8545", |
| | | "0xdd92ea2f41d807a60b29004bf7db807d8ac09212", |
| | | ""); |
| | | |
| | | private String chain; |
| | |
| | | @TableName("dapp_transfer_record") |
| | | public class DappTransferRecordEntity extends BaseEntity { |
| | | |
| | | private String address; |
| | | public static final String TRANSFER_SOURCE_FLAG_ONLINE = "online"; |
| | | public static final String TRANSFER_SOURCE_FLAG_APPLICATION = "application"; |
| | | |
| | | private String fromAddress; |
| | | |
| | | private String toAddress; |
| | | |
| | | private BigDecimal amount; |
| | | |
| | | private String hash; |
| | | |
| | | /** |
| | | * ETH/TRX/BSC |
| | | */ |
| | | private String chainType; |
| | | |
| | | /** |
| | | * online/Application |
| | | */ |
| | | private String sourceFlag; |
| | | |
| | | private String symbol; |
| | | } |
| | |
| | | DappFundFlowEntity selectMineFundFlowByMemberIdAndTime(@Param("time") Long memberId, @Param("time") Date time); |
| | | |
| | | DappFundFlowEntity selectByFromHash(@Param("txHash") String txHash, @Param("status") Integer status); |
| | | |
| | | List<DappFundFlowEntity> selectFundFlowListByAddress(@Param("address") String address, @Param("status") Integer status); |
| | | } |
| | |
| | | |
| | | IPage<DappTransferRecordEntity> selectInPage(@Param("record") DappTransferRecordEntity record, Page<DappTransferRecordEntity> page); |
| | | |
| | | DappTransferRecordEntity selectByHash(@Param("hash") String hash); |
| | | } |
| | |
| | | import cc.mrbird.febs.dapp.entity.DappFundFlowEntity; |
| | | import cc.mrbird.febs.dapp.entity.DappMemberEntity; |
| | | import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity; |
| | | 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.service.DappSystemService; |
| | | 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; |
| | |
| | | import java.math.BigInteger; |
| | | import java.math.RoundingMode; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Slf4j |
| | | @Service |
| | | public class BscCoinContractEvent implements ContractEventService { |
| | | |
| | |
| | | @Override |
| | | public void compile(EthUsdtContract.TransferEventResponse e) { |
| | | if (e.to != null) { |
| | | log.info("触发TFC监听"); |
| | | |
| | | try { |
| | | Thread.sleep(5000); |
| | | } catch (InterruptedException ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | | redisUtils.set(AppContants.REDIS_KEY_BLOCK_COIN_NUM, e.log.getBlockNumber()); |
| | | redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber()); |
| | | int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals(); |
| | | |
| | | // 合约创建时,同时创建地址 |
| | |
| | | // return; |
| | | // } |
| | | |
| | | BigInteger tokens = e.tokens; |
| | | BigDecimal amount = BigDecimal.valueOf(tokens.intValue()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN); |
| | | |
| | | // 如果转账对象地址不为源池地址,且对象地址在系统中存在并未激活,则激活用户 |
| | | if (!e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress())) { |
| | | if (!e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase())) { |
| | | DappMemberEntity toMember = dappMemberDao.selectByAddress(e.to, null); |
| | | if (toMember == null) { |
| | | // toMember = dappMemberService.insertMember(e.to, fromMember.getInviteId()); |
| | |
| | | toMember.setActiveStatus(1); |
| | | dappMemberService.updateById(toMember); |
| | | } |
| | | |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, AppContants.SYMBOL_COIN); |
| | | } |
| | | |
| | | // 卖币 |
| | | if (e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress())) { |
| | | BigInteger tokens = e.tokens; |
| | | BigDecimal amount = BigDecimal.valueOf(tokens.intValue()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN); |
| | | DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), 1); |
| | | if (e.to.equals(ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase())) { |
| | | DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), null); |
| | | if (fundFlow != null && fundFlow.getStatus() != 1) { |
| | | return; |
| | | } |
| | | |
| | | if (fundFlow == null) { |
| | | List<DappFundFlowEntity> flows = dappFundFlowDao.selectFundFlowListByAddress(e.from, 1); |
| | | if (CollUtil.isEmpty(flows)) { |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, AppContants.SYMBOL_COIN); |
| | | log.info("本地无交易:{}", e.log.getTransactionHash()); |
| | | return; |
| | | } |
| | | |
| | | boolean hasFlow = false; |
| | | for (DappFundFlowEntity flow : flows) { |
| | | if (flow.getStatus() == 1) { |
| | | if (amount.compareTo(flow.getTargetAmount()) == 0) { |
| | | hasFlow = true; |
| | | fundFlow = flow; |
| | | fundFlow.setFromHash(e.log.getTransactionHash()); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!hasFlow) { |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, AppContants.SYMBOL_COIN); |
| | | return; |
| | | } |
| | | } |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_APPLICATION, AppContants.SYMBOL_COIN); |
| | | |
| | | BigDecimal newPrice = fundFlow.getNewestPrice(); |
| | | BigDecimal transferAmount = amount.multiply(newPrice); |
| | |
| | | dappFundFlowDao.updateById(fundFlow); |
| | | |
| | | // 划点分配 |
| | | dappSystemService.tradeProfitDistribute(fundFlow.getId()); |
| | | chainProducer.sendDitribProfit(fundFlow.getId()); |
| | | |
| | | OnlineTransferUtil.addTransfer(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundFlow.getId().toString()); |
| | | OnlineTransferUtil.addTransfer(e.from, transferAmount, fundFlow.getType(), 1, ChainEnum.BSC_USDT_SOURCE.name(), AppContants.SYMBOL_USDT, fundFlow.getId().toString()); |
| | | |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("batchNo", fundFlow.getId().toString()); |
| | |
| | | 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.DappFundFlowEntity; |
| | | import cc.mrbird.febs.dapp.entity.DappMemberEntity; |
| | | import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity; |
| | | import cc.mrbird.febs.dapp.entity.DataDictionaryCustom; |
| | | 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.DappOnlineTransferDao; |
| | |
| | | import cc.mrbird.febs.dapp.service.DappMemberService; |
| | | 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 java.math.BigInteger; |
| | | import java.math.RoundingMode; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Slf4j |
| | |
| | | // 判断对方打款地址是否为源池地址 |
| | | if (ChainEnum.BSC_TFC_SOURCE.getAddress().toLowerCase().equals(e.to)) { |
| | | log.info("触发USDT合约监听事件"); |
| | | redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber()); |
| | | |
| | | // 如果得到触发,则休眠10秒。 因为此处监听器触发可能优先于前端调用transfer接口 |
| | | try { |
| | | Thread.sleep(10000); |
| | | Thread.sleep(5000); |
| | | } catch (InterruptedException ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | |
| | | |
| | | BigInteger tokens = e.tokens; |
| | | BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN); |
| | | DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), 1); |
| | | |
| | | if (fundFlow == null) { |
| | | log.info("本地无交易:{}", e.log.getTransactionHash()); |
| | | DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), null); |
| | | if (fundFlow != null && fundFlow.getStatus() != 1) { |
| | | return; |
| | | } |
| | | |
| | | BigDecimal newPrice = fundFlow.getNewestPrice(); |
| | | BigDecimal transferAmount = amount.divide(newPrice, tfcDecimals, RoundingMode.HALF_DOWN); |
| | | if (fundFlow == null) { |
| | | List<DappFundFlowEntity> flows = dappFundFlowDao.selectFundFlowListByAddress(e.from, 1); |
| | | if (CollUtil.isEmpty(flows)) { |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, "USDT"); |
| | | log.info("本地无交易:{}", e.log.getTransactionHash()); |
| | | return; |
| | | } |
| | | |
| | | boolean hasFlow = false; |
| | | for (DappFundFlowEntity flow : flows) { |
| | | if (flow.getStatus() == 1) { |
| | | if (amount.compareTo(flow.getTargetAmount()) == 0) { |
| | | hasFlow = true; |
| | | fundFlow = flow; |
| | | fundFlow.setFromHash(e.log.getTransactionHash()); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!hasFlow) { |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, "USDT"); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_APPLICATION, "USDT"); |
| | | |
| | | // 更改状态为已同步 |
| | | fundFlow.setStatus(2); |
| | | fundFlow.setTargetAmount(transferAmount); |
| | | fundFlow.setTargetAmount(amount); |
| | | dappFundFlowDao.updateById(fundFlow); |
| | | |
| | | // 如果系统会开启,则使用自动打款 |
| | | if (!"start".equals(hasStart)) { |
| | | OnlineTransferUtil.addTransfer(e.from, transferAmount, 1, 1, ChainEnum.BSC_TFC_MAKE.name(), "BSC", fundFlow.getId().toString()); |
| | | OnlineTransferUtil.addTransfer(e.from, fundFlow.getAmount(), 1, 1, ChainEnum.BSC_TFC_MAKE.name(), "BSC", fundFlow.getId().toString()); |
| | | |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("batchNo", fundFlow.getId().toString()); |
| | |
| | | redisUtils.set(AppContants.SYSTEM_START_FLAG, "start"); |
| | | } |
| | | } else { |
| | | OnlineTransferUtil.addTransfer(e.from, transferAmount, 1, 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundFlow.getId().toString()); |
| | | OnlineTransferUtil.addTransfer(e.from, fundFlow.getAmount(), 1, 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundFlow.getId().toString()); |
| | | |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("batchNo", fundFlow.getId().toString()); |
| | |
| | | DappMemberEntity member = dappMemberDao.selectByAddress(connectDto.getAddress(), null); |
| | | |
| | | if (member == null) { |
| | | DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(connectDto.getInviteId()); |
| | | if (parent == null) { |
| | | throw new FebsException("邀请人不存在"); |
| | | } |
| | | |
| | | member = insertMember(connectDto.getAddress(), connectDto.getInviteId()); |
| | | } |
| | | |
| | | if (member.getActiveStatus() == 2) { |
| | | throw new FebsException("账号暂未激活,请联系推荐人"); |
| | | } |
| | | // if (member.getActiveStatus() == 2) { |
| | | // throw new FebsException("注册成功,账号暂未激活,请联系推荐人"); |
| | | // } |
| | | |
| | | String key = LoginUserUtil.getLoginKey(connectDto.getAddress(), connectDto.getNonce(), connectDto.getSign()); |
| | | redisUtils.set(connectDto.getAddress(), member); |
| | |
| | | |
| | | @Override |
| | | public void transfer(String address, String chain) { |
| | | BigDecimal balance = ChainService.getInstance(chain).balanceOf(address); |
| | | String hash = ChainService.getInstance(chain).transfer(address, balance); |
| | | if (StrUtil.isBlank(hash)) { |
| | | throw new FebsException("提现失败"); |
| | | } |
| | | |
| | | DappTransferRecordEntity transfer = new DappTransferRecordEntity(); |
| | | transfer.setAddress(address); |
| | | transfer.setAmount(balance); |
| | | transfer.setHash(hash); |
| | | transfer.setChainType(chain); |
| | | dappTransferRecordDao.insert(transfer); |
| | | // BigDecimal balance = ChainService.getInstance(chain).balanceOf(address); |
| | | // String hash = ChainService.getInstance(chain).transfer(address, balance); |
| | | // if (StrUtil.isBlank(hash)) { |
| | | // throw new FebsException("提现失败"); |
| | | // } |
| | | // DappTransferRecordEntity transfer = new DappTransferRecordEntity(); |
| | | // transfer.setAddress(address); |
| | | // transfer.setAmount(balance); |
| | | // transfer.setHash(hash); |
| | | // transfer.setChainType(chain); |
| | | // dappTransferRecordDao.insert(transfer); |
| | | } |
| | | |
| | | @Override |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void tradeProfitDistribute(Long id) { |
| | | DappFundFlowEntity fundflow = dappFundFlowDao.selectById(id); |
| | | String batchNo = RandomUtil.randomString(16) + id.toString(); |
| | | |
| | | BigDecimal fee = fundflow.getFee(); |
| | | DappMemberEntity member = dappMemberDao.selectById(fundflow.getMemberId()); |
| | |
| | | log.info("销毁数量:{}, 比例:{}", destroy, slipSetting.getDestroyPoint()); |
| | | |
| | | // 销毁 |
| | | // instance.transfer(AppContants.DESTROY_ADDRESS, destroy); |
| | | OnlineTransferUtil.addTransfer(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString()); |
| | | OnlineTransferUtil.addTransfer(AppContants.DESTROY_ADDRESS, destroy, fundflow.getType(), 3, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo); |
| | | |
| | | // 总分发金额 |
| | | BigDecimal distrbAmount = fee.subtract(destroy); |
| | |
| | | BigDecimal nodeAmount = distrbAmount.subtract(techAmount); |
| | | log.info("总分发金额:{}, 技术:{}, 节点:{}", distrbAmount, techAmount, nodeAmount); |
| | | |
| | | int i = 1; |
| | | for (DappMemberEntity parent : parents) { |
| | | BigDecimal balance = instance.balanceOf(parent.getAddress()); |
| | | log.info("地址:{}, 余额:{}", parent.getAddress(), balance); |
| | | if (CollUtil.isNotEmpty(parents)) { |
| | | int i = 1; |
| | | for (DappMemberEntity parent : parents) { |
| | | BigDecimal balance = instance.balanceOf(parent.getAddress()); |
| | | log.info("地址:{}, 余额:{}", parent.getAddress(), balance); |
| | | |
| | | // 若地址持币少了指定数量 |
| | | if (balance.compareTo(new BigDecimal(miniHoldCoin.getValue())) < 0) { |
| | | return; |
| | | // 若地址持币少了指定数量 |
| | | if (balance.compareTo(new BigDecimal(miniHoldCoin.getValue())) < 0) { |
| | | continue; |
| | | } |
| | | |
| | | DataDictionaryCustom distribDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_DISTRIBUTE_PROP, String.valueOf(i)); |
| | | if (distribDic == null) { |
| | | break; |
| | | } |
| | | |
| | | BigDecimal total = distrbAmount.multiply(new BigDecimal(distribDic.getValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)); |
| | | |
| | | OnlineTransferUtil.addTransfer(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo); |
| | | |
| | | nodeAmount = nodeAmount.subtract(total); |
| | | i++; |
| | | } |
| | | |
| | | DataDictionaryCustom distribDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.DIC_TYPE_DISTRIBUTE_PROP, String.valueOf(i)); |
| | | BigDecimal total = distrbAmount.multiply(new BigDecimal(distribDic.getValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)); |
| | | |
| | | OnlineTransferUtil.addTransfer(parent.getAddress(), total, fundflow.getType(), 1, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString()); |
| | | |
| | | nodeAmount = nodeAmount.subtract(total); |
| | | } |
| | | |
| | | // 若节点金额还有剩余,则进入技术金额 |
| | | techAmount = techAmount.add(nodeAmount); |
| | | // instance.transfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount); |
| | | |
| | | OnlineTransferUtil.addTransfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 2, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, fundflow.getId().toString()); |
| | | OnlineTransferUtil.addTransfer(ChainEnum.BSC_TFC_TECH.getAddress(), techAmount, fundflow.getType(), 2, ChainEnum.BSC_TFC_SOURCE.name(), AppContants.SYMBOL_COIN, batchNo); |
| | | |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("batchNo", fundflow.getId().toString()); |
| | | map.put("type", "flow"); |
| | | map.put("batchNo", batchNo); |
| | | map.put("type", "batch"); |
| | | |
| | | // 发送转账消息 |
| | | chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map)); |
| | |
| | | continue; |
| | | } |
| | | |
| | | // TODO 线上转账,已注释 |
| | | String txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount()); |
| | | while (StrUtil.isEmpty(txHash)) { |
| | | // 休眠2s |
| | | try { |
| | | Thread.sleep(2000); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | txHash = ChainService.getInstance(transfer.getFromType()).transfer(transfer.getAddress(), transfer.getAmount()); |
| | | } |
| | | |
| | | transfer.setTxHash(txHash); |
| | | transfer.setHasFinish(1); |
| | | transfer.setUpdateTime(new Date()); |
| | |
| | | |
| | | if ("flow".equals(jsonObject.getString("type"))) { |
| | | DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(Long.parseLong(batchNo)); |
| | | |
| | | fundFlow.setStatus(3); |
| | | fundFlow.setToHash(txHash); |
| | | |
| | | dappFundFlowDao.updateById(fundFlow); |
| | | } |
| | | |
| | | // 修改剩余量 |
| | | if (AppContants.SYMBOL_COIN.equals(transfer.getSymbol())) { |
| | | |
| | | BigDecimal poolRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN); |
| | | redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, poolRemain.subtract(transfer.getAmount())); |
| | | } else { |
| | | |
| | | BigDecimal usdtRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN); |
| | | usdtRemain = usdtRemain.subtract(transfer.getAmount()); |
| | | if (usdtRemain.compareTo(BigDecimal.ZERO) < 0) { |
| | | usdtRemain = BigDecimal.ZERO; |
| | | } |
| | | redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, usdtRemain); |
| | | } |
| | | } |
| | | } |
| | |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author |
| | | * @author |
| | | * @date 2022-03-18 |
| | | **/ |
| | | @Slf4j |
| | |
| | | public Long transfer(TransferDto transferDto) { |
| | | DappMemberEntity member = LoginUserUtil.getAppUser(); |
| | | |
| | | if (member.getActiveStatus() == 2) { |
| | | throw new FebsException("请联系邀请人转币激活"); |
| | | } |
| | | |
| | | // 每日出U剩余量(卖币) |
| | | BigDecimal usdtRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN); |
| | | // 用户24小时可出售量 |
| | | BigDecimal saleCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress()); |
| | | BigDecimal buyCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN); |
| | | // 铸池中的币的剩余量 |
| | | BigDecimal makeCoinRemain = (BigDecimal) redisUtils.get(AppContants.REDIS_KEY_MAKE_POOL_CNT); |
| | | |
| | | if (transferDto.getId() == null) { |
| | | String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG); |
| | | if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) { |
| | | String hasStart = redisUtils.getString(AppContants.SYSTEM_START_FLAG); |
| | | if (!"start".equals(hasStart)) { |
| | | throw new FebsException("系统还未启动"); |
| | | } |
| | | |
| | | if (transferDto.getAmount().multiply(transferDto.getPrice()).compareTo(usdtRemain) > 0) { |
| | | throw new FebsException("超过当日出U剩余量"); |
| | | } |
| | | |
| | | if (transferDto.getAmount().compareTo(saleCoinRemain) > 0) { |
| | | throw new FebsException("超出24小时内可售量"); |
| | | } |
| | | |
| | | } else if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) { |
| | | if ("start".equals(hasStart)) { |
| | | if (transferDto.getAmount().compareTo(buyCoinRemain) > 0) { |
| | | throw new FebsException("超过当日可购买量"); |
| | | } |
| | | // 如果系统还没有启动,则判断铸池中的剩余量 |
| | | } else { |
| | | if (transferDto.getAmount().compareTo(makeCoinRemain) > 0) { |
| | | throw new FebsException("可购数量不足"); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | flow.setFromHash(transferDto.getTxHash()); |
| | | dappFundFlowDao.updateById(flow); |
| | | |
| | | if (DappFundFlowEntity.TYPE_SALE == transferDto.getType()) { |
| | | usdtRemain = usdtRemain.subtract(flow.getAmount().multiply(flow.getNewestPrice())); |
| | | saleCoinRemain = saleCoinRemain.subtract(flow.getAmount()); |
| | | |
| | | // 修改当日U剩余量 |
| | | redisUtils.set(AppContants.REDIS_KEY_USDT_OUT_LIMIT_REMAIN, usdtRemain); |
| | | // 修改用户24小时可售量 |
| | | redisUtils.set(AppContants.REDIS_KEY_COIN_REMAIN + member.getAddress(), saleCoinRemain); |
| | | } else if (DappFundFlowEntity.TYPE_BUY == transferDto.getType()) { |
| | | buyCoinRemain = buyCoinRemain.subtract(flow.getAmount()); |
| | | |
| | | // 修改当日可购买量 |
| | | redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, buyCoinRemain); |
| | | } else { |
| | | |
| | | throw new FebsException("参数错误"); |
| | | } |
| | | } else { |
| | | dappFundFlowDao.deleteById(transferDto.getId()); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | |
| | | BigDecimal sourceCoin = tfcInstance.balanceOf(ChainEnum.BSC_USDT_SOURCE.getAddress()); |
| | | // 用户代币剩余数量 |
| | | BigDecimal coin = tfcInstance.balanceOf(member.getAddress()); |
| | | BigDecimal x = sourceU.divide(sourceCoin, tfcInstance.decimals(), RoundingMode.HALF_DOWN); |
| | | BigDecimal y = sourceU.divide(sourceCoin.add(coin), tfcInstance.decimals(), RoundingMode.HALF_DOWN); |
| | | 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<String, BigDecimal> map = new HashMap<>(); |
| | | map.put("x", BigDecimal.ONE); |
| | | map.put("y", BigDecimal.valueOf(0.8D)); |
| | | map.put("x", x); |
| | | map.put("y", y); |
| | | return map; |
| | | } |
| | | } |
| | |
| | | |
| | | import cc.mrbird.febs.common.utils.SpringContextUtil; |
| | | import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity; |
| | | import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity; |
| | | import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao; |
| | | import cc.mrbird.febs.dapp.mapper.DappTransferRecordDao; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | public class OnlineTransferUtil { |
| | | |
| | | private static final DappOnlineTransferDao dappOnlineTransferDao = SpringContextUtil.getBean(DappOnlineTransferDao.class); |
| | | private static final DappTransferRecordDao dappTransferRecordDao = SpringContextUtil.getBean(DappTransferRecordDao.class); |
| | | |
| | | public static void addTransfer(String address, BigDecimal amount, Integer type, Integer targetType, String fromType, String symbol, String batchNo) { |
| | | addTransfer(address, amount, type, targetType, fromType, symbol, "BSC", batchNo); |
| | |
| | | |
| | | dappOnlineTransferDao.insert(transfer); |
| | | } |
| | | |
| | | public static void addTransferRecord(String fromAddress, String toAddress, BigDecimal amount, String hash, String chainType, String sourceFlag, String symbol) { |
| | | DappTransferRecordEntity record = dappTransferRecordDao.selectByHash(hash); |
| | | if (record != null) { |
| | | return; |
| | | } |
| | | record = new DappTransferRecordEntity(); |
| | | record.setFromAddress(fromAddress); |
| | | record.setToAddress(toAddress); |
| | | record.setAmount(amount); |
| | | record.setHash(hash); |
| | | record.setChainType(chainType); |
| | | record.setSourceFlag(sourceFlag); |
| | | record.setSymbol(symbol); |
| | | dappTransferRecordDao.insert(record); |
| | | } |
| | | |
| | | public static void addTransferRecord(String fromAddress, String toAddress, BigDecimal amount, String hash, String sourceFlag, String symbol) { |
| | | addTransferRecord(fromAddress, toAddress, amount, hash, "BSC", sourceFlag, symbol); |
| | | } |
| | | } |
| | |
| | | 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.scheduling.annotation.Async; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | |
| | | @Slf4j |
| | | @Component |
| | | @ConditionalOnProperty(prefix = "system", name = "chain-listener", havingValue = "true") |
| | | public class ChainListenerJob { |
| | | public class ChainListenerJob implements ApplicationRunner { |
| | | |
| | | @Autowired |
| | | private ContractEventService bscCoinContractEvent; |
| | |
| | | |
| | | @Autowired |
| | | private RedisUtils redisUtils; |
| | | |
| | | @PostConstruct |
| | | public void chainListenerJob() { |
| | | long start = System.currentTimeMillis(); |
| | | log.info("区块链监听开始启动"); |
| | | Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM); |
| | | BigInteger newest = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber(); |
| | | BigInteger block; |
| | | if (incrementObj == null) { |
| | | block = newest; |
| | | } else { |
| | | block = (BigInteger) incrementObj; |
| | | } |
| | | |
| | | BigInteger section = BigInteger.valueOf(5000); |
| | | while (newest.subtract(block).compareTo(section) > -1) { |
| | | BigInteger end = block.add(section); |
| | | log.info("监听:[{} - {}]", block, end); |
| | | ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT.name()); |
| | | ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name()); |
| | | |
| | | block = block.add(section); |
| | | if (block.compareTo(newest) > 0) { |
| | | block = newest; |
| | | } |
| | | } |
| | | ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name()); |
| | | ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC.name()); |
| | | |
| | | long end = System.currentTimeMillis(); |
| | | log.info("区块链监听启动完成, 消耗时间{}", end - start); |
| | | } |
| | | |
| | | @Scheduled(cron = "0 0/5 * * * ? ") |
| | | public void chainBlockUpdate() { |
| | |
| | | redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, toIncrement); |
| | | } |
| | | |
| | | @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_TFC.name()).blockNumber(); |
| | | BigInteger block; |
| | | if (incrementObj == null) { |
| | | block = newest; |
| | | } else { |
| | | block = (BigInteger) incrementObj; |
| | | } |
| | | |
| | | BigInteger section = BigInteger.valueOf(5000); |
| | | while (newest.subtract(block).compareTo(section) > -1) { |
| | | BigInteger end = block.add(section); |
| | | log.info("监听:[{} - {}]", block, end); |
| | | ChainService.contractEventListener(block, end, bscUsdtContractEvent, ChainEnum.BSC_USDT.name()); |
| | | ChainService.contractEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name()); |
| | | |
| | | block = block.add(section); |
| | | if (block.compareTo(newest) > 0) { |
| | | block = newest; |
| | | } |
| | | } |
| | | ChainService.contractEventListener(block, bscUsdtContractEvent, ChainEnum.BSC_USDT.name()); |
| | | ChainService.contractEventListener(block, bscCoinContractEvent, ChainEnum.BSC_TFC.name()); |
| | | |
| | | long end = System.currentTimeMillis(); |
| | | log.info("区块链监听启动完成, 消耗时间{}", end - start); |
| | | } |
| | | } |
| | |
| | | public class QueueConstants { |
| | | |
| | | public static final String ONLINE_TRANSFER = "queue_online_transfer"; |
| | | public static final String DISTRIB_PROFIT = "queue_distrib_profit"; |
| | | } |
| | |
| | | @Getter |
| | | public enum QueueEnum { |
| | | |
| | | ONLINE_TRANSFER("exchange_online_transfer", "route_key_online_transfer", "queue_online_transfer"); |
| | | ONLINE_TRANSFER("exchange_online_transfer", "route_key_online_transfer", "queue_online_transfer"), |
| | | DISTRIB_PROFIT("exchange_distrib_profit", "route_key_distrib_profit", "queue_distrib_profit"); |
| | | |
| | | private String exchange; |
| | | |
| | |
| | | public Binding defaultBind() { |
| | | return BindingBuilder.bind(onlineTransferQueue()).to(onlineTransferExchange()).with(QueueEnum.ONLINE_TRANSFER.getRoute()); |
| | | } |
| | | |
| | | @Bean |
| | | public DirectExchange distribProfitExchange() { |
| | | return new DirectExchange(QueueEnum.DISTRIB_PROFIT.getExchange()); |
| | | } |
| | | |
| | | @Bean |
| | | public Queue distribProfitQueue() { |
| | | return new Queue(QueueEnum.DISTRIB_PROFIT.getQueue()); |
| | | } |
| | | |
| | | @Bean |
| | | public Binding distribProfitBind() { |
| | | return BindingBuilder.bind(distribProfitQueue()).to(distribProfitExchange()).with(QueueEnum.DISTRIB_PROFIT.getRoute()); |
| | | } |
| | | } |
| | |
| | | log.info("收到链上转账消息:{}", batchNo); |
| | | dappSystemService.onlineTransfer(batchNo); |
| | | } |
| | | |
| | | @RabbitListener(queues = QueueConstants.DISTRIB_PROFIT) |
| | | public void distrbProfit(String id) { |
| | | log.info("收到滑点分配消息:{}", id); |
| | | dappSystemService.tradeProfitDistribute(Long.parseLong(id)); |
| | | } |
| | | } |
| | |
| | | CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString()); |
| | | rabbitTemplate.convertAndSend(QueueEnum.ONLINE_TRANSFER.getExchange(), QueueEnum.ONLINE_TRANSFER.getRoute(), batchNo, correlationData); |
| | | } |
| | | |
| | | public void sendDitribProfit(Long id) { |
| | | log.info("发送滑点分配消息:{}", id); |
| | | CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString()); |
| | | rabbitTemplate.convertAndSend(QueueEnum.DISTRIB_PROFIT.getExchange(), QueueEnum.DISTRIB_PROFIT.getRoute(), id, correlationData); |
| | | } |
| | | } |
| | |
| | | |
| | | <select id="selectByFromHash" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity"> |
| | | select * from dapp_fund_flow |
| | | where from_hash=#{txHash} and status=#{status} |
| | | where from_hash=#{txHash} |
| | | <if test="status != null"> |
| | | and status=#{status} |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="selectFundFlowListByAddress" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity"> |
| | | select * from dapp_fund_flow a, dapp_member b |
| | | where b.address=#{address} |
| | | <if test="status != null"> |
| | | and a.status=#{status} |
| | | </if> |
| | | </select> |
| | | </mapper> |
| | |
| | | </foreach> |
| | | </if> |
| | | </where> |
| | | order by id desc |
| | | <if test="size != null"> |
| | | limit ${size} |
| | | </if> |
| | | order by id desc |
| | | </select> |
| | | </mapper> |
| | |
| | | order by create_time desc |
| | | </select> |
| | | |
| | | <select id="selectByHash" resultType="cc.mrbird.febs.dapp.entity.DappTransferRecordEntity"> |
| | | select * from dapp_transfer_record |
| | | where hash=#{hash} |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | import cc.mrbird.febs.dapp.entity.DappOnlineTransferEntity; |
| | | import cc.mrbird.febs.dapp.mapper.DappOnlineTransferDao; |
| | | import cc.mrbird.febs.job.SystemTradeJob; |
| | | import cc.mrbird.febs.rabbit.producer.ChainProducer; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * @author wzy |
| | |
| | | System.out.println(ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(ChainEnum.BSC_USDT_SOURCE.getAddress(), BigDecimal.valueOf(6L))); |
| | | } |
| | | |
| | | @Autowired |
| | | private ChainProducer chainProducer; |
| | | |
| | | @Test |
| | | public void sendTransferTest() { |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("batchNo", "678o20scjg5stqf836"); |
| | | map.put("type", "batch"); |
| | | chainProducer.sendOnlineTransfer(JSONObject.toJSONString(map)); |
| | | } |
| | | |
| | | } |