Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
fix(abigen): correctly parse params in human readable abi (#194)
Browse files Browse the repository at this point in the history
* fix(abigen): correctly parse params in human readable abi

* chore: make clippy happy

* test: remove unwrap

* chore: make clippy happy again

* chore: fix contract.rs example

* chore: rename to contract using human readable format

* examples: add abigen example with path to abi

* fix: pin funty version to fix bitvec error

* chore: remove unused import

* chore: fix deps
  • Loading branch information
gakonst authored Feb 16, 2021
1 parent 457c646 commit a43299c
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 41 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ethers-contract/ethers-contract-abigen/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl Context {
// heuristic for parsing the human readable format

// replace bad chars
let abi_str = abi_str.replace('[', "").replace(']', "").replace(',', "");
let abi_str = abi_str.replace('[', "").replace(']', "");
// split lines and get only the non-empty things
let split: Vec<&str> = abi_str
.split('\n')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub(crate) fn struct_declaration(cx: &Context, abi_name: &proc_macro2::Ident) ->
} else {
quote! {
pub static #abi_name: Lazy<Abi> = Lazy::new(|| {
let abi_str = #abi.replace('[', "").replace(']', "").replace(',', "");
let abi_str = #abi.replace('[', "").replace(']', "");
// split lines and get only the non-empty things
let split: Vec<&str> = abi_str
.split("\n")
Expand Down
10 changes: 5 additions & 5 deletions ethers-contract/ethers-contract-abigen/src/contract/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Context {
.abi
.events()
.map(|event| expand_filter(event))
.collect::<Result<Vec<_>>>()?;
.collect::<Vec<_>>();

if data_types.is_empty() {
return Ok(quote! {});
Expand All @@ -43,7 +43,7 @@ impl Context {
}

/// Expands into a single method for contracting an event stream.
fn expand_filter(event: &Event) -> Result<TokenStream> {
fn expand_filter(event: &Event) -> TokenStream {
// append `filter` to disambiguate with potentially conflicting
// function names
let name = util::safe_ident(&format!("{}_filter", event.name.to_snake_case()));
Expand All @@ -53,13 +53,13 @@ fn expand_filter(event: &Event) -> Result<TokenStream> {
let ev_name = Literal::string(&event.name);

let doc = util::expand_doc(&format!("Gets the contract's `{}` event", event.name));
Ok(quote! {
quote! {

#doc
pub fn #name(&self) -> Event<M, #result> {
self.0.event(#ev_name).expect("event not found (this should never happen)")
}
})
}
}

/// Expands an ABI event into a single event data type. This can expand either
Expand Down Expand Up @@ -317,7 +317,7 @@ mod tests {
anonymous: false,
};

assert_quote!(expand_filter(&event).unwrap(), {
assert_quote!(expand_filter(&event), {
#[doc = "Gets the contract's `Transfer` event"]
pub fn transfer_filter(&self) -> Event<M, TransferFilter> {
self.0
Expand Down
7 changes: 6 additions & 1 deletion ethers-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,17 @@ glob = { version = "0.3.0", default-features = false }
bytes = { version = "1.0.1", features = ["serde"] }
hex = { version = "0.4.2", default-features = false, features = ["std"] }

# bitvec compilation issue
# https://github.com/bitvecto-rs/bitvec/issues/105#issuecomment-778570981
funty = "=1.1.0"


[dev-dependencies]
ethers = { version = "0.2", path = "../ethers" }

serde_json = { version = "1.0.62", default-features = false }
bincode = { version = "1.2.1", default-features = false }
once_cell = { version = "1.5.2", default-features = false }
once_cell = { version = "1.5.2" }


[features]
Expand Down
16 changes: 7 additions & 9 deletions ethers-middleware/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,13 @@ where
mut tx: TransactionRequest,
block: Option<BlockNumber>,
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
if let Some(ref to) = tx.to {
if let NameOrAddress::Name(ens_name) = to {
let addr = self
.inner
.resolve_name(&ens_name)
.await
.map_err(SignerMiddlewareError::MiddlewareError)?;
tx.to = Some(addr.into())
}
if let Some(NameOrAddress::Name(ens_name)) = tx.to {
let addr = self
.inner
.resolve_name(&ens_name)
.await
.map_err(SignerMiddlewareError::MiddlewareError)?;
tx.to = Some(addr.into())
}

// fill any missing fields
Expand Down
16 changes: 7 additions & 9 deletions ethers-middleware/src/transformer/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,13 @@ where
block: Option<BlockNumber>,
) -> Result<PendingTransaction<'_, Self::Provider>, Self::Error> {
// resolve the to field if that's an ENS name.
if let Some(ref to) = tx.to {
if let NameOrAddress::Name(ens_name) = to {
let addr = self
.inner
.resolve_name(&ens_name)
.await
.map_err(TransformerMiddlewareError::MiddlewareError)?;
tx.to = Some(addr.into())
}
if let Some(NameOrAddress::Name(ens_name)) = tx.to {
let addr = self
.inner
.resolve_name(&ens_name)
.await
.map_err(TransformerMiddlewareError::MiddlewareError)?;
tx.to = Some(addr.into())
}

// construct the appropriate proxy tx.
Expand Down
8 changes: 2 additions & 6 deletions ethers-providers/src/pending_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,8 @@ impl<'a, P: JsonRpcClient> Future for PendingTransaction<'a, P> {
ctx.waker().wake_by_ref();
}
PendingTxState::GettingReceipt(fut) => {
if let Ok(receipt) = futures_util::ready!(fut.as_mut().poll(ctx)) {
if let Some(receipt) = receipt {
*this.state = PendingTxState::CheckingReceipt(Box::new(receipt))
} else {
*this.state = PendingTxState::PausedGettingReceipt
}
if let Ok(Some(receipt)) = futures_util::ready!(fut.as_mut().poll(ctx)) {
*this.state = PendingTxState::CheckingReceipt(Box::new(receipt))
} else {
*this.state = PendingTxState::PausedGettingReceipt
}
Expand Down
12 changes: 5 additions & 7 deletions ethers-providers/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,14 +293,12 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
tx.gas = Some(self.estimate_gas(&tx).await?);
}

if let Some(ref to) = tx.to {
if let NameOrAddress::Name(ens_name) = to {
// resolve to an address
let addr = self.resolve_name(&ens_name).await?;
if let Some(NameOrAddress::Name(ref ens_name)) = tx.to {
// resolve to an address
let addr = self.resolve_name(&ens_name).await?;

// set the value
tx.to = Some(addr.into())
}
// set the value
tx.to = Some(addr.into())
}

let tx_hash = self.request("eth_sendTransaction", [tx]).await?;
Expand Down
1 change: 1 addition & 0 deletions ethers/examples/contract_abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"inputs":[{"internalType":"string","name":"value","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":false,"internalType":"string","name":"oldValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ abigen!(
r#"[
function setValue(string)
function getValue() external view (string)
event ValueChanged(address indexed author, address indexed oldAuthor, string oldValue, string newValue)
event ValueChanged(address indexed author, string oldValue, string newValue)
]"#,
event_derives(serde::Deserialize, serde::Serialize)
);

#[tokio::main]
async fn main() -> Result<()> {
// 1. compile the contract (note this requires that you are inside the `ethers/examples` directory)
let compiled = Solc::new("./contract.sol").build()?;
let compiled = Solc::new("**/contract.sol").build()?;
let contract = compiled
.get("SimpleStorage")
.expect("could not find contract");
Expand Down
72 changes: 72 additions & 0 deletions ethers/examples/contract_with_abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use anyhow::Result;
use ethers::{
prelude::*,
utils::{Ganache, Solc},
};
use std::{convert::TryFrom, sync::Arc, time::Duration};

// Generate the type-safe contract bindings by providing the ABI
// definition in human readable format
abigen!(
SimpleContract,
"./ethers/examples/contract_abi.json",
event_derives(serde::Deserialize, serde::Serialize)
);

#[tokio::main]
async fn main() -> Result<()> {
// 1. compile the contract (note this requires that you are inside the `ethers/examples` directory)
let compiled = Solc::new("**/contract.sol").build()?;
let contract = compiled
.get("SimpleStorage")
.expect("could not find contract");
dbg!("OK");

// 2. launch ganache
let ganache = Ganache::new().spawn();

// 3. instantiate our wallet
let wallet: LocalWallet = ganache.keys()[0].clone().into();

// 4. connect to the network
let provider =
Provider::<Http>::try_from(ganache.endpoint())?.interval(Duration::from_millis(10u64));

// 5. instantiate the client with the wallet
let client = SignerMiddleware::new(provider, wallet);
let client = Arc::new(client);

// 6. create a factory which will be used to deploy instances of the contract
let factory = ContractFactory::new(
contract.abi.clone(),
contract.bytecode.clone(),
client.clone(),
);

// 7. deploy it with the constructor arguments
let contract = factory.deploy("initial value".to_string())?.send().await?;

// 8. get the contract's address
let addr = contract.address();

// 9. instantiate the contract
let contract = SimpleContract::new(addr, client.clone());

// 10. call the `setValue` method
// (first `await` returns a PendingTransaction, second one waits for it to be mined)
let _receipt = contract.set_value("hi".to_owned()).send().await?.await?;

// 11. get all events
let logs = contract
.value_changed_filter()
.from_block(0u64)
.query()
.await?;

// 12. get the new value
let value = contract.get_value().call().await?;

println!("Value: {}. Logs: {}", value, serde_json::to_string(&logs)?);

Ok(())
}

0 comments on commit a43299c

Please sign in to comment.