feat: add events enum generation

This commit is contained in:
Matthias Seitz 2021-03-18 11:24:49 +01:00
parent cc96f5c0ce
commit e071b32535
1 changed files with 56 additions and 8 deletions

View File

@ -2,7 +2,7 @@ use super::{types, util, Context};
use anyhow::Result; use anyhow::Result;
use ethers_core::abi::{Event, EventExt, EventParam, Hash, ParamType, SolStruct}; use ethers_core::abi::{Event, EventExt, EventParam, Hash, ParamType, SolStruct};
use inflector::Inflector; use inflector::Inflector;
use proc_macro2::{Literal, TokenStream}; use proc_macro2::{Ident, Literal, TokenStream};
use quote::quote; use quote::quote;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use syn::Path; use syn::Path;
@ -17,12 +17,17 @@ impl Context {
.map(|event| self.expand_event(event)) .map(|event| self.expand_event(event))
.collect::<Result<Vec<_>>>()?; .collect::<Result<Vec<_>>>()?;
if data_types.is_empty() { // only expand enums when multiple events are present
return Ok(quote! {}); let events_enum_decl = if sorted_events.values().flatten().count() > 1 {
} self.expand_events_enum()
} else {
quote! {}
};
Ok(quote! { Ok(quote! {
#( #data_types )* #( #data_types )*
#events_enum_decl
}) })
} }
@ -35,15 +40,58 @@ impl Context {
.map(|event| self.expand_filter(event)) .map(|event| self.expand_filter(event))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if data_types.is_empty() {
return Ok(quote! {});
}
Ok(quote! { Ok(quote! {
#( #data_types )* #( #data_types )*
}) })
} }
/// Generate an enum with a variant for each event
fn expand_events_enum(&self) -> TokenStream {
let sorted_events: BTreeMap<_, _> = self.abi.events.clone().into_iter().collect();
let variants = sorted_events
.values()
.flatten()
.map(expand_struct_name)
.collect::<Vec<_>>();
let enum_name = self.expand_event_enum_name();
quote! {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum #enum_name {
#(#variants(#variants)),*
}
impl ethers_core::abi::Tokenizable for #enum_name {
fn from_token(token: ethers::abi::Token) -> Result<Self, ethers::abi::InvalidOutputType> where
Self: Sized {
#(
if let Ok(decoded) = #variants::from_token(token.clone()) {
return Ok(#enum_name::#variants(decoded))
}
)*
Err(ethers::abi::InvalidOutputType("Failed to decode all event variants".to_string()))
}
fn into_token(self) -> ethers::abi::Token {
match self {
#(
#enum_name::#variants(element) => element.into_token()
),*
}
}
}
impl ethers_core::abi::TokenizableItem for #enum_name { }
}
}
/// The name ident of the events enum
fn expand_event_enum_name(&self) -> Ident {
util::ident(&format!("{}Events", self.contract_name.to_string()))
}
/// 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