feat: Instantiate an event builder without a contract instance (#1882)
* Build an `Event` without requiring a contract instance * Contract unit test * Function to set Event address * Example * Typo to improve readability * CHANGELOG * cargo +nightly fmt * FIX conflict * review: applied Address alias Co-authored-by: Andrea Simeoni <> Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
parent
f4b6178332
commit
845aa4920f
|
@ -4,6 +4,7 @@
|
|||
|
||||
### Unreleased
|
||||
|
||||
- An `Event` builder can be instantiated specifying the event filter type, without the need to instantiate a contract.
|
||||
- Add 'ethers_core::types::OpCode' and use in 'ethers_core::types::VMOperation' [1857](https://github.com/gakonst/ethers-rs/issues/1857)
|
||||
- Remove rust_decimals dependency for ethers-core
|
||||
- Add support for numbers greater than 2^96 for `ethers_core::utils::parse_units` [#1822](https://github.com/gakonst/ethers-rs/issues/1822)
|
||||
|
@ -348,4 +349,4 @@
|
|||
### 0.5.3
|
||||
|
||||
- Added Time Lagged middleware
|
||||
[#457](https://github.com/gakonst/ethers-rs/pull/457)
|
||||
[#457](https://github.com/gakonst/ethers-rs/pull/457)
|
|
@ -191,6 +191,19 @@ impl<M> Contract<M> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<M: Middleware> Contract<M> {
|
||||
/// Returns an [`Event`](crate::builders::Event) builder for the provided event.
|
||||
/// This function operates in a static context, then it does not require a `self`
|
||||
/// to reference to instantiate an [`Event`](crate::builders::Event) builder.
|
||||
pub fn event_of_type<'a, D: EthEvent>(client: &'a Arc<M>) -> Event<'a, M, D> {
|
||||
Event {
|
||||
provider: client,
|
||||
filter: Filter::new().event(&D::abi_signature()),
|
||||
datatype: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Middleware> Contract<M> {
|
||||
/// Creates a new contract from the provided client, abi and address
|
||||
pub fn new(
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
use crate::{log::LogMeta, stream::EventStream, ContractError, EthLogDecode};
|
||||
use ethers_core::{
|
||||
abi::{Detokenize, RawLog},
|
||||
types::{BlockNumber, Filter, Log, Topic, H256},
|
||||
abi::{Address, Detokenize, RawLog},
|
||||
types::{BlockNumber, Filter, Log, Topic, ValueOrArray, H256},
|
||||
};
|
||||
use ethers_providers::{FilterWatcher, Middleware, PubsubClient, SubscriptionStream};
|
||||
use std::{borrow::Cow, marker::PhantomData};
|
||||
|
@ -108,6 +108,12 @@ impl<M, D: EthLogDecode> Event<'_, M, D> {
|
|||
self.filter.topics[3] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's address.
|
||||
pub fn address(mut self, address: ValueOrArray<Address>) -> Self {
|
||||
self.filter = self.filter.address(address);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, M, D> Event<'a, M, D>
|
||||
|
|
|
@ -6,7 +6,7 @@ use ethers_core::types::{Filter, ValueOrArray, H256};
|
|||
#[cfg(not(feature = "celo"))]
|
||||
mod eth_tests {
|
||||
use super::*;
|
||||
use ethers_contract::{LogMeta, Multicall, MulticallVersion};
|
||||
use ethers_contract::{EthEvent, LogMeta, Multicall, MulticallVersion};
|
||||
use ethers_core::{
|
||||
abi::{encode, Detokenize, Token, Tokenizable},
|
||||
types::{transaction::eip712::Eip712, Address, BlockId, Bytes, I256, U256},
|
||||
|
@ -324,6 +324,21 @@ mod eth_tests {
|
|||
assert_eq!(log_2.address, contract_2.address());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn build_event_of_type() {
|
||||
abigen!(
|
||||
AggregatorInterface,
|
||||
r#"[
|
||||
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt)
|
||||
]"#,
|
||||
);
|
||||
|
||||
let anvil = Anvil::new().spawn();
|
||||
let client = connect(&anvil, 0);
|
||||
let event = ethers_contract::Contract::event_of_type::<AnswerUpdatedFilter>(&client);
|
||||
assert_eq!(event.filter, Filter::new().event(&AnswerUpdatedFilter::abi_signature()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn signer_on_node() {
|
||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
use ethers::{contract::Contract, prelude::*};
|
||||
use std::{error::Error, sync::Arc};
|
||||
abigen!(
|
||||
AggregatorInterface,
|
||||
r#"[
|
||||
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt)
|
||||
]"#,
|
||||
);
|
||||
|
||||
const PRICE_FEED_1: &str = "0x7de93682b9b5d80d45cd371f7a14f74d49b0914c";
|
||||
const PRICE_FEED_2: &str = "0x0f00392fcb466c0e4e4310d81b941e07b4d5a079";
|
||||
const PRICE_FEED_3: &str = "0xebf67ab8cff336d3f609127e8bbf8bd6dd93cd81";
|
||||
|
||||
/// Subscribe to a typed event stream without requiring a `Contract` instance.
|
||||
/// In this example we subscribe Chainlink price feeds and filter out them
|
||||
/// by address.
|
||||
/// -------------------------------------------------------------------------------
|
||||
/// In order to run this example you need to include Ws and TLS features
|
||||
/// Run this example with
|
||||
/// `cargo run -p ethers --example subscribe_events_by_type --features="ws","rustls"`
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let client = get_client().await;
|
||||
let client = Arc::new(client);
|
||||
|
||||
// Build an Event by type. We are not tied to a contract instance. We use builder functions to
|
||||
// refine the event filter
|
||||
let event = Contract::event_of_type::<AnswerUpdatedFilter>(&client)
|
||||
.from_block(16022082)
|
||||
.to_block(16022282)
|
||||
.address(ValueOrArray::Array(vec![
|
||||
PRICE_FEED_1.parse()?,
|
||||
PRICE_FEED_2.parse()?,
|
||||
PRICE_FEED_3.parse()?,
|
||||
]));
|
||||
|
||||
let mut stream = event.subscribe_with_meta().await?;
|
||||
|
||||
// Note that `log` has type AnswerUpdatedFilter
|
||||
while let Some(Ok((log, meta))) = stream.next().await {
|
||||
println!("{:?}", log);
|
||||
println!("{:?}", meta)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_client() -> Provider<Ws> {
|
||||
Provider::<Ws>::connect("wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
Loading…
Reference in New Issue