fix
Helius
2022-03-18 143d77c6b6de760304e8fdcf094452097c98842c
fix
23 files added
5 files modified
1095 ■■■■■ changed files
lib/tron-sdk.jar patch | view | raw | blame | history
pom.xml 41 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java 1 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java 14 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/contants/AppContants.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/interceptor/DappInterceptor.java 49 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/utils/ShareCodeUtil.java 118 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java 282 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java 42 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java 50 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/DappController.java 108 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/ApproveDto.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/dto/WalletOperateDto.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java 41 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappWalletMineEntity.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappMemberDao.java 16 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletMineDao.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappWalletService.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java 82 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java 42 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/WalletInfoVo.java 25 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappMemberDao.xml 12 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappWalletCoinDao.xml 8 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappWalletMineDao.xml 8 ●●●●● patch | view | raw | blame | history
lib/tron-sdk.jar
Binary files differ
pom.xml
@@ -304,6 +304,47 @@
            <scope>system</scope>
            <systemPath>${basedir}/lib/core-0.3.0.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>ztron-sdk</groupId>
            <artifactId>ztron-sdk</artifactId>
            <version>0.0.1</version>
            <scope>system</scope>
            <systemPath>${basedir}/lib/tron-sdk.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>org.web3j</groupId>
            <artifactId>core</artifactId>
            <version>4.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.6.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/logging-interceptor -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>logging-interceptor</artifactId>
            <version>3.6.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.web3j/parity -->
        <dependency>
            <groupId>org.web3j</groupId>
            <artifactId>parity</artifactId>
            <version>4.5.10</version>
            <exclusions>
                <exclusion>
                    <artifactId>core</artifactId>
                    <groupId>org.web3j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
src/main/java/cc/mrbird/febs/common/authentication/ShiroConfig.java
@@ -95,6 +95,7 @@
        // 排除手机api请求链接
        filterChainDefinitionMap.put("/api/**", "anon");
        filterChainDefinitionMap.put("/dapp/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java
@@ -1,5 +1,6 @@
package cc.mrbird.febs.common.configure;
import cc.mrbird.febs.common.interceptor.DappInterceptor;
import cc.mrbird.febs.common.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
@@ -15,9 +16,14 @@
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
        registration.addPathPatterns("/api/**");
        registration.excludePathPatterns("/api/common/**");
        registration.excludePathPatterns("/trx/**");
//        InterceptorRegistration registration = registry.addInterceptor(new LoginInterceptor());
//        registration.addPathPatterns("/api/**");
//        registration.addPathPatterns("/dapp/**");
//        registration.excludePathPatterns("/api/common/**");
        InterceptorRegistration registration = registry.addInterceptor(new DappInterceptor());
        registration.addPathPatterns("/dapp/**");
        registration.excludePathPatterns("/dapp/common/**");
    }
}
src/main/java/cc/mrbird/febs/common/contants/AppContants.java
@@ -79,4 +79,8 @@
    public static final String TRX_PRIVATE_KEY = "7a1cdc7aa2976b16cfc79ed8310b1fb53a85780dd27574fa6c5eb7c2aceaa6ae";
    public static final int INT_FLAG_Y = 1;
    public static final int INT_FLAG_N = 2;
}
src/main/java/cc/mrbird/febs/common/interceptor/DappInterceptor.java
New file
@@ -0,0 +1,49 @@
package cc.mrbird.febs.common.interceptor;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.common.utils.SpringContextUtil;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @author wzy
 * @date 2022-03-17
 **/
public class DappInterceptor implements HandlerInterceptor {
    private final DappMemberDao dappMemberDao = SpringContextUtil.getBean(DappMemberDao.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String headAddress = request.getHeader("address");
        if (StrUtil.isBlank(headAddress)) {
            responseUnAuth(response);
            return false;
        }
        DappMemberEntity memberEntity = dappMemberDao.selectByAddress(headAddress);
        if (memberEntity == null) {
            responseUnAuth(response);
            return false;
        }
        request.getSession().setAttribute("member", memberEntity);
        return true;
    }
    private void responseUnAuth(HttpServletResponse response) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write(new ObjectMapper().writeValueAsString(new FebsResponse().code(HttpStatus.UNAUTHORIZED)));
    }
}
src/main/java/cc/mrbird/febs/common/utils/LoginUserUtil.java
New file
@@ -0,0 +1,19 @@
package cc.mrbird.febs.common.utils;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
 * @author wzy
 * @date 2022-03-18
 **/
public class LoginUserUtil {
    public static DappMemberEntity getAppUser() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        return (DappMemberEntity) request.getSession().getAttribute("member");
    }
}
src/main/java/cc/mrbird/febs/common/utils/ShareCodeUtil.java
New file
@@ -0,0 +1,118 @@
package cc.mrbird.febs.common.utils;
import java.util.Random;
/**
 * 邀请码生成器,算法原理:<br/>
 * 1) 获取id: 1127738 <br/>
 * 2) 使用自定义进制转为:gpm6 <br/>
 * 3) 转为字符串,并在后面加'o'字符:gpm6o <br/>
 * 4)在后面随机产生若干个随机数字字符:gpm6o7 <br/>
 * 转为自定义进制后就不会出现o这个字符,然后在后面加个'o',这样就能确定唯一性。最后在后面产生一些随机字符进行补全。<br/>
 */
public class ShareCodeUtil {
    /**
     * 自定义进制(0,1没有加入,容易与o,l混淆)
     */
//    private static final char[] r=new char[]{'q', 'w', 'e', '8', 'a', 's', '2', 'd', 'z', 'x', '9', 'c', '7', 'p', '5', 'i', 'k', '3', 'm', 'j', 'u', 'f', 'r', '4', 'v', 'y', 'l', 't', 'n', '6', 'b', 'g', 'h'};
    private static final char[] r = new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9'};
    /**
     * (不能与自定义进制有重复)
     */
    private static final char b = '0';
    /**
     * 进制长度
     */
    private static final int binLen = r.length;
    /**
     * 序列最小长度
     */
    private static final int s = 8;
    /**
     * 根据ID生成六位随机码
     *
     * @param id ID
     * @return 随机码
     */
    public static String toSerialCode(long id) {
        char[] buf = new char[32];
        int charPos = 32;
        while ((id / binLen) > 0) {
            int ind = (int) (id % binLen);
            buf[--charPos] = r[ind];
            id /= binLen;
        }
        buf[--charPos] = r[(int) (id % binLen)];
        String str = new String(buf, charPos, (32 - charPos));
        // 不够长度的自动随机补全
        if (str.length() < s) {
            StringBuilder sb = new StringBuilder();
            sb.append(b);
            Random rnd = new Random();
            for (int i = 1; i < s - str.length(); i++) {
                sb.append(r[rnd.nextInt(binLen)]);
            }
            str += sb.toString();
        }
        return str;
    }
    /**
     * 根据ID生成六位随机码
     *
     * @param id ID
     * @return 随机码
     */
    public static String toSerialNumberCode(long id) {
        char[] buf = new char[32];
        int charPos = 32;
        while ((id / binLen) > 0) {
            int ind = (int) (id % binLen);
            buf[--charPos] = r[ind];
            id /= binLen;
        }
        buf[--charPos] = r[(int) (id % binLen)];
        String str = new String(buf, charPos, (32 - charPos));
        // 不够长度的自动随机补全
        if (str.length() < s) {
            StringBuilder sb = new StringBuilder();
            sb.append(b);
            Random rnd = new Random();
            for (int i = 1; i < s - str.length(); i++) {
                sb.append(r[rnd.nextInt(binLen)]);
            }
            str += sb.toString();
        }
        return str;
    }
    public static long codeToId(String code) {
        char chs[] = code.toCharArray();
        long res = 0L;
        for (int i = 0; i < chs.length; i++) {
            int ind = 0;
            for (int j = 0; j < binLen; j++) {
                if (chs[i] == r[j]) {
                    ind = j;
                    break;
                }
            }
            if (chs[i] == b) {
                break;
            }
            if (i > 0) {
                res = res * binLen + ind;
            } else {
                res = ind;
            }
        }
        return res;
    }
}
src/main/java/cc/mrbird/febs/dapp/chain/EthService.java
New file
@@ -0,0 +1,282 @@
package cc.mrbird.febs.dapp.chain;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
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.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Convert.Unit;
import org.web3j.utils.Numeric;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
 * ETH类,使用Web3j 下面为使用教程
 * https://kauri.io/article/925d923e12c543da9a0a3e617be963b4/manage-an-ethereum-account-with-java-and-web3js
 *
 * @author Administrator
 *
 */
@Slf4j
public class EthService {
    private static String ethWalletPath = "/home/javaweb/webresource/eth";
    private Web3j web3j;
    /**
     * 服务器地址
     */
    //private static final String ETH_UTL = "http://120.55.86.146:8545";
    //    private static final String ETH_UTL = "http://114.55.250.231:8545";
    private static final String ETH_UTL = "https://mainnet.infura.io/v3/f54a5887a3894ebb9425920701a97fe0";
    public EthService() {
        try {
            HttpService service = new HttpService(ETH_UTL);
            web3j = Web3j.build(service);
        } catch (Exception e) {
            log.error("连接eth网络失败", e);
        }
    }
    /**
     * 查询ETH余额
     *
     * @param address
     * @return
     */
    public static BigDecimal getEthBlance(String address) {
        Web3j web3 = Web3j.build(new HttpService(ETH_UTL));
        EthGetBalance balanceWei;
        try {
            balanceWei = web3.ethGetBalance(address, DefaultBlockParameterName.LATEST).send();
            if (balanceWei.getResult() == null) {
                return null;
            }
            BigDecimal balanceInEther = Convert.fromWei(balanceWei.getBalance().toString(), Unit.ETHER);
            return balanceInEther;
        } catch (Exception e) {
            System.out.println("ETH查询失败:" + address);
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 创建ETH钱包
     *
     * @return
     */
    public static Map<String, String> createEth() {
        Map<String, String> wallet = new HashMap<String, String>();
        try {
            String walletPassword = "secr3t";
            // 文件路径
            String walletDirectory = ethWalletPath;
            String walletName = WalletUtils.generateNewWalletFile(walletPassword, new File(walletDirectory));
            System.out.println("wallet location: " + walletDirectory + "/" + walletName);
            Credentials credentials = WalletUtils.loadCredentials(walletPassword, walletDirectory + "/" + walletName);
            String accountAddress = credentials.getAddress();
            String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);
            // 钱包地址
            wallet.put("address", accountAddress);
            // 钱包私钥
            wallet.put("privateKey", privateKey);
            // 产生的钱包文件地址
            wallet.put("walletLocation", walletDirectory + "/" + walletName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wallet;
    }
    public boolean checkTransferResult(String hash) {
        // 0xa3e6a0ccc3aac30d866a86ca9c0477dd58b7b061787ba40b16c3844803273816 交易hash
        Request<?, EthGetTransactionReceipt> ethGetTransactionReceiptRequest = web3j.ethGetTransactionReceipt(hash);
        EthGetTransactionReceipt send = null;
        try {
            send = ethGetTransactionReceiptRequest.send();
            if(send!=null){
                TransactionReceipt result = send.getResult();
                if(result!=null){
                    String status = result.getStatus();
                    System.out.println(status);//0x1
                    if("0x1".equals(status)){
                        return true;
                    }else{
                        return false;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }
    public static void main(String[] args) throws IOException {
        HttpService service = new HttpService(ETH_UTL);
        Web3j build = Web3j.build(service);
        //Request<?, EthTransaction> ethTransactionRequest = build.ethGetTransactionByHash("0xa3e6a0ccc3aac30d866a86ca9c0477dd58b7b061787ba40b16c3844803273816");
        Request<?, EthGetTransactionReceipt> ethGetTransactionReceiptRequest = build.ethGetTransactionReceipt("0xa3e6a0ccc3aac30d866a86ca9c0477dd58b7b061787ba40b16c3844803273816");
        EthGetTransactionReceipt send = ethGetTransactionReceiptRequest.send();
        String status = send.getResult().getStatus();
        System.out.println(status);//0x1
//        EthTransaction send = ethTransactionRequest.send();
//        String input = send.getResult().getInput();
//        System.out.println(input);
    }
    /**
     *
     * 方法描述:获取代币余额
     *
     * @param fromAddress
     * @param
     * @param
     * @return long
     */
    public BigDecimal tokenGetBalance(String fromAddress) {
        try {
            // 合约地址
            String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
            int decimal = 6;
            String methodName = "balanceOf";
            List<Type> inputParameters = new ArrayList<>();
            List<TypeReference<?>> outputParameters = new ArrayList<>();
            Address address = new Address(fromAddress);
            inputParameters.add(address);
            TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
            };
            outputParameters.add(typeReference);
            Function function = new Function(methodName, inputParameters, outputParameters);
            String data = FunctionEncoder.encode(function);
            Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
            EthCall ethCall;
            BigInteger balanceValue = BigInteger.ZERO;
            try {
                ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
                List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
                balanceValue = (BigInteger) results.get(0).getValue();
            } catch (IOException e) {
                e.printStackTrace();
            }
            double res = new BigDecimal(balanceValue).divide(BigDecimal.valueOf(Math.pow(10, decimal)), 8, RoundingMode.HALF_DOWN).doubleValue();
            if (res > 0) {
                return new BigDecimal(res);
            }
        } catch (Exception e) {
            // logger.error("==============以太坊代币链接获取失败!");
            e.printStackTrace();
        }
        return BigDecimal.ZERO;
    }
    // USDT
    public String tokenSend(String privateKey, String fromAddress, String toAddress, String amount,String gas)
            throws InterruptedException, ExecutionException {
        // Web3j web3j = Web3j.build(new
        // HttpService("https://mainnet.infura.io/v3/882c66ebcfc141abbea22b948fa44321"));
        if(StringUtils.isBlank(gas)){
            gas="70";
        }
        String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        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, Unit.GWEI).toBigInteger(),// 给矿工开的转账单价 单价越高越快
                Convert.toWei("60000", Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
                // 10*80000/1000000000=0.0008 手续费
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        // log.debug("transfer hexValue:" + hexValue);
        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
        //return "hash";
        if (ethSendTransaction.hasError()) {
            // log.info("transfer error:", ethSendTransaction.getError().getMessage());
            return "";
        } else {
            String transactionHash = ethSendTransaction.getTransactionHash();
            // log.info("Transfer transactionHash:" + transactionHash);
            return transactionHash;
        }
    }
    public String ethSend(String privateKey, String fromAddress, String toAddress, String amount,String gas)
            throws InterruptedException, ExecutionException {
        // Web3j web3j = Web3j.build(new
        // HttpService("https://mainnet.infura.io/v3/882c66ebcfc141abbea22b948fa44321"));
        if(StringUtils.isBlank(gas)){
            gas="70";
        }
        Credentials credentials = Credentials.create(privateKey);
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        BigInteger value = Convert.toWei(amount, Unit.ETHER).toBigInteger();
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce,
                Convert.toWei(gas, Unit.GWEI).toBigInteger(),
                Convert.toWei("60000", Unit.WEI).toBigInteger(), toAddress, value);
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);
        EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
        if (ethSendTransaction.hasError()) {
            // log.info("transfer error:", ethSendTransaction.getError().getMessage());
            return "";
        } else {
            String transactionHash = ethSendTransaction.getTransactionHash();
            // log.info("Transfer transactionHash:" + transactionHash);
            return transactionHash;
        }
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
New file
@@ -0,0 +1,42 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.dapp.dto.ApproveDto;
import cc.mrbird.febs.dapp.service.DappMemberService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
 * @author wzy
 * @date 2022-03-17
 **/
@Slf4j
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
@RestController
@Api(value = "dapp公共接口", tags = "dapp公共接口")
@RequestMapping(value = "/dapp/common")
public class ApiCommonController {
    private final DappMemberService dappMemberService;
    @ApiOperation(value = "授权接口", notes = "授权接口")
    @PostMapping(value = "/approve")
    public FebsResponse approve(@RequestBody ApproveDto approveDto) {
        dappMemberService.approve(approveDto);
        return new FebsResponse().success().message("授权成功");
    }
    @ApiOperation(value = "是否授权接口", notes = "是否授权接口")
    @GetMapping(value = "/isApprove/{address}")
    public FebsResponse isApprove(@PathVariable("address") String address) {
        boolean isApprove = dappMemberService.isApprove(address);
        if (isApprove) {
            return new FebsResponse().success().message("已授权");
        }
        return new FebsResponse().fail().message("未授权");
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java
New file
@@ -0,0 +1,50 @@
package cc.mrbird.febs.dapp.controller;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.dapp.dto.WalletOperateDto;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
 * @author wzy
 * @date 2022-03-17
 **/
@Slf4j
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
@RestController
@Api(value = "dapp接口", tags = "dapp接口")
@RequestMapping(value = "/dapp/member")
public class ApiDappMemberController {
    private final DappWalletService dappWalletService;
    @ApiOperation(value = "获取账户信息接口", notes = "获取账号信息接口")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = WalletInfoVo.class)
    })
    @PostMapping(value = "/walletInfo")
    public FebsResponse walletInfo() {
        WalletInfoVo walletInfoVo = dappWalletService.walletInfo();
        return new FebsResponse().success().data(walletInfoVo);
    }
    @ApiOperation(value = "兑换接口", notes = "兑换")
    @PostMapping(value = "/change")
    public FebsResponse change(@RequestBody WalletOperateDto walletOperateDto) {
        return null;
    }
    @ApiOperation(value = "提现接口", notes = "提现接口")
    @PostMapping(value = "/withdraw")
    public FebsResponse withdraw(@RequestBody WalletOperateDto walletOperateDto) {
        return null;
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/DappController.java
@@ -9,16 +9,42 @@
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.tron.trident.core.ApiWrapper;
import org.tron.trident.core.contract.Contract;
import org.tron.trident.core.contract.Trc20Contract;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
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.methods.request.Transaction;
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;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
/**
 * @author wzy
@@ -66,4 +92,86 @@
        token.transferFrom(trxPostDto.getAddress(), "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", amount.intValue(), 0, "memo", 100000000L);
        return new FebsResponse().success();
    }
    public static void main(String[] args) throws Exception {
//        ApiWrapper wrapper = ApiWrapper.ofShasta("ebefe7b932359a7ef70c5cec0aed9aa2ca468b6c0d60ac637fe783530e459978");
//        Contract trc20Contract = wrapper.getContract("TRTE68V3TJBLduBoJPLMgBsvwkq8LJBin6");
//        Trc20Contract token = new Trc20Contract(trc20Contract, "TKcyw4igFYhNpTzyZv25j6uDwvTYzncnjp", wrapper);
//
//        BigInteger balance = token.balanceOf("TKcyw4igFYhNpTzyZv25j6uDwvTYzncnjp");
//        token.transfer("TUy8XwDmdsDKPLDGUrGuNRVMhwSEKtkDcD", balance.longValue(), 0, "memo", 100000000L);
//        ApiWrapper wrapper = ApiWrapper.ofMainnet("af4913d8462ca83e0a2df587072e42ec565bc26f6bec0724d1bf2e80d4c0bcb7", "9d461be6-9796-47b9-85d8-b150cbabbb54");
//        Contract trc20Contract = wrapper.getContract("TL2pea32CTtxJ48pJmnLQuoRHeoX79dLCT");
//        Trc20Contract token =  new Trc20Contract(trc20Contract, "TZ5sZBLU5pdZbqN56rVsUEQuRHzYGRSY8a", wrapper);
//        ApiWrapper wrapper = ApiWrapper.ofMainnet(AppContants.TRX_PRIVATE_KEY, "9d461be6-9796-47b9-85d8-b150cbabbb54");
//
//        Contract trc20Contract = wrapper.getContract("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t");
//        Trc20Contract token = new Trc20Contract(trc20Contract, "TFGbYzGv4Zt2nzFM3uU3uCJZY67WKSveG9", wrapper);
//
//        System.out.println(token.balanceOf("TUy8XwDmdsDKPLDGUrGuNRVMhwSEKtkDcD"));;
        HttpService service = new HttpService("https://mainnet.infura.io/v3/f54a5887a3894ebb9425920701a97fe0");
        Web3j web3j = Web3j.build(service);
//        String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
//        String fromAddress = "0x391040eE5F241711E763D0AC55E775B9b4bD0024";
//        String toAddress = "0xD998DA7362360eFC6daDFEd6E9a32E70640d7600";
//        int decimal = 6;
//        String methodName = "allowance";
//        List<Type> inputParameters = new ArrayList<>();
//        List<TypeReference<?>> outputParameters = new ArrayList<>();
//        Address address = new Address(toAddress);
//        inputParameters.add(address);
//        TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {
//        };
//        outputParameters.add(typeReference);
//        Function function = new Function(methodName, inputParameters, outputParameters);
//        String data = FunctionEncoder.encode(function);
//        Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
//
//        EthCall ethCall;
//        BigInteger balanceValue = BigInteger.ZERO;
//        ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
//        List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
//        System.out.println(results);
//        String gas = "";
//        if(StringUtils.isBlank(gas)){
//            gas="70";
//        }
//        String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
//        Credentials credentials = Credentials.create(privateKey);
//
//        EthGetTransactionCount ethGetTransactionCount = web3j
//                .ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
//
//        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
//
//        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("60000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction);//里程上限
//        // 10*80000/1000000000=0.0008 手续费
//
//        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
//        String hexValue = Numeric.toHexString(signedMessage);
//
//        // log.debug("transfer hexValue:" + hexValue);
//
//        CompletableFuture<EthSendTransaction> ethSendTransactionCompletableFuture = web3j.ethSendRawTransaction(hexValue).sendAsync();
//        EthSendTransaction ethSendTransaction = ethSendTransactionCompletableFuture.get();
    }
}
src/main/java/cc/mrbird/febs/dapp/dto/ApproveDto.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.dapp.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * @author wzy
 * @date 2022-03-18
 **/
@Data
@ApiModel(value = "ApproveDto", description = "授权接口参数接收类")
public class ApproveDto {
    @NotNull(message = "地址不能为空")
    @ApiModelProperty(value = "地址")
    private String address;
    @ApiModelProperty(value = "推荐人")
    private String refererId;
}
src/main/java/cc/mrbird/febs/dapp/dto/WalletOperateDto.java
New file
@@ -0,0 +1,20 @@
package cc.mrbird.febs.dapp.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-03-18
 **/
@Data
@ApiModel(value = "WalletOperateDto", description = "钱包操作参数接收类")
public class WalletOperateDto {
    @ApiModelProperty(value = "金额", example = "1")
    private BigDecimal amount;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java
New file
@@ -0,0 +1,41 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-03-17
 **/
@Data
@TableName("dapp_member")
public class DappMemberEntity extends BaseEntity {
    private String address;
    private BigDecimal balance;
    /**
     * 用户状态 1-正常 2-禁用
     */
    private Integer accountStatus;
    /**
     * 是否可兑换 1-是 2-否
     */
    private Integer changeAble;
    /**
     * 是否可提现 1-是 2-否
     */
    private Integer withdrawAble;
    private String inviteId;
    private String refererId;
    private String refererIds;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappWalletCoinEntity.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-03-17
 **/
@Data
@TableName("dapp_wallet_coin")
public class DappWalletCoinEntity extends BaseEntity {
    private Long memberId;
    private BigDecimal totalAmount;
    private BigDecimal frozenAmount;
    private BigDecimal availableAmount;
}
src/main/java/cc/mrbird/febs/dapp/entity/DappWalletMineEntity.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-03-17
 **/
@Data
@TableName("dapp_wallet_mine")
public class DappWalletMineEntity extends BaseEntity {
    private Long memberId;
    private BigDecimal totalAmount;
    private BigDecimal frozenAmount;
    private BigDecimal availableAmount;
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappMemberDao.java
New file
@@ -0,0 +1,16 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
 * @author wzy
 * @date 2022-03-17
 **/
public interface DappMemberDao extends BaseMapper<DappMemberEntity> {
    DappMemberEntity selectByAddress(@Param("address") String address);
    DappMemberEntity selectMemberInfoByInviteId(@Param("inviteId") String inviteId);
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletCoinDao.java
New file
@@ -0,0 +1,10 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappWalletCoinEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
public interface DappWalletCoinDao extends BaseMapper<DappWalletCoinEntity> {
    DappWalletCoinEntity selectByMemberId(@Param("memberId") Long memberId);
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappWalletMineDao.java
New file
@@ -0,0 +1,10 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappWalletMineEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
public interface DappWalletMineDao extends BaseMapper<DappWalletMineEntity> {
    DappWalletMineEntity selectByMemberId(@Param("memberId") Long memberId);
}
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java
New file
@@ -0,0 +1,12 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.dapp.dto.ApproveDto;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import com.baomidou.mybatisplus.extension.service.IService;
public interface DappMemberService extends IService<DappMemberEntity> {
    void approve(ApproveDto approveDto);
    boolean isApprove(String address);
}
src/main/java/cc/mrbird/febs/dapp/service/DappWalletService.java
New file
@@ -0,0 +1,9 @@
package cc.mrbird.febs.dapp.service;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
public interface DappWalletService {
    WalletInfoVo walletInfo();
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
New file
@@ -0,0 +1,82 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.dapp.dto.ApproveDto;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappWalletCoinEntity;
import cc.mrbird.febs.dapp.entity.DappWalletMineEntity;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappWalletCoinDao;
import cc.mrbird.febs.dapp.mapper.DappWalletMineDao;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-03-17
 **/
@Service
@RequiredArgsConstructor
public class DappMemberServiceImpl extends ServiceImpl<DappMemberDao, DappMemberEntity> implements DappMemberService {
    private final DappMemberDao dappMemberDao;
    private final DappWalletCoinDao dappWalletCoinDao;
    private final DappWalletMineDao dappWalletMineDao;
    @Override
    public void approve(ApproveDto approveDto) {
        DappMemberEntity member = new DappMemberEntity();
        member.setAddress(approveDto.getAddress());
        // TODO 判断地址是否被授权,并获取地址余额
        member.setBalance(BigDecimal.ZERO);
        dappMemberDao.insert(member);
        member.setInviteId(ShareCodeUtil.toSerialCode(member.getId()));
        if (StrUtil.isNotBlank(approveDto.getRefererId())){
            boolean flag = false;
            String parentId = approveDto.getRefererId();
            String ids = "";
            while (!flag && StringUtils.isNotBlank(parentId)) {
                ids += ("," + parentId);
                DappMemberEntity parentMember = dappMemberDao.selectMemberInfoByInviteId(parentId);
                if (parentMember == null) {
                    break;
                }
                parentId = parentMember.getRefererId();
                if(StringUtils.isBlank(parentId)){
                    break;
                }
                if (parentMember.getRefererId().equals(parentMember.getInviteId())) {
                    flag = true;
                }
            }
            member.setRefererIds(ids);
            dappMemberDao.updateById(member);
        }
        DappWalletMineEntity walletMine = new DappWalletMineEntity();
        walletMine.setMemberId(member.getId());
        dappWalletMineDao.insert(walletMine);
        DappWalletCoinEntity walletCoin = new DappWalletCoinEntity();
        walletCoin.setMemberId(member.getId());
        dappWalletCoinDao.insert(walletCoin);
    }
    @Override
    public boolean isApprove(String address) {
        DappMemberEntity memberEntity = dappMemberDao.selectByAddress(address);
        if (memberEntity != null) {
            return true;
        }
        return false;
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
New file
@@ -0,0 +1,42 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappWalletCoinEntity;
import cc.mrbird.febs.dapp.entity.DappWalletMineEntity;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappWalletCoinDao;
import cc.mrbird.febs.dapp.mapper.DappWalletMineDao;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
 * @author wzy
 * @date 2022-03-18
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class DappWalletServiceImpl implements DappWalletService {
    private final DappMemberDao dappMemberDao;
    private final DappWalletMineDao dappWalletMineDao;
    private final DappWalletCoinDao dappWalletCoinDao;
    @Override
    public WalletInfoVo walletInfo() {
        DappMemberEntity member = LoginUserUtil.getAppUser();
        DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId());
        DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId());
        WalletInfoVo walletInfo = new WalletInfoVo();
        walletInfo.setTotalMine(walletMine.getTotalAmount());
        walletInfo.setAvailableMine(walletMine.getAvailableAmount());
        walletInfo.setAvailableWallet(walletCoin.getAvailableAmount());
        return walletInfo;
    }
}
src/main/java/cc/mrbird/febs/dapp/vo/WalletInfoVo.java
New file
@@ -0,0 +1,25 @@
package cc.mrbird.febs.dapp.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-03-18
 **/
@Data
@ApiModel(value = "WalletInfoVo", description = "钱包信息返回参数类")
public class WalletInfoVo {
    @ApiModelProperty(value = "总产量")
    private BigDecimal totalMine;
    @ApiModelProperty(value = "可兑换")
    private BigDecimal availableMine;
    @ApiModelProperty(value = "收入余额")
    private BigDecimal availableWallet;
}
src/main/resources/mapper/dapp/DappMemberDao.xml
New file
@@ -0,0 +1,12 @@
<?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="cc.mrbird.febs.dapp.mapper.DappMemberDao">
    <select id="selectByAddress" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
        select * from dapp_member where address=#{address}
    </select>
    <select id="selectMemberInfoByInviteId" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
        select * from dapp_member where invite_id=#{inviteId}
    </select>
</mapper>
src/main/resources/mapper/dapp/DappWalletCoinDao.xml
New file
@@ -0,0 +1,8 @@
<?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="cc.mrbird.febs.dapp.mapper.DappWalletCoinDao">
    <select id="selectByMemberId" resultType="cc.mrbird.febs.dapp.entity.DappWalletCoinEntity">
        select * from dapp_member_coin where member_id=#{memberId}
    </select>
</mapper>
src/main/resources/mapper/dapp/DappWalletMineDao.xml
New file
@@ -0,0 +1,8 @@
<?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="cc.mrbird.febs.dapp.mapper.DappWalletMineDao">
    <select id="selectByMemberId" resultType="cc.mrbird.febs.dapp.entity.DappWalletMineEntity">
        select * from dapp_member_mine where member_id=#{memberId}
    </select>
</mapper>