首先,我们要有自己的智能合约,我们使用测试网络(ropsten),还要有自己开发编号。申请如下:
地址:
注册登录,创建自己的项目
注意:选择测试ropsten链,复制自己的链接 web3j需要用到。
第二步:使用solidity编译自己的智能合约(个人理解就是链上的服务器脚本),为了案例的丰富性和实用性,全方位的展示web3j调度性,我们使用留言版智能合约模板,solidity代码如下(采用了8.15编译):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
//声明一个 结构体 用于留言保持
struct Message{
string word;
address from;
string timeStr;
}
contract Test_Web3j{
Message[] public AllMsg;
// 构造方法
constructor (){
}
//接受留言
Function setWord(string memory sendMsgStr,string memory tStr)public returns(uint256){
AllMsg.push(Message({word:sendMsgStr,from:msg.sender,timeStr:tStr}));
return AllMsg.length;
}
//查询留言
function getWord() public view returns(uint256,string memory,address,string memory){
if(AllMsg.length==0){ //当没有留言数据时候,返回空
return (0,"", address (0),"");
}else{ //当有留言时候,返回最新的一条
uint256 indexInt=AllMsg.length-1;
Message storage thisMsg=AllMsg[indexInt];
return (AllMsg.length,thisMsg.word,thisMsg.from,thisMsg.timeStr);
}
}
//返回总留言的条数
function getSize() public view returns(uint256){
return AllMsg.length;
}
//测试方法1
function testStr() public pure returns( String memory){
return "hello word";
}
function testInt(uint256 argInt) public pure returns(uint256){
return argInt+10;
}
}
采用remix在线版发布合约,注意浏览器中需要安装metaMask;才需要ropsten有测试币
第三步 java 部分
import Java .math.BigInteger;
import java.util.Arrays;
import java.util.List;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturn decode r;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.crypto. Raw Transaction;
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.EthGetBalance;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.http.HttpService;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.TypeReference;
import org.web3j.tx.Contract;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;
public class mainCreateSolitidyJava {
public static void main(String[] args) {
try {
String url = "#34;;
String contractAddress="0x954e9A986467861********F5aEa8b83cAB63B6"; //合约地址
String fromAddr="0xb4377fb04FE5aDe3C35*******0cd354308807bF"; //查询用户地址
String input Private Key="4369ceac05601**************a29f2ab6a41e7c6f93f3ea55222c5d"; //该账号密钥
//查询一下自己虚拟币的数量
Web3j web3j = Web3j.build(new HttpService(url));
//第二个参数: 区块 的参数,建议选最新区块
EthGetBalance balance = web3j.ethGetBalance(fromAddr, DefaultBlockParameterName.LATEST).send();
String blanceETH = Convert.fromWei(balance.getBalance().toString(), Convert.Unit.ETHER).toPlainString();//.concat(" ether");
System.out.println("====> 拥有的以太坊币 :" + blanceETH);
//测试调用方法一
try {
List input = Arrays.asList(); //输入参数
List output = Arrays.asList(new TypeReference<Utf8String>() {}); //接受返回参数
String methodName = "testStr";
Function function = new Function(methodName, input , output);
String data = FunctionEncoder.encode(function);
Transaction transaction = Transaction.createEthCallTransaction(fromAddr, contractAddress, data);
EthCall ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
System.out.println("==111==>"+results.get(0).getValue());
}catch ( Exception e){
e.printStackTrace();
}
//测试调用方法二
try {
List input = Arrays.asList(new Uint256(100));
List output = Arrays.asList(new TypeReference<Uint256>() {});
String methodName = "testInt";
Function function = new Function(methodName, input, output);
String data = FunctionEncoder.encode(function);
Transaction transaction = Transaction.createEthCallTransaction(fromAddr, contractAddress, data);
EthCall ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
System.out.println("==222==>"+results.get(0).getValue());
}catch (Exception e){
e.printStackTrace();
}
//测试调用方法三
try {
List input = Arrays.asList(new Utf8String("第一条留言"),new Utf8String("这是插入时间"));
List output = Arrays.asList(new TypeReference<Uint256>() {});
String methodName = "setWord";
Function function = new Function(methodName, input, output);
String encodedFunction = FunctionEncoder.encode(function);
BigInteger nonce =NormalUtil.getNonce(web3j,fromAddr); //获取nonce
BigInteger gasPrice = NormalUtil.requestCurrentGasPrice(web3j); //gas数
BigInteger gasLimit = Contract.GAS_LIMIT; //限制gas数
RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, contractAddress, encodedFunction);
Credentials credentials = Credentials.create(inputPrivateKey);
byte [] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
String hexValue = Numeric.toHexString(signMessage);
EthSendTransaction ethResult=web3j.ethSendRawTransaction(hexValue).sendAsync().get();
System.out.println("交易编号:"+ethResult.getTransaction Hash ());
}catch (Exception e){
e.printStackTrace();
}
//获得总留言数量
try {
List input = Arrays.asList();
List ouput = Arrays.asList(new TypeReference<Uint256>() {});
String methodName = "getSize";
Function function = new Function(methodName, input, ouput);
String data = FunctionEncoder.encode(function);
Transaction transaction = Transaction.createEthCallTransaction(fromAddr, contractAddress, data);
EthCall ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
System.out.println("==333==>"+results.get(0).getValue());
}catch (Exception e){
e.printStackTrace();
}
//调用自己合约地址
try {
List input = Arrays.asList();
List ouput = Arrays.asList(new TypeReference<Uint256>(){},new TypeReference<Utf8String>() {},new TypeReference<Address>() {},new TypeReference<Utf8String>() {});
String methodName = "getWord";
Function function = new Function(methodName, input, ouput);
String data = FunctionEncoder.encode(function);
Transaction transaction = Transaction.createEthCallTransaction(fromAddr, contractAddress, data);
EthCall ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).sendAsync().get();
//System.out.println(ethCall.getValue());
List<Type> results = FunctionReturnDecoder.decode(ethCall.getValue(), function.getOutputParameters());
System.out.println("==444==>"+results.get(1).getValue());
}catch (Exception e){
e.printStackTrace();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
Java部分核心难度地方:ethCall和ethSendRawTransaction区别,ethcall调用的方法是不需要gas费用,而ethSendRawTransaction需要,因此此教程中,插入留言就需要使用ethSendRawTransaction方法来调用。
运行结果如下: