From 8f720d592d6ea2229cac4c051828af39f8425325 Mon Sep 17 00:00:00 2001
From: KKSU <15274802129@163.com>
Date: Mon, 03 Jun 2024 11:45:00 +0800
Subject: [PATCH] 批量转账

---
 src/main/java/cc/mrbird/febs/dapp/chain/EthService.java                     |  102 ++++++++++++++++++++++++-
 src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java           |    5 +
 src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java      |   18 +++-
 src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java |   47 +++++++++++
 src/main/java/cc/mrbird/febs/dapp/dto/BatchTransferDto.java                 |   18 ++++
 src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java                     |    9 +
 src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java                      |    5 +
 7 files changed, 191 insertions(+), 13 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java b/src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
index 61e764d..c7a94f6 100644
--- a/src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
@@ -23,6 +23,11 @@
             "9d461be6-9796-47b9-85d8-b150cbabbb54"),
 
 
+    BSC_USDT_LOCAL("BSC", "0xE09705E2D5283ee4b74182Ed5906D30E3b0D5fa8",
+            "a922d1900a99e883c5ca684ea479a81f2c7de6b8efde7e81b3877ff056221460",
+            "https://bsc-dataseed1.ninicoin.io",
+            "0x5dc091e47EDcd24709C7922370806d39e6Ad8be9",
+            ""),
     /**
      * 币安 usdt合约
      * 0x55d398326f99059fF775485246999027B3197955
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java b/src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java
index 95b3fab..451c23e 100644
--- a/src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java
@@ -1,7 +1,10 @@
 package cc.mrbird.febs.dapp.chain;
 
+import cc.mrbird.febs.dapp.dto.BatchTransferDto;
+
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.List;
 
 public interface ContractChainService {
 
@@ -18,6 +21,8 @@
 
     String transfer(String address, BigDecimal amount);
 
+    void transferList(List<BatchTransferDto> batchTransferDtos);
+
     int allowanceCnt(String address);
 
     int decimals();
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/EthService.java b/src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
index 460504e..c2f1a6a 100644
--- a/src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
@@ -1,10 +1,9 @@
 package cc.mrbird.febs.dapp.chain;
 
-import cn.hutool.core.util.HexUtil;
+import cc.mrbird.febs.dapp.dto.BatchTransferDto;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSONObject;
-import org.bouncycastle.jcajce.provider.digest.SHA3;
 import org.web3j.abi.FunctionEncoder;
 import org.web3j.abi.FunctionReturnDecoder;
 import org.web3j.abi.TypeReference;
@@ -12,12 +11,17 @@
 import org.web3j.abi.datatypes.Function;
 import org.web3j.abi.datatypes.Type;
 import org.web3j.abi.datatypes.generated.Uint256;
-import org.web3j.crypto.*;
+import org.web3j.crypto.Credentials;
+import org.web3j.crypto.RawTransaction;
+import org.web3j.crypto.TransactionEncoder;
 import org.web3j.protocol.Web3j;
 import org.web3j.protocol.core.DefaultBlockParameterName;
 import org.web3j.protocol.core.Request;
 import org.web3j.protocol.core.methods.request.Transaction;
-import org.web3j.protocol.core.methods.response.*;
+import org.web3j.protocol.core.methods.response.EthBlockNumber;
+import org.web3j.protocol.core.methods.response.EthCall;
+import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
+import org.web3j.protocol.core.methods.response.EthSendTransaction;
 import org.web3j.protocol.http.HttpService;
 import org.web3j.utils.Convert;
 import org.web3j.utils.Numeric;
@@ -26,8 +30,9 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
-import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 
@@ -252,6 +257,54 @@
         }
     }
 
+    @Override
+    public void transferList(List<BatchTransferDto> batchTransferDtos){
+        String gas = getGas();
+        Credentials credentials = Credentials.create(privateKey);
+        BigInteger nonce = null;
+        try {
+            nonce = web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.LATEST).send().getTransactionCount();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        for(BatchTransferDto batchTransferDto : batchTransferDtos){
+
+            String amount = batchTransferDto.getAmount().toPlainString();
+            String toAddress = batchTransferDto.getToAddress();
+
+            BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
+            amount = amountPow.toPlainString();
+            if (amount.contains(".")) {
+                amount = amount.substring(0, amount.lastIndexOf("."));
+            }
+
+            Function function = new Function("transfer",
+                    Arrays.asList(new Address(toAddress), new Uint256(new BigInteger(amount))),
+                    Arrays.asList(new TypeReference<Type>() {
+                    }));
+
+            String encodedFunction = FunctionEncoder.encode(function);
+
+            RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
+                    Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
+                    Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
+
+            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
+            String hexValue = Numeric.toHexString(signedMessage);
+
+            CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
+            try {
+                EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            } catch (ExecutionException e) {
+                e.printStackTrace();
+            }
+            nonce = nonce.add(BigInteger.ONE);
+        }
+    }
+
     public String tokenTransferFrom(String privateKey, String fromAddress, String toAddress, String amount) throws ExecutionException, InterruptedException {
         String gas = getGas();
 
@@ -334,6 +387,43 @@
         }
     }
 
+
+    public void batchTransfer(List<BatchTransferDto> batchTransferDtos) throws Exception {
+        String gas = getGas();
+        Credentials credentials = Credentials.create(privateKey);
+        BigInteger nonce = web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.LATEST).send().getTransactionCount();
+
+        for(BatchTransferDto batchTransferDto : batchTransferDtos){
+
+            String amount = batchTransferDto.getAmount().toPlainString();
+            String toAddress = batchTransferDto.getToAddress();
+
+            BigDecimal amountPow = new BigDecimal(amount).multiply(BigDecimal.TEN.pow(decimals()));
+            amount = amountPow.toPlainString();
+            if (amount.contains(".")) {
+                amount = amount.substring(0, amount.lastIndexOf("."));
+            }
+
+            Function function = new Function("transfer",
+                    Arrays.asList(new Address(toAddress), new Uint256(new BigInteger(amount))),
+                    Arrays.asList(new TypeReference<Type>() {
+                    }));
+
+            String encodedFunction = FunctionEncoder.encode(function);
+
+            RawTransaction rawTransaction = RawTransaction.createTransaction(nonce,
+                    Convert.toWei(gas, Convert.Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
+                    Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
+
+            byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
+            String hexValue = Numeric.toHexString(signedMessage);
+
+            CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
+            EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
+            nonce = nonce.add(BigInteger.ONE);
+        }
+    }
+
     @Override
     public int allowanceCnt(String address) {
         String allowanceUrl;
diff --git a/src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java b/src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java
index ddbec38..cdbbb46 100644
--- a/src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java
+++ b/src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java
@@ -1,7 +1,6 @@
 package cc.mrbird.febs.dapp.chain;
 
-import cc.mrbird.febs.common.contants.AppContants;
-import cn.hutool.core.util.StrUtil;
+import cc.mrbird.febs.dapp.dto.BatchTransferDto;
 import org.tron.trident.core.ApiWrapper;
 import org.tron.trident.core.contract.Contract;
 import org.tron.trident.core.contract.Trc20Contract;
@@ -9,6 +8,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
+import java.util.List;
 
 /**
  *
@@ -101,6 +101,11 @@
     }
 
     @Override
+    public void transferList(List<BatchTransferDto> batchTransferDtos) {
+
+    }
+
+    @Override
     public int allowanceCnt(String address) {
         return 0;
     }
diff --git a/src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java b/src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java
index 0b9b157..4585a57 100644
--- a/src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java
+++ b/src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java
@@ -4,21 +4,29 @@
 import cc.mrbird.febs.common.controller.BaseController;
 import cc.mrbird.febs.common.entity.FebsResponse;
 import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
 import cc.mrbird.febs.common.utils.FebsUtil;
+import cc.mrbird.febs.dapp.chain.ChainEnum;
+import cc.mrbird.febs.dapp.chain.ChainService;
+import cc.mrbird.febs.dapp.dto.BatchTransferDto;
 import cc.mrbird.febs.dapp.entity.DappAccountMoneyChangeEntity;
 import cc.mrbird.febs.dapp.entity.DappAchieve;
 import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
+import cc.mrbird.febs.dapp.entity.DappMemberEntity;
 import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
+import cc.mrbird.febs.dapp.mapper.DappMemberDao;
 import cc.mrbird.febs.dapp.service.AsyncCjService;
 import cc.mrbird.febs.dapp.service.DappWalletService;
 import cc.mrbird.febs.system.entity.User;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -35,6 +43,7 @@
 
     private final DappWalletService dappWalletService;
     private final DappFundFlowDao dappFundFlowDao;
+    private final DappMemberDao dappMemberDao;
     private final AsyncCjService asyncCjService;
 
     @GetMapping("/dappAchieveItem")
@@ -66,6 +75,42 @@
     public FebsResponse confirmOrder(DappFundFlowEntity dappFundFlowIn){
         String orderIds = dappFundFlowIn.getOrderIds();
         List<String> ids = StrUtil.splitTrim(orderIds, ",");
+        Integer type = 0;
+        List<BatchTransferDto> batchTransferDtos = new ArrayList<>();
+        for(String id : ids){
+            long orderId = Long.parseLong(id);
+            DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(orderId);
+            if(1 != dappFundFlowEntity.getStatus()){
+                continue;
+            }
+            BigDecimal amount = dappFundFlowEntity.getAmount().negate();
+            if(BigDecimal.ZERO.compareTo(amount) >=0){
+                amount = amount.negate();
+            }
+            Long memberId = dappFundFlowEntity.getMemberId();
+            DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
+            batchTransferDtos.add(new BatchTransferDto(dappMemberEntity.getAddress(), amount));
+
+            dappFundFlowEntity.setStatus(2);
+            dappFundFlowDao.updateById(dappFundFlowEntity);
+
+            type = dappFundFlowEntity.getType();
+        }
+        if(CollUtil.isNotEmpty(batchTransferDtos)){
+            if(FlowTypeEnum.USDT_OUT.getValue() == type){
+                ChainService.getInstance(ChainEnum.BSC_USDT.name()).transferList(batchTransferDtos);
+            }else if(FlowTypeEnum.DAI_BI_OUT.getValue() == type){
+                ChainService.getInstance(ChainEnum.BSC_GFA.name()).transferList(batchTransferDtos);
+            }
+        }
+        return new FebsResponse().success();
+    }
+
+    @GetMapping("confirmOrderV2")
+    @ControllerEndpoint(operation = "批量转账", exceptionMessage = "操作失败")
+    public FebsResponse confirmOrderV2(DappFundFlowEntity dappFundFlowIn){
+        String orderIds = dappFundFlowIn.getOrderIds();
+        List<String> ids = StrUtil.splitTrim(orderIds, ",");
         for(String id : ids){
             long orderId = Long.parseLong(id);
             DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(orderId);
diff --git a/src/main/java/cc/mrbird/febs/dapp/dto/BatchTransferDto.java b/src/main/java/cc/mrbird/febs/dapp/dto/BatchTransferDto.java
new file mode 100644
index 0000000..cd88e0f
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/dapp/dto/BatchTransferDto.java
@@ -0,0 +1,18 @@
+package cc.mrbird.febs.dapp.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class BatchTransferDto {
+
+    private String toAddress;
+
+    private BigDecimal amount;
+
+    public BatchTransferDto(String toAddress, BigDecimal amount) {
+        this.toAddress = toAddress;
+        this.amount = amount;
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java
index 5f0051c..693d3d5 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java
@@ -3,10 +3,10 @@
 import cc.mrbird.febs.common.contants.AppContants;
 import cc.mrbird.febs.common.enumerates.DataDicEnum;
 import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
-import cc.mrbird.febs.common.exception.FebsException;
 import cc.mrbird.febs.common.utils.RedisUtils;
 import cc.mrbird.febs.dapp.chain.ChainEnum;
 import cc.mrbird.febs.dapp.chain.ChainService;
+import cc.mrbird.febs.dapp.dto.BatchTransferDto;
 import cc.mrbird.febs.dapp.entity.*;
 import cc.mrbird.febs.dapp.mapper.*;
 import cc.mrbird.febs.dapp.service.AsyncCjService;
@@ -24,7 +24,6 @@
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -328,7 +327,7 @@
                     e.printStackTrace();
                 }
                 if(retryTime < 3){
-                    transfer = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer(dappMemberEntity.getAddress(), amount);
+                    transfer = ChainService.getInstance(ChainEnum.BSC_GFA.name()).transfer(dappMemberEntity.getAddress(), amount);
                 }
                 retryTime ++ ;
             }
@@ -398,7 +397,18 @@
     }
 
     public static void main(String[] args) {
-        String transfer = ChainService.getInstance(ChainEnum.BSC_USDT.name()).transfer("0xCEBfd36e03BD80c7015Cbad17eFfBc33d2923FF3", new BigDecimal("0.1"));
+        List<BatchTransferDto> objects = new ArrayList<>();
+        objects.add(new BatchTransferDto("0xCEBfd36e03BD80c7015Cbad17eFfBc33d2923FF3", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0xF9356131fD2c10B8d834E41C7aDD68E6983c35b9", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0x99dC2D688aA58b7798ebd17C163273875119cBc7", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0x32D13D3C8958c357270515560A61413f8e388b68", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0xf37780139783BeCD19118b84df277dB67B34363B", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0x2Fbd10058cDC4F5d95A593F25C8ce015dFE5779B", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0x597e5F0EDB294e7d28EB10A95aa2EEcd169a2dd7", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0xcFdbC664b8F137b3bD2Debc795bB0c5a6FdBc0bE", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0xcFdbC664b8F137b3bD2Debc795bB0c5a6FdBc0bE", new BigDecimal("0.001")));
+        objects.add(new BatchTransferDto("0xcFdbC664b8F137b3bD2Debc795bB0c5a6FdBc0bE", new BigDecimal("0.001")));
+        ChainService.getInstance(ChainEnum.BSC_USDT_LOCAL.name()).transferList(objects);
 //        BigInteger bigInteger = org.web3j.utils.Convert.toWei("35", org.web3j.utils.Convert.Unit.GWEI).toBigInteger();
 //        System.out.println(bigInteger);
     }

--
Gitblit v1.9.1