diff --git a/Cargo.lock b/Cargo.lock index d4dd2855..6ed09954 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "anyhow" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.5.1" @@ -165,6 +170,23 @@ dependencies = [ "uint 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethers" +version = "0.1.0" +dependencies = [ + "anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "ethers-abi 0.1.0", + "ethers-contract 0.1.0", + "ethers-providers 0.1.0", + "ethers-signers 0.1.0", + "ethers-types 0.1.0", + "ethers-utils 0.1.0", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethers-abi" version = "0.1.0" @@ -1076,6 +1098,17 @@ dependencies = [ "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-macros" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1326,6 +1359,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum async-trait 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" @@ -1444,6 +1478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" "checksum tiny-keccak 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" "checksum tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" +"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" "checksum tokio-rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4" "checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" "checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" diff --git a/Cargo.toml b/Cargo.toml index 2b06e327..bc52e772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = [ - # "./crates/ethers", + "./crates/ethers", "./crates/ethers-abi", "./crates/ethers-contract", # "./crates/ethers-derive", @@ -10,35 +10,3 @@ members = [ "./crates/ethers-types", "./crates/ethers-utils", ] - -# [dependencies] -# ethers-derive = { path = "ethers-derive", optional = true } -# -# ethereum-types = { version = "0.9.2", default-features = false, features = ["serialize"] } -# url = { version = "2.1.1", default-features = false } -# async-trait = { version = "0.1.31", default-features = false } -# reqwest = { version = "0.10.4", default-features = false, features = ["json", "rustls-tls"] } -# serde = { version = "1.0.110", default-features = false, features = ["derive"] } -# serde_json = { version = "1.0.53", default-features = false } -# thiserror = { version = "1.0.19", default-features = false } -# rustc-hex = { version = "2.1.0", default-features = false } -# rand = { version = "0.5.1", default-features = false } # this should be the same rand crate version as the one in secp -# secp256k1 = { version = "0.17.2", default-features = false, features = ["std", "recovery", "rand"] } -# zeroize = { version = "1.1.0", default-features = false } -# tiny-keccak = { version = "2.0.2", default-features = false } -# -# solc = { git = "https://github.com/paritytech/rust_solc", optional = true } -# rlp = "0.4.5" -# ethabi = "12.0.0" -# bincode = "1.2.1" -# arrayvec = "0.5.1" -# -# [dev-dependencies] -# tokio = { version = "0.2.21", features = ["macros"] } -# failure = "0.1.8" -# rand = { version = "0.5.1" } -# -# [features] -# default = ["derive"] -# derive = ["ethers-derive"] -# diff --git a/README.md b/README.md index 195169d4..5db323cb 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,15 @@ Complete Ethereum wallet implementation and utilities in Rust (with WASM and FFI - [x] User friendly transaction APIs - [x] Type-safe EIP-155 transactions +- [x] Querying past events - [ ] Event Monitoring - [ ] Deploy and interact with smart contracts - [ ] Type safe smart contract bindings - [ ] Hardware wallet support - [ ] ... +## Directory Structure + ## Acknowledgements This library would not have been possibly without the great work of the creators of [`rust-web3`]() and [`ethcontract-rs`]() @@ -19,33 +22,3 @@ This library would not have been possibly without the great work of the creators A lot of the code was inspired and adapted from them, to a unified and opinionated interface. That said, Rust-web3 is ~9k LoC (tests included) and ethcontract-rs is 11k lines, so in total about 20k lines of code with tests. This library is xxx LoC. - -## Examples - -### Sending a transaction with an offline key - -```rust -use ethers::{types::TransactionRequest, HttpProvider, MainnetWallet}; -use std::convert::TryFrom; - -// connect to the network -let provider = HttpProvider::try_from("http://localhost:8545")?; - -// create a wallet and connect it to the provider -let client = "15c42bf2987d5a8a73804a8ea72fb4149f88adf73e98fc3f8a8ce9f24fcb7774" - .parse::()? - .connect(&provider); - -// craft the transaction using the builder pattern -let tx = TransactionRequest::new() - .send_to_str("986eE0C8B91A58e490Ee59718Cca41056Cf55f24")? - .value(10000); - -// send it! -let tx = client.sign_and_send_transaction(tx, None).await?; - -// get the mined tx -let tx = client.get_transaction(tx.hash).await?; - -println!("{}", serde_json::to_string(&tx)?); -``` diff --git a/crates/ethers-abi/src/lib.rs b/crates/ethers-abi/src/lib.rs index d7001e33..b372e3f2 100644 --- a/crates/ethers-abi/src/lib.rs +++ b/crates/ethers-abi/src/lib.rs @@ -7,7 +7,7 @@ pub use ethabi::Contract as Abi; pub use ethabi::*; mod tokens; -pub use tokens::{Detokenize, Tokenizable, TokenizableItem, Tokenize}; +pub use tokens::{Detokenize, InvalidOutputType, Tokenizable, TokenizableItem, Tokenize}; /// Extension trait for `ethabi::Function`. pub trait FunctionExt { diff --git a/crates/ethers-abi/src/tokens.rs b/crates/ethers-abi/src/tokens.rs index a90f7d49..d6bbb234 100644 --- a/crates/ethers-abi/src/tokens.rs +++ b/crates/ethers-abi/src/tokens.rs @@ -1,5 +1,6 @@ //! Contract Functions Output types. //! Adapted from: https://github.com/tomusdrw/rust-web3/blob/master/src/contract/tokens.rs +#[allow(clippy::all)] use crate::Token; use arrayvec::ArrayVec; diff --git a/crates/ethers/Cargo.toml b/crates/ethers/Cargo.toml index 5ca63397..808e2c60 100644 --- a/crates/ethers/Cargo.toml +++ b/crates/ethers/Cargo.toml @@ -4,8 +4,35 @@ version = "0.1.0" authors = ["Georgios Konstantopoulos "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["full"] +full = [ + "abi", + "contract", + "providers", + "signers", + "types", + "utils", +] + +abi = ["ethers-abi"] +contract = ["ethers-contract"] +providers = ["ethers-providers"] +signers = ["ethers-signers"] +types = ["ethers-types"] +utils = ["ethers-utils"] [dependencies] +ethers-abi = { path = "../ethers-abi", optional = true } +ethers-contract = { path = "../ethers-contract", optional = true } +ethers-providers = { path = "../ethers-providers", optional = true } +ethers-signers = { path = "../ethers-signers", optional = true } +ethers-types = { path = "../ethers-types", optional = true } +ethers-utils = { path = "../ethers-utils", optional = true } -# TODO: Make this have features for each available module +[dev-dependencies] +anyhow = "1.0.31" +tokio = { version = "0.2.21", features = ["macros"] } +serde_json = "1.0.53" +rand = "0.5.1" # note: when passing RNGs, they must be with version 0.5.1 +serde = { version = "1.0.110", features = ["derive"] } diff --git a/examples/contract.rs b/crates/ethers/examples/contract.rs similarity index 89% rename from examples/contract.rs rename to crates/ethers/examples/contract.rs index 23d7e593..578a8b62 100644 --- a/examples/contract.rs +++ b/crates/ethers/examples/contract.rs @@ -1,9 +1,12 @@ -use ethabi::Token; use ethers::{ - contract::{Contract, Detokenize}, + abi::{Detokenize, InvalidOutputType, Token}, + contract::Contract, + providers::HttpProvider, + signers::MainnetWallet, types::Address, - HttpProvider, MainnetWallet, }; + +use anyhow::Result; use serde::Serialize; use std::convert::TryFrom; @@ -18,9 +21,7 @@ struct ValueChanged { } impl Detokenize for ValueChanged { - fn from_tokens( - tokens: Vec, - ) -> Result { + fn from_tokens(tokens: Vec) -> Result { let author: Address = tokens[0].clone().to_address().unwrap(); let old_value = tokens[1].clone().to_string().unwrap(); let new_value = tokens[2].clone().to_string().unwrap(); @@ -34,7 +35,7 @@ impl Detokenize for ValueChanged { } #[tokio::main] -async fn main() -> Result<(), failure::Error> { +async fn main() -> Result<()> { // connect to the network let provider = HttpProvider::try_from("http://localhost:8545")?; diff --git a/examples/get_logs.rs b/crates/ethers/examples/get_logs.rs similarity index 87% rename from examples/get_logs.rs rename to crates/ethers/examples/get_logs.rs index 0e1b25c5..197102d4 100644 --- a/examples/get_logs.rs +++ b/crates/ethers/examples/get_logs.rs @@ -1,11 +1,12 @@ +use anyhow::Result; use ethers::{ + providers::HttpProvider, types::{Address, Filter}, - HttpProvider, }; use std::convert::TryFrom; #[tokio::main] -async fn main() -> Result<(), failure::Error> { +async fn main() -> Result<()> { // connect to the network let provider = HttpProvider::try_from("http://localhost:8545")?; diff --git a/examples/local_signer.rs b/crates/ethers/examples/local_signer.rs similarity index 85% rename from examples/local_signer.rs rename to crates/ethers/examples/local_signer.rs index 6575b60d..596b215e 100644 --- a/examples/local_signer.rs +++ b/crates/ethers/examples/local_signer.rs @@ -1,8 +1,9 @@ -use ethers::{types::TransactionRequest, HttpProvider, MainnetWallet}; +use anyhow::Result; +use ethers::{providers::HttpProvider, signers::MainnetWallet, types::TransactionRequest}; use std::convert::TryFrom; #[tokio::main] -async fn main() -> Result<(), failure::Error> { +async fn main() -> Result<()> { // connect to the network let provider = HttpProvider::try_from("http://localhost:8545")?; diff --git a/examples/sign.rs b/crates/ethers/examples/sign.rs similarity index 88% rename from examples/sign.rs rename to crates/ethers/examples/sign.rs index 69ec04b6..35103636 100644 --- a/examples/sign.rs +++ b/crates/ethers/examples/sign.rs @@ -1,4 +1,4 @@ -use ethers::{MainnetWallet as Wallet, Signer}; +use ethers::signers::{MainnetWallet as Wallet, Signer}; fn main() { let message = "Some data"; diff --git a/examples/transfer_eth.rs b/crates/ethers/examples/transfer_eth.rs similarity index 94% rename from examples/transfer_eth.rs rename to crates/ethers/examples/transfer_eth.rs index dc83eab6..f51ee97e 100644 --- a/examples/transfer_eth.rs +++ b/crates/ethers/examples/transfer_eth.rs @@ -1,11 +1,12 @@ +use anyhow::Result; use ethers::{ + providers::HttpProvider, types::{BlockNumber, TransactionRequest}, - HttpProvider, }; use std::convert::TryFrom; #[tokio::main] -async fn main() -> Result<(), failure::Error> { +async fn main() -> Result<()> { // connect to the network let provider = HttpProvider::try_from("http://localhost:8545")?; let accounts = provider.get_accounts().await?; diff --git a/crates/ethers/src/lib.rs b/crates/ethers/src/lib.rs index 87ef084b..7450f8d3 100644 --- a/crates/ethers/src/lib.rs +++ b/crates/ethers/src/lib.rs @@ -15,23 +15,32 @@ //! More examples can be found in the [`examples` directory of the //! repositry](https://github.com/gakonst/ethers-rs) -pub mod providers; -pub use providers::HttpProvider; +#[cfg(feature = "abi")] +pub mod abi { + pub use ethers_abi::*; +} -pub mod contract; -pub use contract::Contract; +#[cfg(feature = "contract")] +pub mod contract { + pub use ethers_contract::*; +} -pub(crate) mod signers; -pub use signers::{AnyWallet, MainnetWallet, Signer}; +#[cfg(feature = "providers")] +pub mod providers { + pub use ethers_providers::*; +} -/// Ethereum related datatypes -pub mod types; +#[cfg(feature = "signers")] +pub mod signers { + pub use ethers_signers::*; +} -/// Re-export solc for convenience -pub use solc; +#[cfg(feature = "types")] +pub mod types { + pub use ethers_types::*; +} -/// Various utilities -pub mod utils; - -/// ABI utilities -pub mod abi; +#[cfg(feature = "utils")] +pub mod utils { + pub use ethers_utils::*; +}