| | |
| | | package com.yami.trading.api.controller.exchange; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.yami.trading.admin.dto.PurchaseRecordDto; |
| | | import com.yami.trading.bean.data.domain.Realtime; |
| | | import com.yami.trading.bean.exchange.ExchangeApplyOrder; |
| | | import com.yami.trading.bean.exchange.dto.ExchangeSymbolDto; |
| | | import com.yami.trading.bean.exchange.dto.SumEtfDto; |
| | | import com.yami.trading.bean.ico.domain.Ico; |
| | | import com.yami.trading.bean.item.domain.Item; |
| | | import com.yami.trading.bean.model.*; |
| | | import com.yami.trading.bean.purchasing.dto.ExchangeLock; |
| | | import com.yami.trading.bean.syspara.domain.Syspara; |
| | | import com.yami.trading.common.domain.Result; |
| | | import com.yami.trading.common.domain.UUIDEntity; |
| | | import com.yami.trading.common.exception.YamiShopBindException; |
| | | import com.yami.trading.common.util.Arith; |
| | | import com.yami.trading.common.util.DateUtils; |
| | | import com.yami.trading.common.util.StringUtils; |
| | | import com.yami.trading.common.util.ThreadUtils; |
| | | import com.yami.trading.common.util.*; |
| | | import com.yami.trading.security.common.util.SecurityUtils; |
| | | import com.yami.trading.service.CapitaltWalletService; |
| | | import com.yami.trading.service.RealNameAuthRecordService; |
| | |
| | | import com.yami.trading.service.exchange.ExchangeApplyOrderService; |
| | | import com.yami.trading.service.item.ItemService; |
| | | import com.yami.trading.service.syspara.SysparaService; |
| | | import com.yami.trading.service.user.PurchaseRecordService; |
| | | import com.yami.trading.service.user.UserService; |
| | | import com.yami.trading.service.user.WalletExtendService; |
| | | import com.yami.trading.util.ConverterUtil; |
| | | import io.swagger.annotations.Api; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.CrossOrigin; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.DecimalFormat; |
| | | import java.time.LocalDate; |
| | | import java.util.*; |
| | | |
| | | /** |
| | |
| | | ItemService itemService; |
| | | @Autowired |
| | | CapitaltWalletService capitaltWalletService; |
| | | @Autowired |
| | | WalletExtendService walletExtendService; |
| | | @Autowired |
| | | PurchaseRecordService purchaseRecordService; |
| | | |
| | | |
| | | /** |
| | | * 12.29定制ico购买 |
| | | */ |
| | | @RequestMapping(action + "ico_buy.action") |
| | | public Object ico_buy(HttpServletRequest request) { |
| | | |
| | | // 委托数量 |
| | | String volume = request.getParameter("volume"); |
| | | String session_token = request.getParameter("session_token"); |
| | | String symbol = request.getParameter("symbol"); |
| | | // limit order的交易价格 |
| | | String price = request.getParameter("price"); |
| | | // 计划委托 是之前火币那边拷贝学过来的一个功能 只是只有一个盘在用,暂时注释不用 |
| | | // 是否计划委托 |
| | | String is_trigger_order = request.getParameter("is_trigger_order"); |
| | | // 计划委托的触发价 |
| | | String trigger_price = request.getParameter("trigger_price"); |
| | | // 订单报价类型。 "limit":限价 "opponent":对手价(市价) |
| | | String order_price_type = request.getParameter("order_price_type"); |
| | | |
| | | Result<Object> result = getObjectResult(volume, session_token, symbol, price, is_trigger_order, trigger_price, order_price_type); |
| | | if(!result.isSucceed()){ |
| | | return result; |
| | | } |
| | | |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | User user = userService.getById(partyId); |
| | | |
| | | PurchaseRecord purchaseRecord = purchaseRecordService.getOne(new LambdaQueryWrapper<>(PurchaseRecord.class) |
| | | .eq(PurchaseRecord::getUserId, user.getUserId())); |
| | | |
| | | BigDecimal amount = new BigDecimal(volume).divide(new BigDecimal(price)).setScale(4,RoundingMode.HALF_UP); |
| | | if(ObjectUtil.isEmpty(purchaseRecord)){ |
| | | PurchaseRecord record = new PurchaseRecord(); |
| | | record.setUserId(user.getUserId()); |
| | | record.setPurchaseQuantity(amount); |
| | | record.setPurchasePrice(new BigDecimal(price)); |
| | | record.setTotalAmount(new BigDecimal(volume)); |
| | | purchaseRecordService.save(record); |
| | | return Result.succeed(); |
| | | } |
| | | purchaseRecord.setPurchaseQuantity(purchaseRecord.getPurchaseQuantity().add(amount)); |
| | | purchaseRecord.setTotalAmount(purchaseRecord.getTotalAmount().add(new BigDecimal(volume))); |
| | | purchaseRecord.setPurchasePrice(purchaseRecord.getTotalAmount().divide(purchaseRecord.getPurchaseQuantity(), 4,RoundingMode.HALF_UP)); |
| | | purchaseRecordService.updateById(purchaseRecord); |
| | | return Result.succeed(); |
| | | } |
| | | |
| | | /** |
| | | * 12.29定制ico购买 |
| | | */ |
| | | @RequestMapping(action + "get_ico_position.action") |
| | | public Object get_ico_position(HttpServletRequest request) { |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | User user = userService.getById(partyId); |
| | | List<Realtime> realtime_list = this.dataService.realtime("pendleusdt"); |
| | | Realtime realtime = null; |
| | | if (realtime_list.size() > 0) { |
| | | realtime = realtime_list.get(0); |
| | | } |
| | | BigDecimal close = BigDecimal.ZERO; |
| | | if (null != realtime) { |
| | | close = realtime.getClose(); |
| | | } |
| | | |
| | | |
| | | |
| | | PurchaseRecord purchaseRecord = purchaseRecordService.getOne(new LambdaQueryWrapper<>(PurchaseRecord.class) |
| | | .eq(PurchaseRecord::getUserId, user.getUserId())); |
| | | if(ObjectUtil.isNotEmpty(purchaseRecord)){ |
| | | PurchaseRecordDto purchaseRecordDto = ConverterUtil.convert(purchaseRecord, PurchaseRecordDto.class); |
| | | Item item = itemService.getOne(new LambdaQueryWrapper<Item>().eq(Item::getName, "CLK/USDT")); |
| | | if (item != null) { |
| | | WalletExtend walletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) |
| | | .eq(WalletExtend::getWallettype, item.getSymbol()) |
| | | .eq(WalletExtend::getPartyId, user.getUserId()) |
| | | .last(" limit 1")); |
| | | if (walletExtend != null) { |
| | | purchaseRecordDto.setPurchaseQuantity(BigDecimal.valueOf(walletExtend.getAmount()).setScale(4,RoundingMode.HALF_UP)); |
| | | } |
| | | } |
| | | |
| | | purchaseRecordDto.setCurrentPrice(close); |
| | | //持仓市值 |
| | | purchaseRecordDto.setPositionvalue(close.multiply(purchaseRecordDto.getPurchaseQuantity()).setScale(4, RoundingMode.HALF_UP)); |
| | | //均价总额 |
| | | BigDecimal currentTotalPrice = purchaseRecordDto.getPurchaseQuantity().multiply(purchaseRecord.getPurchasePrice()); |
| | | BigDecimal profit = purchaseRecordDto.getPositionvalue().subtract(currentTotalPrice); |
| | | purchaseRecordDto.setProfit(profit.setScale(4, RoundingMode.HALF_UP)); |
| | | if (currentTotalPrice.compareTo(BigDecimal.ZERO) != 0) { |
| | | BigDecimal profitPercent = (purchaseRecordDto.getPositionvalue().subtract(currentTotalPrice)).divide(currentTotalPrice,4,RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP); |
| | | purchaseRecordDto.setProfitPercent(profitPercent); |
| | | } |
| | | purchaseRecordDto.setLockingTime(LocalDate.of(2026, 2, 4)); |
| | | return Result.succeed(purchaseRecordDto); |
| | | } |
| | | return Result.succeed(new PurchaseRecordDto()); |
| | | } |
| | | |
| | | /** |
| | | * 兑换币 如果是使用usdt兑换其他币种,则直接执行正常买币open流程 如果是其他币种--》usdt 则是直接卖币流程 |
| | |
| | | } |
| | | symbol = symbol.toLowerCase(); |
| | | symbol_to = symbol_to.toLowerCase(); |
| | | String relation_order_no = UUID.randomUUID().toString(); |
| | | // 如果是使用usdt兑换其他币种,则直接执行正常买币open流程 |
| | | if ("usdt".equals(symbol) || "usdt".equals(symbol_to)) { |
| | | ExchangeApplyOrder order = new ExchangeApplyOrder(); |
| | | order.setPartyId(partyId); |
| | | order.setVolume(volume); |
| | | order.setOrderPriceType("opponent"); |
| | | order.setRelationOrderNo(relation_order_no); |
| | | if ("usdt".equals(symbol)) { |
| | | order.setSymbol(symbol_to); |
| | | double openPrice = getRealtimePrice(symbol_to); |
| | | order.setPrice(openPrice); |
| | | order.setOffset(ExchangeApplyOrder.OFFSET_OPEN); |
| | | } else if ("usdt".equals(symbol_to)) { |
| | | order.setSymbol(symbol); |
| | | double closePrice = getRealtimePrice(symbol); |
| | | order.setPrice(closePrice); |
| | | order.setOffset(ExchangeApplyOrder.OFFSET_CLOSE); |
| | | |
| | | Map<String, Object> parities = parities(symbol, symbol_to, volume_temp); |
| | | Object getVolume = parities.get("get_volume"); |
| | | if(symbol.equals("usdt")){ |
| | | CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); |
| | | if(userIdWallet.getMoney().compareTo(new BigDecimal(volume_temp)) < 0){ |
| | | throw new YamiShopBindException("not sufficient funds"); |
| | | } |
| | | exchangeApplyOrderService.saveCreate(order); |
| | | } else { |
| | | // 非usdt则需要进行一次卖出 |
| | | ExchangeApplyOrder order_sell = new ExchangeApplyOrder(); |
| | | order_sell.setPartyId(partyId); |
| | | order_sell.setSymbol(symbol); |
| | | order_sell.setOffset(ExchangeApplyOrder.OFFSET_CLOSE); |
| | | order_sell.setVolume(volume); |
| | | order_sell.setOrderPriceType("opponent"); |
| | | order_sell.setRelationOrderNo(relation_order_no); |
| | | double sellClose = getRealtimePrice(symbol); |
| | | order_sell.setPrice(sellClose); |
| | | this.exchangeApplyOrderService.saveCreate(order_sell); |
| | | double close = getRealtimePrice(symbol); |
| | | double sub = Arith.sub(volume, |
| | | Arith.mul(volume, sysparaService.find("exchange_apply_order_sell_fee").getDouble())); |
| | | double amount = Arith.mul(sub, close); |
| | | // 再买入币种 |
| | | ExchangeApplyOrder order_buy = new ExchangeApplyOrder(); |
| | | order_buy.setPartyId(partyId); |
| | | order_buy.setSymbol(symbol_to); |
| | | order_buy.setOffset(ExchangeApplyOrder.OFFSET_OPEN); |
| | | order_buy.setVolume(amount); |
| | | order_buy.setRelationOrderNo(relation_order_no); |
| | | order_buy.setOrderPriceType("opponent"); |
| | | double buyClose = getRealtimePrice(symbol_to); |
| | | order_buy.setPrice(buyClose); |
| | | exchangeApplyOrderService.saveCreate(order_buy); |
| | | Double value = Double.valueOf(volume_temp); |
| | | capitaltWalletService.update(userIdWallet, -value); |
| | | |
| | | WalletExtend walletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) |
| | | .eq(WalletExtend::getWallettype, symbol_to) |
| | | .eq(WalletExtend::getPartyId,partyId) |
| | | .last(" limit 1")); |
| | | if(ObjectUtil.isNotEmpty(walletExtend)){ |
| | | Double valueOf = Double.valueOf(getVolume.toString()); |
| | | walletExtend.setAmount(walletExtend.getAmount() + valueOf); |
| | | System.out.println("-----------------------:"+walletExtend.toString()); |
| | | walletExtendService.update(walletExtend,new LambdaUpdateWrapper<WalletExtend>().eq(UUIDEntity::getUuid,walletExtend.getUuid())); |
| | | }else{ |
| | | WalletExtend extend = new WalletExtend(); |
| | | extend.setPartyId(partyId); |
| | | extend.setWallettype(symbol_to); |
| | | extend.setAmount(Double.valueOf(getVolume.toString())); |
| | | walletExtendService.save(extend); |
| | | } |
| | | }else if(symbol_to.equals("usdt")){ |
| | | |
| | | |
| | | WalletExtend walletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) |
| | | .eq(WalletExtend::getWallettype, symbol) |
| | | .eq(WalletExtend::getPartyId,partyId) |
| | | .last(" limit 1")); |
| | | if(ObjectUtil.isEmpty(walletExtend) || walletExtend.getAmount() < Double.valueOf(volume_temp)){ |
| | | throw new YamiShopBindException("not sufficient funds"); |
| | | } |
| | | Double valueOf = Double.valueOf(volume_temp); |
| | | walletExtend.setAmount(walletExtend.getAmount() - valueOf); |
| | | walletExtendService.update(walletExtend,new LambdaUpdateWrapper<WalletExtend>().eq(UUIDEntity::getUuid,walletExtend.getUuid())); |
| | | |
| | | |
| | | CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); |
| | | capitaltWalletService.update(userIdWallet,Double.valueOf(getVolume.toString())); |
| | | }else{ |
| | | WalletExtend walletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) |
| | | .eq(WalletExtend::getWallettype, symbol) |
| | | .eq(WalletExtend::getPartyId,partyId) |
| | | .last(" limit 1")); |
| | | if(ObjectUtil.isEmpty(walletExtend) || walletExtend.getAmount() < Double.valueOf(volume_temp)){ |
| | | throw new YamiShopBindException("not sufficient funds"); |
| | | } |
| | | Double valueOf = Double.valueOf(volume_temp); |
| | | walletExtend.setAmount(walletExtend.getAmount() - valueOf); |
| | | walletExtendService.update(walletExtend,new LambdaUpdateWrapper<WalletExtend>().eq(UUIDEntity::getUuid,walletExtend.getUuid())); |
| | | |
| | | WalletExtend toWalletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) |
| | | .eq(WalletExtend::getWallettype, symbol_to) |
| | | .eq(WalletExtend::getPartyId,partyId) |
| | | .last(" limit 1")); |
| | | Double value = Double.valueOf(getVolume.toString()); |
| | | if(ObjectUtil.isNotEmpty(toWalletExtend)){ |
| | | toWalletExtend.setAmount(toWalletExtend.getAmount() + value); |
| | | walletExtendService.update(toWalletExtend,new LambdaUpdateWrapper<WalletExtend>().eq(UUIDEntity::getUuid,toWalletExtend.getUuid())); |
| | | }else{ |
| | | WalletExtend extend = new WalletExtend(); |
| | | extend.setPartyId(partyId); |
| | | extend.setWallettype(symbol_to); |
| | | extend.setAmount(value); |
| | | walletExtendService.save(extend); |
| | | } |
| | | } |
| | | return Result.succeed(); |
| | | } |
| | | |
| | | private double getRealtimePrice(String symbol) { |
| | | List<Realtime> realtimes = dataService.realtime(symbol); |
| | | double close = 1; |
| | | if (realtimes != null && realtimes.size() > 0) { |
| | | close = realtimes.get(0).getClose().doubleValue(); |
| | | } else { |
| | | throw new YamiShopBindException("参数错误"); |
| | | } |
| | | return close; |
| | | } |
| | | |
| | | /** |
| | | * 首次进入页面,传递session_token |
| | | */ |
| | | @RequestMapping(action + "view.action") |
| | | public Result view() { |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | Map<String, Object> session = new HashMap<String, Object>(); |
| | | String session_token = sessionTokenService.savePut(partyId); |
| | | session.put("session_token", session_token); |
| | | return Result.succeed(session); |
| | | } |
| | | |
| | | /** |
| | | * 兑换汇率 |
| | | */ |
| | | @RequestMapping(action + "buy_and_sell_fee.action") |
| | | public Object buy_and_sell_fee(HttpServletRequest request) { |
| | | // 需兑换币种 |
| | | String symbol = request.getParameter("symbol"); |
| | | // 兑换后的币种 |
| | | String symbol_to = request.getParameter("symbol_to"); |
| | | if (symbol.equals(symbol_to)) { |
| | | throw new YamiShopBindException("请选择正确的币种"); |
| | | } |
| | | // 委托数量 |
| | | String volume_temp = request.getParameter("volume"); |
| | | if (StringUtils.isNullOrEmpty(volume_temp) |
| | | || !StringUtils.isDouble(volume_temp) || Double.valueOf(volume_temp) < 0) { |
| | | throw new YamiShopBindException("请输入正确的兑换数量"); |
| | | } |
| | | public Map<String,Object> parities(String symbol,String symbol_to,String volume_temp){ |
| | | Map<String, Object> data = new HashMap<String, Object>(); |
| | | symbol = symbol.toLowerCase(); |
| | | symbol_to = symbol_to.toLowerCase(); |
| | |
| | | if (symbol_price == 0) { |
| | | symbol_price = 1; |
| | | } |
| | | data.put("get_rate", Arith.div(symbol_price, symbol_to_price, 5)); |
| | | data.put("get_rate", Arith.div(symbol_price, symbol_to_price, 8)); |
| | | // 总手续费比例 |
| | | double all_fee = Arith.add(buy_fee, sell_fee); |
| | | // 实际兑换数量= 兑换数量-手续费数量 |
| | |
| | | // 实际价值 = 实际兑换数量 * 被兑换品种价格 |
| | | double fact_price = Arith.mul(fact_volume, symbol_price); |
| | | // 实际获取数量 = 实际价值 / 将要兑换的品种的价值 |
| | | data.put("get_volume", Arith.div(fact_price, symbol_to_price, 5)); |
| | | data.put("get_volume", Arith.div(fact_price, symbol_to_price, 8)); |
| | | } |
| | | return Result.succeed(data); |
| | | return data; |
| | | } |
| | | |
| | | |
| | | private double getRealtimePrice(String symbol) { |
| | | List<Realtime> realtimes = dataService.realtime(symbol); |
| | | double close = 1; |
| | | if (realtimes != null && realtimes.size() > 0) { |
| | | close = realtimes.get(0).getClose().doubleValue(); |
| | | } else { |
| | | throw new YamiShopBindException("参数错误"); |
| | | } |
| | | return close; |
| | | } |
| | | |
| | | /** |
| | | * 首次进入页面,传递session_token |
| | | */ |
| | | @RequestMapping(action + "view.action") |
| | | public Result view() { |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | Map<String, Object> session = new HashMap<String, Object>(); |
| | | String session_token = sessionTokenService.savePut(partyId); |
| | | session.put("session_token", session_token); |
| | | return Result.succeed(session); |
| | | } |
| | | |
| | | /** |
| | | * 兑换汇率 |
| | | */ |
| | | @RequestMapping(action + "buy_and_sell_fee.action") |
| | | public Object buy_and_sell_fee(HttpServletRequest request) { |
| | | // 需兑换币种 |
| | | String symbol = request.getParameter("symbol"); |
| | | // 兑换后的币种 |
| | | String symbol_to = request.getParameter("symbol_to"); |
| | | if (symbol.equals(symbol_to)) { |
| | | throw new YamiShopBindException("请选择正确的币种"); |
| | | } |
| | | // 委托数量 |
| | | String volume_temp = request.getParameter("volume"); |
| | | if (StringUtils.isNullOrEmpty(volume_temp) |
| | | || !StringUtils.isDouble(volume_temp) || Double.valueOf(volume_temp) < 0) { |
| | | throw new YamiShopBindException("请输入正确的兑换数量"); |
| | | } |
| | | Map<String, Object> parities = parities(symbol, symbol_to, volume_temp); |
| | | return Result.succeed(parities); |
| | | } |
| | | |
| | | /** |
| | |
| | | String session_token = sessionTokenService.savePut(partyId); |
| | | data.put("session_token", session_token); |
| | | data.put("fee", sysparaService.find("exchange_apply_order_sell_fee").getSvalue()); |
| | | Item item = itemService.findCurrBySymbol(symbol); |
| | | data.put("status", item.getStatus() == null || item.getStatus() == 1 ? 1 :0); |
| | | } |
| | | return Result.succeed(data); |
| | | } |
| | |
| | | String volume = request.getParameter("volume"); |
| | | String session_token = request.getParameter("session_token"); |
| | | String symbol = request.getParameter("symbol"); |
| | | // Item bySymbol = itemService.findBySymbol(symbol); |
| | | // if(bySymbol == null){ |
| | | // throw new YamiShopBindException("当前币对不存在"); |
| | | // } |
| | | // boolean isOpen = MarketOpenChecker.isMarketOpenByItemCloseType(bySymbol.getOpenCloseType()); |
| | | // if(!isOpen){ |
| | | // throw new YamiShopBindException("当前已经休市"); |
| | | // } |
| | | // limit order的交易价格 |
| | | String price = request.getParameter("price"); |
| | | // 计划委托 是之前火币那边拷贝学过来的一个功能 只是只有一个盘在用,暂时注释不用 |
| | |
| | | String trigger_price = request.getParameter("trigger_price"); |
| | | // 订单报价类型。 "limit":限价 "opponent":对手价(市价) |
| | | String order_price_type = request.getParameter("order_price_type"); |
| | | return getObjectResult(volume, session_token, symbol, price, is_trigger_order, trigger_price, order_price_type); |
| | | } |
| | | |
| | | @NotNull |
| | | private Result<Object> getObjectResult(String volume, String session_token, String symbol, String price, String is_trigger_order, String trigger_price, String order_price_type) { |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | if (StringUtils.isNullOrEmpty(volume) |
| | | || !StringUtils.isDouble(volume) |
| | |
| | | throw new YamiShopBindException("无网络"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | RealNameAuthRecord party_kyc = realNameAuthRecordService.getByUserId(partyId); |
| | |
| | | return Result.succeed(); |
| | | } |
| | | |
| | | public static boolean isAfterFebruary9th2026() { |
| | | LocalDate today = LocalDate.now(); |
| | | LocalDate targetDate = LocalDate.of(2026, 2, 9); |
| | | |
| | | return today.isAfter(targetDate); |
| | | } |
| | | |
| | | /** |
| | | * 币币交易-卖出 |
| | | */ |
| | |
| | | String order_price_type = request.getParameter("order_price_type"); |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | boolean lock = false; |
| | | |
| | | // |
| | | // if(symbol.equals("pendleusdt") && !isAfterFebruary9th2026()){ |
| | | // throw new YamiShopBindException("此币还没有发行时间"); |
| | | // } |
| | | |
| | | |
| | | if (StringUtils.isNullOrEmpty(volume) |
| | | || !StringUtils.isDouble(volume) |
| | | || Double.valueOf(volume) <= 0) { |