Advertisement

以太坊区块链java开发:web3j

阅读量:

以太坊 java开发依赖

复制代码
     <dependency>

    
         <groupId>org.web3j</groupId>
    
         <artifactId>core</artifactId>
    
         <version>3.5.0</version>
    
     </dependency>
    
    
    
    
    AI写代码

连接到以太坊同步节点

复制代码
 private String gethURL = "http://localhost:8545";

    
  
    
     private void connectGeth() {
    
         // --rpcport value HTTP-RPC服务器监听端口(默认值:8545)
    
         this.web3j = Admin.build(new HttpService(gethURL));
    
         if(null==web3j) {
    
             System.out.println("connectGeth error");
    
         }
    
     }
    
    
    
    
    AI写代码

创建账户,需要输入密码,返回账户地址 0x00000...

复制代码
     public String addAccount(String password) {

    
         // walletId:$|chainId:$|account:$
    
         if (web3j == null)
    
             connectGeth();
    
         String account = "";
    
         try {
    
  
    
             String fileName = WalletUtils.generateNewWalletFile(password, new File(keystorePath));
    
             Credentials credentials = WalletUtils.loadCredentials(password, keystorePath + "/" + fileName);
    
             account = credentials.getAddress();
    
  
    
         } catch (InvalidAlgorithmParameterException e1) {
    
             e1.printStackTrace();
    
         } catch (NoSuchAlgorithmException e1) {
    
             e1.printStackTrace();
    
         } catch (NoSuchProviderException e1) {
    
             e1.printStackTrace();
    
         } catch (CipherException e1) {
    
             e1.printStackTrace();
    
         } catch (IOException e1) {
    
             e1.printStackTrace();
    
         }
    
         addCredentials(account, password);
    
         return account;
    
     }
    
    
    
    
    AI写代码

以太币(矿币)转账

复制代码
     private void transfer_ETH(String _from, String password, String _to, BigInteger value, Long logId) {

    
     Credentials credentials = loadCredentials(_from, password);
    
     try {
    
         //获取nonce
    
         EthGetTransactionCount count=web3j.ethGetTransactionCount(_from, DefaultBlockParameterName.LATEST).send();
    
         BigInteger nonce=count.getTransactionCount();
    
         //创建交易
    
         //BigInteger val=Convert.toWei(new BigDecimal(value), Unit.ETHER).toBigInteger();
    
         RawTransaction rawTransaction=RawTransaction.createEtherTransaction(nonce, GAS_PRICE, GAS_LIMIT, _to, value);
    
         //验证签名
    
         byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
    
         String hexValue=Numeric.toHexString(signMessage);
    
         //发送交易
    
         CompletableFuture<EthSendTransaction> sendAsync = web3j.ethSendRawTransaction(hexValue).sendAsync();
    
         sendAsync.whenComplete((v,e)->{
    
             //交易回调
    
             new Thread(() -> {
    
                 callBackService.callbackEthSendTransaction(v, logId, e);
    
             }).start();
    
         });
    
     }catch(Exception e) {
    
 			
    
     }
    
     }
    
    
    
    
    AI写代码

加载已有账户的凭证

keystorePath是凭证文件保存的文件夹地址,例如:/home/geth/keystore

这里读取文件之前,先去全局map(预加载)里检查是否能拿到凭证

复制代码
     private Credentials loadCredentials(String address,String password){

    
     Credentials credentials=credentialsMap.get(address);
    
     if(CommonUtil.isNull(credentials)){
    
         //往map里加
    
         credentials=addCredentials(address,password);
    
     }
    
     return credentials;
    
     }
    
     private  Credentials addCredentials(String address,String password){
    
     Credentials credentials=null;
    
     try {
    
         File file = new File(keystorePath);
    
         File[] files = file.listFiles();
    
         if(files!=null && files.length>0){
    
             for (File f : files) {
    
                 String a=address.trim().substring(2);
    
                 if (f.getName().contains(a)) {
    
                     //取到这个文件,并生成credentials对象
    
                     credentials = WalletUtils.loadCredentials(password, f);
    
                     break;
    
                 }
    
             }
    
         }
    
         if (!CommonUtil.isNull(credentials)){
    
             credentialsMap.putIfAbsent(address, credentials);
    
         }else {
    
             throw new RuntimeException("读取凭证错误,请检查钱包文件是否存在");
    
         }
    
     } catch (IOException  | CipherException e) {
    
         e.printStackTrace();
    
     }
    
     return credentials;
    
     }
    
    
    
    
    AI写代码

以太坊还包括合约发布的代币-虚拟币

加载执行合约也是非常常见的

智能合约由solidity语言开发,可以编译为java文件

可以使用VScode下载solidity插件,将合约编译 .sol ---> .bin .abi .json

基于genode-3.5.0.jar工具的SolidityFunctionWrapperGenerator类的主要功能模块

复制代码
 <!-- https://mvnrepository.com/artifact/org.web3j/codegen -->

    
  
    
 <dependency>
    
  
    
 <groupId>org.web3j</groupId>
    
  
    
 <artifactId>codegen</artifactId>
    
  
    
 <version>3.5.0</version>
    
  
    
 </dependency>
    
    
    
    
    AI写代码

并需要附带参数

复制代码
 #来自https://docs.web3j.io/smart_contracts.html

    
  
    
 $ web3j solidity generate [--javaTypes|--solidityTypes] /path/to/<smart-contract>.bin /path/to/<smart-contract>.abi -o /path/to/src/main/java -p com.your.organisation.name
    
    
    
    
    AI写代码
复制代码
 private static final String USAGE = "solidity generate "

    
     + "[--javaTypes|--solidityTypes] "
    
     + "<input binary file>.bin <input abi file>.abi "
    
     + "-p|--package <base package name> "
    
     + "-o|--output <destination base directory>";
    
    
    
    
    AI写代码

从输出文件夹拿到编译好的java合约代码

调用合约方法 加载合约需要合约地址

复制代码
 //GAS_PRICE可以动态获取

    
 private BigInteger GAS_PRICE = BigInteger.valueOf(22_000_000_000L);
    
 //GAS_LIMIT参数固定
    
 private final BigInteger GAS_LIMIT = BigInteger.valueOf(43_000);
    
 /** * USDT的转账方法
    
 */
    
 private void transfer_USDT(String _from, String password, String _to, BigInteger value, Long logId) {
    
     //拿到凭证
    
     Credentials credentials = loadCredentials(_from, password);
    
     //使用凭证加载合约 需要知道合约的地址 这里涉及到GAS 是为交易手续费 从合约调用方账户上扣除以太币
    
     TetherToken contract = TetherToken.load(USDTAddress, getWeb3j(), credentials, GAS_PRICE, GAS_LIMIT);
    
     //调用合约方法
    
     RemoteCall<TransactionReceipt> transfer = contract.transfer(_to, value);
    
     CompletableFuture<TransactionReceipt> sendAsync = transfer.sendAsync();
    
     //异步执行 并添加回调方法
    
     sendAsync.whenComplete((v,e)->{
    
     new Thread(() -> {
    
         callBackService.callbackTransactionReceipt(v, logId, e);
    
     }).start();
    
     });
    
 }
    
    
    
    
    AI写代码

有一部分合约并不公开源码

当无法直接编译生成Java合约为二进制代码时

abi包括一个合约所有方法、参数、返回值

以下做一个简单的示例,并不支持很多参数类型

复制代码
 import java.io.IOException;

    
 import java.math.BigInteger;
    
 import java.util.ArrayList;
    
 import java.util.List;
    
  
    
 import org.web3j.abi.TypeReference;
    
 import org.web3j.abi.datatypes.Address;
    
 import org.web3j.abi.datatypes.Bool;
    
 import org.web3j.abi.datatypes.Int;
    
 import org.web3j.abi.datatypes.Type;
    
 import org.web3j.abi.datatypes.Uint;
    
 import org.web3j.abi.datatypes.Utf8String;
    
 import org.web3j.crypto.Credentials;
    
 import org.web3j.protocol.Web3j;
    
 import org.web3j.tx.Contract;
    
  
    
 import com.alibaba.fastjson.JSON;
    
 import okkpp.function.Function;
    
 import okkpp.function.Param;
    
  
    
 public class WidelyContract extends Contract {
    
  
    
     private List<Function> functions;
    
  
    
     @SuppressWarnings("deprecation")
    
     protected WidelyContract(String abi, String contractBinary, String contractAddress, Web3j web3j,
    
             Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
    
         super(contractBinary, contractAddress, web3j, credentials, gasPrice, gasLimit);
    
         this.functions = JSON.parseArray(abi, Function.class);
    
     }
    
  
    
     public static WidelyContract load(String abi, String contractBinary, String contractAddress, Web3j web3j,
    
             Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
    
         return new WidelyContract(abi, contractBinary, contractAddress, web3j, credentials, gasPrice, gasLimit);
    
     }
    
  
    
     @SuppressWarnings("rawtypes")
    
     public Type<?> excute(String functionName, String... params) throws IOException {
    
         List<Type> inputs = null;
    
         List<TypeReference<?>> outputs = null;
    
         for (Function f : functions) {
    
             if (functionName.equals(f.getName())) {
    
                 inputs = getInputs(f.getInputs(), params);
    
                 outputs = getOutputs(f.getOutputs());
    
             }
    
         }
    
         return executeCallSingleValueReturn(new org.web3j.abi.datatypes.Function(functionName, inputs, outputs));
    
     }
    
  
    
     @SuppressWarnings("rawtypes")
    
     private List<Type> getInputs(List<Param> inputs, String[] params) {
    
         int size = inputs.size();
    
         List<Type> result = new ArrayList<Type>();
    
         for (int i = 0; i < size; i++) {
    
             result.add(getParam(inputs.get(i).getType(), params[i]));
    
         }
    
         return result;
    
     }
    
  
    
     private List<TypeReference<?>> getOutputs(List<Param> outputs) {
    
         int size = outputs.size();
    
         List<TypeReference<?>> result = new ArrayList<>();
    
         for (int i = 0; i < size; i++) {
    
             result.add(getType(outputs.get(i).getType()));
    
         }
    
         return result;
    
     }
    
  
    
     private TypeReference<?> getType(String type) {
    
         switch (type) {
    
         case "address": {
    
             return new TypeReference<Address>() {
    
             };
    
         }
    
         case "string": {
    
             return new TypeReference<Utf8String>() {
    
             };
    
         }
    
         case "bool": {
    
             return new TypeReference<Bool>() {
    
             };
    
         }
    
         }
    
         if (type.startsWith("uint")) {
    
             return new TypeReference<Uint>() {
    
             };
    
         }
    
         if (type.startsWith("int")) {
    
             return new TypeReference<Int>() {
    
             };
    
         }
    
         return null;
    
     }
    
  
    
     @SuppressWarnings("rawtypes")
    
     private Type getParam(String type, String input) {
    
         switch (type) {
    
         case "address": {
    
             return new Address(input);
    
         }
    
         case "string": {
    
             return new Utf8String(input);
    
         }
    
         case "bool": {
    
             return new Bool(input.equals("true"));
    
         }
    
         }
    
         if (type.startsWith("uint")) {
    
             return new Uint(new BigInteger(input));
    
         }
    
         if (type.startsWith("int")) {
    
             return new Int(new BigInteger(input));
    
         }
    
         return null;
    
     }
    
 }
    
    
    
    
    AI写代码

另附自定义Function类

复制代码
 import java.util.List;

    
  
    
 public class Function {
    
  
    
     private boolean constant;
    
     private String name;
    
     private boolean payable;
    
     private String stateMutability;
    
     private String type;
    
     private List<Param> inputs;
    
     private List<Param> outputs;
    
  
    
     public boolean isConstant() {
    
         return constant;
    
     }
    
  
    
     public void setConstant(boolean constant) {
    
         this.constant = constant;
    
     }
    
  
    
     public String getName() {
    
         return name;
    
     }
    
  
    
     public void setName(String name) {
    
         this.name = name;
    
     }
    
  
    
     public boolean isPayable() {
    
         return payable;
    
     }
    
  
    
     public void setPayable(boolean payable) {
    
         this.payable = payable;
    
     }
    
  
    
     public String getStateMutability() {
    
         return stateMutability;
    
     }
    
  
    
     public void setStateMutability(String stateMutability) {
    
         this.stateMutability = stateMutability;
    
     }
    
  
    
     public String getType() {
    
         return type;
    
     }
    
  
    
     public void setType(String type) {
    
         this.type = type;
    
     }
    
  
    
     public List<Param> getInputs() {
    
         return inputs;
    
     }
    
  
    
     public void setInputs(List<Param> inputs) {
    
         this.inputs = inputs;
    
     }
    
  
    
     public List<Param> getOutputs() {
    
         return outputs;
    
     }
    
  
    
     public void setOutputs(List<Param> outputs) {
    
         this.outputs = outputs;
    
     }
    
  
    
     @Override
    
     public String toString() {
    
         return "Function [constant=" + constant + ", name=" + name + ", payable=" + payable + ", stateMutability="
    
                 + stateMutability + ", type=" + type + ", inputs=" + inputs + ", outputs=" + outputs + "]";
    
     }
    
 }
    
    
    
    
    AI写代码

与Param类

复制代码
 public class Param {

    
  
    
     private String name;
    
     private String type;
    
  
    
     public String getName() {
    
         return name;
    
     }
    
  
    
     public void setName(String name) {
    
         this.name = name;
    
     }
    
  
    
     public String getType() {
    
         return type;
    
     }
    
  
    
     public void setType(String type) {
    
         this.type = type;
    
     }
    
  
    
     @Override
    
     public String toString() {
    
         return "Param [name=" + name + ", type=" + type + "]";
    
     }
    
 }
    
    
    
    
    AI写代码

全部评论 (0)

还没有任何评论哟~