过滤器和事件

过滤器提供了一些在以太坊网络中发生的一些确定的事件通知。在以太坊网络中有三个类型的过滤器:

  1. 区块过滤器

  2. 等待交易过滤器

  3. 话题过滤器

区块过滤器和等待交易过滤器提供了网络中新交易以及新区块的通知。

话题过滤器要复杂的多。这可以让你去创建基于你的需求的过滤器。

不幸的是,除非你在使用连接到Geth的WebSocket连接,通过JSON-RPC接口使用过滤器是一个无聊的过程,你需要通过同步的HTTP请求或者IPC请求去轮询以太坊客户端来找出对于过滤器来说的更新。另外的区块和交易过滤器只提供了交易和区块的hash,所以你需要通过进一步的请求来获取真正的交易或者区块。

web3j管理了Filter的实现解决了这些问题,所以你通过使用这些过滤器拥有一个完全的异步的事件。它使用RxJava的Observables,它支持方便的API来使用这些事件,这将有助于通过功能组合JSON-RPC调用。

提示

Infura中不支持过滤器。

区块和交易过滤器

为了监听所有被加到区块链的新区快(false参数指定了我们只需要区块,不需要绑定的交易):

Subscription subscription = web3j.blockObservable(false).subscribe(block -> {
    ...
});

为了监听所有被加到区块链中的新交易:

Subscription subscription = web3j.transactionObservable().subscribe(tx -> {
    ...
});

为了接收所有被提交到网络中等待成交的交易(在他们被打包进区块之前):

Subscription subscription = web3j.pendingTransactionObservable().subscribe(tx -> {
    ...
});

订阅应该总是在他们不再需要的时候通过unsubscribe被取消。

subscription.unsubscribe();

其他回调

还有其他回调仅仅只提供了交易和区块的hash值,你可以通过Web3jRx接口获取更多信息。

回放过滤器

web3j提供了回放区块以及交易历史的过滤器。

回放在区块链上的一定区间内区块:

Subscription subscription = web3j.replayBlocksObservable(
        <startBlockNumber>, <endBlockNumber>, <fullTxObjects>)
        .subscribe(block -> {
            ...
});

回放区块区间内的单独交易:

Subscription subscription = web3j.replayTransactionsObservable(
        <startBlockNumber>, <endBlockNumber>)
        .subscribe(tx -> {
            ...
});

你也可以用web3j回放所有区块直到最近的区块,并且web3j也提供了通知(通过提交的观察者)一旦你捕获了。

Subscription subscription = web3j.catchUpToLatestBlockObservable(
        <startBlockNumber>, <fullTxObjects>, <onCompleteObservable>)
        .subscribe(block -> {
            ...
});

或者,如果你想回放所有的区块直到最近的区块,然后随后的新生成的区块会被通知。

Subscription subscription = web3j.catchUpToLatestAndSubscribeToNewBlocksObservable(
        <startBlockNumber>, <fullTxObjects>)
        .subscribe(block -> {
            ...
});

如上所说,包含了所有区块的交易:

Subscription subscription = web3j.catchUpToLatestAndSubscribeToNewTransactionsObservable(
        <startBlockNumber>)
        .subscribe(tx -> {
            ...
});

所有上面的过滤器都可以通过Web3jRx接口。

话题过滤器和EVM事件

话题过滤器捕捉发生在网络上的以太坊虚拟机(EVM)事件。这些事件是被智能合约生成的,并且保存在关联的智能合约的交易日志中。

Solidity documentation提供了EVM事件的概览。

你可以使用EthFilter类型指定你想要过滤器监听的话题。这可以包含你想要过滤的智能合约地址。你也可以过滤一个特殊的话题。单独的话题代表了在智能合约上被索引的参数:

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

这个过滤器也可以通过相似的语法来创建区块和交易过滤器:

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

过滤器主题只跟被索引的Solidity事件变量相关。过滤没有索引的事件变量是不可能的。另外,对于所有被索引的时间变量是边长数组类型比方说string或bytes,这些值的Keccak256被保存在EVM的日志中。保存或过滤所有的值是不可能的。

如果你创建了一个没有关联主题的过滤器实例,所有发生在网络中的EVM事件都会被这个过滤器捕获。

功能组成的说明

除了send()sendAsync(),所有web3j支持的JSON-RPC方法实现了observable()方法来创建一个异步执行请求的Obervable。这使得组合JSON-RPC方法调用很直接。

举个例子,blockObservable可以自己组装一些分散的JSON-RPC调用:

public Observable<EthBlock> blockObservable(
        boolean fullTransactionObjects, long pollingInterval) {
    return this.ethBlockHashObservable(pollingInterval)
            .flatMap(blockHash ->
                    web3j.ethGetBlockByHash(blockHash, fullTransactionObjects).observable());
}

在这里,我们先创建了一个提供新创建区块hash的observable。然后使用flatMap来调用ethGetBlockByHash来获得区块的详细信息。

更多例子

请访问ObservableIT来获取更多示例。

你可以查看测试用例EventFilterIT来获取过滤器API的说明。

Last updated