feat: generate EthLogDecode implementations
This commit is contained in:
parent
c4d87d11b8
commit
855fd2deb2
|
@ -63,7 +63,7 @@ impl Context {
|
||||||
#(#variants(#variants)),*
|
#(#variants(#variants)),*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ethers_core::abi::Tokenizable for #enum_name {
|
impl ethers::abi::Tokenizable for #enum_name {
|
||||||
|
|
||||||
fn from_token(token: ethers::abi::Token) -> Result<Self, ethers::abi::InvalidOutputType> where
|
fn from_token(token: ethers::abi::Token) -> Result<Self, ethers::abi::InvalidOutputType> where
|
||||||
Self: Sized {
|
Self: Sized {
|
||||||
|
@ -83,7 +83,21 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ethers_core::abi::TokenizableItem for #enum_name { }
|
impl ethers::abi::TokenizableItem for #enum_name { }
|
||||||
|
|
||||||
|
impl ethers::contract::EthLogDecode for #enum_name {
|
||||||
|
fn decode_log(log: ðers::abi::RawLog) -> Result<Self, ethers::abi::Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
#(
|
||||||
|
if let Ok(decoded) = #variants::decode_log(log) {
|
||||||
|
return Ok(#enum_name::#variants(decoded))
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
Err(ethers::abi::Error::InvalidData)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +106,24 @@ impl Context {
|
||||||
util::ident(&format!("{}Events", self.contract_name.to_string()))
|
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> {
|
||||||
|
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())
|
||||||
|
} else {
|
||||||
|
Some(expand_struct_name(event))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Expands an event property type.
|
/// Expands an event property type.
|
||||||
///
|
///
|
||||||
/// Note that this is slightly different than an expanding a Solidity type as
|
/// Note that this is slightly different than an expanding a Solidity type as
|
||||||
|
@ -258,17 +290,16 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expands an ABI event into an identifier for its event data type.
|
/// Expands an ABI event into an identifier for its event data type.
|
||||||
fn expand_struct_name(event: &Event) -> TokenStream {
|
fn expand_struct_name(event: &Event) -> Ident {
|
||||||
// TODO: get rid of `Filter` suffix?
|
// TODO: get rid of `Filter` suffix?
|
||||||
let name = format!("{}Filter", event.name.to_pascal_case());
|
let name = format!("{}Filter", event.name.to_pascal_case());
|
||||||
let event_name = util::ident(&name);
|
util::ident(&name)
|
||||||
quote! { #event_name }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expands an event data structure from its name-type parameter pairs. Returns
|
/// Expands an event data structure from its name-type parameter pairs. Returns
|
||||||
/// a tuple with the type definition (i.e. the struct declaration) and
|
/// a tuple with the type definition (i.e. the struct declaration) and
|
||||||
/// construction (i.e. code for creating an instance of the event data).
|
/// construction (i.e. code for creating an instance of the event data).
|
||||||
fn expand_data_struct(name: &TokenStream, params: &[(TokenStream, TokenStream)]) -> TokenStream {
|
fn expand_data_struct(name: &Ident, params: &[(TokenStream, TokenStream)]) -> TokenStream {
|
||||||
let fields = params
|
let fields = params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, ty)| quote! { pub #name: #ty })
|
.map(|(name, ty)| quote! { pub #name: #ty })
|
||||||
|
@ -279,7 +310,7 @@ fn expand_data_struct(name: &TokenStream, params: &[(TokenStream, TokenStream)])
|
||||||
|
|
||||||
/// Expands an event data named tuple from its name-type parameter pairs.
|
/// Expands an event data named tuple from its name-type parameter pairs.
|
||||||
/// Returns a tuple with the type definition and construction.
|
/// Returns a tuple with the type definition and construction.
|
||||||
fn expand_data_tuple(name: &TokenStream, params: &[(TokenStream, TokenStream)]) -> TokenStream {
|
fn expand_data_tuple(name: &Ident, params: &[(TokenStream, TokenStream)]) -> TokenStream {
|
||||||
let fields = params
|
let fields = params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, ty)| quote! { pub #ty })
|
.map(|(_, ty)| quote! { pub #ty })
|
||||||
|
@ -406,7 +437,7 @@ mod tests {
|
||||||
let cx = test_context();
|
let cx = test_context();
|
||||||
let params = cx.expand_params(&event).unwrap();
|
let params = cx.expand_params(&event).unwrap();
|
||||||
let name = expand_struct_name(&event);
|
let name = expand_struct_name(&event);
|
||||||
let definition = expand_data_tuple(&name, ¶ms);
|
let definition = expand_data_tuple(name, ¶ms);
|
||||||
|
|
||||||
assert_quote!(definition, {
|
assert_quote!(definition, {
|
||||||
struct FooFilter(pub bool, pub Address);
|
struct FooFilter(pub bool, pub Address);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{base::decode_event, stream::EventStream, ContractError};
|
use crate::{base::decode_event, stream::EventStream, ContractError, EthLogDecode};
|
||||||
|
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{Detokenize, Event as AbiEvent, RawLog},
|
abi::{Detokenize, Event as AbiEvent, RawLog},
|
||||||
|
@ -29,7 +29,16 @@ pub trait EthEvent: Detokenize {
|
||||||
|
|
||||||
/// Returns true if this is an anonymous event
|
/// Returns true if this is an anonymous event
|
||||||
fn is_anonymous() -> bool;
|
fn is_anonymous() -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience implementation
|
||||||
|
impl<T: EthEvent> EthLogDecode for T {
|
||||||
|
fn decode_log(log: &RawLog) -> Result<Self, ethers_core::abi::Error>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
T::decode_log(log)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for managing the event filter before querying or streaming its logs
|
/// Helper for managing the event filter before querying or streaming its logs
|
||||||
|
|
|
@ -5,7 +5,9 @@ use ethers_core::abi::RawLog;
|
||||||
/// A trait for types (events) that can be decoded from a `RawLog`
|
/// A trait for types (events) that can be decoded from a `RawLog`
|
||||||
pub trait EthLogDecode {
|
pub trait EthLogDecode {
|
||||||
/// decode from a `RawLog`
|
/// decode from a `RawLog`
|
||||||
fn decode_log(log: &RawLog) -> Result<Self, Error> where Self: Sized;
|
fn decode_log(log: &RawLog) -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a series of logs into a vector
|
/// Decodes a series of logs into a vector
|
||||||
|
|
Loading…
Reference in New Issue