最近公司做NFT市场开发,特记录一下自己在使用web3j组件测试调用区块链合约的时使用的方法和踩过的坑,便于自己以后查看。
主要用到工具有4个
idea,谷歌浏览,小狐狸钱包(metamask)插件,remix在线智能合约平台
1、准备工作
1.1、java项目
在pom.xml中添加引用仓库地址,添加web3j的引入
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<!--web3j-->
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.8.4</version>
<exclusions>
<exclusion>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</exclusion>
<exclusion>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
1.2、智能合约
开始前,必须有一个用于测试的区块链智能合约,进入以太坊官网提供的在线平台,地址为:https://remix.ethereum.org/,编写测试合约。
编写完成,编译测试无误后,部署合约,方法选择如下
因为选择通过web3的方式来发布合约,所以同步会要求登录小狐狸(MetaMask),我这里事先就已经添加好了币安测试链,如果各位没有添加的话,自己自行添加哈
1.3 合约转化
合约发布成功后,测试一下合约内的方法是否可以正常使用,一切OK了以后,在remix中的编译模块内,将abi和bin保存放入本地文件中用于生成java文件。
说明一下哦,在生成java文件时,本地要有web3j的资源文件,我事先已经做好了准备工作了,如果你们没有的话,就自己查下哈。
进入cmd命令窗口
命令如下
web3j solidity generate --abiFile=abi文件地址 -o 文件生成地址 -p 文件包名
以下是我的合约生成的java文件
package com.XX.XXX.contracts.constants;
import io.reactivex.Flowable;
import io.reactivex.functions.Function;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.web3j.abi.EventEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.BaseEventResponse;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
/**
* <p>Auto generated code.
* <p><strong>Do not modify!</strong>
* <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
* or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the
* <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 4.5.5.
*/
@SuppressWarnings("rawtypes")
public class EventTest extends Contract {
private static final String BINARY = "Bin file was not provided";
public static final String FUNC_CHANGENAME = "changeName";
public static final String FUNC_COUNTS = "counts";
public static final String FUNC_INCREMENT = "increment";
public static final String FUNC_NAME = "name";
public static final Event INCREMENT_EVENT = new Event("Increment",
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>(true) {}, new TypeReference<Address>() {}));
;
public static final Event CHANGENAMEEVENT_EVENT = new Event("changeNameEvent",
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Address>() {}));
;
@Deprecated
protected EventTest(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
}
protected EventTest(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
}
@Deprecated
protected EventTest(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
protected EventTest(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
}
public List<IncrementEventResponse> getIncrementEvents(TransactionReceipt transactionReceipt) {
List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(INCREMENT_EVENT, transactionReceipt);
ArrayList<IncrementEventResponse> responses = new ArrayList<IncrementEventResponse>(valueList.size());
for (Contract.EventValuesWithLog eventValues : valueList) {
IncrementEventResponse typedResponse = new IncrementEventResponse();
typedResponse.log = eventValues.getLog();
typedResponse.which = (BigInteger) eventValues.getIndexedValues().get(0).getValue();
typedResponse.who = (String) eventValues.getNonIndexedValues().get(0).getValue();
responses.add(typedResponse);
}
return responses;
}
public Flowable<IncrementEventResponse> incrementEventFlowable(EthFilter filter) {
return web3j.ethLogFlowable(filter).map(new Function<Log, IncrementEventResponse>() {
@Override
public IncrementEventResponse apply(Log log) {
Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(INCREMENT_EVENT, log);
IncrementEventResponse typedResponse = new IncrementEventResponse();
typedResponse.log = log;
typedResponse.which = (BigInteger) eventValues.getIndexedValues().get(0).getValue();
typedResponse.who = (String) eventValues.getNonIndexedValues().get(0).getValue();
return typedResponse;
}
});
}
public Flowable<IncrementEventResponse> incrementEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
filter.addSingleTopic(EventEncoder.encode(INCREMENT_EVENT));
return incrementEventFlowable(filter);
}
public List<ChangeNameEventEventResponse> getChangeNameEventEvents(TransactionReceipt transactionReceipt) {
List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(CHANGENAMEEVENT_EVENT, transactionReceipt);
ArrayList<ChangeNameEventEventResponse> responses = new ArrayList<ChangeNameEventEventResponse>(valueList.size());
for (Contract.EventValuesWithLog eventValues : valueList) {
ChangeNameEventEventResponse typedResponse = new ChangeNameEventEventResponse();
typedResponse.log = eventValues.getLog();
typedResponse.str = (String) eventValues.getNonIndexedValues().get(0).getValue();
typedResponse.who = (String) eventValues.getNonIndexedValues().get(1).getValue();
responses.add(typedResponse);
}
return responses;
}
public Flowable<ChangeNameEventEventResponse> changeNameEventEventFlowable(EthFilter filter) {
return web3j.ethLogFlowable(filter).map(new Function<Log, ChangeNameEventEventResponse>() {
@Override
public ChangeNameEventEventResponse apply(Log log) {
Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(CHANGENAMEEVENT_EVENT, log);
ChangeNameEventEventResponse typedResponse = new ChangeNameEventEventResponse();
typedResponse.log = log;
typedResponse.str = (String) eventValues.getNonIndexedValues().get(0).getValue();
typedResponse.who = (String) eventValues.getNonIndexedValues().get(1).getValue();
return typedResponse;
}
});
}
public Flowable<ChangeNameEventEventResponse> changeNameEventEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
filter.addSingleTopic(EventEncoder.encode(CHANGENAMEEVENT_EVENT));
return changeNameEventEventFlowable(filter);
}
public RemoteFunctionCall<TransactionReceipt> changeName(String str) {
final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
FUNC_CHANGENAME,
Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(str)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}
public RemoteFunctionCall<TransactionReceipt> counts(BigInteger param0) {
final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
FUNC_COUNTS,
Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(param0)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}
public RemoteFunctionCall<TransactionReceipt> increment(BigInteger which) {
final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
FUNC_INCREMENT,
Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(which)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}
public RemoteFunctionCall<TransactionReceipt> name() {
final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(
FUNC_NAME,
Arrays.<Type>asList(),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}
@Deprecated
public static EventTest load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
return new EventTest(contractAddress, web3j, credentials, gasPrice, gasLimit);
}
@Deprecated
public static EventTest load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
return new EventTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
public static EventTest load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
return new EventTest(contractAddress, web3j, credentials, contractGasProvider);
}
public static EventTest load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
return new EventTest(contractAddress, web3j, transactionManager, contractGasProvider);
}
public static class IncrementEventResponse extends BaseEventResponse {
public BigInteger which;
public String who;
}
public static class ChangeNameEventEventResponse extends BaseEventResponse {
public String str;
public String who;
}
}
2、测试合约方法的调用和合约事件监听
说明:
web3j通过rpc的方式建立连接,连接方式我测试时,用了两种方式,一种是http的方式调用合约的方法,websocket的方式调用的事件监听,两种方式测试都是OK的
package com.xx.xxx.contracts.util;
import com.nft.service.contracts.constants.ContractConstants;
import com.nft.service.contracts.constants.EventTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.web3j.abi.EventValues;
import org.web3j.abi.datatypes.Type;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthEstimateGas;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.protocol.websocket.WebSocketService;
import org.web3j.tx.Contract;
import org.web3j.tx.ReadonlyTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.DefaultGasProvider;
import java.io.IOException;
import java.math.BigInteger;
import java.net.ConnectException;
import java.util.concurrent.ExecutionException;
/**
* @author viowio
* @version v1.0
* @date 17:52 2022/4/9
* @description ERC20工具类
*/
public class TestUtil {
private static Web3j web3j = Web3j.build(new HttpService("https://data-seed-prebsc-2-s1.binance.org:8545/"));
private static final Logger logger = LoggerFactory.getLogger(TestUtil.class);
public static void changeName(){
String token = "合约地址";
try {
Credentials credentials = Credentials.create("换成自己的测试钱包地址私钥");
BigInteger currentGasPrice = web3j.ethGasPrice().sendAsync().get().getGasPrice();
EventTest eventTest = EventTest.load(token, web3j, credentials, new DefaultGasProvider() {
/**
* 使用动态获取的 Gas Price
* @return
*/
@Override
public BigInteger getGasPrice() {
return currentGasPrice;
}
});
RemoteFunctionCall<TransactionReceipt> changeNames = eventTest.changeName("0x7503D2667a3Af2a5f5268B9628F7Bb0A3E6282B4");
TransactionReceipt transactionReceipt = changeNames.sendAsync().get();
String transactionHash = transactionReceipt.getTransactionHash();
logger.info("changeName hash: {}",transactionHash);
}catch (ExecutionException | InterruptedException ex){
logger.info(ex.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void changeNameEvent() throws ConnectException {
String token = "合约地址";
String wsurl = ContractConstants.WEBSOCKET_RPC;
//实例化websocket
WebSocketService webSocketService = new WebSocketService(wsurl,true);
//建立连接
webSocketService.connect();
//实例化web3j
Web3j client = Web3j.build(webSocketService);
TransactionManager transactionManager = new ReadonlyTransactionManager(web3j, token);
try {
//方式一
/* client.ethLogFlowable(
new EthFilter(
DefaultBlockParameterName.EARLIEST,
DefaultBlockParameterName.LATEST,
// 合约地址
token
)
).subscribe(event -> {
System.out.println(event);
// => Log{removed=false, logIndex='0x39', transactionIndex='0x13', transactionHash='0x9c3653c27946cb39c3a256229634cfedbca54f146a740f46b661b986590f8358', blockHash='0x1e674b9d111601519f977b75f9a1865ba359b474550ff5d0d87daec1f543d64d', blockNumber='0xb83ccd', address='0x7b52aae43e962ce6a9a1b7e79f549582ae8bcff9', data='0x', type='null', topics=[0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000006ab3d0bd875f8667026d2a9bb3060ec44380bcc2, 0x0000000000000000000000000000000000000000000000000000000000000017]}
}, Throwable::printStackTrace);*/
//方式二
/*Credentials credentials = Credentials.create("换成自己的测试钱包地址私钥");
BigInteger currentGasPrice = web3j.ethGasPrice().sendAsync().get().getGasPrice();
EventTest eventTest = EventTest.load(token, web3j, credentials, new DefaultGasProvider() {
*//**
* 使用动态获取的 Gas Price
* @return
*//*
@Override
public BigInteger getGasPrice() {
return currentGasPrice;
}
});
eventTest
.changeNameEventEventFlowable(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST)
.subscribe(event -> {
Log log = event.log;
EventValues eventValues = Contract.staticExtractEventParameters(EventTest.CHANGENAMEEVENT_EVENT, log);
for (Type nonIndexedValue : eventValues.getNonIndexedValues()) {
System.out.println(nonIndexedValue.getValue());
}
});*/
//方式3
Credentials credentials = Credentials.create("换成自己的测试钱包地址私钥");
BigInteger currentGasPrice = client.ethGasPrice().sendAsync().get().getGasPrice();
EventTest eventTest = EventTest.load(token, client, credentials, new DefaultGasProvider() {
/**
* 使用动态获取的 Gas Price
* @return
*/
@Override
public BigInteger getGasPrice() {
return currentGasPrice;
}
});
eventTest
.changeNameEventEventFlowable(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST)
.subscribe(event -> {
Log log = event.log;
logger.info("transactionHash: {}",log.getTransactionHash());
//解析时间返回的参数
EventValues eventValues = Contract.staticExtractEventParameters(EventTest.CHANGENAMEEVENT_EVENT, log);
for (Type nonIndexedValue : eventValues.getNonIndexedValues()) {
System.out.println(nonIndexedValue.getValue());
}
});
}catch (Exception e) {
e.printStackTrace();
}
}
}
事件测试结果
16:32:05.978 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0xd4fac21ba08d7496d8025281c37e932b914ea3bb9dce48e73bd3c08ac934fdd3
test
0x5ae241178c67689ead468bf5170b3105011a5766
16:32:05.979 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0x42aff4ead062feb340a2fa68c73b5024a0d58029287a2f0acc62156c60780d97
test
0x5ae241178c67689ead468bf5170b3105011a5766
16:32:05.980 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0x1050583b9e907378fb61289ab5b373f195f4d332c5fd7d273e2c817554c90f7b
123
0x5ae241178c67689ead468bf5170b3105011a5766
16:32:05.980 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0xc86374d895f83bfef380a9a1f4cc5a15ddfcc78090305cff5e4367460d423af4
1237
0x5ae241178c67689ead468bf5170b3105011a5766
16:32:05.981 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0xf76fbd23e603109752215c5455e3920a08583de8728c2a42699f61aa45959d29
12374
0x5ae241178c67689ead468bf5170b3105011a5766
16:32:05.981 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0x0d751916f7ae66162959138c0a700feb136153fabee8d8b25a10e410fe74f904
1237455
0x5ae241178c67689ead468bf5170b3105011a5766
16:32:05.981 [restartedMain] INFO c.n.s.c.u.TestUtil - [lambda$changeNameEvent$0,146] - transactionHash: 0xe03249489b93e287e9d033f547c2a36a741c7b3ae49e5c95542315816f4af572
12374556
0x5ae241178c67689ead468bf5170b3105011a5766
OK,暂时完事了。
最后补充一下文章来源:https://www.toymoban.com/news/detail-412833.html
如果没有的rpc地址的,可以搜一下,也可以使用我上面的那个地址,不过仅限于测试用哦。文章来源地址https://www.toymoban.com/news/detail-412833.html
到了这里,关于java web3j4.8.4版本的使用记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!