src/main/java/cc/mrbird/febs/common/contants/AppContants.java
@@ -170,4 +170,7 @@ public static final String RESP_PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANyCPnifddX7HYN/wexyqxt3cFCKoE1/+lCIv7i+Epo83xlwbRet6rTXyGX7JCs5qpg1UvC+LuB+Relv8bZPEwScLmu0B5awwDmY954974KD6Yn/JdHi2WT933QvmDs9PFqUfnQd0KhfAUF6eS2K0quwN9DOLX5UIcEZSE9SOwkdAgMBAAECgYAt52Mv4yo5qHQFavQoz9o09pFIAwPJ/mlSmJUo1VC0ERX0isX7FvZ0PTN3n2dxJCkSVI92lHDXxRGyvd4YsK9pdErGVL2DecbbER7069y94g/uHsYq15skzLlyUNhyu2FOUCsVFy+M/C0qk14z/xG1ze3GWNHP1oc1leAYpoWmAQJBAPXxRvYTxmZAFv3J4pcf/FXqmUXdbJI5sHWXe6Pcs+rIuil5ePqX6AQBoQ5PalYhe5/kKzr7Gy6GSzlpztuOV50CQQDlhrTNytQdDCNIOL8uw3t4D8mDGuslPcRoykmaCQhd4NvaqLZrBS8k+TuS2+v5ryng3HhcYjR0h1MHHG69En+BAkEAzt2G5mxzsIWv0QACi0LoKAwPp+g67jN/7SjhYk69Nnpnu4Lk80LacKQ+J588vf2j0jVE93NGxbdHhp8s0xfDMQJBAJFlOqVeRe28oaD/aYRLCqyse39Ujv6BWSj0c5li/WzSoxKpaxzyJMIsK2PFcn8xSbsKjigfgZELpDnN9gxJaoECQCn+tZB0g9WJMaGNCMdlStPHAO2ajS1HY6BV5Xq13hixAdp5bLzbg0GrY25MrpTCFBEqCx+7F4cYUvVazLuAK6g="; public static final LinkedList<String> ENCRYPT_METHOD = new LinkedList<>(); public static final String IDO_MEMBER_RECOMMEND_CNT = "IDO_MEMBER_RECOMMEND_CNT"; public static final String IDO_BOX_PRIZE = "IDO_BOX_PRIZE"; } src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
@@ -90,7 +90,16 @@ "9378c6a5becdcade151e98b2ee30239bcb11642e362a068a5bc7667f3d17b1fc", "https://bsc-dataseed1.ninicoin.io", "0x46ac4921e58773ca22826df1640672b91b1db2b3", ""); ""), /** * 卡牌 */ BSC_NFT_SDC("BSC", "0xf6b06a30196aa5e318232a3b61319eab0fd4a3bf", "9378c6a5becdcade151e98b2ee30239bcb11642e362a068a5bc7667f3d17b1fc", "https://bsc-dataseed1.ninicoin.io", "0x46ac4921e58773ca22826df1640672b91b1db2b3", ""); private String chain; src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java
@@ -24,4 +24,6 @@ BigInteger blockNumber(); BigInteger totalSupply(); BigInteger safeMintNFT(String address); } src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
@@ -360,4 +360,40 @@ } return BigInteger.ZERO; } @Override public BigInteger safeMintNFT(String toAddress) { String gas = getGas(); try { Credentials credentials = Credentials.create(privateKey); EthGetTransactionCount ethGetTransactionCount = web3j .ethGetTransactionCount(ownerAddress, DefaultBlockParameterName.LATEST).sendAsync().get(); BigInteger nonce = ethGetTransactionCount.getTransactionCount(); Function function = new Function("safeMint", Arrays.asList(new Address(toAddress)), Arrays.asList(new TypeReference<Type>() { })); String encodedFunction = FunctionEncoder.encode(function); RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(), Convert.toWei("1000000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction); byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); String hexValue = Numeric.toHexString(signedMessage); CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync(); EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get(); if (ethSendTransaction.hasError()) { return ""; } else { return ethSendTransaction.getTransactionHash(); } } catch (Exception e) { e.printStackTrace(); return ""; } } } src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java
@@ -113,4 +113,9 @@ public BigInteger totalSupply() { return null; } @Override public BigInteger safeMintNFT(String address) { return null; } } src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java
@@ -84,6 +84,13 @@ return new FebsResponse().success().data(dappMemberService.findTeamList(teamListDto)); } @ApiOperation(value = "开盲盒", notes = "开盲盒") @PostMapping(value = "/boxSurprise") public FebsResponse boxSurprise() { int cnt = dappWalletService.boxSurprise(); return new FebsResponse().success().data(cnt); } @PostMapping(value = "/logout") public FebsResponse logout() { DappMemberEntity member = LoginUserUtil.getAppUser(); src/main/java/cc/mrbird/febs/dapp/entity/DappFundFlowEntity.java
@@ -47,7 +47,7 @@ private BigDecimal amount; /** * 类型 1-买入 2-卖出 3-采矿 * 类型 1-买入 2-卖出 3-采矿 4-返利 5-获取盲盒 6-开盲盒获取卡牌 7-推荐奖励 */ private Integer type; src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java
@@ -25,4 +25,14 @@ @TableField(exist = false) private String address; /** * usdt余额 */ private BigDecimal usdtAmount; /** * 盲盒数量 */ private Integer boxCnt; } src/main/java/cc/mrbird/febs/dapp/service/DappWalletService.java
@@ -39,4 +39,6 @@ Long transfer(TransferDto transferDto); Map<String, BigDecimal> calPrice(PriceDto priceDto); int boxSurprise(); } src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -289,9 +289,12 @@ } else { member.setNodeType(2); } dappMemberDao.insert(member); DappWalletCoinEntity walletCoin = new DappWalletCoinEntity(); walletCoin.setMemberId(member.getId()); dappWalletCoinDao.insert(walletCoin); if (StrUtil.isEmpty(refererId)) { refererId = "0"; // 若没有推荐人,则直接激活 src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
@@ -294,7 +294,7 @@ } // 挖矿数量 BigDecimal mine = transferPoll.multiply(balance.divide(allInternet, instance.decimals(), RoundingMode.HALF_UP)); BigDecimal mine = transferPoll.multiply(new BigDecimal("0.2")).multiply(balance.divide(allInternet, instance.decimals(), RoundingMode.HALF_UP)); if (mine.compareTo(BigDecimal.ZERO) < 1) { continue; } @@ -423,7 +423,9 @@ } // 最低容量(百分比) private final BigDecimal volProp = new BigDecimal("0.5"); private final BigDecimal volProp = new BigDecimal("2"); // 每日增/减百分比 private final BigDecimal changeProp = new BigDecimal("1"); @Override public void transferPoolSetting() { @@ -444,7 +446,7 @@ transferPool.setTodayVol(total); transferPool.setTodayProp(volProp); transferPool.setFinishCnt(0); transferPool.setFinishCnt(0); transferPool.setUnFinishCnt(0); redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL, transferPool); redisUtils.set(AppContants.REDIS_KEY_TRANSFER_POOL_VOL_REMAIN, total); @@ -462,8 +464,8 @@ if (remain.compareTo(BigDecimal.ZERO) == 0) { int finishCnt = transferPool.getFinishCnt() + 1; BigDecimal targetProp = transferPool.getTodayProp(); if (finishCnt == 5) { targetProp = transferPool.getTodayVol().add(volProp); if (finishCnt == 1) { targetProp = transferPool.getTodayVol().add(changeProp); transferPool.setTodayProp(targetProp); transferPool.setFinishCnt(0); } else { @@ -478,8 +480,8 @@ } else { int unFinishCnt = transferPool.getUnFinishCnt() + 1; BigDecimal targetProp = transferPool.getTodayProp(); if (unFinishCnt >= 3) { targetProp = transferPool.getTodayProp().compareTo(volProp) == 0 ? volProp : transferPool.getTodayProp().subtract(volProp); if (unFinishCnt >= 1) { targetProp = transferPool.getTodayProp().compareTo(volProp) == 0 ? volProp : transferPool.getTodayProp().subtract(changeProp); transferPool.setTodayProp(targetProp); transferPool.setUnFinishCnt(0); } else { src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
@@ -17,6 +17,7 @@ import cc.mrbird.febs.dapp.entity.*; 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.WalletInfoVo; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -340,4 +341,38 @@ map.put("y", y); return map; } @Override public int boxSurprise() { DappMemberEntity member = LoginUserUtil.getAppUser(); DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId()); if (walletCoin.getBoxCnt() < 1) { throw new FebsException("盲盒数量不足"); } 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(); return box.getIndex(); } } src/main/java/cc/mrbird/febs/dapp/utils/BoxUtils.java
New file @@ -0,0 +1,124 @@ package cc.mrbird.febs.dapp.utils; import cc.mrbird.febs.common.contants.AppContants; import cc.mrbird.febs.common.utils.RedisUtils; import cc.mrbird.febs.common.utils.SpringContextUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @author wzy * @date 2022-07-14 **/ @Slf4j public class BoxUtil { // public static volatile List<Box> boxList = Collections.synchronizedList(new ArrayList<>()); private static final RedisUtils redisUtils = SpringContextUtil.getBean(RedisUtils.class); public synchronized static Box openBox() { String redisStr = redisUtils.getString(AppContants.IDO_BOX_PRIZE); List<Box> boxList = JSONObject.parseArray(redisStr, Box.class); if (CollUtil.isEmpty(boxList)) { boxList = Collections.synchronizedList(new ArrayList<>()); Box box1 = new Box(1, 95); Box box2 = new Box(2, 3); Box box3 = new Box(3, 2); boxList.add(box1); boxList.add(box2); boxList.add(box3); } int min = 1; int minIndex = 1; int max = 1; for (int i = 0; i < boxList.size(); i++) { Box box = boxList.get(i); if (i != 0) { Box lastBox = (Box) boxList.get(i - 1); minIndex += lastBox.getCount(); } max += box.getCount(); box.setMin(minIndex); box.setMax(max); } int i = RandomUtil.randomInt(min, max); Box result = new Box(); for (Box box : boxList) { if (box.getMin() <= i && box.getMax() > i) { result = box; int count = box.getCount(); count--; box.setCount(count); if (count == 0) { boxList.remove(box); } break; } } redisUtils.set(AppContants.IDO_BOX_PRIZE, JSONObject.toJSONString(boxList)); return result; } public static class Box { private int index; private int count; public Box() {} public Box(int index, int count) { this.index = index; this.count = count; } private int min; private int max; public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getMin() { return min; } public void setMin(int min) { this.min = min; } public int getMax() { return max; } public void setMax(int max) { this.max = max; } } } src/main/java/cc/mrbird/febs/job/SystemTradeJob.java
@@ -60,7 +60,9 @@ /** * 挖矿 * * 以中转池成交数1:1出矿(中转池卖出多少,矿池则1:1出币),每个地址所得=出币量*(单个地址持币量/全网持币量) * 以中转池成交数1:0.2出矿(中转池卖出多少,矿池则1:0.2出币),每个地址所得=出币量*(单个地址持币量/全网持币量) * source限矿算法: * TODO 按前一天价格,有跌幅则按实际产矿量减半。 */ @Scheduled(cron = "0 0 2 * * ?") public void mineJob() { src/main/resources/application-prod.yml
@@ -47,6 +47,6 @@ time-zone: GMT+8 system: online-transfer: false chain-listener: false online-transfer: true chain-listener: true trade-job: false