Browse Source

质押初始化

dq 1 month ago
parent
commit
4a7d5e9f51
34 changed files with 1165 additions and 0 deletions
  1. 3 0
      bex-cloud-staking-api/.gitignore
  2. 66 0
      bex-cloud-staking-api/pom.xml
  3. 18 0
      bex-cloud-staking-api/src/main/java/com/bex/staking/StakingApplication.java
  4. 14 0
      bex-cloud-staking-api/src/main/java/com/bex/staking/config/GlobalExceptionHandler.java
  5. 17 0
      bex-cloud-staking-api/src/main/java/com/bex/staking/config/MybatisPlusConfig.java
  6. 345 0
      bex-cloud-staking-api/src/main/java/com/bex/staking/controller/StakingController.java
  7. 21 0
      bex-cloud-staking-api/src/main/resources/application-dev.yml
  8. 80 0
      bex-cloud-staking-api/src/main/resources/application.yml
  9. 44 0
      bex-cloud-staking-api/src/main/resources/logback.xml
  10. 3 0
      bex-cloud-staking-core/.gitignore
  11. 74 0
      bex-cloud-staking-core/pom.xml
  12. 23 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/enums/PositionStatus.java
  13. 23 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/enums/ProductStatus.java
  14. 23 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/enums/StakingStatus.java
  15. 13 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/exception/StakingException.java
  16. 10 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/dto/StakingOrderQuery.java
  17. 18 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/dto/StakingOrderReq.java
  18. 16 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingHomeVO.java
  19. 27 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingOngoingOrderDetailVO.java
  20. 24 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingOrderListVO.java
  21. 11 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingOrderResp.java
  22. 25 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingPreviewVO.java
  23. 25 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingProductDetailVO.java
  24. 18 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingProductVO.java
  25. 11 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingProfitItemVO.java
  26. 25 0
      bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingRedeemOrderDetailVO.java
  27. 3 0
      bex-cloud-staking-entity/.gitignore
  28. 40 0
      bex-cloud-staking-entity/pom.xml
  29. 3 0
      bex-cloud-staking-service/.gitignore
  30. 82 0
      bex-cloud-staking-service/pom.xml
  31. 15 0
      bex-cloud-staking-service/src/main/java/com/bex/staking/grpc/StakingGrpcClientConfig.java
  32. 5 0
      bex-cloud-staking-service/src/main/java/com/bex/staking/service/StakingService.java
  33. 15 0
      bex-cloud-staking-service/src/main/java/com/bex/staking/service/impl/StakingServiceImpl.java
  34. 25 0
      pom.xml

+ 3 - 0
bex-cloud-staking-api/.gitignore

@@ -0,0 +1,3 @@
+target/
+*.iml
+.idea/

+ 66 - 0
bex-cloud-staking-api/pom.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.bex</groupId>
+        <artifactId>bex-cloud-staking</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>bex-cloud-staking-api</artifactId>
+    <name>BEX 质押服务 - 接口模块</name>
+    <description>HTTP接口路由、请求/响应处理及API文档</description>
+
+    <dependencies>
+        <!-- 依赖核心模块 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-staking-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- 依赖实体模块 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-staking-entity</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- 依赖业务模块 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-staking-service</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- Spring Boot Web -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!-- Nacos 服务发现 -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!-- SpringDoc OpenAPI -->
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-common</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 18 - 0
bex-cloud-staking-api/src/main/java/com/bex/staking/StakingApplication.java

@@ -0,0 +1,18 @@
+package com.bex.staking;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * 质押服务启动类
+ */
+@SpringBootApplication(scanBasePackages = "com.bex.staking")
+@MapperScan("com.bex.staking.mapper")
+@EnableScheduling
+public class StakingApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(StakingApplication.class, args);
+    }
+}

+ 14 - 0
bex-cloud-staking-api/src/main/java/com/bex/staking/config/GlobalExceptionHandler.java

@@ -0,0 +1,14 @@
+package com.bex.staking.config;
+
+import com.bex.common.web.BaseGlobalExceptionHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler extends BaseGlobalExceptionHandler {
+    @Override
+    protected String getModuleName() {
+        return "Staking";
+    }
+}

+ 17 - 0
bex-cloud-staking-api/src/main/java/com/bex/staking/config/MybatisPlusConfig.java

@@ -0,0 +1,17 @@
+package com.bex.staking.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MybatisPlusConfig {
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        return interceptor;
+    }
+}

+ 345 - 0
bex-cloud-staking-api/src/main/java/com/bex/staking/controller/StakingController.java

@@ -0,0 +1,345 @@
+package com.bex.staking.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.bex.common.model.R;
+import com.bex.staking.model.dto.StakingOrderQuery;
+import com.bex.staking.model.vo.*;
+import com.bex.staking.service.StakingService;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/v1/staking")
+@RequiredArgsConstructor
+public class StakingController {
+
+
+    /**
+     * 获取质押首页信息
+     * @param userId
+     * @return
+     */
+    @GetMapping("/home")
+    public R<StakingHomeVO> stake(
+            @RequestHeader("X-User-Id") Long userId) {
+        StakingHomeVO vo = new StakingHomeVO();
+        // 1. 用户资产 mock
+        vo.setAvailableBalance("124494.01");
+        vo.setAvailableUnit("BEX");
+        vo.setTotalProfit("801.41");
+        vo.setTotalProfitUnit("BEX");
+        vo.setPendingProfit("33.49");
+        vo.setPendingProfitUnit("BEX");
+        vo.setSettleRule("每日10:00 结算收益到待领取,点击领取后到账。累计收益达到本金 80% 时,到期可能触发通缩赎回。");
+        return R.success(vo);
+    }
+
+    /**
+     * 获取推荐质押产品列表
+     * @param page
+     * @param size
+     * @return
+     */
+    @GetMapping("/recommendationPage")
+    public R<Page<StakingProductVO>> list(
+            @RequestParam(value = "page", defaultValue = "1") Integer page,
+            @RequestParam(value = "size", defaultValue = "10") Integer size,
+            @RequestParam(value = "isRecommendation", defaultValue = "true") Boolean isRecommendation) {
+
+        Page<StakingProductVO> pageData = new Page<>(page, size);
+        List<StakingProductVO> productList = new ArrayList<>();
+
+        if (isRecommendation) {
+
+            StakingProductVO p1 = new StakingProductVO();
+            p1.setProductId("1001");
+            p1.setProductName("BEX 3个月质押");
+            p1.setApr("24%");
+            p1.setStatus("可质押");
+            p1.setPeriodRate("6.0000%");
+            p1.setProfitMode("10点结算");
+            p1.setMinInvestNum("100 BEX");
+            p1.setThresholdRule("80% 通缩");
+            p1.setLockDay(90);
+
+            StakingProductVO p2 = new StakingProductVO();
+            p2.setProductId("1002");
+            p2.setProductName("BEX 6个月质押");
+            p2.setApr("34%");
+            p2.setStatus("可质押");
+            p2.setPeriodRate("6.0000%");
+            p2.setProfitMode("10点结算");
+            p2.setMinInvestNum("100 BEX");
+            p2.setThresholdRule("80% 通缩");
+            p2.setLockDay(180);
+
+            productList.add(p1);
+            productList.add(p2);
+            pageData.setRecords(productList);
+        } else {
+            // 1. BEX 3个月质押 - 可质押
+            StakingProductVO p1 = new StakingProductVO();
+            p1.setProductId("1001");
+            p1.setProductName("BEX 3个月质押");
+            p1.setApr("24%");
+            p1.setStatus("可质押");
+            p1.setPeriodRate("6.0000%");
+            p1.setProfitMode("10点结算");
+            p1.setMinInvestNum("100 BEX");
+            p1.setThresholdRule("80% 通缩");
+            p1.setLockDay(90);
+            p1.setCountDown(null);
+
+            // 2. BEX 6个月质押 - 即将开启(带倒计时)
+            StakingProductVO p2 = new StakingProductVO();
+            p2.setProductId("1002");
+            p2.setProductName("BEX 6个月质押");
+            p2.setApr("44%");
+            p2.setStatus("即将开启");
+            p2.setPeriodRate("6.0000%");
+            p2.setProfitMode("10点结算");
+            p2.setMinInvestNum("100 BEX");
+            p2.setThresholdRule("80% 通缩");
+            p2.setLockDay(180);
+            p2.setCountDown(System.currentTimeMillis() + 36000000L);
+
+            // 3. BEX 6个月质押 - 已结束
+            StakingProductVO p3 = new StakingProductVO();
+            p3.setProductId("1003");
+            p3.setProductName("BEX 6个月质押");
+            p3.setApr("78%");
+            p3.setStatus("已结束");
+            p3.setPeriodRate("6.0000%");
+            p3.setProfitMode("10点结算");
+            p3.setMinInvestNum("100 BEX");
+            p3.setThresholdRule("80% 通缩");
+            p3.setLockDay(180);
+            p3.setCountDown(null);
+
+            productList.add(p1);
+            productList.add(p2);
+            productList.add(p3);
+            pageData.setRecords(productList);
+        }
+        return R.success(pageData);
+    }
+
+
+    /**
+     * 质押产品详情接口
+     */
+    @GetMapping("/detail/{id}")
+    public R<StakingProductDetailVO> getProductDetail(@PathVariable("id") Long id) {
+        StakingProductDetailVO vo = new StakingProductDetailVO();
+        // Mock 3个月质押数据
+        vo.setProductId("1001");
+        vo.setProductName("BEX 3个月质押");
+        vo.setStatus("可质押");
+        vo.setIsShowTwap(true);
+        vo.setApr("24%");
+
+        vo.setPeriodDay(90);
+        vo.setPeriodRate("6.0000%");
+        vo.setDailyRate("0.066666%");
+        vo.setMinInvestNum("100 BEX");
+
+        vo.setBaseAmount("1,000 BEX");
+        vo.setDailyProfit("0.666666 BEX");
+        vo.setTotalProfit("60.0000 BEX");
+
+        return R.ok(vo);
+    }
+
+    /**
+     * 质押预览接口(输入数量后返回预览结果)
+     */
+    @GetMapping("/preview")
+    public R<StakingPreviewVO> stakingPreview(
+            @RequestParam(value = "productId", required = false) Long productId,
+            @RequestParam(value = "stakingNum", required = false) BigDecimal stakingNum
+    ) {
+        StakingPreviewVO vo = new StakingPreviewVO();
+        // 可用资产
+        vo.setAvailableBalance("12,000");
+        vo.setAvailableUnit("BEX");
+        // 价格&价值
+        vo.setEntryPrice("1.250000 USDT");
+        vo.setInitialValue("1,250.0000 USDT");
+        // 收益
+        vo.setDailyProfit("0.666666 BEX");
+        vo.setTotalProfit("60.0000 BEX");
+        vo.setExpireTime(System.currentTimeMillis());
+        vo.setTriggerThreshold("800.0000 BEX");
+        // 文案&规则
+        vo.setRiskTip("我已理解收益按 BEX 计发,若累计收益达到本金 80%,到期可能触发通缩赎回和销毁流程。");
+        vo.setIdempotentTip("创建订单将使用幂等键提交。网络超时后复用同一请求,不生成重复订单。");
+        vo.setValidSecond(30);
+
+        return R.ok(vo);
+    }
+
+
+    /**
+     * 我的质押订单列表接口
+     */
+    @PostMapping("/order/page")
+    public R<Page<StakingOrderListVO>> getStakingOrderList(@RequestBody StakingOrderQuery query) {
+        List<StakingOrderListVO> list = new ArrayList<>();
+        Page<StakingOrderListVO> pageData = new Page<>(query.getPage(), query.getSize());
+        // 订单1:进行中 - 3个月质押
+        StakingOrderListVO order1 = new StakingOrderListVO();
+        order1.setOrderId("100001");
+        order1.setProductName("BEX 3个月质押");
+        order1.setOrderNo("STK202605181004150001");
+        order1.setOrderStatus("进行中");
+        order1.setPrincipal("1,000 BEX");
+        order1.setTotalProfit("20 BEX");
+        order1.setExpireTime(System.currentTimeMillis());
+        order1.setProfitMode("10点结算");
+        order1.setProgressPercent(50);
+
+        // 订单2:通缩赎回 - 6个月质押
+        StakingOrderListVO order2 = new StakingOrderListVO();
+        order2.setOrderId("100002");
+        order2.setProductName("BEX 6个月质押");
+        order2.setOrderNo("STK202605181004150001");
+        order2.setOrderStatus("通缩赎回");
+        order2.setReturnPrincipal("1,000 BEX");
+        order2.setBurnAmount("20 BEX");
+        order2.setTotalProfitAmount("1,600 BEX");
+        order2.setStatusDesc("已完成");
+
+        // 订单3:进行中 - 9个月质押
+        StakingOrderListVO order3 = new StakingOrderListVO();
+        order3.setOrderId("100003");
+        order3.setProductName("BEX 9个月质押");
+        order3.setOrderNo("STK202605181004150001");
+        order3.setOrderStatus("进行中");
+        order3.setPrincipal("1,000 BEX");
+        order3.setTotalProfit("20 BEX");
+        order3.setExpireTime(System.currentTimeMillis());
+        order3.setProfitMode("10点结算");
+        order3.setProgressPercent(50);
+
+        list.add(order1);
+        list.add(order2);
+        list.add(order3);
+
+        // 标签筛选逻辑
+        if ("ongoing".equals(query.getTabType())) {
+            list = list.stream().filter(o -> "进行中".equals(o.getOrderStatus())).collect(Collectors.toList());
+        } else if ("redeemed".equals(query.getTabType())) {
+            list = list.stream().filter(o -> "通缩赎回".equals(o.getOrderStatus())).collect(Collectors.toList());
+        }
+        pageData.setRecords(list);
+
+        return R.ok(pageData);
+    }
+
+
+    /**
+     * 质押订单详情接口
+     */
+    @GetMapping("/order/detail/{orderId}")
+    public R<StakingOngoingOrderDetailVO> getOrderDetail(@PathVariable("orderId") Long orderId) {
+        StakingOngoingOrderDetailVO vo = new StakingOngoingOrderDetailVO();
+        // 基础信息
+        vo.setProductName("BEX 3个月质押");
+        vo.setOrderNo("STK202605181004150001");
+        vo.setOrderStatus("进行中");
+
+        // 本金&收益
+        vo.setPrincipalNum("1,000 BEX");
+        vo.setTotalProfit("20 BEX");
+        vo.setSettleDayInfo("30 / 90");
+        vo.setRemainDay("60 天");
+
+        // 价格价值
+        vo.setEntryPrice("1.250000 USDT");
+        vo.setInitialValue("1,250.0000 USDT");
+        vo.setShrinkThreshold("800 BEX");
+        vo.setExpireTime(System.currentTimeMillis());
+
+        // 收益进度
+        List<StakingProfitItemVO> profitList = new ArrayList<>();
+        StakingProfitItemVO item1 = new StakingProfitItemVO();
+        item1.setProfitStatus("收益待领取");
+        item1.setProfitDate(System.currentTimeMillis() - 3600000L);
+        item1.setProfitAmount("0.666666 BEX 待领取");
+        item1.setRemark("");
+
+        StakingProfitItemVO item2 = new StakingProfitItemVO();
+        item2.setProfitStatus("收益待领取");
+        item2.setProfitDate(System.currentTimeMillis() - 3600000L);
+        item2.setProfitAmount("0.666666 BEX 待领取");
+        item2.setRemark("");
+
+        StakingProfitItemVO item3 = new StakingProfitItemVO();
+        item3.setProfitStatus("等待 10:00 结算");
+        item3.setProfitDate(null);
+        item3.setProfitAmount("");
+        item3.setRemark("系统每日固定时间结算,失败可补算");
+
+        profitList.add(item1);
+        profitList.add(item2);
+        profitList.add(item3);
+        vo.setProfitList(profitList);
+
+        return R.ok(vo);
+    }
+
+
+
+    /**
+     * 通缩赎回订单详情接口
+     */
+    @GetMapping("/redeem/detail/{orderId}")
+    public R<StakingRedeemOrderDetailVO> getRedeemOrderDetail(@PathVariable("orderId") Long orderId) {
+        StakingRedeemOrderDetailVO vo = new StakingRedeemOrderDetailVO();
+
+        // 状态信息
+        vo.setStatusDesc("通缩赎回已完成");
+        vo.setStatusTip("返还本金已到账,收益已计入待领取,销毁数量已记录");
+
+        // 核心结果
+        vo.setReturnPrincipal("1,000 BEX");
+        vo.setBurnAmount("1,000 BEX");
+
+        // 清算计算
+        vo.setOriginalPrincipal("2,000 BEX");
+        vo.setTotalProfit("1,600 BEX");
+        vo.setEntryPrice("1.000000 USDT");
+        vo.setExpirePrice("2.000000 USDT");
+        vo.setRedeemFormula("min(P, V0 / Pt)");
+        vo.setBurnTxHash("0x8f0b7f3e");
+
+        // 提示文案
+        vo.setProfitTip("收益1,600 BEX归用户所有,已计入待领取;本次通缩只影响本金返还与销毁数量。");
+
+        return R.ok(vo);
+    }
+
+    /**
+     * 领取收益
+     */
+    @GetMapping("/profit/claim")
+    public R<Boolean> claimProfit() {
+        return R.ok(true);
+    }
+
+    /**
+     * 确认质押
+     */
+    @GetMapping("/stake/confirm")
+    public R<Boolean> confirmStake() {
+        return R.ok(true);
+    }
+
+
+}

+ 21 - 0
bex-cloud-staking-api/src/main/resources/application-dev.yml

@@ -0,0 +1,21 @@
+spring:
+  cloud:
+    nacos:
+      discovery:
+        server-addr: 38.92.8.232:8848
+        namespace:
+        username: nacos
+        password: nacos
+  data:
+    redis:
+      host: 38.92.8.232
+      port: 6379
+      password: Redis@123456
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://38.92.8.232:3306/bex_staking?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
+    username: root
+    password: cywl@2026
+  rocketmq:
+    name-server: 38.92.8.232:9876

+ 80 - 0
bex-cloud-staking-api/src/main/resources/application.yml

@@ -0,0 +1,80 @@
+server:
+  port: 8251
+
+spring:
+  application:
+    name: bex-cloud-staking
+  grpc:
+    server:
+      port: 9106
+    client:
+      channels:
+        asset-service:
+          address: 'static://localhost:9093'
+          negotiation-type: plaintext
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://${MYSQL_HOST:38.92.8.232}:${MYSQL_PORT:3306}/${MYSQL_DB:bex_staking}?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
+    username: ${MYSQL_USER:root}
+    password: ${MYSQL_PASSWORD:cywl@2026}
+    druid:
+      initial-size: 5
+      min-idle: 5
+      max-active: 20
+      max-wait: 60000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      validation-query: SELECT 1
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+  data:
+    redis:
+      host: ${REDIS_HOST:38.92.8.232}
+      port: ${REDIS_PORT:6379}
+      password: ${REDIS_PASSWORD:cywl@2026}
+      database: ${REDIS_DB:0}
+      lettuce:
+        pool:
+          max-active: 32
+          max-idle: 16
+          min-idle: 5
+          max-wait: 3000ms
+  cloud:
+    nacos:
+      discovery:
+        server-addr: ${NACOS_SERVER_ADDR:38.92.8.232:8848}
+        username: ${NACOS_USERNAME:nacos}
+        password: ${NACOS_PASSWORD:nacos}
+        namespace: ${NACOS_NAMESPACE:f007e307-3ecf-4911-ac47-37aebcc7e5f0}
+
+mybatis-plus:
+  mapper-locations: classpath*:/mapper/**/*.xml
+  type-aliases-package: com.bex.staking.entity.domain
+  configuration:
+    map-underscore-to-camel-case: true
+    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
+  global-config:
+    db-config:
+      id-type: assign_id
+      logic-delete-field: deleted
+      logic-delete-value: 1
+      logic-not-delete-value: 0
+
+rocketmq:
+  name-server: ${ROCKETMQ_NAME_SERVER:38.92.8.232:9876}
+  producer:
+    group: staking-producer-group
+    send-message-timeout: 3000
+    retry-times-when-send-failed: 2
+
+springdoc:
+  swagger-ui:
+    path: /swagger-ui.html
+  api-docs:
+    path: /v3/api-docs
+
+logging:
+  level:
+    com.bex.staking: debug

+ 44 - 0
bex-cloud-staking-api/src/main/resources/logback.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <property name="LOG_PATH" value="/home/bex/java/logs/staking"/>
+    <property name="LOG_PREFIX" value="staking"/>
+    <property name="LOG_MAX_HISTORY" value="30"/>
+
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_PATH}/${LOG_PREFIX}-%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>${LOG_MAX_HISTORY}</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <root level="DEBUG">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
+
+    <logger name="com.bex" level="DEBUG" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+
+    <logger name="org.apache.seata" level="INFO" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+    <logger name="io.seata" level="INFO" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </logger>
+</configuration>

+ 3 - 0
bex-cloud-staking-core/.gitignore

@@ -0,0 +1,3 @@
+target/
+*.iml
+.idea/

+ 74 - 0
bex-cloud-staking-core/pom.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.bex</groupId>
+        <artifactId>bex-cloud-staking</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>bex-cloud-staking-core</artifactId>
+    <name>BEX 质押服务 - 核心模块</name>
+    <description>核心配置、常量定义、工具类及基础依赖</description>
+
+    <dependencies>
+        <!-- Spring Boot 基础支持 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <!-- Spring Boot 配置处理器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <!-- Hutool 工具类库 -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+        <!-- Guava 核心工具库 -->
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <!-- Apache Commons Lang3 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <!-- Apache Commons IO -->
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <!-- Apache Commons Codec -->
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+        <!-- MapStruct 对象映射 -->
+        <dependency>
+            <groupId>org.mapstruct</groupId>
+            <artifactId>mapstruct</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-json</artifactId>
+        </dependency>
+        <!-- Jakarta Validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-common</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 23 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/enums/PositionStatus.java

@@ -0,0 +1,23 @@
+package com.bex.staking.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PositionStatus {
+    ACTIVE("ACTIVE"),
+    MATURED("MATURED"),
+    REDEEMED("REDEEMED");
+
+    private final String value;
+
+    public static PositionStatus fromValue(String value) {
+        for (PositionStatus status : values()) {
+            if (status.value.equals(value)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("Unknown PositionStatus: " + value);
+    }
+}

+ 23 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/enums/ProductStatus.java

@@ -0,0 +1,23 @@
+package com.bex.staking.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum ProductStatus {
+    ACTIVE("ACTIVE"),
+    SOLD_OUT("SOLD_OUT"),
+    DISABLED("DISABLED");
+
+    private final String value;
+
+    public static ProductStatus fromValue(String value) {
+        for (ProductStatus status : values()) {
+            if (status.value.equals(value)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("Unknown ProductStatus: " + value);
+    }
+}

+ 23 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/enums/StakingStatus.java

@@ -0,0 +1,23 @@
+package com.bex.staking.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum StakingStatus {
+    STAKING("STAKING"),
+    UNSTAKING("UNSTAKING"),
+    UNSTAKED("UNSTAKED");
+
+    private final String value;
+
+    public static StakingStatus fromValue(String value) {
+        for (StakingStatus status : values()) {
+            if (status.value.equals(value)) {
+                return status;
+            }
+        }
+        throw new IllegalArgumentException("Unknown StakingStatus: " + value);
+    }
+}

+ 13 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/exception/StakingException.java

@@ -0,0 +1,13 @@
+package com.bex.staking.exception;
+
+import com.bex.common.exception.BexException;
+
+public class StakingException extends BexException {
+    public StakingException(int code, String message) {
+        super(code, message);
+    }
+
+    public StakingException(int code, String message, Throwable cause) {
+        super(code, message, cause);
+    }
+}

+ 10 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/dto/StakingOrderQuery.java

@@ -0,0 +1,10 @@
+package com.bex.staking.model.dto;
+
+import lombok.Data;
+
+@Data
+public class StakingOrderQuery {
+    private String tabType;    // 标签类型:all全部 / ongoing进行中 / redeemed已赎回
+    private Integer page;
+    private Integer size;
+}

+ 18 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/dto/StakingOrderReq.java

@@ -0,0 +1,18 @@
+package com.bex.staking.model.dto;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import java.math.BigDecimal;
+
+@Data
+public class StakingOrderReq {
+    @NotBlank(message = "产品ID不能为空")
+    private Long productId;
+
+    @DecimalMin(value = "100", message = "质押数量最小100 BEX")
+    private BigDecimal stakingNum; // 质押数量
+
+    @NotBlank(message = "幂等键不能为空")
+    private String idempotentKey; // 幂等键,防重复下单
+}

+ 16 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingHomeVO.java

@@ -0,0 +1,16 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingHomeVO {
+
+    // 用户资产
+    private String availableBalance;  // 可用余额
+    private String availableUnit;     // 单位 BEX
+    private String totalProfit;       // 总收益
+    private String totalProfitUnit;
+    private String pendingProfit;     // 待领取收益
+    private String pendingProfitUnit;
+    private String settleRule;
+}

+ 27 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingOngoingOrderDetailVO.java

@@ -0,0 +1,27 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class StakingOngoingOrderDetailVO {
+    // 订单基础信息
+    private String productName;
+    private String orderNo;
+    private String orderStatus;
+
+    // 本金收益信息
+    private String principalNum;
+    private String totalProfit;
+    private String settleDayInfo;
+    private String remainDay;
+
+    // 价格与价值
+    private String entryPrice;
+    private String initialValue;
+    private String shrinkThreshold;
+    private Long expireTime;
+
+    // 收益进度列表
+    private List<StakingProfitItemVO> profitList;
+}

+ 24 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingOrderListVO.java

@@ -0,0 +1,24 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingOrderListVO {
+    private String orderId;
+    private String productName;       // 产品名称
+    private String orderNo;           // 订单编号
+    private String orderStatus;       // 订单状态:进行中/通缩赎回/已完成
+
+    // 进行中订单字段
+    private String principal;         // 本金
+    private String totalProfit;       // 累计收益
+    private Long expireTime;        // 到期时间
+    private String profitMode;        // 收益方式
+    private Integer progressPercent;  // 进度百分比
+
+    // 通缩赎回/已完成订单字段
+    private String returnPrincipal;   // 返还本金
+    private String burnAmount;        // 销毁数量
+    private String totalProfitAmount; // 收益总额
+    private String statusDesc;        // 状态描述
+}

+ 11 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingOrderResp.java

@@ -0,0 +1,11 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingOrderResp {
+    private Long orderId;        // 质押订单ID
+    private String orderNo;      // 订单编号
+    private String stakingNum;   // 质押数量
+    private String createTime;   // 下单时间
+}

+ 25 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingPreviewVO.java

@@ -0,0 +1,25 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingPreviewVO {
+    // 资产信息
+    private String availableBalance;    // 可用余额
+    private String availableUnit;
+
+    // 价格&价值
+    private String entryPrice;          // 入场价格 USDT
+    private String initialValue;       // 初始价值 USDT
+
+    // 收益信息
+    private String dailyProfit;        // 预计每日收益
+    private String totalProfit;        // 预计总收益
+    private Long expireTime;         // 到期时间
+    private String triggerThreshold;   // 触发阈值
+
+    // 规则
+    private String riskTip;            // 风险提示文案
+    private String idempotentTip;      // 幂等键提示
+    private Integer validSecond;       // 预览有效时长(秒)
+}

+ 25 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingProductDetailVO.java

@@ -0,0 +1,25 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+import java.math.BigDecimal;
+
+@Data
+public class StakingProductDetailVO {
+    // 基础信息
+    private String productId;
+    private String productName;
+    private String status;          // 可质押
+    private Boolean isShowTwap;     // 是否展示TWAP价格
+    private String apr;              // 展示APR
+
+    // 收益参数
+    private Integer periodDay;      // 周期(天)
+    private String periodRate;       // 期间收益率
+    private String dailyRate;       // 日收益率
+    private String minInvestNum;    // 起投数量
+
+    // 收益预估
+    private String baseAmount;      // 预估基准数量
+    private String dailyProfit;     // 预计每日收益
+    private String totalProfit;     // 预计总收益
+}

+ 18 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingProductVO.java

@@ -0,0 +1,18 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingProductVO {
+
+    private String productId;
+    private String productName;
+    private String apr;             // 年化
+    private String status;          // 可质押
+    private String periodRate;      // 周期利率
+    private String profitMode;      // 结算方式
+    private String minInvestNum;    // 最小质押
+    private String thresholdRule;   // 通缩规则
+    private Integer lockDay;        // 锁仓天数
+    private Long countDown;       // 倒计时(即将开启时展示,为空不展示)
+}

+ 11 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingProfitItemVO.java

@@ -0,0 +1,11 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingProfitItemVO {
+    private String profitStatus;    // 状态:收益待领取 / 等待10:00结算
+    private Long profitDate;       // 收益日期
+    private String profitAmount;     // 收益数量
+    private String remark;           // 备注文案
+}

+ 25 - 0
bex-cloud-staking-core/src/main/java/com/bex/staking/model/vo/StakingRedeemOrderDetailVO.java

@@ -0,0 +1,25 @@
+package com.bex.staking.model.vo;
+
+import lombok.Data;
+
+@Data
+public class StakingRedeemOrderDetailVO {
+    // 状态信息
+    private String statusDesc;               // 状态:通缩赎回已完成
+    private String statusTip;                // 状态说明文案
+
+    // 核心结果
+    private String returnPrincipal;         // 返还本金
+    private String burnAmount;              // 销毁数量
+
+    // 清算计算
+    private String originalPrincipal;       // 原始本金P
+    private String totalProfit;             // 累计收益R
+    private String entryPrice;              // 入场价格S0
+    private String expirePrice;             // 到期价格Pt
+    private String redeemFormula;           // 赎回公式
+    private String burnTxHash;              // 销毁交易哈希
+
+    // 提示文案
+    private String profitTip;               // 收益说明文案
+}

+ 3 - 0
bex-cloud-staking-entity/.gitignore

@@ -0,0 +1,3 @@
+target/
+*.iml
+.idea/

+ 40 - 0
bex-cloud-staking-entity/pom.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.bex</groupId>
+        <artifactId>bex-cloud-staking</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>bex-cloud-staking-entity</artifactId>
+    <name>BEX 质押服务 - 实体模块</name>
+    <description>数据模型定义、实体类与Mapper接口</description>
+
+    <dependencies>
+        <!-- 依赖核心模块 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-staking-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- MyBatis-Plus 注解支持 -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-spring-boot4-starter</artifactId>
+        </dependency>
+        <!-- Protobuf 消息定义 -->
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-common</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 3 - 0
bex-cloud-staking-service/.gitignore

@@ -0,0 +1,3 @@
+target/
+*.iml
+.idea/

+ 82 - 0
bex-cloud-staking-service/pom.xml

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.bex</groupId>
+        <artifactId>bex-cloud-staking</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>bex-cloud-staking-service</artifactId>
+    <name>BEX 质押服务 - 业务模块</name>
+    <description>核心业务逻辑、服务接口定义及实现</description>
+
+    <dependencies>
+        <!-- 依赖核心模块 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-staking-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- 依赖实体模块 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-staking-entity</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- MyBatis-Plus JSqlParser 分页插件 -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-jsqlparser</artifactId>
+        </dependency>
+        <!-- Druid 连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-4-starter</artifactId>
+        </dependency>
+        <!-- MySQL 驱动 -->
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <!-- Redis -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <!-- Redisson 分布式锁 -->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+        </dependency>
+        <!-- Spring gRPC 客户端 -->
+        <dependency>
+            <groupId>org.springframework.grpc</groupId>
+            <artifactId>spring-grpc-spring-boot-starter</artifactId>
+        </dependency>
+        <!-- gRPC Proto 定义 -->
+        <dependency>
+            <groupId>com.bex</groupId>
+            <artifactId>bex-cloud-proto</artifactId>
+        </dependency>
+        <!-- RocketMQ -->
+        <dependency>
+            <groupId>org.apache.rocketmq</groupId>
+            <artifactId>rocketmq-spring-boot-starter</artifactId>
+        </dependency>
+        <!-- Micrometer 链路追踪 -->
+        <dependency>
+            <groupId>io.micrometer</groupId>
+            <artifactId>micrometer-tracing-bridge-brave</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.zipkin.reporter2</groupId>
+            <artifactId>zipkin-reporter-brave</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 15 - 0
bex-cloud-staking-service/src/main/java/com/bex/staking/grpc/StakingGrpcClientConfig.java

@@ -0,0 +1,15 @@
+package com.bex.staking.grpc;
+
+import com.bex.proto.asset.AssetServiceGrpc;
+import org.springframework.grpc.client.GrpcChannelFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class StakingGrpcClientConfig {
+
+    @Bean
+    AssetServiceGrpc.AssetServiceBlockingStub assetStub(GrpcChannelFactory channels) {
+        return AssetServiceGrpc.newBlockingStub(channels.createChannel("asset-service"));
+    }
+}

+ 5 - 0
bex-cloud-staking-service/src/main/java/com/bex/staking/service/StakingService.java

@@ -0,0 +1,5 @@
+package com.bex.staking.service;
+
+public interface StakingService {
+
+}

+ 15 - 0
bex-cloud-staking-service/src/main/java/com/bex/staking/service/impl/StakingServiceImpl.java

@@ -0,0 +1,15 @@
+package com.bex.staking.service.impl;
+
+import com.bex.staking.service.StakingService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class StakingServiceImpl implements StakingService {
+
+
+}

+ 25 - 0
pom.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.bex</groupId>
+        <artifactId>bex-cloud-parent</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../bex-cloud-parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>bex-cloud-staking</artifactId>
+    <packaging>pom</packaging>
+    <name>BEX 质押服务 (bex-cloud-staking)</name>
+    <description>质押产品管理、质押/赎回、收益结算</description>
+
+    <modules>
+        <module>bex-cloud-staking-core</module>
+        <module>bex-cloud-staking-entity</module>
+        <module>bex-cloud-staking-service</module>
+        <module>bex-cloud-staking-api</module>
+    </modules>
+</project>