feat: multiple addresses on Filter (#375)
* feat: support multiple addresses in filters To support filtering of 1..n addresses we had to add the ValueOrArray enum to the log types and refactor some ethers-contract code Fixes: #240 Signed-off-by: Sebastian Martinez <sebastinez@me.com> * chore: fmt * fix: use legacy tx in unit test due to Ganache Co-authored-by: Sebastian Martinez <sebastinez@me.com>
This commit is contained in:
parent
99e9a687ca
commit
60ff4660df
|
@ -7,7 +7,7 @@ use crate::{
|
|||
|
||||
use ethers_core::{
|
||||
abi::{Abi, Detokenize, Error, EventExt, Function, Tokenize},
|
||||
types::{Address, Filter, NameOrAddress, Selector},
|
||||
types::{Address, Filter, NameOrAddress, Selector, ValueOrArray},
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "legacy"))]
|
||||
|
@ -178,7 +178,7 @@ impl<M: Middleware> Contract<M> {
|
|||
pub fn event_with_filter<D: EthLogDecode>(&self, filter: Filter) -> Event<M, D> {
|
||||
Event {
|
||||
provider: &self.client,
|
||||
filter: filter.address(self.address),
|
||||
filter: filter.address(ValueOrArray::Value(self.address)),
|
||||
datatype: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use ethers::{contract::ContractFactory, types::H256};
|
||||
use ethers::{
|
||||
contract::ContractFactory,
|
||||
types::{Filter, ValueOrArray, H256},
|
||||
};
|
||||
|
||||
mod common;
|
||||
pub use common::*;
|
||||
|
@ -338,6 +341,43 @@ mod eth_tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn watch_subscription_events_multiple_addresses() {
|
||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||
let ganache = Ganache::new().spawn();
|
||||
let client = connect(&ganache, 0);
|
||||
let contract_1 = deploy(client.clone(), abi.clone(), bytecode.clone()).await;
|
||||
let contract_2 = deploy(client.clone(), abi.clone(), bytecode).await;
|
||||
|
||||
let ws = Provider::connect(ganache.ws_endpoint()).await.unwrap();
|
||||
let filter = Filter::new().address(ValueOrArray::Array(vec![
|
||||
contract_1.address(),
|
||||
contract_2.address(),
|
||||
]));
|
||||
let mut stream = ws.subscribe_logs(&filter).await.unwrap();
|
||||
|
||||
// and we make a few calls
|
||||
let call = contract_1
|
||||
.method::<_, H256>("setValue", "1".to_string())
|
||||
.unwrap()
|
||||
.legacy();
|
||||
let pending_tx = call.send().await.unwrap();
|
||||
let _receipt = pending_tx.await.unwrap();
|
||||
|
||||
let call = contract_2
|
||||
.method::<_, H256>("setValue", "2".to_string())
|
||||
.unwrap()
|
||||
.legacy();
|
||||
let pending_tx = call.send().await.unwrap();
|
||||
let _receipt = pending_tx.await.unwrap();
|
||||
|
||||
// unwrap the option of the stream, then unwrap the decoding result
|
||||
let log_1 = stream.next().await.unwrap();
|
||||
let log_2 = stream.next().await.unwrap();
|
||||
assert_eq!(log_1.address, contract_1.address());
|
||||
assert_eq!(log_2.address, contract_2.address());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn signer_on_node() {
|
||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||
|
|
|
@ -181,9 +181,7 @@ pub struct Filter {
|
|||
pub block_option: FilterBlockOption,
|
||||
|
||||
/// Address
|
||||
// TODO: The spec says that this can also be an array, do we really want to
|
||||
// monitor for the same event for multiple contracts?
|
||||
address: Option<Address>,
|
||||
address: Option<ValueOrArray<Address>>,
|
||||
|
||||
/// Topics
|
||||
// TODO: We could improve the low level API here by using ethabi's RawTopicFilter
|
||||
|
@ -331,7 +329,7 @@ impl Filter {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn address<T: Into<Address>>(mut self, address: T) -> Self {
|
||||
pub fn address<T: Into<ValueOrArray<Address>>>(mut self, address: T) -> Self {
|
||||
self.address = Some(address.into());
|
||||
self
|
||||
}
|
||||
|
@ -449,7 +447,7 @@ mod tests {
|
|||
let ser = serialize(&filter);
|
||||
assert_eq!(ser, json!({ "topics": [] }));
|
||||
|
||||
let filter = filter.address(addr);
|
||||
let filter = filter.address(ValueOrArray::Value(addr));
|
||||
|
||||
let ser = serialize(&filter);
|
||||
assert_eq!(ser, json!({"address" : addr, "topics": []}));
|
||||
|
|
Loading…
Reference in New Issue