fix: switch to new Event builder
This commit is contained in:
parent
cf29488aae
commit
36ac73e764
|
@ -34,14 +34,18 @@ impl Context {
|
|||
/// Generate the event filter methods for the contract
|
||||
pub fn event_methods(&self) -> Result<TokenStream> {
|
||||
let sorted_events: BTreeMap<_, _> = self.abi.events.clone().into_iter().collect();
|
||||
let data_types = sorted_events
|
||||
let filter_methods = sorted_events
|
||||
.values()
|
||||
.flatten()
|
||||
.map(|event| self.expand_filter(event))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let events_method = self.expand_events_method();
|
||||
|
||||
Ok(quote! {
|
||||
#( #data_types )*
|
||||
#( #filter_methods )*
|
||||
|
||||
#events_method
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -106,21 +110,27 @@ impl Context {
|
|||
util::ident(&format!("{}Events", self.contract_name.to_string()))
|
||||
}
|
||||
|
||||
/// The type that the `events` function should return
|
||||
///
|
||||
/// The generated enum type if more than 1 events are present
|
||||
/// The event name if only 1 event is present
|
||||
/// `None` otherwise
|
||||
fn expand_events_type(&self) -> Option<Ident> {
|
||||
/// Expands the `events` function that bundles all declared events of this contract
|
||||
fn expand_events_method(&self) -> TokenStream {
|
||||
let sorted_events: BTreeMap<_, _> = self.abi.events.clone().into_iter().collect();
|
||||
|
||||
let mut iter = sorted_events.values().flatten();
|
||||
let event = iter.next()?;
|
||||
|
||||
if iter.next().is_some() {
|
||||
Some(self.expand_event_enum_name())
|
||||
if let Some(event) = iter.next() {
|
||||
let ty = if iter.next().is_some() {
|
||||
self.expand_event_enum_name()
|
||||
} else {
|
||||
expand_struct_name(event)
|
||||
};
|
||||
|
||||
quote! {
|
||||
/// Returns an [`Event`](ethers_contract::builders::Event) builder for all events of this contract
|
||||
pub fn events(&self) -> ethers_contract::builders::Event<M, #ty> {
|
||||
self.0.event_with_filter(Default::default())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Some(expand_struct_name(event))
|
||||
quote! {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,13 +218,12 @@ impl Context {
|
|||
let name = util::safe_ident(&format!("{}_filter", event.name.to_snake_case()));
|
||||
// let result = util::ident(&event.name.to_pascal_case());
|
||||
let result = expand_struct_name(event);
|
||||
let ev_name = Literal::string(&event.name);
|
||||
|
||||
let doc = util::expand_doc(&format!("Gets the contract's `{}` event", event.name));
|
||||
quote! {
|
||||
#doc
|
||||
pub fn #name(&self) -> ethers_contract::builders::Event<M, #result> {
|
||||
self.0.event(#ev_name).expect("event not found (this should never happen)")
|
||||
self.0.event()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use super::{
|
||||
use crate::{
|
||||
base::{encode_function_data, AbiError, BaseContract},
|
||||
call::ContractCall,
|
||||
event::Event,
|
||||
event::{EthEvent, Event},
|
||||
EthLogDecode,
|
||||
};
|
||||
|
||||
use ethers_core::{
|
||||
|
@ -179,19 +180,25 @@ impl<M: Middleware> Contract<M> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns an [`Event`](crate::builders::Event) builder for the provided event name.
|
||||
/// TODO(mattsse) keep this but remove event
|
||||
pub fn event<D: Detokenize>(&self, name: &str) -> Result<Event<M, D>, Error> {
|
||||
/// Returns an [`Event`](crate::builders::Event) builder for the provided event.
|
||||
pub fn event<D: EthEvent>(&self) -> Event<M, D> {
|
||||
self.event_with_filter(Filter::new().event(&D::abi_signature()))
|
||||
}
|
||||
|
||||
/// Returns an [`Event`](crate::builders::Event) builder with the provided filter.
|
||||
pub fn event_with_filter<D: EthLogDecode>(&self, filter: Filter) -> Event<M, D> {
|
||||
Event {
|
||||
provider: &self.client,
|
||||
filter: filter.address(self.address),
|
||||
datatype: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an [`Event`](crate::builders::Event) builder with the provided name.
|
||||
pub fn event_by_name<D: EthLogDecode>(&self, name: &str) -> Result<Event<M, D>, Error> {
|
||||
// get the event's full name
|
||||
let event = self.base_contract.abi.event(name)?;
|
||||
Ok(Event {
|
||||
provider: &self.client,
|
||||
filter: Filter::new()
|
||||
.event(&event.abi_signature())
|
||||
.address(self.address),
|
||||
event: &event,
|
||||
datatype: PhantomData,
|
||||
})
|
||||
Ok(self.event_with_filter(Filter::new().event(&event.abi_signature())))
|
||||
}
|
||||
|
||||
/// Returns a transaction builder for the provided function name. If there are
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{base::decode_event, stream::EventStream, ContractError, EthLogDecode};
|
||||
use crate::{stream::EventStream, ContractError, EthLogDecode};
|
||||
|
||||
use ethers_core::{
|
||||
abi::{Detokenize, Event as AbiEvent, RawLog},
|
||||
abi::{Detokenize, RawLog},
|
||||
types::{BlockNumber, Filter, Log, TxHash, ValueOrArray, H256, U64},
|
||||
};
|
||||
use ethers_providers::{FilterWatcher, Middleware, PubsubClient, SubscriptionStream};
|
||||
|
@ -31,12 +31,12 @@ pub trait EthEvent: Detokenize {
|
|||
fn is_anonymous() -> bool;
|
||||
|
||||
/// Returns an Event builder for the ethereum event represented by this types ABI signature.
|
||||
fn new<M: Middleware>(filter: Filter, provider: &M) -> Event2<M, Self>
|
||||
fn new<M: Middleware>(filter: Filter, provider: &M) -> Event<M, Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let filter = filter.event(&Self::abi_signature());
|
||||
Event2 {
|
||||
Event {
|
||||
filter,
|
||||
provider,
|
||||
datatype: PhantomData,
|
||||
|
@ -57,7 +57,7 @@ impl<T: EthEvent> EthLogDecode for T {
|
|||
/// Helper for managing the event filter before querying or streaming its logs
|
||||
#[derive(Debug)]
|
||||
#[must_use = "event filters do nothing unless you `query` or `stream` them"]
|
||||
pub struct Event2<'a, M, D> {
|
||||
pub struct Event<'a, M, D> {
|
||||
/// The event filter's state
|
||||
pub filter: Filter,
|
||||
pub(crate) provider: &'a M,
|
||||
|
@ -66,7 +66,7 @@ pub struct Event2<'a, M, D> {
|
|||
}
|
||||
|
||||
// TODO: Improve these functions
|
||||
impl<M, D: EthLogDecode> Event2<'_, M, D> {
|
||||
impl<M, D: EthLogDecode> Event<'_, M, D> {
|
||||
/// Sets the filter's `from` block
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
|
@ -114,7 +114,7 @@ impl<M, D: EthLogDecode> Event2<'_, M, D> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, M, D> Event2<'a, M, D>
|
||||
impl<'a, M, D> Event<'a, M, D>
|
||||
where
|
||||
M: Middleware,
|
||||
D: EthLogDecode,
|
||||
|
@ -140,7 +140,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, M, D> Event2<'a, M, D>
|
||||
impl<'a, M, D> Event<'a, M, D>
|
||||
where
|
||||
M: Middleware,
|
||||
<M as Middleware>::Provider: PubsubClient,
|
||||
|
@ -167,7 +167,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<M, D> Event2<'_, M, D>
|
||||
impl<M, D> Event<'_, M, D>
|
||||
where
|
||||
M: Middleware,
|
||||
D: EthLogDecode,
|
||||
|
@ -215,164 +215,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper for managing the event filter before querying or streaming its logs
|
||||
#[derive(Debug)]
|
||||
#[must_use = "event filters do nothing unless you `query` or `stream` them"]
|
||||
pub struct Event<'a: 'b, 'b, M, D> {
|
||||
/// The event filter's state
|
||||
pub filter: Filter,
|
||||
/// The ABI of the event which is being filtered
|
||||
pub event: &'b AbiEvent,
|
||||
pub(crate) provider: &'a M,
|
||||
pub(crate) datatype: PhantomData<D>,
|
||||
}
|
||||
|
||||
// TODO: Improve these functions
|
||||
impl<M, D: Detokenize> Event<'_, '_, M, D> {
|
||||
/// Sets the filter's `from` block
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.filter = self.filter.from_block(block);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's `to` block
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn to_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.filter = self.filter.to_block(block);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's `blockHash`. Setting this will override previously
|
||||
/// set `from_block` and `to_block` fields.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn at_block_hash<T: Into<H256>>(mut self, hash: T) -> Self {
|
||||
self.filter = self.filter.at_block_hash(hash);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's 0th topic (typically the event name for non-anonymous events)
|
||||
pub fn topic0<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.filter.topics[0] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's 1st topic
|
||||
pub fn topic1<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.filter.topics[1] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's 2nd topic
|
||||
pub fn topic2<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.filter.topics[2] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the filter's 3rd topic
|
||||
pub fn topic3<T: Into<ValueOrArray<H256>>>(mut self, topic: T) -> Self {
|
||||
self.filter.topics[3] = Some(topic.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, M, D> Event<'a, 'b, M, D>
|
||||
where
|
||||
M: Middleware,
|
||||
D: 'b + Detokenize + Clone,
|
||||
{
|
||||
/// Returns a stream for the event
|
||||
pub async fn stream(
|
||||
&'a self,
|
||||
) -> Result<
|
||||
// Wraps the FilterWatcher with a mapping to the event
|
||||
EventStream<'a, FilterWatcher<'a, M::Provider, Log>, D, ContractError<M>>,
|
||||
ContractError<M>,
|
||||
> {
|
||||
let filter = self
|
||||
.provider
|
||||
.watch(&self.filter)
|
||||
.await
|
||||
.map_err(ContractError::MiddlewareError)?;
|
||||
Ok(EventStream::new(
|
||||
filter.id,
|
||||
filter,
|
||||
Box::new(move |log| self.parse_log(log)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, M, D> Event<'a, 'b, M, D>
|
||||
where
|
||||
M: Middleware,
|
||||
<M as Middleware>::Provider: PubsubClient,
|
||||
D: 'b + Detokenize + Clone,
|
||||
{
|
||||
/// Returns a subscription for the event
|
||||
pub async fn subscribe(
|
||||
&'a self,
|
||||
) -> Result<
|
||||
// Wraps the SubscriptionStream with a mapping to the event
|
||||
EventStream<'a, SubscriptionStream<'a, M::Provider, Log>, D, ContractError<M>>,
|
||||
ContractError<M>,
|
||||
> {
|
||||
let filter = self
|
||||
.provider
|
||||
.subscribe_logs(&self.filter)
|
||||
.await
|
||||
.map_err(ContractError::MiddlewareError)?;
|
||||
Ok(EventStream::new(
|
||||
filter.id,
|
||||
filter,
|
||||
Box::new(move |log| self.parse_log(log)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, D> Event<'_, '_, M, D>
|
||||
where
|
||||
M: Middleware,
|
||||
D: Detokenize + Clone,
|
||||
{
|
||||
/// Queries the blockchain for the selected filter and returns a vector of matching
|
||||
/// event logs
|
||||
pub async fn query(&self) -> Result<Vec<D>, ContractError<M>> {
|
||||
let logs = self
|
||||
.provider
|
||||
.get_logs(&self.filter)
|
||||
.await
|
||||
.map_err(ContractError::MiddlewareError)?;
|
||||
let events = logs
|
||||
.into_iter()
|
||||
.map(|log| self.parse_log(log))
|
||||
.collect::<Result<Vec<_>, ContractError<M>>>()?;
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
/// Queries the blockchain for the selected filter and returns a vector of logs
|
||||
/// along with their metadata
|
||||
pub async fn query_with_meta(&self) -> Result<Vec<(D, LogMeta)>, ContractError<M>> {
|
||||
let logs = self
|
||||
.provider
|
||||
.get_logs(&self.filter)
|
||||
.await
|
||||
.map_err(ContractError::MiddlewareError)?;
|
||||
let events = logs
|
||||
.into_iter()
|
||||
.map(|log| {
|
||||
let meta = LogMeta::from(&log);
|
||||
let event = self.parse_log(log)?;
|
||||
Ok((event, meta))
|
||||
})
|
||||
.collect::<Result<_, ContractError<M>>>()?;
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
fn parse_log(&self, log: Log) -> Result<D, ContractError<M>> {
|
||||
Ok(decode_event(self.event, log.topics, log.data)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata inside a log
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct LogMeta {
|
||||
|
|
Loading…
Reference in New Issue