与来自Java应用程序(We3j)的智能合约进行交互



我对从Java应用程序与智能合约交互的工作流程(顺序)有很多疑问,所以我将首先解释我所做的事情,然后提出我的问题,如果我的理解有问题,请告诉我。

1- 我写了智能合约 2-使用松露获取智能合约java包装器。(合同.java) 3-使用testrpc测试合约

我有 2 个类使用 testrpc 帐户(凭据)与智能合约交互并调用其函数

每个类(node1.java,node2.java)调用智能合约中名为(send)的函数,将其数据发送到链。

我添加了一个事件,如果 2 个节点向那里发送了数据,则会触发该事件

我不明白的是,我如何让java代码(假设MainProgram.class)始终检查该事件。因为我需要检查两个节点是否都发送了他们的数据,所以我将调用另一个函数来分析这些数据。

我如何管理,控制和检查哪些事务已经完成或未完成,我的意思是如何使用java代码中的事件,让代码永远运行并检查此事件是否发生,执行操作。

希望我能清楚地解释我需要什么

提前谢谢你。

我对你之前的一个问题的回答适用于这里。是的,您可能希望设置一个专用进程来侦听事件。但是,您不需要帐户,甚至不需要成为智能合约的所有者或客户端来监听公共区块链上的事件(这就是为什么它被认为是"公共的")。

要收听事件,您只需要合约 ABI 和合约地址。两者都应该很容易获得。您可以在此合约发出的所有事件上设置侦听器。来自 web3j 文档:

您可以使用 EthFilter 类型指定要应用于筛选器的主题。这可以包括您希望应用过滤器的智能合约的地址。您还可以提供要筛选的特定主题。其中各个主题表示智能合约上的索引参数:

EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST,
DefaultBlockParameterName.LATEST, <contract-address>)
[.addSingleTopic(...) | .addOptionalTopics(..., ...) | ...];

然后可以使用与上述块和事务过滤器类似的语法创建此过滤器:

web3j.ethLogObservable(filter).subscribe(log -> {
...
});

通过指定块参数,您可以决定要在历史记录中开始处理事件的时间。请记住,在以太坊中,事件实际上是区块链上的日志。当您侦听事件时,您实际上是在日志中查找活动,因为块被添加到链中。因此,您可以根据需要追溯历史,并查看较旧的块来处理旧事件。

要收听合同中的所有事件,您只需执行以下操作:

EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, <CONTRACT_ADDRESS>);
web3.ethLogObservable(filter).subscribe(log -> System.out.println(log.toString());

关于与 ETHfilter 的合约地址的重要说明- Web3j 中合约地址存在错误EthFilter.API 不喜欢合约地址中的前导"0x"。要解决此问题,如果您使用的是合约对象,请使用contract.getContractAddress().substring(2);发送合约地址

如果您对特定事件感兴趣,则需要在过滤器中添加主题。下面的示例将侦听抛出的所有MyEvent事件,其中包含单个索引地址参数和两个非索引uint256参数:

Web3j web3j = Web3j.build(new HttpService());
Event event = new Event("MyEvent",
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}));
EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, <CONTRACT_ADDRESS>);
filter.addSingleTopic(EventEncoder.encode(event));
web3j.ethLogObservable(filter).subscribe(log -> System.out.println(log.toString()));

上述可以在任何服务器进程中运行。在服务器进程中,您可以通过本地节点(使用new HttpService()时为默认本地主机)连接到网络。或者,您可以使用 Infura 注册,创建 API 密钥,并使用和使用其节点集群(示例 Ropsten URL:new HttpService("https://ropsten.infura.io/<YOUR_API_KEY>");)

最新更新