pom.xml
@@ -10,7 +10,7 @@ </parent> <groupId>com.xcong</groupId> <artifactId>excoin</artifactId> <version>0.0.1-SNAPSHOT</version> <version>roc</version> <name>excoin</name> <description>Demo project for Spring Boot</description> src/main/java/com/xcong/excoin/common/enumerates/CoinTypeEnum.java
@@ -6,5 +6,5 @@ * @author wzy */ public enum CoinTypeEnum { USDT, BTC, ETH, LTC, EOS, XRP, BCH, ETC USDT, BTC, ETH, LTC, EOS, XRP, BCH, ETC,ROC } src/main/java/com/xcong/excoin/common/enumerates/SymbolEnum.java
@@ -15,7 +15,7 @@ ,EOS("EOS", "EOS/USDT") ,XRP("XRP", "XRP/USDT") ,ETC("ETC", "ETC/USDT") ,NEKK("NEKK", "NEKK/USDT"); ,ROC("ROC", "ROC/USDT"); private String name; src/main/java/com/xcong/excoin/modules/blackchain/model/RocCreateAcoountModel.java
New file @@ -0,0 +1,10 @@ package com.xcong.excoin.modules.blackchain.model; import lombok.Data; @Data public class RocCreateAcoountModel { private String password; private String walletName; private String terminalId; } src/main/java/com/xcong/excoin/modules/blackchain/service/Impl/BlockSeriveImpl.java
@@ -5,18 +5,13 @@ import javax.annotation.Resource; import com.xcong.excoin.modules.blackchain.service.*; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.common.LoginUserUtils; import com.xcong.excoin.common.response.Result; import com.xcong.excoin.modules.blackchain.service.BlockSerive; import com.xcong.excoin.modules.blackchain.service.BtcService; import com.xcong.excoin.modules.blackchain.service.EthService; import com.xcong.excoin.modules.blackchain.service.LtcService; import com.xcong.excoin.modules.blackchain.service.UsdtService; import com.xcong.excoin.modules.blackchain.service.XrpService; import com.xcong.excoin.modules.member.dao.MemberCoinAddressDao; import com.xcong.excoin.modules.member.dao.MemberDao; import com.xcong.excoin.modules.member.entity.MemberCoinAddressEntity; @@ -185,6 +180,10 @@ } } break; case "ROC": address = RocService.createWallet(); map.put("address", address); break; default: break; } src/main/java/com/xcong/excoin/modules/blackchain/service/RocService.java
New file @@ -0,0 +1,33 @@ package com.xcong.excoin.modules.blackchain.service; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.blackchain.model.RocCreateAcoountModel; import org.apache.commons.lang3.StringUtils; /** * ROC币种接入 */ public class RocService { private final static String URL = "http://api.rocwallet.cc"; private final static String CREATE_WALLET= "/init/createaccount"; public static String createWallet(){ RocCreateAcoountModel createAcoountModel = new RocCreateAcoountModel(); createAcoountModel.setPassword("123456"); createAcoountModel.setTerminalId("rocexcoin"); createAcoountModel.setWalletName("coin"); String post = HttpUtil.jsonPost(URL+CREATE_WALLET, JSONObject.toJSONString(createAcoountModel)); if(StringUtils.isBlank(post)){ return null; } JSONObject jsonObject = JSONObject.parseObject(post); Object code = jsonObject.get("code"); if("0".equals(code.toString())){ Object o = jsonObject.getJSONObject("data").get("address"); return o.toString(); } return null; } } src/main/java/com/xcong/excoin/modules/coin/controller/OrderCoinController.java
@@ -5,7 +5,9 @@ import javax.annotation.Resource; import javax.validation.Valid; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.coin.entity.OrderCoinsEntity; import com.xcong.excoin.modules.symbols.constants.SymbolsConstats; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -63,12 +65,13 @@ @ApiOperation(value = "提交买卖订单", notes = "提交买卖订单") @PostMapping(value="/submitSalesWalletCoinOrder") public Result submitSalesWalletCoinOrder(@RequestBody @Valid SubmitSalesWalletCoinOrderDto submitSalesWalletCoinOrderDto) { log.info("买卖单参数[{}]", JSONObject.toJSONString(submitSalesWalletCoinOrderDto)); String symbol = submitSalesWalletCoinOrderDto.getSymbol(); Integer type = submitSalesWalletCoinOrderDto.getType(); Integer tradeType = submitSalesWalletCoinOrderDto.getTradeType(); BigDecimal price = submitSalesWalletCoinOrderDto.getPrice(); BigDecimal amount = submitSalesWalletCoinOrderDto.getAmount(); if("NEKK".equals(symbol)){ if(SymbolsConstats.EXCHANGE_SYMBOLS.contains(symbol)){ return orderCoinService.submitSalesWalletCoinOrderWithMatch(symbol,type,tradeType,price,amount,submitSalesWalletCoinOrderDto.getEntrustAmount()); }else{ src/main/java/com/xcong/excoin/modules/coin/parameter/vo/OrderWalletCoinVo.java
@@ -48,6 +48,12 @@ */ @ApiModelProperty(value = "委托价") private BigDecimal entrustPrice; /** * 委托价 */ @ApiModelProperty(value = "委托价") private BigDecimal entrustAmount; /** * 成交量 */ src/main/java/com/xcong/excoin/modules/coin/service/BlockCoinService.java
@@ -16,4 +16,6 @@ public void updateTrc20(); public void updateRoc(); } src/main/java/com/xcong/excoin/modules/coin/service/impl/BlockCoinServiceImpl.java
@@ -481,6 +481,12 @@ } @Override public void updateRoc() { // 更新ROC } private String generateNo() { // 生成订单号 Long timestamp = System.currentTimeMillis(); src/main/java/com/xcong/excoin/modules/coin/service/impl/OrderCoinServiceImpl.java
@@ -7,14 +7,18 @@ import javax.annotation.Resource; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.blackchain.service.RocService; import com.xcong.excoin.modules.coin.mapper.OrderCoinsDealMapper; import com.xcong.excoin.modules.platform.entity.PlatformCnyUsdtExchangeEntity; import com.xcong.excoin.modules.platform.entity.PlatformSymbolsCoinEntity; import com.xcong.excoin.modules.symbols.constants.SymbolsConstats; import com.xcong.excoin.trade.CoinTrader; import com.xcong.excoin.trade.CoinTraderFactory; import com.xcong.excoin.trade.ExchangeTrade; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -169,8 +173,10 @@ BigDecimal nowPriceinBigDecimal = price; //查询当前价 BigDecimal nowPrice = new BigDecimal(redisUtils.getString(CoinTypeConvert.convertToKey(symbol + "/USDT"))); System.out.println(symbol + "当前价:" + nowPrice); if(OrderCoinsEntity.ORDERTYPE_BUY.equals(type) && OrderCoinsEntity.TRADETYPE_MARKETPRICE.equals(tradeType)){ amount = entrustAmount.divide(nowPrice,BigDecimal.ROUND_DOWN); amount = entrustAmount.divide(nowPrice, 8, BigDecimal.ROUND_DOWN); System.out.println(symbol + "市价量:" + amount); } // 处理市价 // 获取交易管理的杠杠倍率,手续费率等信息,由平台进行设置 @@ -253,6 +259,7 @@ order.setEntrustCnt(amount); order.setEntrustPrice(price); order.setDealCnt(amount); order.setEntrustAmount(entrustAmount); if ((OrderCoinsEntity.TRADETYPE_FIXEDPRICE.equals(tradeType) && type.equals(1) && price.compareTo(nowPrice) >= 0) || (OrderCoinsEntity.TRADETYPE_FIXEDPRICE.equals(tradeType) && type.equals(2) && price.compareTo(nowPrice) <= 0)) { // 手续费用(手续费=建仓价X数量X手续费率) @@ -333,7 +340,15 @@ symbol = symbol.toUpperCase(); MemberWalletCoinEntity walletCoin = memberWalletCoinDao.selectWalletCoinBymIdAndCode(memberId, symbol); if (ObjectUtil.isEmpty(walletCoin)) { return Result.fail(MessageSourceUtils.getString("order_service_0003")); // 创建这个钱包 walletCoin = new MemberWalletCoinEntity(); walletCoin.setAvailableBalance(BigDecimal.ZERO); walletCoin.setFrozenBalance(BigDecimal.ZERO); walletCoin.setTotalBalance(BigDecimal.ZERO); walletCoin.setBorrowedFund(BigDecimal.ZERO); walletCoin.setMemberId(memberId); walletCoin.setWalletCode(symbol); memberWalletCoinDao.insert(walletCoin); } // 查询交易设置 PlatformTradeSettingEntity tradeSetting = platformTradeSettingDao.findTradeSetting(); @@ -341,18 +356,21 @@ return Result.fail(MessageSourceUtils.getString("order_service_0009")); } // 手续费用(手续费=建仓价X数量X手续费率) BigDecimal closingPrice ; BigDecimal closingPrice = BigDecimal.ZERO; // 总费用分两种 1,限价交易 是价格*数量+手续费 2,市价交易 用户输入的金额+手续费 //总费用 = 成交价*数量+手续费 BigDecimal totalPayPrice ; BigDecimal totalPayPrice = BigDecimal.ZERO; if(OrderCoinsEntity.TRADETYPE_FIXEDPRICE.equals(tradeType) ){ // 限价 closingPrice = price.multiply(amount).multiply(tradeSetting.getCoinFeeRatio()); totalPayPrice = price.multiply(amount).add(closingPrice); entrustAmount = price.multiply(amount); }else{ // 市价 if(OrderCoinsEntity.ORDERTYPE_BUY==type){ closingPrice = entrustAmount.multiply(tradeSetting.getCoinFeeRatio()); totalPayPrice = entrustAmount.add(closingPrice); } } // BigDecimal totalPayPricCoin = nowPrice.multiply(amount).add(closingPrice); @@ -385,6 +403,8 @@ // 成交量 先设置为0 order.setDealCnt(BigDecimal.ZERO); order.setEntrustCnt(BigDecimal.ZERO); order.setEntrustPrice(BigDecimal.ZERO); // 成交价 //order.setDealPrice(price); // 成交金额 @@ -394,27 +414,24 @@ // 手续费 order.setFeeAmount(closingPrice); if(OrderCoinsEntity.TRADETYPE_FIXEDPRICE.equals(tradeType)){ // 限价 是需要价格和数量 可以得到成交金额 // 下单量 order.setEntrustCnt(amount); // 下单价格 order.setEntrustPrice(price); order.setEntrustAmount(amount.multiply(price)); }else{ if(OrderCoinsEntity.ORDERTYPE_BUY.equals(type)){ // 市价 只有金额 order.setEntrustAmount(entrustAmount); }else{ // 市价卖单 // 下单量 order.setEntrustCnt(amount); // 下单价格 order.setEntrustPrice(price); order.setEntrustAmount(amount.multiply(price)); order.setEntrustPrice(BigDecimal.ZERO); order.setEntrustAmount(BigDecimal.ZERO); } } orderCoinsDao.insert(order); @@ -422,40 +439,24 @@ //冻结相应的资产 if (OrderCoinsEntity.ORDERTYPE_BUY.equals(type)) { //如果是买入,所对应的币种增加,USDT账户减少金额 BigDecimal availableBalance = walletCoinUsdt.getAvailableBalance().subtract(totalPayPrice); BigDecimal frozenBalance = walletCoinUsdt.getFrozenBalance().add(totalPayPrice); walletCoinUsdt.setAvailableBalance(availableBalance); walletCoinUsdt.setFrozenBalance(frozenBalance); memberWalletCoinDao.updateById(walletCoinUsdt); // BigDecimal availableBalance = walletCoinUsdt.getAvailableBalance().subtract(totalPayPrice); // BigDecimal frozenBalance = walletCoinUsdt.getFrozenBalance().add(totalPayPrice); // walletCoinUsdt.setAvailableBalance(availableBalance); // walletCoinUsdt.setFrozenBalance(frozenBalance); // memberWalletCoinDao.updateById(walletCoinUsdt); memberWalletCoinDao.updateWalletBalance(walletCoinUsdt.getId(),totalPayPrice.negate(),totalPayPrice.negate(),entrustAmount); } else { //如果是卖出,币种减少,USDT增加 BigDecimal availableBalance = walletCoin.getAvailableBalance().subtract(amount); BigDecimal frozenBalance = walletCoin.getFrozenBalance().add(amount); walletCoin.setAvailableBalance(availableBalance); walletCoin.setFrozenBalance(frozenBalance); memberWalletCoinDao.updateById(walletCoin); // BigDecimal availableBalance = walletCoin.getAvailableBalance().subtract(amount); // BigDecimal frozenBalance = walletCoin.getFrozenBalance().add(amount); // walletCoin.setAvailableBalance(availableBalance); // walletCoin.setFrozenBalance(frozenBalance); // memberWalletCoinDao.updateById(walletCoin); memberWalletCoinDao.updateWalletBalance(walletCoin.getId(),amount.negate(),amount.negate(),amount); } // 加入到撮合 CoinTrader trader = factory.getTrader(symbol); trader.trade(order); // // 流水记录 TODO // MemberAccountFlowEntity record = new MemberAccountFlowEntity(); // record.setMemberId(memberId); // if (OrderCoinsEntity.ORDERTYPE_BUY.equals(type)) { // record.setPrice(totalPayPrice.setScale(4, BigDecimal.ROUND_DOWN)); // record.setSource(MemberAccountFlowEntity.SOURCE_BUY + symbol); // record.setRemark(MemberAccountFlowEntity.REMARK_BUY + symbol + ":" + amount); // } else { // record.setPrice(totalPayPrice.negate().setScale(4, BigDecimal.ROUND_DOWN)); // record.setSource(MemberAccountFlowEntity.SOURCE_SALE + symbol); // record.setRemark(MemberAccountFlowEntity.REMARK_SALE + symbol + ":" + amount); // } // record.setSymbol(symbol); // record.setBalance(walletCoinUsdt.getAvailableBalance()); // // memberAccountFlowEntityDao.insert(record); return Result.ok(MessageSourceUtils.getString("order_service_0011")); } @@ -498,7 +499,11 @@ Long memberId = LoginUserUtils.getAppLoginUser().getId(); OrderCoinsEntity orderCoinsEntity = orderCoinsDao.selectById(orderId); if (ObjectUtil.isNotEmpty(orderCoinsEntity) && orderCoinsEntity.getMemberId() == memberId) { if (orderCoinsEntity.getOrderStatus() == OrderCoinsEntity.ORDERSTATUS_CANCEL) { // 如果是撮合交易单 if (SymbolsConstats.EXCHANGE_SYMBOLS.contains(orderCoinsEntity.getSymbol())) { return this.cancelEntrustWalletCoinOrderForMatch(orderId); } if (orderCoinsEntity.getOrderStatus() == OrderCoinsEntity.ORDERSTATUS_CANCEL || orderCoinsEntity.getOrderStatus()==OrderCoinsEntity.ORDERSTATUS_DONE) { return Result.fail(MessageSourceUtils.getString("order_service_0012")); } orderCoinsEntity.setOrderStatus(OrderCoinsEntity.ORDERSTATUS_CANCEL); @@ -580,7 +585,7 @@ CoinTrader trader = factory.getTrader(orderCoinsEntity.getSymbol()); trader.cancelOrder(orderCoinsEntity); if (ObjectUtil.isNotEmpty(orderCoinsEntity) && orderCoinsEntity.getMemberId() == memberId) { if (orderCoinsEntity.getOrderStatus() == OrderCoinsEntity.ORDERSTATUS_CANCEL) { if (orderCoinsEntity.getOrderStatus() == OrderCoinsEntity.ORDERSTATUS_CANCEL || orderCoinsEntity.getOrderStatus()==OrderCoinsEntity.ORDERSTATUS_DONE) { return Result.fail(MessageSourceUtils.getString("order_service_0012")); } orderCoinsEntity.setOrderStatus(OrderCoinsEntity.ORDERSTATUS_CANCEL); @@ -611,15 +616,23 @@ if (ObjectUtil.isNotEmpty(walletCoin)) { //手续费 = 开仓价*数量*手续费率 //返还金额=开仓价*未成交数量+手续费 BigDecimal returnBalance = orderCoinsEntity.getDealAmount(); walletCoin.setAvailableBalance(walletCoin.getAvailableBalance().add(returnBalance)); BigDecimal returnBalance = orderCoinsEntity.getEntrustAmount().subtract(orderCoinsEntity.getDealAmount()); // 需要退回的手续费 BigDecimal returnFee = BigDecimal.ZERO; if (returnBalance.compareTo(orderCoinsEntity.getEntrustAmount()) == 0) { returnFee = orderCoinsEntity.getFeeAmount(); } else { // 按比例退回 BigDecimal needFee = orderCoinsEntity.getDealAmount().divide(orderCoinsEntity.getEntrustAmount(), 8, BigDecimal.ROUND_DOWN).multiply(orderCoinsEntity.getFeeAmount()); returnFee = orderCoinsEntity.getFeeAmount().subtract(needFee); } walletCoin.setAvailableBalance(walletCoin.getAvailableBalance().add(returnBalance).add(returnFee)); walletCoin.setFrozenBalance(walletCoin.getFrozenBalance().subtract(returnBalance)); memberWalletCoinDao.updateById(walletCoin); // 流水记录 MemberAccountFlowEntity record = new MemberAccountFlowEntity(); record.setSource(MemberAccountFlowEntity.SOURCE_CANCEL); record.setRemark(MemberAccountFlowEntity.REMARK_CANCEL + symbol + MemberAccountFlowEntity.REMARK_RETURNBALANCE + returnBalance); record.setRemark(MemberAccountFlowEntity.REMARK_CANCEL + symbol + MemberAccountFlowEntity.REMARK_RETURNBALANCE + returnBalance.add(returnFee)); record.setBalance(walletCoin.getAvailableBalance()); record.setMemberId(memberId); record.setSymbol(symbol); @@ -631,8 +644,8 @@ //如果是限价卖出,撤单将对应的钱包冻结金额返回 MemberWalletCoinEntity walletCoin = memberWalletCoinDao.selectWalletCoinBymIdAndCode(memberId, symbol); if (ObjectUtil.isNotEmpty(walletCoin)) { BigDecimal returnBalance = orderCoinsEntity.getEntrustCnt(); // 卖出按卖出的数量计算手续费 BigDecimal returnBalance = orderCoinsEntity.getEntrustCnt().subtract(orderCoinsEntity.getDealCnt()); walletCoin.setAvailableBalance(walletCoin.getAvailableBalance().add(returnBalance)); walletCoin.setFrozenBalance(walletCoin.getFrozenBalance().subtract(returnBalance)); memberWalletCoinDao.updateById(walletCoin); @@ -802,7 +815,7 @@ @Transactional(rollbackFor = Exception.class) public void dealEntrustCoinOrder() { List<String> ignoreTypes = new ArrayList<>(); ignoreTypes.add("NEKK"); ignoreTypes.add(SymbolsConstats.ROC); List<OrderCoinsEntity> list = orderCoinsDao.selectAllEntrustingCoinOrderList(ignoreTypes); if (CollUtil.isNotEmpty(list)) { for (OrderCoinsEntity orderCoinsEntity : list) { @@ -869,7 +882,9 @@ } } @Transactional public void handleOrder(List<ExchangeTrade> trades){ // 处理撮合交易的订单 for(ExchangeTrade exchangeTrade : trades){ if(exchangeTrade==null){ @@ -889,16 +904,28 @@ // 买卖单都需要处理 // 买单 OrderCoinsEntity buyOrderCoinsEntity = orderCoinsDao.selectById(buyOrderId); if(buyOrderCoinsEntity==null){ return; } BigDecimal buyEntrustCnt = buyOrderCoinsEntity.getEntrustCnt(); if(buyEntrustCnt==null){ buyEntrustCnt = BigDecimal.ZERO; } Long memberId = buyOrderCoinsEntity.getMemberId(); if(buyOrderCoinsEntity!=null){ // 比较剩余的量 BigDecimal dealAmount = buyOrderCoinsEntity.getDealAmount(); // 单的总金额 BigDecimal entrustAmount = buyOrderCoinsEntity.getEntrustAmount(); BigDecimal add = dealAmount.add(buyTurnover); BigDecimal closingPrice = buyTurnover.multiply(new BigDecimal("0.002")); //成交量 BigDecimal dealCnt = buyOrderCoinsEntity.getDealCnt().add(amount); // 创建一个完成的单 OrderCoinsDealEntity detail = new OrderCoinsDealEntity(); detail.setMemberId(buyOrderCoinsEntity.getMemberId()); //detail.setOrderId(order.getId()); detail.setOrderId(buyOrderCoinsEntity.getId()); detail.setOrderNo(buyOrderCoinsEntity.getOrderNo()); detail.setOrderType(buyOrderCoinsEntity.getOrderType()); detail.setTradeType(buyOrderCoinsEntity.getTradeType()); @@ -907,11 +934,11 @@ detail.setEntrustPrice(buyOrderCoinsEntity.getEntrustPrice()); detail.setDealPrice(price); detail.setDealAmount(buyTurnover); //detail.setFeeAmount(closingPrice); detail.setFeeAmount(closingPrice); detail.setOrderStatus(OrderCoinsDealEntity.ORDERSTATUS_DONE); orderCoinDealDao.insert(detail); // 如果这个单成交完 更改状态 if(add.compareTo(entrustAmount)>=0){ if (add.compareTo(entrustAmount) >= 0 ||(buyEntrustCnt.compareTo(BigDecimal.ZERO)>0 &&dealCnt.compareTo(buyEntrustCnt)>=0) ) { OrderCoinsEntity update = new OrderCoinsEntity(); update.setId(buyOrderId); update.setDealAmount(entrustAmount); @@ -939,7 +966,7 @@ // 创建一个完成的单 OrderCoinsDealEntity detail = new OrderCoinsDealEntity(); detail.setMemberId(sellOrderCoinsEntity.getMemberId()); //detail.setOrderId(order.getId()); detail.setOrderId(sellOrderCoinsEntity.getId()); detail.setOrderNo(sellOrderCoinsEntity.getOrderNo()); detail.setOrderType(sellOrderCoinsEntity.getOrderType()); detail.setTradeType(sellOrderCoinsEntity.getTradeType()); @@ -971,12 +998,47 @@ update.setUpdateTime(new Date()); orderCoinsDao.updateById(update); } // 卖币得到的usdt MemberWalletCoinEntity memberWalletCoinEntity = memberWalletCoinDao.selectWalletCoinBymIdAndCode(sellOrderCoinsEntity.getMemberId(), sellOrderCoinsEntity.getSymbol()); if(memberWalletCoinEntity!=null){ memberWalletCoinDao.updateWalletBalance(memberWalletCoinEntity.getId(),buyTurnover,buyTurnover,null); // 买币扣除冻结usdt 增加币种的可用 MemberWalletCoinEntity usdtWallet = memberWalletCoinDao.selectWalletCoinBymIdAndCode(buyOrderCoinsEntity.getMemberId(), MemberWalletCoinEnum.WALLETCOINCODE.getValue()); if (usdtWallet != null) { // 减少usdt冻结 memberWalletCoinDao.updateWalletBalance(usdtWallet.getId(), null, null, buyTurnover.negate()); } // 增加买的币 MemberWalletCoinEntity buySymbolWallet = memberWalletCoinDao.selectWalletCoinBymIdAndCode(buyOrderCoinsEntity.getMemberId(), buyOrderCoinsEntity.getSymbol()); if (buySymbolWallet != null) { memberWalletCoinDao.updateWalletBalance(buySymbolWallet.getId(), amount, amount, null); } // 流水记录 MemberAccountFlowEntity record = new MemberAccountFlowEntity(); record.setMemberId(buyOrderCoinsEntity.getMemberId()); record.setPrice(buyTurnover.setScale(4, BigDecimal.ROUND_DOWN).negate()); record.setSource(MemberAccountFlowEntity.SOURCE_BUY + buyOrderCoinsEntity.getSymbol()); record.setRemark(MemberAccountFlowEntity.REMARK_BUY + buyOrderCoinsEntity.getSymbol() + ":" + amount); record.setSymbol(buyOrderCoinsEntity.getSymbol()); record.setBalance(usdtWallet.getAvailableBalance().subtract(buyTurnover)); memberAccountFlowEntityDao.insert(record); // 卖家需要减少冻结的币种 增加usdt MemberWalletCoinEntity memberWalletCoinEntity = memberWalletCoinDao.selectWalletCoinBymIdAndCode(sellOrderCoinsEntity.getMemberId(), sellOrderCoinsEntity.getSymbol()); if (memberWalletCoinEntity != null) { // 更新卖币减少的币种 memberWalletCoinDao.updateWalletBalance(memberWalletCoinEntity.getId(), null, null, amount.negate()); } // 更新卖币得到的usdt MemberWalletCoinEntity sellWalletCoinEntity = memberWalletCoinDao.selectWalletCoinBymIdAndCode(sellOrderCoinsEntity.getMemberId(), MemberWalletCoinEnum.WALLETCOINCODE.getValue()); if (sellOrderCoinsEntity != null) { memberWalletCoinDao.updateWalletBalance(sellWalletCoinEntity.getId(), buyTurnover, buyTurnover, null); } // 流水记录 MemberAccountFlowEntity recordSell = new MemberAccountFlowEntity(); recordSell.setMemberId(sellOrderCoinsEntity.getMemberId()); recordSell.setPrice(buyTurnover.setScale(4, BigDecimal.ROUND_DOWN)); recordSell.setSource(MemberAccountFlowEntity.SOURCE_SALE + buyOrderCoinsEntity.getSymbol()); recordSell.setRemark(MemberAccountFlowEntity.REMARK_SALE + buyOrderCoinsEntity.getSymbol() + ":" + amount.toPlainString()); recordSell.setSymbol(buyOrderCoinsEntity.getSymbol()); recordSell.setBalance(sellWalletCoinEntity.getAvailableBalance().add(buyTurnover)); memberAccountFlowEntityDao.insert(recordSell); } } } @@ -1043,4 +1105,5 @@ CoinTrader trader = factory.getTrader(symbol); trader.trade(order); } } src/main/java/com/xcong/excoin/modules/symbols/constants/SymbolsConstats.java
New file @@ -0,0 +1,12 @@ package com.xcong.excoin.modules.symbols.constants; import java.util.ArrayList; import java.util.List; public class SymbolsConstats { public final static List<String> EXCHANGE_SYMBOLS = new ArrayList<>(); public final static String ROC = "ROC"; static { EXCHANGE_SYMBOLS.add("ROC"); } } src/main/java/com/xcong/excoin/modules/symbols/controller/SymbolsController.java
@@ -1,5 +1,6 @@ package com.xcong.excoin.modules.symbols.controller; import com.alibaba.fastjson.JSON; import com.huobi.client.model.Candlestick; import com.xcong.excoin.common.response.Result; import com.xcong.excoin.modules.symbols.parameter.dto.KlineDetailDto; src/main/java/com/xcong/excoin/modules/symbols/service/impl/SymbolsServiceImpl.java
@@ -128,6 +128,11 @@ PlatformCnyUsdtExchangeEntity cnyUsdtExchange = platformCnyUsdtExchangeDao.getCNYAndUSDTOne(); // 获取当日k线数据 Candlestick symbolObject = (Candlestick) redisUtils.get(symbol); if(symbolObject==null){ symbolObject = new Candlestick(); symbolObject.setOpen(new BigDecimal(1)); symbolObject.setAmount(new BigDecimal(1)); } // 获取当前币种最新价 BigDecimal newestPrice = new BigDecimal(redisUtils.getString(CoinTypeConvert.convertToKey(symbol))); // 获取当日k线的开盘价 src/main/java/com/xcong/excoin/processor/DefaultCoinProcessor.java
@@ -362,7 +362,7 @@ // 存储昨日K线 if("day".equals(rangeUnit)){ redisUtils.set("NEKK/USDT",kLine); redisUtils.set("ROC/USDT",kLine); } } src/main/java/com/xcong/excoin/quartz/job/BlockCoinUpdateJob.java
@@ -60,4 +60,11 @@ blockCoinService.updateXrp(); } /** * ETH_USDT 同步 */ @Scheduled(cron = "0 0/5 * * * ? ") public void rocUpdate() { blockCoinService.updateEthUsdt(); } } src/main/java/com/xcong/excoin/quartz/job/CoinTradeInitJob.java
@@ -10,6 +10,7 @@ import com.xcong.excoin.modules.coin.dao.OrderCoinsDao; import com.xcong.excoin.modules.coin.entity.OrderCoinsEntity; import com.xcong.excoin.modules.coin.service.OrderCoinService; import com.xcong.excoin.modules.symbols.constants.SymbolsConstats; import com.xcong.excoin.modules.symbols.service.SymbolsService; import com.xcong.excoin.processor.CoinProcessor; import com.xcong.excoin.processor.CoinProcessorFactory; @@ -43,7 +44,7 @@ **/ @Slf4j @Component //@ConditionalOnProperty(prefix = "app", name = "trade", havingValue = "true") @ConditionalOnProperty(prefix = "app", name = "trade", havingValue = "true") public class CoinTradeInitJob { @Resource @@ -69,7 +70,7 @@ @PostConstruct public void initCoinTrade() { log.info("#=======撮合交易器开启=======#"); String symbol = "NEKK"; String symbol = SymbolsConstats.ROC; CoinTrader newTrader = new CoinTrader(symbol); newTrader.setExchangeProducer(exchangeProducer); //newTrader.setKafkaTemplate(kafkaTemplate); @@ -104,7 +105,7 @@ processor.initializeThumb(); //processor.initializeUsdRate(); processor.setIsHalt(false); List<ExchangeTrade> nekk = orderCoinDealDao.selectOrderCoinDealByTime("NEKK", null, null); List<ExchangeTrade> nekk = orderCoinDealDao.selectOrderCoinDealByTime(SymbolsConstats.ROC, null, null); processor.process(nekk); String symbolUsdt = symbol; if(!symbol.contains("USDT")){ src/main/java/com/xcong/excoin/quartz/job/KLineGeneratorJob.java
@@ -1,28 +1,16 @@ package com.xcong.excoin.quartz.job; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.huobi.client.model.Candlestick; import com.xcong.excoin.modules.coin.dao.OrderCoinDealDao; import com.xcong.excoin.modules.coin.entity.OrderCoinsDealEntity; import com.xcong.excoin.modules.coin.service.OrderCoinService; import com.xcong.excoin.processor.CoinProcessorFactory; import com.xcong.excoin.trade.TradePlateModel; import com.xcong.excoin.utils.RedisUtils; import com.xcong.excoin.websocket.CandlestickModel; import com.xcong.excoin.websocket.NewCandlestick; import com.xcong.excoin.websocket.TradePlateSendWebSocket; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Random; /** @@ -40,35 +28,19 @@ @Scheduled(cron = "0/1 * * * * *") //@Scheduled(cron = "0/40 * * * * *") public void test(){ // for(int i=1;i<=2;i++){ // OrderCoinsDealEntity detail = new OrderCoinsDealEntity(); // detail.setMemberId(13L); // //detail.setOrderId(111); // detail.setOrderNo("tete"); // detail.setOrderType(1); // detail.setTradeType(1); // detail.setSymbol("NEKK"); // detail.setSymbolCnt(new BigDecimal(10)); // detail.setEntrustPrice(new BigDecimal(10)); // detail.setDealPrice(new BigDecimal(i*10*Math.random())); // detail.setDealAmount(new BigDecimal(50)); // detail.setFeeAmount(new BigDecimal(1)); // detail.setOrderStatus(OrderCoinsDealEntity.ORDERSTATUS_DONE); // orderCoinDealDao.insert(detail); // } Random random = new Random(); Integer type = OrderCoinsDealEntity.ORDERTYPE_BUY; Integer tradeType = OrderCoinsDealEntity.TRADETYPE_FIXEDPRICE; int i = random.nextInt(100); if(i==0){ i=10; double random1 = Math.random(); BigDecimal price = new BigDecimal(random1).setScale(4, RoundingMode.HALF_UP).multiply(new BigDecimal("2")); if(price.compareTo(BigDecimal.ZERO)==0){ price = BigDecimal.ONE; } BigDecimal price = new BigDecimal(i); orderCoinService.initOrders("NEKK",type,tradeType,price,new BigDecimal(2),null); orderCoinService.initOrders("NEKK",OrderCoinsDealEntity.ORDERTYPE_SELL,tradeType,price,new BigDecimal(2),null); System.out.println(price); orderCoinService.initOrders("ROC",type,tradeType,price,new BigDecimal(2),null); orderCoinService.initOrders("ROC",OrderCoinsDealEntity.ORDERTYPE_SELL,tradeType,price,new BigDecimal(2),null); } @@ -130,6 +102,11 @@ long time = calendar.getTimeInMillis(); processor.generateKLine(1, Calendar.HOUR_OF_DAY, time); // 四小时K线 int hour = calendar.get(Calendar.HOUR_OF_DAY); if(hour%4==0){ processor.generateKLine(4, Calendar.HOUR_OF_DAY, time); } } }); } src/main/java/com/xcong/excoin/quartz/job/NewestPriceUpdateJob.java
@@ -52,8 +52,8 @@ // TODO 测试环境关闭这个插入redis redisUtils.set(CoinTypeConvert.convertToKey(symbol), price); // 比较 websocketPriceService.comparePriceAsc(symbol, price); websocketPriceService.comparePriceDesc(symbol, price); //websocketPriceService.comparePriceAsc(symbol, price); //websocketPriceService.comparePriceDesc(symbol, price); //System.out.println("比较完毕:"+symbol+"-"+price); } src/main/java/com/xcong/excoin/quartz/job/NotionalPoolingJob.java
@@ -27,7 +27,7 @@ /** * usdt 归集 */ @Scheduled(cron = "0 5/30 * * * ? ") // @Scheduled(cron = "0 5/30 * * * ? ") public void poolUsdtEth() { try { log.info("USDT归集开始"); @@ -38,13 +38,13 @@ } } @Scheduled(cron = "0 2/8 * * * ? ") //@Scheduled(cron = "0 2/8 * * * ? ") public void usdtEthPoolCheck() { log.info("USDTETH归集结果扫描开始"); usdtEthService.usdtEthPoolCheck(); } @Scheduled(cron = "0 2/30 * * * ? ") //@Scheduled(cron = "0 2/30 * * * ? ") public void poolEth() { try { usdtEthService.ethPool(); src/main/java/com/xcong/excoin/quartz/job/UsdtCnyExchangePriceUpdateJob.java
@@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.platform.dao.PlatformCnyUsdtExchangeDao; import com.xcong.excoin.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; @@ -28,6 +29,9 @@ @Resource private PlatformCnyUsdtExchangeDao cnyUsdtExchangeDao; @Resource private RedisUtils redisUtils; @Scheduled(cron = "0 */5 * * * ? ") public void updateUsdtCnyExchange() { @@ -59,6 +63,7 @@ if ("200".equals(code)) { JSONObject jsonData = (JSONObject) jsonObject.get("data"); cnyUsdtExchangeDao.updateUsdt(BigDecimal.valueOf(jsonData.getDouble("price"))); redisUtils.set("platform_cny_usdt_exchange",BigDecimal.valueOf(jsonData.getDouble("price"))); } } catch (Exception e) { e.printStackTrace(); src/main/java/com/xcong/excoin/rabbit/consumer/ExchangeConsumer.java
@@ -49,7 +49,7 @@ */ @RabbitListener(queues = RabbitMqConfig.QUEUE_TRADE_PLATE) public void tradePlate(String content) { tradePlateSendWebSocket.sendMessagePlate("NEKK/USDT",content,null); tradePlateSendWebSocket.sendMessagePlate("ROC/USDT",content,null); } /** src/main/java/com/xcong/excoin/rabbit/consumer/OperateOrderPriceConsumer.java
@@ -17,7 +17,7 @@ * @author helius */ @Component @ConditionalOnProperty(prefix = "app", name = "newest-price-update-job", havingValue = "true") @ConditionalOnProperty(prefix = "app", name = "newest-price-update-job-contract", havingValue = "true") public class OperateOrderPriceConsumer { src/main/java/com/xcong/excoin/rabbit/init/OrderProducerInit.java
@@ -27,7 +27,7 @@ */ @Slf4j @Component @ConditionalOnProperty(prefix = "app", name = "newest-price-update-job", havingValue = "true") @ConditionalOnProperty(prefix = "app", name = "newest-price-update-job-contract", havingValue = "true") public class OrderProducerInit { @Resource src/main/java/com/xcong/excoin/trade/CoinTrader.java
@@ -2,6 +2,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.coin.entity.OrderCoinsEntity; import com.xcong.excoin.modules.coin.service.OrderCoinService; import com.xcong.excoin.rabbit.producer.ExchangeProducer; @@ -139,9 +140,16 @@ return; } // 如果 if(OrderCoinsEntity.ORDERTYPE_BUY==exchangeOrder.getOrderType()){ if (exchangeOrder.getEntrustAmount().compareTo(BigDecimal.ZERO) <= 0 || exchangeOrder.getEntrustAmount().subtract(exchangeOrder.getDealAmount()).compareTo(BigDecimal.ZERO) <= 0) { return; } }else{ if (exchangeOrder.getEntrustCnt().compareTo(BigDecimal.ZERO) <= 0 || exchangeOrder.getEntrustCnt().subtract(exchangeOrder.getDealCnt()).compareTo(BigDecimal.ZERO) <= 0) { return; } } TreeMap<BigDecimal, MergeOrder> limitPriceOrderList; LinkedList<OrderCoinsEntity> marketPriceOrderList; @@ -402,6 +410,7 @@ availAmount = calculateTradedAmount(matchOrder, dealPrice); //计算成交量 取少的 BigDecimal tradedAmount = (availAmount.compareTo(needAmount) >= 0 ? needAmount : availAmount); System.out.println("成交量:"+tradedAmount); //logger.info("dealPrice={},amount={}", dealPrice, tradedAmount); //如果成交额为0说明剩余额度无法成交,退出 if (tradedAmount.compareTo(BigDecimal.ZERO) == 0) { src/main/java/com/xcong/excoin/utils/CoinTypeConvert.java
@@ -22,8 +22,8 @@ return "EOS/USDT"; case "etcusdt": return "ETC/USDT"; case "nekkusdt": return "NEKK/USDT"; case "rocusdt": return "ROC/USDT"; default: return null; } @@ -33,8 +33,8 @@ switch (symbol) { case "BTC/USDT": return "btcusdt"; case "NEKK/USDT": return "nekkusdt"; case "ROC/USDT": return "rocusdt"; default: return null; } @@ -56,8 +56,8 @@ return "EOS_NEW_PRICE"; case "ETC/USDT": return "ETC_NEW_PRICE"; case "NEKK/USDT": return "NEKK_NEW_PRICE"; case "ROC/USDT": return "ROC_NEW_PRICE"; default: return null; } src/main/java/com/xcong/excoin/websocket/TradePlateSendWebSocket.java
@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject; import com.huobi.client.model.Candlestick; import com.xcong.excoin.common.contants.AppContants; import com.xcong.excoin.modules.symbols.constants.SymbolsConstats; import com.xcong.excoin.trade.CoinTraderFactory; import com.xcong.excoin.utils.CoinTypeConvert; import com.xcong.excoin.utils.RedisUtils; @@ -82,6 +83,7 @@ JSONObject jsonObject = JSON.parseObject(message); // 盘口的判断 if (jsonObject.containsKey("sub") && jsonObject.get("sub").toString().contains("depth")) { String sub = jsonObject.get("sub").toString(); String symbol = sub.split("\\.")[1]; symbol = CoinTypeConvert.convert(symbol); @@ -95,9 +97,9 @@ // 发送一次盘口 CoinTraderFactory factory = SpringContextHolder.getBean(CoinTraderFactory.class); // 发送订阅消息 String nekk = factory.getTrader("NEKK").sendTradePlateMessage(); String nekk = factory.getTrader(SymbolsConstats.ROC).sendTradePlateMessage(); SubResultModel subResultModel = new SubResultModel(); subResultModel.setId("nekkusdt"); subResultModel.setId("rocusdt"); subResultModel.setSubbed(sub); synchronized (session){ try { @@ -188,7 +190,7 @@ String key = "KINE_{}_{}"; // 币币k线数据 //key = StrUtil.format(key, symbol, period); key = StrUtil.format(key, "NEKK/USDT", period); key = StrUtil.format(key, "ROC/USDT", period); RedisUtils bean = SpringContextHolder.getBean(RedisUtils.class); Object o = bean.get(key); List<CandlestickModel> candlestickModels = new ArrayList<>(); src/main/resources/application-test.yml
@@ -7,9 +7,9 @@ profiles: active: dev datasource: url: jdbc:mysql://120.27.238.55:3306/kss_framework?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8 username: ct_test password: 123456 url: jdbc:mysql://47.114.114.219:3306/db_roc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8 username: roc_user password: roc123pasd!@ driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: @@ -91,17 +91,17 @@ app: debug: true debug: false redis_expire: 3000 kline-update-job: false newest-price-update-job: false newest-price-update-job: true #日线 该任务不能与最新价处于同一个服务器 trade: false trade: true day-line: false other-job: false loop-job: false other-job: true loop-job: true rabbit-consumer: true block-job: false block-job: true aliyun: oss: src/main/resources/mapper/member/MemberWalletCoinDao.xml
@@ -43,13 +43,19 @@ update member_wallet_coin <set> <if test="availableBalance != null"> available_balance = IFNULL(available_balance, 0) + #{availableBalance}, available_balance = ( case when IFNULL(available_balance, 0) + #{availableBalance}>0 then IFNULL(available_balance, 0) + #{availableBalance} else 0 end ), </if> <if test="totalBalance != null"> total_balance = IFNULL(total_balance, 0) + #{totalBalance}, total_balance = ( case when IFNULL(total_balance, 0) + #{totalBalance}>0 then IFNULL(total_balance, 0) + #{totalBalance} else 0 end ), </if> <if test="frozenBalance != null"> frozen_balance = IFNULL(frozen_balance, 0) + #{frozenBalance}, frozen_balance = ( case when IFNULL(frozen_balance, 0) + #{frozenBalance}>0 then IFNULL(frozen_balance, 0) + #{frozenBalance} else 0 end ), </if> </set> where id=#{id} src/test/java/com/xcong/excoin/TradeTest.java
New file @@ -0,0 +1,34 @@ package com.xcong.excoin; import com.xcong.excoin.modules.coin.dao.OrderCoinsDao; import com.xcong.excoin.modules.coin.entity.OrderCoinsEntity; import com.xcong.excoin.modules.coin.service.OrderCoinService; import com.xcong.excoin.trade.CoinTrader; import com.xcong.excoin.utils.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import java.math.BigDecimal; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @Slf4j @SpringBootTest public class TradeTest { @Resource private OrderCoinService orderCoinService; @Resource OrderCoinsDao orderCoinsDao; @Resource RedisUtils redisUtils; @Test public void buy(){ redisUtils.set("ROC_NEW_PRICE",new BigDecimal("12.33")); } }