2 Commits bc2a6581ab ... e78cdbfad6

Author SHA1 Message Date
  cjwen e78cdbfad6 Merge remote-tracking branch 'origin/master' 1 year ago
  cjwen 848181ae94 fix: ams 地址和交易记录模块优化 1 year ago

+ 29 - 6
src/main/java/com/ichaoj/ams/controller/AddressController.java

@@ -1,6 +1,10 @@
 package com.ichaoj.ams.controller;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.ichaoj.ams.request.address.BatchAddressRequest;
 import com.ichaoj.ams.request.address.BatchKeyStoreRequest;
 import com.ichaoj.ams.request.address.PageAddressRequest;
@@ -11,6 +15,8 @@ import com.ichaoj.common.annotation.AuthResource;
 import com.ichaoj.common.exception.ErrorServiceException;
 import com.ichaoj.common.model.PublicPage;
 import com.ichaoj.common.model.PublicResult;
+import com.ichaoj.common.model.PublicUserInfo;
+import com.ichaoj.web.context.SuperWhaleContext;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.validation.annotation.Validated;
@@ -18,7 +24,9 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author cjwen
@@ -42,18 +50,18 @@ public class AddressController {
     @PostMapping("/download/batch-keystore")
     @AuthResource
     @Validated
-    public void batchKeystore(HttpServletResponse response,@RequestBody @Validated BatchKeyStoreRequest keyStoreRequest) {
+    public void batchKeystore(HttpServletResponse response, @RequestBody @Validated BatchKeyStoreRequest keyStoreRequest) {
         addressService.batchKeystore(keyStoreRequest.getGroupName(), response);
     }
 
-    @Operation(summary = "添加精品号")
+    @Operation(summary = "批量添加精品号")
     @PostMapping("/add/premium-address")
     @AuthResource
-    public PublicResult<Object> addPremiumAddress(@RequestBody PremiumAddressRequest addressRequest) {
-        if (StrUtil.isBlank(addressRequest.getAddress())) {
-            throw new ErrorServiceException("The address cannot be blank");
+    public PublicResult<Object> addPremiumAddress(@RequestBody List<PremiumAddressRequest> requestList) {
+        if (CollectionUtil.isEmpty(requestList)) {
+            throw new ErrorServiceException("至少需要一个精品号");
         }
-        addressService.addPremiumAddress(addressRequest);
+        addressService.addPremiumAddress(requestList);
         return PublicResult.success();
     }
 
@@ -73,4 +81,19 @@ public class AddressController {
         return PublicResult.success(result);
     }
 
+    @Operation(summary = "统计当前用户的精品号和批量号数量")
+    @GetMapping("/count-address")
+    @AuthResource
+    public PublicResult<Map<String, Object>> countAddress() {
+        String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
+        Map<String, Object> map = new HashMap<>(5);
+        map.put("batchCount", addressService.count(new LambdaQueryWrapper<AmsAddressAccount>()
+                        .eq(AmsAddressAccount::getUserId, userId)
+                .eq(AmsAddressAccount::getAddressType, 1)));
+        map.put("premiumCount", addressService.count(new LambdaQueryWrapper<AmsAddressAccount>()
+                .eq(AmsAddressAccount::getUserId, userId)
+                .eq(AmsAddressAccount::getAddressType, 0)));
+        return PublicResult.success(map);
+    }
+
 }

+ 26 - 0
src/main/java/com/ichaoj/ams/controller/AirdropProjectController.java

@@ -1,11 +1,19 @@
 package com.ichaoj.ams.controller;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ichaoj.ams.entity.AmsAirdropTask;
 import com.ichaoj.ams.request.airdrop.CreateAirdropProject;
 import com.ichaoj.ams.request.airdrop.PageProjectRequest;
 import com.ichaoj.ams.request.airdrop.UpdateAirdropProject;
 import com.ichaoj.ams.response.airdrop.AirdropProjectResponse;
+import com.ichaoj.ams.response.airdrop.ProjectDetailResponse;
+import com.ichaoj.ams.response.task.TaskResponse;
 import com.ichaoj.ams.service.IAmsAirdropProjectService;
+import com.ichaoj.ams.service.IAmsAirdropTaskService;
 import com.ichaoj.common.annotation.AuthResource;
+import com.ichaoj.common.exception.ErrorServiceException;
 import com.ichaoj.common.model.PublicPage;
 import com.ichaoj.common.model.PublicResult;
 import io.swagger.v3.oas.annotations.Operation;
@@ -14,6 +22,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.util.List;
 
 /**
  * <p>
@@ -30,6 +39,8 @@ public class AirdropProjectController {
 
     @Resource
     private IAmsAirdropProjectService airdropProjectService;
+    @Resource
+    private IAmsAirdropTaskService taskService;
 
     @PostMapping
     @Operation(summary = "创建空投项目")
@@ -62,4 +73,19 @@ public class AirdropProjectController {
         PublicPage<AirdropProjectResponse> result = airdropProjectService.pageAirdropProject(projectRequest);
         return PublicResult.success(result);
     }
+
+
+    @GetMapping("/detail/{projectId}")
+    @Operation(summary = "根据项目id查询详情")
+    @AuthResource
+    public PublicResult<ProjectDetailResponse> getByProjectId(@PathVariable String projectId) {
+        if (StrUtil.isBlank(projectId)){
+            throw new ErrorServiceException("projectId 不能为空");
+        }
+        ProjectDetailResponse project = BeanUtil.copyProperties(airdropProjectService.getById(projectId), ProjectDetailResponse.class);
+        List<AmsAirdropTask> tasks = taskService.list(new LambdaQueryWrapper<AmsAirdropTask>().eq(AmsAirdropTask::getAirdropProjectId, project.getAmsProjectId()));
+        List<TaskResponse> taskResponses = BeanUtil.copyToList(tasks, TaskResponse.class);
+        project.setTasks(taskResponses);
+        return PublicResult.success(project);
+    }
 }

+ 21 - 0
src/main/java/com/ichaoj/ams/entity/AmsTradeRecord.java

@@ -3,8 +3,10 @@ package com.ichaoj.ams.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+
 import java.io.Serializable;
 import java.time.LocalDateTime;
+
 import lombok.Getter;
 import lombok.Setter;
 
@@ -39,6 +41,25 @@ public class AmsTradeRecord implements Serializable {
      */
     private String executeId;
 
+    /**
+     * gas费
+     */
+    private String gas;
+
+    /**
+     * 金额
+     */
+    private String amount;
+    /**
+     * 金额
+     */
+    private String currentBalance;
+
+    /**
+     * 公链id
+     */
+    private String chainId;
+
     /**
      * 交易状态(0:进行中,1:已完成)
      */

+ 13 - 0
src/main/java/com/ichaoj/ams/mapper/AmsAddressAccountMapper.java

@@ -1,7 +1,11 @@
 package com.ichaoj.ams.mapper;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ichaoj.ams.request.address.PageAddressRequest;
+import com.ichaoj.ams.response.address.AddressResponse;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -13,4 +17,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface AmsAddressAccountMapper extends BaseMapper<AmsAddressAccount> {
 
+    /**
+     * 分页查询地址
+     *
+     * @param buildPageObj 分页参数
+     * @param request      查询参数
+     * @param userId       用户id
+     * @return 分页结果
+     */
+    Page<AddressResponse> pageAddress(Page<AmsAddressAccount> buildPageObj, @Param("request") PageAddressRequest request, @Param("userId") String userId);
 }

+ 10 - 1
src/main/java/com/ichaoj/ams/request/address/PageAddressRequest.java

@@ -15,7 +15,16 @@ import lombok.EqualsAndHashCode;
 @Schema(title = "分页查询地址")
 public class PageAddressRequest extends PublicPage<AddressResponse> {
 
-    @Schema(title = "当前地址组名称")
+    @Schema(title = "查询字段")
+    private String queryValue;
+
     private String groupName;
 
+    @Schema(title = "地址类型(0:精品号,1:批量号)")
+    private Integer addressType;
+
+    private String orderBy;
+
+    private String orderType;
+
 }

+ 14 - 0
src/main/java/com/ichaoj/ams/request/record/CreateTradeRecordRequest.java

@@ -38,5 +38,19 @@ public class CreateTradeRecordRequest {
      */
     private LocalDateTime createTime;
 
+    /**
+     * gas费
+     */
+    private String gas;
+
+    /**
+     * 金额
+     */
+    private String amount;
+
+    /**
+     * 金额
+     */
+    private String currentBalance;
 
 }

+ 3 - 0
src/main/java/com/ichaoj/ams/response/address/AddressResponse.java

@@ -2,6 +2,7 @@ package com.ichaoj.ams.response.address;
 
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 /**
@@ -31,6 +32,8 @@ public class AddressResponse {
      */
     private String groupName;
 
+    private BigDecimal totalGas;
+
     /**
      * 最后操作时间
      */

+ 22 - 0
src/main/java/com/ichaoj/ams/response/airdrop/ProjectDetailResponse.java

@@ -0,0 +1,22 @@
+package com.ichaoj.ams.response.airdrop;
+
+import com.ichaoj.ams.response.task.TaskResponse;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+/**
+ * @author : cjwen
+ * @date : 2023/05/22 11:05
+ */
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(title = "项目详情")
+public class ProjectDetailResponse extends AirdropProjectResponse{
+
+    private List<TaskResponse> tasks;
+
+}

+ 53 - 0
src/main/java/com/ichaoj/ams/response/record/TradeRecordResponse.java

@@ -1,8 +1,13 @@
 package com.ichaoj.ams.response.record;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.time.LocalDateTime;
+import java.util.Date;
+
 /**
  * @author : cjwen
  * @date : 2023/05/18 10:55
@@ -10,4 +15,52 @@ import lombok.Data;
 @Data
 @Schema(title = "交互记录")
 public class TradeRecordResponse {
+
+    private String tradeRecordId;
+
+    /**
+     * 链上交易id
+     */
+    private String txId;
+
+    /**
+     * 执行id
+     */
+    private String executeId;
+
+    /**
+     * gas费
+     */
+    private String gas;
+
+    /**
+     * 金额
+     */
+    private String amount;
+
+    /**
+     * 金额
+     */
+    private String currentBalance;
+
+    /**
+     * 公链id
+     */
+    private String chainId;
+
+    /**
+     * 交易状态(0:进行中,1:已完成)
+     */
+    private Integer status;
+
+    /**
+     * 地址
+     */
+    private String address;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
 }

+ 2 - 2
src/main/java/com/ichaoj/ams/service/IAmsAddressAccountService.java

@@ -31,9 +31,9 @@ public interface IAmsAddressAccountService extends IService<AmsAddressAccount> {
     /**
      * 添加精品号
      *
-     * @param address 精品号地址
+     * @param requestList 精品号地址
      */
-    void addPremiumAddress(PremiumAddressRequest address);
+    void addPremiumAddress(List<PremiumAddressRequest> requestList);
 
     /**
      * 批量下载keystore文件

+ 56 - 16
src/main/java/com/ichaoj/ams/service/impl/AmsAddressAccountServiceImpl.java

@@ -10,12 +10,14 @@ import com.ichaoj.ams.common.bean.Wallet;
 import com.ichaoj.ams.common.util.WalletUtil;
 import com.ichaoj.ams.common.util.ZipUtil;
 import com.ichaoj.ams.entity.AmsAddressAccount;
+import com.ichaoj.ams.entity.AmsTradeRecord;
 import com.ichaoj.ams.mapper.AmsAddressAccountMapper;
 import com.ichaoj.ams.request.address.BatchAddressRequest;
 import com.ichaoj.ams.request.address.PageAddressRequest;
 import com.ichaoj.ams.request.address.PremiumAddressRequest;
 import com.ichaoj.ams.response.address.AddressResponse;
 import com.ichaoj.ams.service.IAmsAddressAccountService;
+import com.ichaoj.ams.service.IAmsTradeRecordService;
 import com.ichaoj.common.exception.ErrorServiceException;
 import com.ichaoj.common.model.PublicPage;
 import com.ichaoj.common.model.PublicUserInfo;
@@ -23,11 +25,17 @@ import com.ichaoj.mybatis.service.SuperWhaleServiceImpl;
 import com.ichaoj.web.context.SuperWhaleContext;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.File;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static com.ichaoj.ams.constant.AmsConstant.WALLET_FILE_PATH;
@@ -44,6 +52,9 @@ import static com.ichaoj.ams.constant.AmsConstant.WALLET_FILE_PATH;
 @Slf4j
 public class AmsAddressAccountServiceImpl extends SuperWhaleServiceImpl<AmsAddressAccountMapper, AmsAddressAccount> implements IAmsAddressAccountService {
 
+    @Resource
+    private IAmsTradeRecordService tradeRecordService;
+
     @Override
     public List<String> batchCreateAddress(BatchAddressRequest batchAddressRequest) {
         String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
@@ -92,35 +103,64 @@ public class AmsAddressAccountServiceImpl extends SuperWhaleServiceImpl<AmsAddre
 
     @Override
     public PublicPage<AddressResponse> pageAddress(PageAddressRequest pageAddressRequest) {
-        LambdaQueryWrapper<AmsAddressAccount> wrapper = Wrappers.lambdaQuery();
-        wrapper.eq(StrUtil.isNotBlank(pageAddressRequest.getGroupName())
-                        , AmsAddressAccount::getGroupName
-                        , pageAddressRequest.getGroupName())
-                .eq(AmsAddressAccount::getUserId, SuperWhaleContext.getContext(PublicUserInfo.class).getUserId())
-                .orderByDesc(AmsAddressAccount::getCreateTime);
-
-        Page<AmsAddressAccount> result = this.page(this.buildPageObj(pageAddressRequest), wrapper);
+        String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
+        Page<AddressResponse> result = this.baseMapper.pageAddress(this.buildPageObj(pageAddressRequest), pageAddressRequest, userId);
         return this.convertPublicPage(result, resp -> BeanUtil.copyProperties(resp, AddressResponse.class));
     }
 
     @Override
     public List<String> queryGroupList() {
         LambdaQueryWrapper<AmsAddressAccount> wrapper = Wrappers.lambdaQuery();
-        wrapper.eq(AmsAddressAccount::getUserId,SuperWhaleContext.getContext(PublicUserInfo.class).getUserId())
+        wrapper.eq(AmsAddressAccount::getUserId, SuperWhaleContext.getContext(PublicUserInfo.class).getUserId())
+                .eq(AmsAddressAccount::getAddressType, 1)
                 .groupBy(AmsAddressAccount::getGroupName);
         return this.list(wrapper).stream().map(AmsAddressAccount::getGroupName).distinct().collect(Collectors.toList());
     }
 
     /**
      * 添加精品号
-     *
-     * @param request 精品号参数
      */
     @Override
-    public void addPremiumAddress(PremiumAddressRequest request) {
+    @Transactional(rollbackFor = Exception.class)
+    public void addPremiumAddress(List<PremiumAddressRequest> requestList) {
         String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
-        AmsAddressAccount account = getAddressCountInstance(userId, request.getAddress(), 0, request.getChainId(), request.getGroupName());
-        this.save(account);
+        List<AmsAddressAccount> accounts = new ArrayList<>();
+        for (PremiumAddressRequest request : requestList) {
+            verifyDuplicate(requestList.stream().map(PremiumAddressRequest::getGroupName).collect(Collectors.toList()));
+            List<AmsAddressAccount> addresses = this.getByGroupNameAndUserId(request.getGroupName(), userId);
+            if (CollectionUtil.isNotEmpty(addresses)) {
+                throw new ErrorServiceException("你已经创建了" + request.getGroupName() + "精品号,请更换地址组名称重试!");
+            }
+            AmsAddressAccount account = getAddressCountInstance(userId,
+                    request.getAddress(),
+                    0,
+                    request.getChainId(),
+                    request.getGroupName());
+            accounts.add(account);
+        }
+        this.saveBatch(accounts);
+    }
+
+    /**
+     * 验证 List<PremiumAddressRequest> 列表是否有重复对象PremiumAddressRequest,如有重复,返回重复对象的下标
+     */
+    public void verifyDuplicate(List<String> list) {
+        List<Integer> duplicates = new ArrayList<>();
+        // 使用Set记录已经出现过的对象
+        Set<String> set = new HashSet<>();
+        for (int i = 0; i < list.size(); i++) {
+            String request = list.get(i);
+            // 如果set中已经包含obj,则表示obj重复
+            if (set.contains(request)) {
+                duplicates.add(i + 1);
+            } else {
+                set.add(request);
+            }
+        }
+        String collect = duplicates.stream().map(String::valueOf).collect(Collectors.joining(StrUtil.COMMA));
+        if (StrUtil.isNotBlank(collect)) {
+            throw new ErrorServiceException("你创建的第" + collect + "个精品号是重复的,请更换地址组名称重试!");
+        }
     }
 
     @Override
@@ -134,13 +174,13 @@ public class AmsAddressAccountServiceImpl extends SuperWhaleServiceImpl<AmsAddre
         if (addresses.get(0).getAddressType() != 1) {
             throw new ErrorServiceException(groupName + "为非批量号地址组,不允许下载");
         }
+
         ZipUtil.createZip(groupName, response, userId);
     }
 
     private AmsAddressAccount getAddressCountInstance(
             String userId, String address,
-            Integer addressType, String chainId,
-            String groupName) {
+            Integer addressType, String chainId, String groupName) {
         AmsAddressAccount account = new AmsAddressAccount();
         account.setAddress(address);
         account.setAddressType(addressType);

+ 1 - 0
src/main/java/com/ichaoj/ams/service/impl/AmsAirdropTaskServiceImpl.java

@@ -48,6 +48,7 @@ public class AmsAirdropTaskServiceImpl extends SuperWhaleServiceImpl<AmsAirdropT
         LambdaQueryWrapper<AmsAirdropTask> wrapper = Wrappers.lambdaQuery();
         wrapper
                 .like(StrUtil.isNotBlank(taskRequest.getQueryValue()), AmsAirdropTask::getTaskName, taskRequest.getQueryValue())
+                .or().eq(StrUtil.isNotBlank(taskRequest.getQueryValue()), AmsAirdropTask::getAmsTaskId, taskRequest.getQueryValue())
                 .eq(taskRequest.getTaskType() != null, AmsAirdropTask::getTaskType, taskRequest.getTaskType())
                 .orderByDesc(AmsAirdropTask::getCreateTime);
         Page<AmsAirdropTask> result = this.page(this.buildPageObj(taskRequest), wrapper);

+ 2 - 1
src/main/java/com/ichaoj/ams/service/impl/AmsExecuteRecordServiceImpl.java

@@ -57,7 +57,8 @@ public class AmsExecuteRecordServiceImpl extends SuperWhaleServiceImpl<AmsExecut
         LambdaQueryWrapper<AmsExecuteRecord> wrapper = Wrappers.lambdaQuery();
         wrapper
                 .eq(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getExecuteId, executeRequest.getQueryValue())
-                .or().like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getGroupName, executeRequest.getQueryValue())
+                .or(w->w.like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getGroupName, executeRequest.getQueryValue())
+                        .like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getTaskId, executeRequest.getQueryValue()))
                 .orderByDesc(AmsExecuteRecord::getCreateTime);
         Page<AmsExecuteRecord> result = this.page(this.buildPageObj(executeRequest), wrapper);
         return this.convertPublicPage(result, s -> BeanUtil.copyProperties(s, ExecuteResponse.class));

+ 29 - 21
src/main/java/com/ichaoj/ams/service/impl/AmsTradeRecordServiceImpl.java

@@ -1,7 +1,6 @@
 package com.ichaoj.ams.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
@@ -23,9 +22,7 @@ import org.springframework.stereotype.Service;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.*;
 import java.util.stream.Collectors;
 
 /**
@@ -40,12 +37,15 @@ import java.util.stream.Collectors;
 @Slf4j
 public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRecordMapper, AmsTradeRecord> implements IAmsTradeRecordService {
 
+    private final static ScheduledExecutorService AMS_SCHEDULER = Executors.newScheduledThreadPool(5);
+
     @Override
     public PublicPage<TradeRecordResponse> pageTradeRecord(PageTradeRecordRequest pageRequest) {
         LambdaQueryWrapper<AmsTradeRecord> wrapper = Wrappers.lambdaQuery();
         wrapper
                 .eq(StrUtil.isNotBlank(pageRequest.getQueryValue()), AmsTradeRecord::getExecuteId, pageRequest.getQueryValue())
-                .or().eq(StrUtil.isNotBlank(pageRequest.getQueryValue()), AmsTradeRecord::getTxId, pageRequest.getQueryValue())
+                .or(w -> w.eq(StrUtil.isNotBlank(pageRequest.getQueryValue()), AmsTradeRecord::getTxId, pageRequest.getQueryValue())
+                        .eq(StrUtil.isNotBlank(pageRequest.getQueryValue()), AmsTradeRecord::getAddress, pageRequest.getQueryValue()))
                 .orderByDesc(AmsTradeRecord::getCreateTime);
         Page<AmsTradeRecord> result = this.page(this.buildPageObj(pageRequest), wrapper);
         return this.convertPublicPage(result, s -> BeanUtil.copyProperties(s, TradeRecordResponse.class));
@@ -70,24 +70,30 @@ public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRec
                 log.info("amount: {}", currenAmount);
                 String address = getUnusedAddress(addressMap, addresses);
                 if (i == 0) {
-                    saveTrade(executeId, address);
+                    saveTrade(executeId, address, gas, currenAmount);
                     // todo 调用链上交易
                 } else {
                     int sleepSeconds = RandomUtil.randomInt(intervalMin, intervalMax);
-                    log.info("当前是第{} 笔交易,需要等待{} 分钟", i + 1, sleepSeconds);
-                    try {
-                        AmsTradeRecord record = this.getOne(
-                                new LambdaQueryWrapper<AmsTradeRecord>()
-                                        .eq(AmsTradeRecord::getExecuteId, executeId)
-                                        .eq(AmsTradeRecord::getAddress, address)
-                        );
-                        if (record == null) {
-                            TimeUnit.MILLISECONDS.sleep(sleepSeconds * 1000L + RandomUtil.randomInt(100, 999));
-                            saveTrade(executeId, address);
-                            // todo 调用链上交易
-                        }
-                    } catch (InterruptedException e) {
-                        e.printStackTrace();
+                    long sleep = sleepSeconds * 60L + RandomUtil.randomInt(1, 30);
+                    log.info("执行器{} ,总共有{} 条交易需要执行,当前是{},第{} 笔交易,需要等待{} 分钟",
+                            executeId,
+                            addresses.size(),
+                            address, i + 1,
+                            sleep);
+                    AmsTradeRecord record = this.getOne(
+                            new LambdaQueryWrapper<AmsTradeRecord>()
+                                    .eq(AmsTradeRecord::getExecuteId, executeId)
+                                    .eq(AmsTradeRecord::getAddress, address)
+                    );
+
+                    if (record == null) {
+                        AMS_SCHEDULER.schedule(new TimerTask() {
+                            @Override
+                            public void run() {
+                                saveTrade(executeId, address, gas, currenAmount);
+                                // todo 调用链上交易
+                            }
+                        }, sleep, TimeUnit.SECONDS);
                     }
                 }
                 addressMap.put(address, true);
@@ -104,13 +110,15 @@ public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRec
         return RandomUtil.randomBigDecimal(BigDecimal.ZERO, new BigDecimal(maxGas));
     }
 
-    private void saveTrade(String executeId, String address) {
+    private void saveTrade(String executeId, String address, BigDecimal gas, BigDecimal amount) {
         CreateTradeRecordRequest trade = CreateTradeRecordRequest.builder()
                 .address(address)
                 .executeId(executeId)
                 .createTime(LocalDateTime.now())
                 .status(0)
                 .txId(IdUtil.simpleUUID())
+                .gas(gas.toPlainString())
+                .amount(amount.toPlainString())
                 .build();
         this.save(BeanUtil.copyProperties(trade, AmsTradeRecord.class));
     }

+ 42 - 1
src/main/resources/mapper/AmsAddressAccountMapper.xml

@@ -1,5 +1,46 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ichaoj.ams1.mapper.AmsAddressAccountMapper">
+<mapper namespace="com.ichaoj.ams.mapper.AmsAddressAccountMapper">
+    <select id="pageAddress" resultType="com.ichaoj.ams.response.address.AddressResponse">
+        SELECT
+        IFNULL( SUM(tr.gas), 0 ) AS totalGas,
+        a.ams_address_id,
+        a.user_id,
+        a.address,
+        a.chain_id,
+        a.address_type,
+        a.group_name,
+        a.keystore,
+        a.last_oper_time,
+        a.create_time
+        FROM `ams_address_account` a
+        left join ams_trade_record tr
+        on a.address = tr.address
+        and tr.flag = 0
+        where a.flag = 0
+        <if test="userId != null and userId != ''">
+            and a.user_id = #{userId}
+        </if>
+        <if test="request.queryValue != null and request.queryValue != ''">
+            and a.group_name like concat('%',#{request.queryValue},'%')
+            or a.address = #{request.queryValue}
+        </if>
+        <if test="request.groupName != null and request.groupName != ''">
+            and a.group_name = #{request.groupName}
+        </if>
+        <if test="request.addressType != null and request.addressType >= 0">
+            and a.address_type = #{request.addressType}
+        </if>
+        GROUP BY a.address
 
+        <if test="request.orderBy != null and request.orderBy != ''
+         and request.orderType != null and request.orderType != ''">
+            order by ${request.orderBy} ${request.orderType}
+        </if>
+
+        <if test="request.orderBy == null or request.orderBy == ''
+         or request.orderType == null or request.orderType == ''">
+            order by a.create_time desc
+        </if>
+    </select>
 </mapper>

+ 1 - 1
src/main/resources/mapper/AmsAirdropProjectMapper.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ichaoj.ams1.mapper.AmsAirdropProjectMapper">
+<mapper namespace="com.ichaoj.ams.mapper.AmsAirdropProjectMapper">
 
 </mapper>

+ 1 - 1
src/main/resources/mapper/AmsAirdropTaskMapper.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ichaoj.ams1.mapper.AmsAirdropTaskMapper">
+<mapper namespace="com.ichaoj.ams.mapper.AmsAirdropTaskMapper">
 
 </mapper>