3.加入智能合约

首先安装solc(用于编译智能合约)和web3j命令行工具(用于打包智能合约)

npm install -g solc

web3j安装地址: Releases · web3j/web3j · GitHub,选择对应操作系统

首先准备一个智能合约 Owner.sol,建议先在remix上测试一下Remix - Ethereum IDE

//SPDX-License-Identifier:UNLICENSED

pragma solidity  >=0.7.0 <0.9.0;

contract Qwner {
        address private owner;
        event OwnerSet(address oldAddress,address newAddress);
        modifier isOwner(){
            require (msg.sender==owner,"Caller is not owner!");
            _;
        }
        constructor (){
            owner = msg.sender;
            emit OwnerSet( address(0) , owner);
        }
        function changeOwner (address newOwner) public isOwner {
            emit OwnerSet(owner, newOwner);
            owner = newOwner;
            
        }
        function getOwner()public view returns (address) {
            return owner;
        }

}

先编译  solcjs Owner.sol --bin --abi --optimize -o .\ 然后你可以看到当前文件夹下生成了两个文件,.abi和.bin,这名字有点反人类,最好改成Owner.abi和Owner.bin

 然后打包成把合约打包成Java文件使用如下命令,其中-p是指定包名

web3j  generate solidity -a src\main\Owner.abi -b src\main\Owner.bin -o src\main\java\ -p com.example

执行完上述命令后可以看到src\main\java\com\example下多了一个Owner.java文件

 接着就是代码,包括部署智能合约,调用智能合约的函数:

package com.example;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.List;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.DefaultGasProvider;

class Cpp{
    public static void main(String[] args) {
        try {
            Web3j web3j = Web3j.build(new HttpService("http://127.0.0.1:8545"));
            //创建钱包
            Credentials defaulCredential = Credentials.create(App.privateKey1);
            BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
            //这个类的作用是你能够根据你不同函数名称灵活的选择不同的GasPrice和GasLimit
            ContractGasProvider  myGasProvider = new DefaultGasProvider(){
                @Override
                public BigInteger getGasPrice(String contractFunc ) {
                    return gasPrice;
                }
                @Override
                public BigInteger getGasLimit(String contractFunc ){
                    return BigInteger.valueOf(6721975);
                }
            };    
            //部署合约,并打印合约地址
            Owner myContract = Owner.deploy(web3j, defaulCredential, myGasProvider).send();
            System.out.println("deploy contract: "+myContract.isValid());
            System.out.println("contract adddress: "+myContract.getContractAddress());
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}
public class App 
{
    static Web3j web3j = null;
    //ganache上的accounts[0]和accounts[1]的私钥
    static String privateKey1 = "0x64685c9589ef1e937e8009eba589059d4b7b10bb44a6efc6eeb436c7f47ab85c";
    static String privateKey2 = "0xae7d780682ee82c5301152bec4ddb51ada56944135d211130a582f33c52d7c1d";
    //硬编码,填入合约部署后输出的合约地址
    static String contractAddress = "0x30a856cd0aaf589b99152331ae4bc1193ed32570";

    public static void main(String[] args )
    {
        try {
            web3j = Web3j.build(new HttpService("http://127.0.0.1:8545"));
            String clientVersion = web3j.web3ClientVersion().send().getWeb3ClientVersion();
            System.out.println("clientVersion : "+clientVersion);
            List<String> accounts = web3j.ethAccounts().send().getAccounts(); 
            System.out.println("accounts"+accounts);
            //连个私钥accounts[0]和accounts[1]
            Credentials defaulCredential = Credentials.create(privateKey1);
            Credentials secondCredentials = Credentials.create(privateKey2);
            BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
            ContractGasProvider  myGasProvider = new DefaultGasProvider(){
                @Override
                public BigInteger getGasPrice(String contractFunc ) {
                    return gasPrice;
                }
                @Override
                public BigInteger getGasLimit(String contractFunc ){
                    return BigInteger.valueOf(6721975);
                }
            };
            BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
            String command;
            //根据地址获取合约实例,注意这两个合约实例不同之处在于他们的用户不同,第一个合约对应accounts[0],第二给合约对应accounts[1]
            Owner myContract = Owner.load(contractAddress, web3j,defaulCredential , myGasProvider);
            Owner secondContract = Owner.load(contractAddress, web3j,secondCredentials , myGasProvider);
            //判断合约是否合法,这一步也很重要
            if(myContract.isValid()==false||secondContract.isValid()==false) {
                throw new Exception("load contract error");
            }
            System.out.println("load contract: "+myContract.isValid()+" "+secondContract.isValid());
            System.out.println("contract adddress: "+myContract.getContractAddress()+"  "+secondContract.getContractAddress());
             
            boolean exit = false;
            TransactionReceipt receipt;
            while (exit == false) {
                System.out.println("please input command :");
                command = br.readLine();
                switch (command){
                    case "set":{
                        //accounts[0]把Owner设成accounts[1],accounts[1]再设成accounts[0],如此循环
                        if( myContract.getOwner().send().equals( accounts.get(0) ) ){
                            receipt = myContract.changeOwner(accounts.get(1)).send();          
                        }
                        else {
                            receipt = secondContract.changeOwner(accounts.get(0)).send();                         
                        }
                        System.out.println(receipt);
                        System.out.println("now owner is ");
                        System.out.println(myContract.getOwner().send());
                        
                        break;
                    }
                    case "get":{
                        System.out.println("now owner is ");
                        System.out.println(myContract.getOwner().send());
                        break;
                    }
                    case "exit": {
                        System.out.println("you type exit");
                        exit = true;
                        break;
                    }
                    default :{
                        System.out.println("wrong command input again");
                        break;
                    }
                }
            }                      
        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

部署合约(Cpp中main函数输出)

加载合约并调用合约函数 (App中main函数输出)

4.事件监听 

还能监听区块链事件,主要有三种:监听区块,监听交易,监听合约事件

package com.example;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;

import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.DefaultGasProvider;

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

public class App 
{
    static Web3j web3j = Web3j.build(new HttpService("http://127.0.0.1:8545"));
    static String privateKey = "0x36308cc80ca2e632b0fb90d8acbe316d4c23f782f03131d4406a0026ed5de9e7";
    static String contractAddress = "0x30a856cd0aaf589b99152331ae4bc1193ed32570";
    static DefaultBlockParameterName earliest = DefaultBlockParameterName.EARLIEST;
    static DefaultBlockParameterName latest = DefaultBlockParameterName.LATEST;
    public static void main( String[] args )
    {
        try {
            String clientVersion = web3j.web3ClientVersion().send().getWeb3ClientVersion();
            System.out.println(clientVersion);
            Credentials defaulCredential = Credentials.create(privateKey);
            BigInteger gasLimit = BigInteger.valueOf(6721975);
            BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
            ContractGasProvider simplProvider = new DefaultGasProvider(){
                @Override
                public BigInteger getGasPrice(String contractFunc ) {
                    return gasPrice;
                }
                @Override
                public BigInteger getGasLimit(String contractFunc ){
                    return gasLimit;
                }
            };
            Owner mycontract = Owner.load(contractAddress, web3j, defaulCredential, simplProvider);
            if(mycontract.isValid()==false){
                throw new Exception("load error");
            }
            System.out.println("load contract: "+mycontract.isValid());

            //使用CompositeDisposable
            CompositeDisposable disposableSet = new CompositeDisposable();
            //监听区块
            Disposable blockSubscription  =web3j.blockFlowable(false).subscribe( block -> {
                System.out.println("new block: "+block.getBlock().getHash());
            } );
            //监听交易
            Disposable txsubcription = web3j.transactionFlowable().subscribe( tx -> {
                System.out.println("new tx: from "+tx.getFrom()+ "; to "+tx.getTo());
            } );
            //监听合约的OwnerSet事件
            Disposable ownersetSubscription = mycontract.ownerSetEventFlowable(latest, latest).subscribe(res -> {
                System.out.println(res.log);
                System.out.println("owner chage: old "+res.oldAddress+" new "+res.newAddress);
            });
            
            disposableSet.add(blockSubscription);
            disposableSet.add(txsubcription);
            disposableSet.add(ownersetSubscription);
            System.out.println(disposableSet);
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String command =null;
            while(true){
                System.out.println("input command: ");
                command = br.readLine();
                if(command.equals("stop")){
                    disposableSet.dispose();
                    System.out.println(disposableSet);
                    break;
                } else {
                    continue;
                }
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }
}

控制台输出: 

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐