diff --git a/ethers-contract/src/contract.rs b/ethers-contract/src/contract.rs index f8b4bf8f..90d97b3c 100644 --- a/ethers-contract/src/contract.rs +++ b/ethers-contract/src/contract.rs @@ -109,7 +109,7 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc}; /// ```no_run /// # async fn foo() -> Result<(), Box> { /// use ethers_core::{abi::Abi, types::Address}; -/// use ethers_contract::Contract; +/// use ethers_contract::{Contract, EthEvent}; /// use ethers_providers::{Provider, Http, Middleware}; /// use ethers_signers::Wallet; /// use std::convert::TryFrom; @@ -120,7 +120,7 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc}; /// # let client = Provider::::try_from("http://localhost:8545").unwrap(); /// # let contract = Contract::new(address, abi, client); /// -/// #[derive(Clone, Debug)] +/// #[derive(Clone, Debug, EthEvent)] /// struct ValueChanged { /// old_author: Address, /// new_author: Address, @@ -128,25 +128,8 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc}; /// new_value: String, /// } /// -/// impl Detokenize for ValueChanged { -/// fn from_tokens(tokens: Vec) -> Result { -/// let old_author: Address = tokens[1].clone().into_address().unwrap(); -/// let new_author: Address = tokens[1].clone().into_address().unwrap(); -/// let old_value = tokens[2].clone().into_string().unwrap(); -/// let new_value = tokens[3].clone().into_string().unwrap(); -/// -/// Ok(Self { -/// old_author, -/// new_author, -/// old_value, -/// new_value, -/// }) -/// } -/// } -/// -/// /// let logs: Vec = contract -/// .event("ValueChanged")? +/// .event() /// .from_block(0u64) /// .query() /// .await?; diff --git a/ethers-contract/tests/common/derive.rs b/ethers-contract/tests/common/derive.rs index e52e98f0..08628611 100644 --- a/ethers-contract/tests/common/derive.rs +++ b/ethers-contract/tests/common/derive.rs @@ -1,5 +1,5 @@ use ethers::core::types::{H160, H256, I256, U128, U256}; -use ethers_contract::{EthAbiType, EthEvent}; +use ethers_contract::{abigen, EthAbiType, EthEvent}; use ethers_core::abi::Tokenizable; use ethers_core::types::Address; @@ -213,3 +213,26 @@ fn can_derive_indexed_and_anonymous_attribute() { ValueChangedEvent::abi_signature() ); } + +#[test] +fn can_generate_ethevent_from_json() { + abigen!(DsProxyFactory, + "ethers-middleware/contracts/DsProxyFactory.json", + methods { + build(address) as build_with_owner; + } + ); + + assert_eq!( + "Created(address,address,address,address)", + CreatedFilter::abi_signature() + ); + + assert_eq!( + H256([ + 37, 155, 48, 202, 57, 136, 92, 109, 128, 26, 11, 93, 188, 152, 134, 64, 243, 194, 94, + 47, 55, 83, 31, 225, 56, 197, 197, 175, 137, 85, 212, 27, + ]), + CreatedFilter::signature() + ); +} diff --git a/ethers-contract/tests/common/mod.rs b/ethers-contract/tests/common/mod.rs index fe3f8773..70f12c1c 100644 --- a/ethers-contract/tests/common/mod.rs +++ b/ethers-contract/tests/common/mod.rs @@ -4,7 +4,7 @@ use ethers_core::{ types::{Address, Bytes}, }; -use ethers_contract::{Contract, ContractFactory, EthAbiType}; +use ethers_contract::{Contract, ContractFactory, EthEvent}; use ethers_core::utils::{GanacheInstance, Solc}; use ethers_middleware::signer::SignerMiddleware; use ethers_providers::{Http, Middleware, Provider}; @@ -13,7 +13,7 @@ use std::{convert::TryFrom, sync::Arc, time::Duration}; // Note: The `EthAbiType` derive macro implements the necessary conversion between `Tokens` and // the struct -#[derive(Clone, Debug, EthAbiType)] +#[derive(Clone, Debug, EthEvent)] pub struct ValueChanged { pub old_author: Address, pub new_author: Address, diff --git a/ethers-contract/tests/contract.rs b/ethers-contract/tests/contract.rs index 5a17c643..16fface7 100644 --- a/ethers-contract/tests/contract.rs +++ b/ethers-contract/tests/contract.rs @@ -109,8 +109,7 @@ mod eth_tests { // and we can fetch the events let logs: Vec = contract - .event("ValueChanged") - .unwrap() + .event() .from_block(0u64) .topic1(client.address()) // Corresponds to the first indexed parameter .query() @@ -123,8 +122,7 @@ mod eth_tests { // and we can fetch the events at a block hash let hash = client.get_block(1).await.unwrap().unwrap().hash.unwrap(); let logs: Vec = contract - .event("ValueChanged") - .unwrap() + .event() .at_block_hash(hash) .topic1(client.address()) // Corresponds to the first indexed parameter .query() @@ -256,14 +254,14 @@ mod eth_tests { let contract = deploy(client, abi.clone(), bytecode).await; // We spawn the event listener: - let event = contract.event::("ValueChanged").unwrap(); + let event = contract.event::(); let mut stream = event.stream().await.unwrap(); assert_eq!(stream.id, 1.into()); // Also set up a subscription for the same thing let ws = Provider::connect(ganache.ws_endpoint()).await.unwrap(); let contract2 = ethers_contract::Contract::new(contract.address(), abi, ws); - let event2 = contract2.event::("ValueChanged").unwrap(); + let event2 = contract2.event::(); let mut subscription = event2.subscribe().await.unwrap(); assert_eq!(subscription.id, 2.into()); diff --git a/ethers-contract/tests/decode_logs2.rs b/ethers-contract/tests/decode_logs2.rs new file mode 100644 index 00000000..83381972 --- /dev/null +++ b/ethers-contract/tests/decode_logs2.rs @@ -0,0 +1,9 @@ +use ethers_contract::{abigen, EthEvent}; +// use ethers_core::abi::Tokenizable; +// +abigen!(DsProxyFactory, + "ethers-middleware/contracts/DsProxyFactory.json", + methods { + build(address) as build_with_owner; + } +); diff --git a/ethers-middleware/contracts/DsProxyFactory.json b/ethers-middleware/contracts/DsProxyFactory.json new file mode 100644 index 00000000..72161d66 --- /dev/null +++ b/ethers-middleware/contracts/DsProxyFactory.json @@ -0,0 +1,95 @@ +[ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "isProxy", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "cache", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "build", + "outputs": [ + { + "name": "proxy", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "build", + "outputs": [ + { + "name": "proxy", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "name": "proxy", + "type": "address" + }, + { + "indexed": false, + "name": "cache", + "type": "address" + } + ], + "name": "Created", + "type": "event" + } +] \ No newline at end of file diff --git a/ethers-middleware/src/transformer/ds_proxy/factory.rs b/ethers-middleware/src/transformer/ds_proxy/factory.rs index eefb5739..0e5b23e6 100644 --- a/ethers-middleware/src/transformer/ds_proxy/factory.rs +++ b/ethers-middleware/src/transformer/ds_proxy/factory.rs @@ -15,6 +15,18 @@ pub static ADDRESS_BOOK: Lazy> = Lazy::new(|| { m }); +/// +/// Generated with +/// ```no_run +/// # use ethers_contract::abigen; +/// abigen!(DsProxyFactory, +/// "ethers-middleware/contracts/DsProxyFactory.json", +/// methods { +/// build() as build_with_sender; +/// } +/// ); +/// ``` +/// // Auto-generated type-safe bindings pub use dsproxyfactory_mod::*; #[allow(clippy::too_many_arguments)] @@ -23,7 +35,7 @@ mod dsproxyfactory_mod { #![allow(unused_imports)] use ethers_contract::{ builders::{ContractCall, Event}, - Contract, Lazy, + Contract, EthEvent, Lazy, }; use ethers_core::{ abi::{parse_abi, Abi, Detokenize, InvalidOutputType, Token, Tokenizable}, @@ -64,8 +76,19 @@ mod dsproxyfactory_mod { .method_hash([41, 113, 3, 136], p0) .expect("method not found (this should never happen)") } - #[doc = "Calls the contract's `build` (0xf3701da2) function"] - pub fn build(&self, owner: Address) -> ContractCall { + ///Calls the contract's `build` (0x8e1a55fc) function + pub fn build_with_sender( + &self, + ) -> ethers_contract::builders::ContractCall { + self.0 + .method_hash([142, 26, 85, 252], ()) + .expect("method not found (this should never happen)") + } + ///Calls the contract's `build` (0xf3701da2) function + pub fn build( + &self, + owner: ethers_core::types::Address, + ) -> ethers_contract::builders::ContractCall { self.0 .method_hash([243, 112, 29, 162], owner) .expect("method not found (this should never happen)") @@ -76,60 +99,22 @@ mod dsproxyfactory_mod { .method_hash([96, 199, 210, 149], ()) .expect("method not found (this should never happen)") } - #[doc = "Gets the contract's `Created` event"] - pub fn created_filter(&self) -> Event { - self.0 - .event("Created") - .expect("event not found (this should never happen)") + ///Gets the contract's `Created` event + pub fn created_filter(&self) -> ethers_contract::builders::Event { + self.0.event() + } + + /// Returns an [`Event`](ethers_contract::builders::Event) builder for all events of this contract + pub fn events(&self) -> ethers_contract::builders::Event { + self.0.event_with_filter(Default::default()) } } - #[derive(Clone, Debug, Default, Eq, PartialEq)] + #[derive(Clone, Debug, Default, Eq, PartialEq, EthEvent)] + #[ethevent(abi = "Created(address,address,address,address)")] pub struct CreatedFilter { pub sender: Address, pub owner: Address, pub proxy: Address, pub cache: Address, } - impl CreatedFilter { - #[doc = r" Retrieves the signature for the event this data corresponds to."] - #[doc = r" This signature is the Keccak-256 hash of the ABI signature of"] - #[doc = r" this event."] - pub const fn signature() -> H256 { - H256([ - 37, 155, 48, 202, 57, 136, 92, 109, 128, 26, 11, 93, 188, 152, 134, 64, 243, 194, - 94, 47, 55, 83, 31, 225, 56, 197, 197, 175, 137, 85, 212, 27, - ]) - } - #[doc = r" Retrieves the ABI signature for the event this data corresponds"] - #[doc = r" to. For this event the value should always be:"] - #[doc = r""] - #[doc = "`Created(address,address,address,address)`"] - pub const fn abi_signature() -> &'static str { - "Created(address,address,address,address)" - } - } - impl Detokenize for CreatedFilter { - fn from_tokens(tokens: Vec) -> Result { - if tokens.len() != 4 { - return Err(InvalidOutputType(format!( - "Expected {} tokens, got {}: {:?}", - 4, - tokens.len(), - tokens - ))); - } - #[allow(unused_mut)] - let mut tokens = tokens.into_iter(); - let sender = Tokenizable::from_token(tokens.next().expect("this should never happen"))?; - let owner = Tokenizable::from_token(tokens.next().expect("this should never happen"))?; - let proxy = Tokenizable::from_token(tokens.next().expect("this should never happen"))?; - let cache = Tokenizable::from_token(tokens.next().expect("this should never happen"))?; - Ok(CreatedFilter { - sender, - owner, - proxy, - cache, - }) - } - } }