web3j教程:以太坊過濾器(filter)篩選和智慧合約事件(event)監聽
web3j過濾器提供以太坊網路發生的某些事件的通知,對java和安卓程式設計師來說很有用。在Ethereum以太坊中支援三類過濾器:
- 塊濾波器(Block filters)
- 未決交易過濾器(Pending transaction filters)
- 主題過濾器(Topic filters)
塊過濾器和未決交易過濾器提供了在網路上建立新交易或塊的通知。
主題過濾器更靈活。允許根據提供的特定標準建立過濾器。
不幸的是,除非你使用WebSocket
連線到Geth,否則通過JSON-RPC API來處理過濾器是一個繁瑣的過程,這裡需要輪詢以太坊客戶端,以便了解HTTP和IPC所請求的實時同步特徵,是否有任何新的更新到你的過濾器。此外,塊和交易過濾器只提供交易或區塊鏈hash值,因此需要進一步的請求來獲得hash對應的實際交易或塊。
web3j的過濾器解決了這些問題,因此你有一個完全非同步的基於事件的API來處理過濾器。它使用RXJava的可觀測性Observables,它提供了與事件協同工作的一致API,這有助於通過功能組合將JSON-RPC呼叫連結在一起。
注:Infura
不支援過濾器。
塊和交易過濾器
接收所有新塊把它們新增到區塊鏈(false引數指定我們只需要塊就ok,而不需要嵌入交易):
Subscription subscription = web3j.blockObservable(false).subscribe(block -> {
...
});
接收所有新交易,把它們新增到塊鏈:
Subscription subscription = web3j.transactionObservable().subscribe(tx -> {
...
});
接收所有待提交交易並提交到網路(即在它們被分組在一起之前):
Subscription subscription = web3j.pendingTransactionObservable().subscribe(tx -> {
...
});
不再需要的時候取消訂閱unsubscribe
:
subscription.unsubscribe();
另外還提供了其他回撥,它們簡單地提供了塊或交易hash,這些細節涉及
再現過濾器
webjs還提供用於再現塊和交易歷史的過濾器。
從區塊鏈再現一系列塊:
Subscription subscription = web3j.replayBlocksObservable(
<startBlockNumber>, <endBlockNumber>, <fullTxObjects>)
.subscribe(block -> {
...
});
再現包含在一個塊範圍內的單個交易:
Subscription subscription = web3j.replayTransactionsObservable(
<startBlockNumber>, <endBlockNumber>)
.subscribe(tx -> {
...
});
也可以獲得Web3J再現最新的塊,並在你看過後提供通知(通過提交Observable
):
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)事件的細節。這些事件是由智慧合約建立的,並存儲在與智慧合約相關聯的交易日誌中。
使用EthFilter型別指定希望應用於過濾器的主題。這可以包括希望應用過濾器的智慧合約的地址。你還可以提供特定的主題進行篩選。其中單個主題表示智慧合約上的索引引數:
EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST,
DefaultBlockParameterName.LATEST, <contract-address>)
[.addSingleTopic(...) | .addOptionalTopics(..., ...) | ...];
然後可以使用類似於上面的塊和交易過濾器的語法建立該過濾器:
web3j.ethLogObservable(filter).subscribe(log -> {
...
});
過濾器主題只能引用索引的Solidity事件引數。不可能對非索引事件引數進行篩選。此外,對於可變長度陣列型別(如字串和位元組)的任何索引事件引數,它們的值的Keccak-256
hash 儲存在EVM日誌上。不可能使用它們的全部值來儲存或篩選。
如果建立一個沒有與之相關聯的主題的過濾器例項,則在網路中發生的所有EVM事件都將由過濾器捕獲。
操作組合標註
除了send()
和sendAsync
之外,所有JSON-RPC方法在web3j中都實現了支援observable()方法來建立可觀察的非同步執行請求。這使得將JSON-RPC呼叫組合成新的函式是非常容易和直接的。
例如, blockObservable本身由許多單獨的JSON-RPC呼叫組成:
public Observable<EthBlock> blockObservable(
boolean fullTransactionObjects, long pollingInterval) {
return this.ethBlockHashObservable(pollingInterval)
.flatMap(blockHash ->
web3j.ethGetBlockByHash(blockHash, fullTransactionObjects).observable());
}
在這裡,我們首先建立一個可觀察的,它提供每個新建立的塊的塊雜湊的通知。然後,我們使用flatMap
呼叫ethGetBlockByHash
,以獲得完整的塊細節,這是傳遞給可觀察者的訂閱伺服器的細節。
進一步的例子
對於使用手動篩選器API的演示,可以檢視EventFilterIT。