Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: function call enums EthCall macro and more #517

Merged
merged 27 commits into from
Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
db51b38
fix: do not sort event variants
mattsse Oct 16, 2021
90b2c1b
style: use deref over clone
mattsse Oct 16, 2021
42bb563
style: refactor some stuff
mattsse Oct 16, 2021
28bd693
feat: add ethcall trait
mattsse Oct 16, 2021
7ec449c
feat: include in abigen
mattsse Oct 16, 2021
21b79ce
feat: add bare bones eth call derive
mattsse Oct 16, 2021
748a0a2
feat: impl EthCall derive
mattsse Oct 16, 2021
053b311
feat: support enums
mattsse Oct 16, 2021
00f8ed9
feat: use abigen enum derive
mattsse Oct 16, 2021
c6af805
fix: concrete abi and map errors
mattsse Oct 16, 2021
36e62a7
test: first call test
mattsse Oct 16, 2021
12fa801
rustfmt
mattsse Oct 16, 2021
62a53cc
chore: use correct trait name on error
mattsse Oct 16, 2021
3a1047f
feat: derive display for call structs
mattsse Oct 16, 2021
1deadab
feat: add from conversion
mattsse Oct 17, 2021
a011619
test: add convert test
mattsse Oct 17, 2021
f37fe20
chore: docs and test
mattsse Oct 17, 2021
cc12a49
chore: update changelog
mattsse Oct 17, 2021
d862a75
cargo fix
mattsse Oct 17, 2021
091d9cc
feat: add unit type derive support and more test
mattsse Oct 17, 2021
4897b0b
chore: patch ethabi
mattsse Oct 17, 2021
449f988
chore: rm ethabi patch
mattsse Oct 17, 2021
3ffb8be
feat: add encode/decode trait impls
mattsse Oct 17, 2021
7be4b59
style: use AsRef<[u8]>
mattsse Oct 17, 2021
68a8acb
Update ethers-contract/ethers-contract-abigen/src/contract/methods.rs
mattsse Oct 18, 2021
ee9aa89
style: reindent macro body
mattsse Oct 18, 2021
9277ebc
test: add tuple event test
mattsse Oct 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Unreleased

- add `EthCall` trait and derive macro which generates matching structs for contract calls [#517](https://github.com/gakonst/ethers-rs/pull/517)
- `abigen!` now generates `Display` for all events using the new `EthDisplay` macro [#513](https://github.com/gakonst/ethers-rs/pull/513)
- `abigen!` now supports overloaded functions natively [#501](https://github.com/gakonst/ethers-rs/pull/501)
- `abigen!` now supports multiple contracts [#498](https://github.com/gakonst/ethers-rs/pull/498)
Expand Down
9 changes: 7 additions & 2 deletions ethers-contract/ethers-contract-abigen/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub struct ExpandedContract {
pub contract: TokenStream,
/// All event impls of the contract
pub events: TokenStream,
/// All contract call struct related types
pub call_structs: TokenStream,
/// The contract's internal structs
pub abi_structs: TokenStream,
}
Expand All @@ -41,6 +43,7 @@ impl ExpandedContract {
imports,
contract,
events,
call_structs,
abi_structs,
} = self;
quote! {
Expand All @@ -52,6 +55,7 @@ impl ExpandedContract {
#imports
#contract
#events
#call_structs
#abi_structs
}
}
Expand Down Expand Up @@ -111,8 +115,8 @@ impl Context {
// 3. impl block for the event functions
let contract_events = self.event_methods()?;

// 4. impl block for the contract methods
let contract_methods = self.methods()?;
// 4. impl block for the contract methods and their corresponding types
let (contract_methods, call_structs) = self.methods_and_call_structs()?;

// 5. Declare the structs parsed from the human readable abi
let abi_structs_decl = self.abi_structs()?;
Expand Down Expand Up @@ -146,6 +150,7 @@ impl Context {
imports,
contract,
events: events_decl,
call_structs,
abi_structs: abi_structs_decl,
})
}
Expand Down
68 changes: 25 additions & 43 deletions ethers-contract/ethers-contract-abigen/src/contract/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use inflector::Inflector;
use proc_macro2::{Ident, Literal, TokenStream};
use quote::quote;
use std::collections::BTreeMap;
use syn::Path;

impl Context {
/// Expands each event to a struct + its impl Detokenize block
Expand Down Expand Up @@ -33,9 +32,10 @@ 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 sorted_events: BTreeMap<_, _> = self.abi.events.iter().collect();
let filter_methods = sorted_events
.values()
.map(std::ops::Deref::deref)
.flatten()
.map(|event| self.expand_filter(event))
.collect::<Vec<_>>();
Expand All @@ -51,9 +51,9 @@ impl Context {

/// 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
let variants = self
.abi
.events
.values()
.flatten()
.map(|e| expand_struct_name(e, self.event_aliases.get(&e.abi_signature()).cloned()))
Expand All @@ -65,33 +65,11 @@ impl Context {
let ethers_contract = util::ethers_contract_crate();

quote! {
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, #ethers_contract::EthAbiType)]
pub enum #enum_name {
#(#variants(#variants)),*
}

impl #ethers_core::abi::Tokenizable for #enum_name {

fn from_token(token: #ethers_core::abi::Token) -> Result<Self, #ethers_core::abi::InvalidOutputType> where
Self: Sized {
#(
if let Ok(decoded) = #variants::from_token(token.clone()) {
return Ok(#enum_name::#variants(decoded))
}
)*
Err(#ethers_core::abi::InvalidOutputType("Failed to decode all event variants".to_string()))
}

fn into_token(self) -> #ethers_core::abi::Token {
match self {
#(
#enum_name::#variants(element) => element.into_token()
),*
}
}
}
impl #ethers_core::abi::TokenizableItem for #enum_name { }

impl #ethers_contract::EthLogDecode for #enum_name {
fn decode_log(log: &#ethers_core::abi::RawLog) -> Result<Self, #ethers_core::abi::Error>
where
Expand Down Expand Up @@ -153,8 +131,8 @@ impl Context {

/// Expands an event property type.
///
/// Note that this is slightly different than an expanding a Solidity type as
/// complex types like arrays and strings get emited as hashes when they are
/// Note that this is slightly different from expanding a Solidity type as
/// complex types like arrays and strings get emitted as hashes when they are
/// indexed.
/// If a complex types matches with a struct previously parsed by the AbiParser,
/// we can replace it
Expand Down Expand Up @@ -213,8 +191,8 @@ impl Context {
})
}

/// Expands an ABI event into name-type pairs for each of its parameters.
fn expand_params(&self, event: &Event) -> Result<Vec<(TokenStream, TokenStream, bool)>> {
/// Expands the name-type pairs for the given inputs
fn expand_event_params(&self, event: &Event) -> Result<Vec<(TokenStream, TokenStream, bool)>> {
event
.inputs
.iter()
Expand Down Expand Up @@ -264,7 +242,7 @@ impl Context {

let event_name = expand_struct_name(event, sig);

let params = self.expand_params(event)?;
let params = self.expand_event_params(event)?;
// expand as a tuple if all fields are anonymous
let all_anonymous_fields = event.inputs.iter().all(|input| input.name.is_empty());
let data_type_definition = if all_anonymous_fields {
Expand All @@ -273,7 +251,7 @@ impl Context {
expand_data_struct(&event_name, &params)
};

let derives = expand_derives(&self.event_derives);
let derives = util::expand_derives(&self.event_derives);

let ethers_contract = util::ethers_contract_crate();

Expand Down Expand Up @@ -323,16 +301,20 @@ fn expand_data_struct(name: &Ident, params: &[(TokenStream, TokenStream, bool)])
fn expand_data_tuple(name: &Ident, params: &[(TokenStream, TokenStream, bool)]) -> TokenStream {
let fields = params
.iter()
.map(|(_, ty, _)| quote! { pub #ty })
.map(|(_, ty, indexed)| {
if *indexed {
quote! {
#[ethevent(indexed)] pub #ty }
} else {
quote! {
pub #ty }
}
mattsse marked this conversation as resolved.
Show resolved Hide resolved
})
.collect::<Vec<_>>();

quote! { struct #name( #( #fields ),* ); }
}

fn expand_derives(derives: &[Path]) -> TokenStream {
quote! {#(#derives),*}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -450,7 +432,7 @@ mod tests {
};

let cx = test_context();
let params = cx.expand_params(&event).unwrap();
let params = cx.expand_event_params(&event).unwrap();
let name = expand_struct_name(&event, None);
let definition = expand_data_struct(&name, &params);

Expand Down Expand Up @@ -482,7 +464,7 @@ mod tests {
};

let cx = test_context_with_alias("Foo(bool,address)", "FooAliased");
let params = cx.expand_params(&event).unwrap();
let params = cx.expand_event_params(&event).unwrap();
let alias = Some(util::ident("FooAliased"));
let name = expand_struct_name(&event, alias);
let definition = expand_data_struct(&name, &params);
Expand Down Expand Up @@ -515,7 +497,7 @@ mod tests {
};

let cx = test_context();
let params = cx.expand_params(&event).unwrap();
let params = cx.expand_event_params(&event).unwrap();
let name = expand_struct_name(&event, None);
let definition = expand_data_tuple(&name, &params);

Expand Down Expand Up @@ -544,7 +526,7 @@ mod tests {
};

let cx = test_context_with_alias("Foo(bool,address)", "FooAliased");
let params = cx.expand_params(&event).unwrap();
let params = cx.expand_event_params(&event).unwrap();
let alias = Some(util::ident("FooAliased"));
let name = expand_struct_name(&event, alias);
let definition = expand_data_tuple(&name, &params);
Expand Down
Loading