|
|
@@ -10,6 +10,7 @@ import com.bizzan.bitrade.entity.*;
|
|
|
import com.bizzan.bitrade.entity.MemberWallet;
|
|
|
import com.bizzan.bitrade.service.Base.BaseService;
|
|
|
import com.bizzan.bitrade.util.MessageResult;
|
|
|
+import com.bizzan.bitrade.util.RedisManager;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.context.annotation.Lazy;
|
|
|
@@ -71,6 +72,57 @@ public class StakingService extends BaseService {
|
|
|
@Autowired
|
|
|
private LocaleMessageSourceService msService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private CoinService coinService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisManager redisManager;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * IDO 预售:USDT 按现货价闪兑为质押币后走质押流程
|
|
|
+ */
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public MessageResult stakeWithUsdt(Long memberId, Long configId, BigDecimal usdtAmount) {
|
|
|
+ StakingConfig config = stakingConfigDao.findOne(configId);
|
|
|
+ if (config == null || config.getStatus() != 1) {
|
|
|
+ return MessageResult.error(msService.getMessage("STAKING_CONFIG_NOT_FOUND"));
|
|
|
+ }
|
|
|
+ if (usdtAmount == null || usdtAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return MessageResult.error(msService.getMessage("STAKING_AMOUNT_INVALID"));
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal price = redisManager.getSpotPriceUsdt(config.getCoinUnit());
|
|
|
+ if (price == null || price.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
+ return MessageResult.error(msService.getMessage("STAKING_PRICE_UNAVAILABLE"));
|
|
|
+ }
|
|
|
+
|
|
|
+ Coin coin = coinService.findByUnit(config.getCoinUnit());
|
|
|
+ if (coin == null) {
|
|
|
+ return MessageResult.error(msService.getMessage("COIN_ILLEGAL"));
|
|
|
+ }
|
|
|
+ int scale = coin.getWithdrawScale() > 0 ? coin.getWithdrawScale() : 8;
|
|
|
+ BigDecimal coinAmount = usdtAmount.divide(price, scale, RoundingMode.DOWN);
|
|
|
+
|
|
|
+ MessageResult validateResult = validateAmount(config, coinAmount);
|
|
|
+ if (validateResult.getCode() != 0) {
|
|
|
+ return validateResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ MemberWallet usdtWallet = memberWalletService.findByCoinUnitAndMemberId("USDT", memberId);
|
|
|
+ BigDecimal usdtBalance = usdtWallet != null ? usdtWallet.getBalance() : BigDecimal.ZERO;
|
|
|
+ if (usdtBalance.compareTo(usdtAmount) < 0) {
|
|
|
+ return MessageResult.error(msService.getMessage("STAKING_USDT_INSUFFICIENT"));
|
|
|
+ }
|
|
|
+
|
|
|
+ MessageResult swapResult = memberWalletService.flashSwapUsdtToCoin(
|
|
|
+ memberId, config.getCoinUnit(), usdtAmount, price);
|
|
|
+ if (swapResult.getCode() != 0) {
|
|
|
+ return swapResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ return executeStake(memberId, configId, config, coinAmount);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 用户质押:冻结余额,创建质押订单和流水
|
|
|
*
|
|
|
@@ -81,40 +133,38 @@ public class StakingService extends BaseService {
|
|
|
*/
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public MessageResult stake(Long memberId, Long configId, BigDecimal amount) {
|
|
|
- // 1. 查询质押配置
|
|
|
StakingConfig config = stakingConfigDao.findOne(configId);
|
|
|
if (config == null || config.getStatus() != 1) {
|
|
|
return MessageResult.error(msService.getMessage("STAKING_CONFIG_NOT_FOUND"));
|
|
|
}
|
|
|
|
|
|
- // 2. 校验质押金额范围
|
|
|
MessageResult validateResult = validateAmount(config, amount);
|
|
|
if (validateResult.getCode() != 0) {
|
|
|
return validateResult;
|
|
|
}
|
|
|
|
|
|
- // 3. 校验资金账户余额
|
|
|
MemberWallet fundWallet = memberWalletService.findByCoinUnitAndMemberId(config.getCoinUnit(), memberId);
|
|
|
BigDecimal currentBalance = fundWallet != null ? fundWallet.getBalance() : BigDecimal.ZERO;
|
|
|
if (currentBalance.compareTo(amount) < 0) {
|
|
|
return MessageResult.error(msService.getMessage("STAKING_INSUFFICIENT_BALANCE"));
|
|
|
}
|
|
|
|
|
|
- // 4. 资金账户 → 质押锁定(原子操作:扣资金、增锁定、记流水)
|
|
|
+ return executeStake(memberId, configId, config, amount);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 资金账户扣款并创建质押订单(调用前须已完成余额/金额校验) */
|
|
|
+ private MessageResult executeStake(Long memberId, Long configId, StakingConfig config, BigDecimal amount) {
|
|
|
MessageResult freezeResult = memberWalletService.stakeFundToLocked(memberId, config.getCoinUnit(), amount);
|
|
|
if (freezeResult.getCode() != 0) {
|
|
|
return freezeResult;
|
|
|
}
|
|
|
|
|
|
- // 5. 计算解冻时间
|
|
|
Date stakingTime = new Date();
|
|
|
Date unlockTime = calcUnlockTime(stakingTime, config.getLockDays());
|
|
|
|
|
|
- // 6. 创建质押订单
|
|
|
StakingOrder order = buildStakingOrder(memberId, configId, config.getCoinUnit(), amount, stakingTime, unlockTime);
|
|
|
stakingOrderDao.save(order);
|
|
|
|
|
|
- // 7. 创建质押流水(type=0 质押:可用转入锁定)
|
|
|
StakingRecord record = buildStakingRecord(memberId, order.getId(), config.getCoinUnit(), amount, 0, "用户质押");
|
|
|
stakingRecordDao.save(record);
|
|
|
|