KKSU
2024-06-03 8f720d592d6ea2229cac4c051828af39f8425325
批量转账
6 files modified
1 files added
204 ■■■■■ changed files
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ContractChainService.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java 102 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/TrxService.java 9 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/MemberMoneyFlowController.java 47 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/BatchTransferDto.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/AsyncCjServiceImpl.java 18 ●●●● patch | view | raw | blame | history
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
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();
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;
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;
    }
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);
src/main/java/cc/mrbird/febs/dapp/dto/BatchTransferDto.java
New file
@@ -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;
    }
}
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);
    }