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);
}
}
}
控制台输出:
文章来源:https://www.toymoban.com/news/detail-423158.html
文章来源地址https://www.toymoban.com/news/detail-423158.html
到了这里,关于Web3j使用教程(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!