From a76fa6bfbf5cbc46ca51bffc884819e4a0eb19dd Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sun, 26 Feb 2023 15:28:17 +0100 Subject: [PATCH 1/2] docs: fix broken links --- .../src/contract/methods.rs | 4 +- .../src/source/online.rs | 2 +- ethers-middleware/src/gas_oracle/median.rs | 13 +++---- ethers-providers/src/rpc/transports/common.rs | 5 ++- ethers-solc/src/cache.rs | 37 +++++++++++-------- ethers-solc/src/compile/project.rs | 15 ++++---- ethers-solc/src/config.rs | 8 ++-- ethers-solc/src/filter.rs | 13 ++++--- ethers-solc/src/lib.rs | 5 +-- ethers-solc/src/resolver/mod.rs | 4 +- 10 files changed, 59 insertions(+), 47 deletions(-) diff --git a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs index 246e716ec..de11b029e 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs @@ -371,8 +371,8 @@ impl Context { /// convention of suffixing the function name with _with /// /// The first function or the function with the least amount of arguments should - /// be named as in the ABI, the following functions suffixed with _with_ + - /// additional_params[0].name + (_and_(additional_params[1+i].name))* + /// be named as in the ABI, the following functions suffixed with: + /// `_with_ + additional_params[0].name + (_and_(additional_params[1+i].name))*` fn get_method_aliases(&self) -> Result> { let mut aliases = self.method_aliases.clone(); diff --git a/ethers-contract/ethers-contract-abigen/src/source/online.rs b/ethers-contract/ethers-contract-abigen/src/source/online.rs index 3a6f04c06..053014815 100644 --- a/ethers-contract/ethers-contract-abigen/src/source/online.rs +++ b/ethers-contract/ethers-contract-abigen/src/source/online.rs @@ -119,7 +119,7 @@ impl Source { /// Parse `s` as an explorer ("etherscan"), explorer domain ("etherscan.io") or a chain that has /// an explorer ("mainnet"). /// - /// The URL can be either :
or /.../
+ /// The URL can be either `:
` or `/.../
` fn from_explorer(s: &str, url: &Url) -> Result { let explorer: Explorer = s.parse().or_else(|_| Explorer::from_chain(s.parse()?))?; let address = last_segment_address(url).ok_or_else(|| eyre::eyre!("Invalid URL: {url}"))?; diff --git a/ethers-middleware/src/gas_oracle/median.rs b/ethers-middleware/src/gas_oracle/median.rs index c6dd6c7ec..def9c55f2 100644 --- a/ethers-middleware/src/gas_oracle/median.rs +++ b/ethers-middleware/src/gas_oracle/median.rs @@ -75,21 +75,20 @@ impl GasOracle for Median { } } -/// Weighted fractile by key +/// Weighted fractile by key. /// -/// Sort the values in place by key and return the weighted fractile value such -/// that `fractile` fraction of the values by weight are less than or equal to -/// the value. +/// Sort the values in place by key and return the weighted fractile value such that `fractile` +/// fraction of the values by weight are less than or equal to the value. /// -/// Returns None if the values are empty. +/// Returns `None` if the values are empty. /// /// Note: it doesn't handle NaNs or other special float values. /// -/// See +/// See: /// /// # Panics /// -/// Panics if [`fractile`] is not in the range $[0, 1]$. +/// Panics if `fractile` is not in the range `0.0..=1.0`. fn weighted_fractile_by_key<'a, T, F, K>( fractile: f32, values: &'a mut [(f32, T)], diff --git a/ethers-providers/src/rpc/transports/common.rs b/ethers-providers/src/rpc/transports/common.rs index 9caab6b12..072cf7d63 100644 --- a/ethers-providers/src/rpc/transports/common.rs +++ b/ethers-providers/src/rpc/transports/common.rs @@ -24,9 +24,10 @@ pub struct JsonRpcError { pub data: Option, } -/// Recursively traverses the value, looking for hex data that it can extract +/// Recursively traverses the value, looking for hex data that it can extract. +/// /// Inspired by ethers-js logic: -/// https://github.com/ethers-io/ethers.js/blob/9f990c57f0486728902d4b8e049536f2bb3487ee/packages/providers/src.ts/json-rpc-provider.ts#L25-L53 +/// fn spelunk_revert(value: &Value) -> Option { match value { Value::String(s) => s.parse().ok(), diff --git a/ethers-solc/src/cache.rs b/ethers-solc/src/cache.rs index 0a335fa92..08fba251e 100644 --- a/ethers-solc/src/cache.rs +++ b/ethers-solc/src/cache.rs @@ -463,7 +463,7 @@ impl CacheEntry { /// Reads all artifact files associated with the `CacheEntry` /// - /// **Note:** all artifact file paths should be absolute, see [`Self::join`] + /// **Note:** all artifact file paths should be absolute. fn read_artifact_files( &self, ) -> Result>>> { @@ -579,27 +579,32 @@ impl CacheEntry { /// and which `Artifacts` can be reused. #[derive(Debug)] pub(crate) struct ArtifactsCacheInner<'a, T: ArtifactOutput> { - /// preexisting cache file + /// The preexisting cache file. pub cache: SolFilesCache, - /// all already existing artifacts + + /// All already existing artifacts. pub cached_artifacts: Artifacts, - /// relationship between all the files + + /// Relationship between all the files. pub edges: GraphEdges, - /// the project + + /// The project. pub project: &'a Project, - /// all files that were filtered because they haven't changed + + /// All the files that were filtered because they haven't changed. pub filtered: HashMap)>, - /// the corresponding cache entries for all sources that were deemed to be dirty + + /// The corresponding cache entries for all sources that were deemed to be dirty. /// - /// `CacheEntry` are grouped by their solidity file. + /// `CacheEntry` are grouped by their Solidity file. /// During preprocessing the `artifacts` field of a new `CacheEntry` is left blank, because in /// order to determine the artifacts of the solidity file, the file needs to be compiled first. /// Only after the `CompilerOutput` is received and all compiled contracts are handled, see - /// [`crate::ArtifactOutput::on_output()`] all artifacts, their disk paths, are determined and - /// can be populated before the updated [`crate::SolFilesCache`] is finally written to disk, - /// see [`Cache::finish()`] + /// [`crate::ArtifactOutput::on_output`] all artifacts, their disk paths, are determined and + /// can be populated before the updated [`crate::SolFilesCache`] is finally written to disk. pub dirty_source_files: HashMap)>, - /// the file hashes + + /// The file hashes. pub content_hashes: HashMap, } @@ -652,7 +657,7 @@ impl<'a, T: ArtifactOutput> ArtifactsCacheInner<'a, T> { } } - /// Returns the set of [Source]s that need to be included in the [CompilerOutput] in order to + /// Returns the set of [Source]s that need to be included in the `CompilerOutput` in order to /// recompile the project. /// /// We define _dirty_ sources as files that: @@ -661,12 +666,12 @@ impl<'a, T: ArtifactOutput> ArtifactsCacheInner<'a, T> { /// - their imports were changed /// - their artifact is missing /// - /// A _dirty_ file is always included in the [CompilerInput]. + /// A _dirty_ file is always included in the `CompilerInput`. /// A _dirty_ file can also include clean files - files that do not match any of the above /// criteria - which solc also requires in order to compile a dirty file. /// /// Therefore, these files will also be included in the filtered output but not marked as dirty, - /// so that their [OutputSelection] can be optimized in the [CompilerOutput] and their (empty) + /// so that their `OutputSelection` can be optimized in the `CompilerOutput` and their (empty) /// artifacts ignored. fn filter(&mut self, sources: Sources, version: &Version) -> FilteredSources { // all files that are not dirty themselves, but are pulled from a dirty file @@ -906,7 +911,7 @@ impl<'a, T: ArtifactOutput> ArtifactsCache<'a, T> { } } - /// Consumes the `Cache`, rebuilds the [`SolFileCache`] by merging all artifacts that were + /// Consumes the `Cache`, rebuilds the `SolFileCache` by merging all artifacts that were /// filtered out in the previous step (`Cache::filtered`) and the artifacts that were just /// compiled and written to disk `written_artifacts`. /// diff --git a/ethers-solc/src/compile/project.rs b/ethers-solc/src/compile/project.rs index 1233ba752..e5f503a4c 100644 --- a/ethers-solc/src/compile/project.rs +++ b/ethers-solc/src/compile/project.rs @@ -80,11 +80,10 @@ //! If caching is enabled in the [Project](crate::Project) a cache file will be created upon a //! successful solc build. The [cache file](crate::cache::SolFilesCache) stores metadata for all the //! files that were provided to solc. -//! For every file the cache file contains a dedicated [cache -//! entry](crate::cache::CacheEntry), which represents the state of the file. A solidity file can -//! contain several contracts, for every contract a separate [artifact](crate::Artifact) is emitted. -//! Therefor the entry also tracks all artifacts emitted by a file. A solidity file can also be -//! compiled with several solc versions. +//! For every file the cache file contains a dedicated [cache entry](crate::cache::CacheEntry), +//! which represents the state of the file. A solidity file can contain several contracts, for every +//! contract a separate [artifact](crate::Artifact) is emitted. Therefor the entry also tracks all +//! artifacts emitted by a file. A solidity file can also be compiled with several solc versions. //! //! For example in `A(<=0.8.10) imports C(>0.4.0)` and //! `B(0.8.11) imports C(>0.4.0)`, both `A` and `B` import `C` but there's no solc version that's @@ -252,10 +251,12 @@ impl<'a, T: ArtifactOutput> ProjectCompiler<'a, T> { /// The main reason is to debug all states individually #[derive(Debug)] struct PreprocessedState<'a, T: ArtifactOutput> { - /// contains all sources to compile + /// Contains all the sources to compile. sources: FilteredCompilerSources, - /// cache that holds [CacheEntry] object if caching is enabled and the project is recompiled + + /// Cache that holds `CacheEntry` objects if caching is enabled and the project is recompiled cache: ArtifactsCache<'a, T>, + sparse_output: SparseOutputFilter, } diff --git a/ethers-solc/src/config.rs b/ethers-solc/src/config.rs index 84eb4fb1c..b224a8715 100644 --- a/ethers-solc/src/config.rs +++ b/ethers-solc/src/config.rs @@ -76,8 +76,9 @@ impl ProjectPathsConfig { } } - /// Same as [Self::paths()] but strips the `root` form all paths, - /// [ProjectPaths::strip_prefix_all()] + /// Same as [`paths`][ProjectPathsConfig::paths] but strips the `root` form all paths. + /// + /// See: [`ProjectPaths::strip_prefix_all`] pub fn paths_relative(&self) -> ProjectPaths { let mut paths = self.paths(); paths.strip_prefix_all(&self.root); @@ -790,7 +791,8 @@ impl SolcConfigBuilder { } } -/// Container for all `--include-path` arguments for Solc, se also [Solc docs](https://docs.soliditylang.org/en/v0.8.9/using-the-compiler.html#base-path-and-import-remapping +/// Container for all `--include-path` arguments for Solc, see also +/// [Solc docs](https://docs.soliditylang.org/en/v0.8.9/using-the-compiler.html#base-path-and-import-remapping). /// /// The `--include--path` flag: /// > Makes an additional source directory available to the default import callback. Use this option diff --git a/ethers-solc/src/filter.rs b/ethers-solc/src/filter.rs index 604414bb7..549c84641 100644 --- a/ethers-solc/src/filter.rs +++ b/ethers-solc/src/filter.rs @@ -287,14 +287,17 @@ impl FilteredSource { /// Helper type that determines the state of a source file #[derive(Debug)] pub struct FilteredSourceInfo { - /// path to the source file + /// Path to the source file. pub file: PathBuf, - /// contents of the file + + /// Contents of the file. pub source: Source, - /// idx in the [GraphEdges] + + /// Index in the [GraphEdges]. pub idx: usize, - /// whether this file is actually dirty + + /// Whether this file is actually dirty. /// - /// See also [ArtifactsCacheInner::is_dirty()] + /// See also `ArtifactsCacheInner::is_dirty` pub dirty: bool, } diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs index 9d2947f7e..dfbcaec12 100644 --- a/ethers-solc/src/lib.rs +++ b/ethers-solc/src/lib.rs @@ -1,5 +1,4 @@ #![deny(rustdoc::broken_intra_doc_links)] -#![allow(rustdoc::private_intra_doc_links)] pub mod artifacts; pub mod sourcemap; @@ -24,7 +23,7 @@ pub use compile::{ }; mod config; -pub use config::{AllowedLibPaths, PathStyle, ProjectPathsConfig, SolcConfig}; +pub use config::{AllowedLibPaths, PathStyle, ProjectPaths, ProjectPathsConfig, SolcConfig}; pub mod remappings; use crate::artifacts::{Source, SourceFile, StandardJsonCompilerInput}; @@ -280,7 +279,7 @@ impl Project { /// /// This will autodetect the appropriate `Solc` version(s) to use when compiling the provided /// `Sources`. Solc auto-detection follows semver rules, see also - /// [`crate::resolver::Graph::get_input_node_versions()`] + /// `Graph::get_input_node_versions` /// /// # Errors /// diff --git a/ethers-solc/src/resolver/mod.rs b/ethers-solc/src/resolver/mod.rs index 08b1b0f16..0610b71da 100644 --- a/ethers-solc/src/resolver/mod.rs +++ b/ethers-solc/src/resolver/mod.rs @@ -179,7 +179,9 @@ impl GraphEdges { /// /// This is a preprocess function that attempts to resolve those libraries that will the /// solidity `file` will be required to link. And further restrict this list to libraries - /// that won't be inlined See also [SolLibrary](parse::SolLibrary) + /// that won't be inlined. + /// + /// See also `parse::SolLibrary`. pub fn get_link_references(&self, file: impl AsRef) -> HashSet<&PathBuf> { let mut link_references = HashSet::new(); for import in self.all_imported_nodes(self.node_id(file)) { From 226a98615d22a193b3a41bc97c50c75ac7ce97c0 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 27 Feb 2023 13:40:59 +0100 Subject: [PATCH 2/2] docs: update READMEs and module-level documentation --- CONTRIBUTING.md | 2 +- Cargo.toml | 2 +- README.md | 100 +++++++++++------------ assets/CONTRACT_README.md | 1 - assets/CORE_README.md | 1 - assets/MIDDLEWARE_README.md | 1 - assets/PROVIDERS_README.md | 1 - assets/SIGNERS_README.md | 1 - assets/SOLC_README.md | 1 - ethers-addressbook/Cargo.toml | 4 +- ethers-addressbook/README.md | 15 ++++ ethers-addressbook/src/lib.rs | 9 ++- ethers-contract/README.md | 6 +- ethers-core/README.md | 58 ++++++------- ethers-core/src/abi/mod.rs | 6 +- ethers-core/src/types/mod.rs | 2 + ethers-etherscan/README.md | 22 +++++ ethers-etherscan/src/contract.rs | 14 ++-- ethers-etherscan/src/lib.rs | 3 +- ethers-middleware/README.md | 119 +++++++++++++-------------- ethers-middleware/src/lib.rs | 3 +- ethers-providers/README.md | 74 ++++++++++------- ethers-providers/src/lib.rs | 5 +- ethers-signers/README.md | 34 +++++++- ethers-signers/src/lib.rs | 5 +- ethers-solc/src/lib.rs | 1 + src/lib.rs | 135 +++++++++++++------------------ 27 files changed, 334 insertions(+), 291 deletions(-) delete mode 120000 assets/CONTRACT_README.md delete mode 120000 assets/CORE_README.md delete mode 120000 assets/MIDDLEWARE_README.md delete mode 120000 assets/PROVIDERS_README.md delete mode 120000 assets/SIGNERS_README.md delete mode 120000 assets/SOLC_README.md create mode 100644 ethers-addressbook/README.md create mode 100644 ethers-etherscan/README.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7c0c387f3..24f5e4ca5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,7 @@ us! The ethers-rs project adheres to the [Rust Code of Conduct][coc]. This describes the _minimum_ behavior expected from all contributors. Instances of violations of the Code of Conduct can be reported by contacting the project team at [me@gakonst.com](mailto:me@gakonst.com). -[coc]: https://github.com/rust-lang/rust/blob/master/CODE_OF_CONDUCT.md +[coc]: https://www.rust-lang.org/policies/code-of-conduct ## Contributing in Issues diff --git a/Cargo.toml b/Cargo.toml index 6c2794acf..9a8cbf3e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" documentation = "https://docs.rs/ethers" repository = "https://github.com/gakonst/ethers-rs" homepage = "https://docs.rs/ethers" -description = "Complete Ethereum library and wallet implementation in Rust." +description = "A complete Ethereum and Celo Rust library" [workspace] members = [ diff --git a/README.md b/README.md index c85e9f9e6..51c82280f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -#

ethers.rs

+#

ethers-rs

-**Complete Ethereum and Celo wallet implementation and utilities in Rust** +**A complete Ethereum and Celo Rust library** ![Github Actions](https://github.com/gakonst/ethers-rs/workflows/Tests/badge.svg) [![Telegram Chat](https://img.shields.io/endpoint?color=neon&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fethers_rs)](https://t.me/ethers_rs) @@ -9,42 +9,34 @@ [crates-badge]: https://img.shields.io/crates/v/ethers.svg [crates-url]: https://crates.io/crates/ethers -## Documentation - -Extensive documentation and examples are available [here](https://docs.rs/ethers). - -Alternatively, you may clone the repository and run `cd ethers/ && cargo doc --open` - -Examples are organized into individual crates under the `/examples` folder. -You can run any of the examples by executing: -```bash -# cargo run -p --example -cargo run -p examples-big-numbers --example math_operations -``` +## Quickstart -## Add ethers-rs to your repository +Add this to your Cargo.toml: ```toml [dependencies] - -ethers = "1.0.0" +ethers = "1.0.2" ``` - +And this to your code: -## Running the tests +```rust +use ethers::prelude::*; +``` -Tests require the following installed: +## Documentation -1. [`solc`](https://solidity.readthedocs.io/en/latest/installing-solidity.html) (>=0.8.10). We also recommend using [solc-select](https://github.com/crytic/solc-select) for more flexibility. -2. [`anvil`](https://github.com/foundry-rs/foundry/blob/master/anvil/README.md) -3. [`geth`](https://github.com/ethereum/go-ethereum) +View the API reference [here](https://docs.rs/ethers) or the online book [here](https://gakonst.com/ethers-rs). -In addition, it is recommended that you set the `ETHERSCAN_API_KEY` environment variable -for [the abigen via Etherscan](https://github.com/gakonst/ethers-rs/blob/master/ethers-contract/tests/it/abigen.rs) tests. -You can get one [here](https://etherscan.io/apis). +Examples are organized into individual crates under the `/examples` folder. +You can run any of the examples by executing: + +```bash +# cargo run -p --example +cargo run -p examples-big-numbers --example math_operations +``` -### EVM-compatible chains support +## EVM-compatible chains support There are many chains live which are Ethereum JSON-RPC & EVM compatible, but do not yet have support for [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) Typed Transactions. This means @@ -53,8 +45,7 @@ address that, you must use the `legacy` feature flag: ```toml [dependencies] - -ethers = { version = "1.0.0", features = ["legacy"] } +ethers = { version = "1.0.2", features = ["legacy"] } ``` ### Polygon support @@ -73,8 +64,7 @@ You can get one [here](https://snowtrace.io/apis). ```toml [dependencies] - -ethers = { version = "1.0.0", features = ["celo"] } +ethers = { version = "1.0.2", features = ["celo"] } ``` Celo's transactions differ from Ethereum transactions by including 3 new fields: @@ -111,8 +101,7 @@ Websockets support is turned on via the feature-flag `ws`: ```toml [dependencies] - -ethers = { version = "1.0.0", features = ["ws"] } +ethers = { version = "1.0.2", features = ["ws"] } ``` ### Interprocess Communication (IPC) @@ -121,8 +110,7 @@ IPC support is turned on via the feature-flag `ipc`: ```toml [dependencies] - -ethers = { version = "1.0.0", features = ["ipc"] } +ethers = { version = "1.0.2", features = ["ipc"] } ``` ### HTTP Secure (HTTPS) @@ -134,16 +122,14 @@ To enable `rustls`: ```toml [dependencies] - -ethers = { version = "1.0.0", features = ["rustls"] } +ethers = { version = "1.0.2", features = ["rustls"] } ``` To enable `openssl`: ```toml [dependencies] - -ethers = { version = "1.0.0", features = ["openssl"] } +ethers = { version = "1.0.2", features = ["openssl"] } ``` ## Note on WASM and FFI bindings @@ -171,24 +157,22 @@ Join the [ethers-rs telegram](https://t.me/ethers_rs) to chat with the community ## Contributing Thanks for your help improving the project! We are so happy to have you! We have -[a contributing guide](https://github.com/gakonst/ethers-rs/blob/master/CONTRIBUTING.md) to -help you get involved in the ethers-rs project. +[a contributing guide](./CONTRIBUTING.md) to help you get involved in the ethers-rs project. -If you make a Pull Request, do not forget to add your changes in the [CHANGELOG](CHANGELOG.md) and ensure your code is -properly formatted with `cargo +nightly fmt` and clippy is happy `cargo clippy`, you can even try to let clippy fix simple -issues itself: `cargo +nightly clippy --fix -Z unstable-options` +If you open a Pull Request, do not forget to add your changes in the [CHANGELOG](./CHANGELOG.md), ensure your code is +properly formatted with `cargo +nightly fmt` and that Clippy is happy `cargo clippy`; you can even try to let clippy fix simple +issues itself: `cargo +nightly clippy --fix` -## Related Projects +### Running the tests -This library would not have been possible without the great work done in: +Tests require the following installed: -- [`ethers.js`](https://github.com/ethers-io/ethers.js/) -- [`rust-web3`](https://github.com/tomusdrw/rust-web3/) -- [`ethcontract-rs`](https://github.com/gnosis/ethcontract-rs/) -- [`guac_rs`](https://github.com/althea-net/guac_rs/tree/master/web3/src/jsonrpc) +1. [`solc`](https://docs.soliditylang.org/en/latest/installing-solidity.html) (>=0.8.0). We also recommend using [svm](https://github.com/roynalnaruto/svm-rs) for more flexibility. +2. [`anvil`](https://github.com/foundry-rs/foundry/blob/master/anvil/README.md) +3. [`geth`](https://github.com/ethereum/go-ethereum) -A lot of the code was inspired and adapted from them, to a unified and opinionated interface, -built with async/await and std futures from the ground up. +Additionally, the `ETHERSCAN_API_KEY` environment variable has to be set to run [`ethers-etherscan`](./ethers-etherscan) tests. +You can get one [here](https://etherscan.io/apis). ## Projects using ethers-rs @@ -199,3 +183,15 @@ built with async/await and std futures from the ground up. - [Celo Threshold BLS DKG](https://github.com/celo-org/celo-threshold-bls-rs/): CLI for using Celo as a data availability network for the Joint-Feldman BLS DKG - [Celo Plumo Prover](https://github.com/celo-org/plumo-prover): Creates Celo's ultralight client proof from on-chain data - [Celo SNARK Setup Coordinator](https://github.com/celo-org/snark-setup-operator): Coordinator for executing a pipelined Groth16 SNARK setup + +## Credits + +This library would not have been possible without the great work done in: + +- [`ethers.js`](https://github.com/ethers-io/ethers.js/) +- [`rust-web3`](https://github.com/tomusdrw/rust-web3/) +- [`ethcontract-rs`](https://github.com/gnosis/ethcontract-rs/) +- [`guac_rs`](https://github.com/althea-net/guac_rs/) + +A lot of the code was inspired and adapted from them, to a unified and opinionated interface, +built with async/await and std futures from the ground up. diff --git a/assets/CONTRACT_README.md b/assets/CONTRACT_README.md deleted file mode 120000 index c28ebb7e3..000000000 --- a/assets/CONTRACT_README.md +++ /dev/null @@ -1 +0,0 @@ -../ethers-contract/README.md \ No newline at end of file diff --git a/assets/CORE_README.md b/assets/CORE_README.md deleted file mode 120000 index b61206a8a..000000000 --- a/assets/CORE_README.md +++ /dev/null @@ -1 +0,0 @@ -../ethers-core/README.md \ No newline at end of file diff --git a/assets/MIDDLEWARE_README.md b/assets/MIDDLEWARE_README.md deleted file mode 120000 index 31026c1a9..000000000 --- a/assets/MIDDLEWARE_README.md +++ /dev/null @@ -1 +0,0 @@ -../ethers-middleware/README.md \ No newline at end of file diff --git a/assets/PROVIDERS_README.md b/assets/PROVIDERS_README.md deleted file mode 120000 index 149647fbc..000000000 --- a/assets/PROVIDERS_README.md +++ /dev/null @@ -1 +0,0 @@ -../ethers-providers/README.md \ No newline at end of file diff --git a/assets/SIGNERS_README.md b/assets/SIGNERS_README.md deleted file mode 120000 index ea8f7facd..000000000 --- a/assets/SIGNERS_README.md +++ /dev/null @@ -1 +0,0 @@ -../ethers-signers/README.md \ No newline at end of file diff --git a/assets/SOLC_README.md b/assets/SOLC_README.md deleted file mode 120000 index bb5c3c0ff..000000000 --- a/assets/SOLC_README.md +++ /dev/null @@ -1 +0,0 @@ -../ethers-solc/README.md \ No newline at end of file diff --git a/ethers-addressbook/Cargo.toml b/ethers-addressbook/Cargo.toml index 3dd8ee1b9..f13e7792b 100644 --- a/ethers-addressbook/Cargo.toml +++ b/ethers-addressbook/Cargo.toml @@ -11,8 +11,8 @@ repository = "https://github.com/gakonst/ethers-rs" keywords = ["ethereum", "web3", "celo", "ethers"] [dependencies] +ethers-core = { version = "^1.0.0", path = "../ethers-core", default-features = false } + once_cell = "1.17.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" - -ethers-core = { path = "../ethers-core", version = "^1.0.0" } diff --git a/ethers-addressbook/README.md b/ethers-addressbook/README.md new file mode 100644 index 000000000..434ce7b54 --- /dev/null +++ b/ethers-addressbook/README.md @@ -0,0 +1,15 @@ +# ethers-addressbook + +A collection of commonly used smart contract addresses. + +For more information, please refer to the [book](https://gakonst.com/ethers-rs). + +## Examples + +```rust +use ethers_addressbook::{contract, Chain}; + +let weth = contract("weth").unwrap(); +let mainnet_address = weth.address(Chain::Mainnet).unwrap(); +assert_eq!(mainnet_address, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".parse().unwrap()); +``` diff --git a/ethers-addressbook/src/lib.rs b/ethers-addressbook/src/lib.rs index 2acbfc424..c2acc2f69 100644 --- a/ethers-addressbook/src/lib.rs +++ b/ethers-addressbook/src/lib.rs @@ -1,7 +1,10 @@ -use ethers_core::types::{Address, Chain}; +#![doc = include_str!("../README.md")] +#![deny(unsafe_code, rustdoc::broken_intra_doc_links)] + +pub use ethers_core::types::{Address, Chain}; + use once_cell::sync::Lazy; use serde::Deserialize; - use std::collections::HashMap; const CONTRACTS_JSON: &str = include_str!("./contracts/contracts.json"); @@ -9,7 +12,7 @@ const CONTRACTS_JSON: &str = include_str!("./contracts/contracts.json"); static ADDRESSBOOK: Lazy> = Lazy::new(|| serde_json::from_str(CONTRACTS_JSON).unwrap()); -/// Wrapper around a hash map that maps a [chain](https://github.com/gakonst/ethers-rs/blob/master/ethers-core/src/types/chain.rs) to the contract's deployed address on that chain. +/// Wrapper around a hash map that maps a [Chain] to the contract's deployed address on that chain. #[derive(Clone, Debug, Deserialize)] pub struct Contract { addresses: HashMap, diff --git a/ethers-contract/README.md b/ethers-contract/README.md index d56586135..b91644f21 100644 --- a/ethers-contract/README.md +++ b/ethers-contract/README.md @@ -1,4 +1,6 @@ -Type-safe abstractions for interacting with Ethereum smart contracts +# ethers-core + +Type-safe abstractions for interacting with Ethereum smart contracts. Interacting with a smart contract requires broadcasting carefully crafted [transactions](ethers_core::types::TransactionRequest) where the `data` field @@ -10,6 +12,8 @@ This module provides the [`Contract`] and [`ContractFactory`] abstractions so that you do not have to worry about that. It also provides typesafe bindings via the [`abigen`] macro and the [`Abigen` builder]. +For more information, please refer to the [book](https://gakonst.com/ethers-rs). + [`contractfactory`]: ./struct.ContractFactory.html [`contract`]: ./struct.Contract.html [`abigen`]: ./macro.abigen.html diff --git a/ethers-core/README.md b/ethers-core/README.md index 15cba6ce2..d41318558 100644 --- a/ethers-core/README.md +++ b/ethers-core/README.md @@ -1,4 +1,6 @@ -# Ethereum types, cryptography and utilities. +# ethers-core + +Ethereum data types, cryptography and utilities. It is recommended to use the `utils`, `types` and `abi` re-exports instead of the `core` module to simplify your imports. @@ -6,43 +8,43 @@ the `core` module to simplify your imports. This library provides type definitions for Ethereum's main datatypes along with other utilities for interacting with the Ethereum ecosystem -## Signing an ethereum-prefixed message - -Signing in Ethereum is done by first prefixing the message with -`"\x19Ethereum Signed Message:\n" + message.length`, and then signing the hash -of the result. +For more information, please refer to the [book](https://gakonst.com/ethers-rs). -```rust,ignore -# async fn foo() -> Result<(), Box> { -use ethers::signers::{Signer, LocalWallet}; +## Feature flags -let message = "Some data"; -let wallet = LocalWallet::new(&mut rand::thread_rng()); +- `eip712`: Provides the `Eip712` trait and derive procedural macro for EIP-712 encoding of typed data. -// Sign the message -let signature = wallet.sign_message(message).await?; +## ABI -// Recover the signer from the message -let recovered = signature.recover(message)?; - -assert_eq!(recovered, wallet.address()); -# Ok(()) -# } -``` +This crate re-exports the [`ethabi`](https://docs.rs/ethabi) crate's functions +under the `abi` module, as well as the +[`secp256k1`](https://docs.rs/libsecp256k1) and [`rand`](https://docs.rs/rand) +crates for convenience. ## Utilities The crate provides utilities for launching local Ethereum testnets by using `ganache-cli` via the `GanacheBuilder` struct. -# Features +## Examples -- ["eip712"] | Provides Eip712 trait for EIP-712 encoding of typed data for - derived structs +Calculate the UniswapV2 pair address for two ERC20 tokens: -# ABI Encoding and Decoding +```rust +# use ethers_core::abi::{self, Token}; +# use ethers_core::types::{Address, H256}; +# use ethers_core::utils; +let factory: Address = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f".parse()?; -This crate re-exports the [`ethabi`](https://docs.rs/ethabi) crate's functions -under the `abi` module, as well as the -[`secp256k1`](https://docs.rs/libsecp256k1) and [`rand`](https://docs.rs/rand) -crates for convenience. +let token_a: Address = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".parse()?; +let token_b: Address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".parse()?; +let encoded = abi::encode_packed(&[Token::Address(token_a), Token::Address(token_b)])?; +let salt = utils::keccak256(encoded); + +let init_code_hash: H256 = "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f".parse()?; + +let pair = utils::get_create2_address_from_hash(factory, salt, init_code_hash); +let weth_usdc = "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc".parse()?; +assert_eq!(pair, weth_usdc); +# Ok::<(), Box>(()) +``` diff --git a/ethers-core/src/abi/mod.rs b/ethers-core/src/abi/mod.rs index 7cc733a59..f777d89a2 100644 --- a/ethers-core/src/abi/mod.rs +++ b/ethers-core/src/abi/mod.rs @@ -1,5 +1,7 @@ -//! This module implements extensions to the [`ethabi`](https://docs.rs/ethabi) API. -// Adapted from [Gnosis' ethcontract](https://github.com/gnosis/ethcontract-rs/blob/master/common/src/abiext.rs) +//! Extensions to the [`ethabi`](https://docs.rs/ethabi) API. +//! +//! Adapted from [Gnosis' `ethcontract-rs`](https://github.com/gnosis/ethcontract-rs). + use crate::{ types::{Bytes, Selector, Uint8, H256, H512, I256, U128, U256, U64}, utils::id, diff --git a/ethers-core/src/types/mod.rs b/ethers-core/src/types/mod.rs index 99eeadb57..ce00d1c84 100644 --- a/ethers-core/src/types/mod.rs +++ b/ethers-core/src/types/mod.rs @@ -1,3 +1,5 @@ +//! Ethereum data types. + pub type Selector = [u8; 4]; // Re-export common ethereum datatypes with more specific names diff --git a/ethers-etherscan/README.md b/ethers-etherscan/README.md new file mode 100644 index 000000000..d9e3dce4e --- /dev/null +++ b/ethers-etherscan/README.md @@ -0,0 +1,22 @@ +# ethers-etherscan + +Bindings for the [etherscan.io web API](https://docs.etherscan.io). + +For more information, please refer to the [book](https://gakonst.com/ethers-rs). + +## Examples + +```rust,no_run +# use ethers_core::types::Chain; +# use ethers_etherscan::Client; +# async fn foo() -> Result<(), Box> { +let client = Client::new(Chain::Mainnet, "")?; +// Or using environment variables +let client = Client::new_from_env(Chain::Mainnet)?; + +let address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".parse()?; +let metadata = client.contract_source_code(address).await?; +assert_eq!(metadata.items[0].contract_name, "DAO"); +# Ok(()) +# } +``` diff --git a/ethers-etherscan/src/contract.rs b/ethers-etherscan/src/contract.rs index 2b5adb23a..4e80bbf84 100644 --- a/ethers-etherscan/src/contract.rs +++ b/ethers-etherscan/src/contract.rs @@ -363,14 +363,12 @@ impl Client { /// ```no_run /// # use ethers_etherscan::Client; /// # use ethers_core::types::Chain; - /// - /// # #[tokio::main] - /// # async fn main() { - /// let client = Client::new(Chain::Mainnet, "API_KEY").unwrap(); - /// let meta = client - /// .contract_source_code("0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".parse().unwrap()) - /// .await.unwrap(); - /// let code = meta.source_code(); + /// # async fn foo() -> Result<(), Box> { + /// let client = Client::new(Chain::Mainnet, "")?; + /// let address = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".parse()?; + /// let metadata = client.contract_source_code(address).await?; + /// assert_eq!(metadata.items[0].contract_name, "DAO"); + /// # Ok(()) /// # } /// ``` pub async fn contract_source_code(&self, address: Address) -> Result { diff --git a/ethers-etherscan/src/lib.rs b/ethers-etherscan/src/lib.rs index 276829096..7e629e2a0 100644 --- a/ethers-etherscan/src/lib.rs +++ b/ethers-etherscan/src/lib.rs @@ -1,4 +1,5 @@ -//! Bindings for [etherscan.io web api](https://docs.etherscan.io/) +#![doc = include_str!("../README.md")] +#![deny(unsafe_code, rustdoc::broken_intra_doc_links)] use crate::errors::{is_blocked_by_cloudflare_response, is_cloudflare_security_challenge}; use contract::ContractMetadata; diff --git a/ethers-middleware/README.md b/ethers-middleware/README.md index 75a9b328e..c66835e05 100644 --- a/ethers-middleware/README.md +++ b/ethers-middleware/README.md @@ -1,93 +1,83 @@ +# ethers-middleware + Your ethers application interacts with the blockchain through a [`Provider`](ethers_providers::Provider) abstraction. [`Provider`](ethers_providers::Provider) is a special type of [`Middleware`](ethers_providers::Middleware) that can be composed with others to obtain a layered architecture. This approach promotes "Open Closed Principle", "Single Responsibility" and composable patterns. The building process happens in a wrapping fashion, and starts from a [`Provider`](ethers_providers::Provider) being the first element in the stack. This process continues having new middlewares being pushed on top of a layered data structure. +For more information, please refer to the [book](https://gakonst.com/ethers-rs). ## Available Middleware -- [`Signer`](./signer/struct.SignerMiddleware.html): Signs transactions locally, with a private key or a hardware wallet. -- [`Nonce Manager`](./nonce_manager/struct.NonceManagerMiddleware.html): Manages nonces locally. Allows to sign multiple consecutive transactions without waiting for them to hit the mempool. -- [`Gas Escalator`](./gas_escalator/struct.GasEscalatorMiddleware.html): Bumps transactions gas price in the background to avoid getting them stuck in the memory pool. A [`GasEscalatorMiddleware`](crate::gas_escalator::GasEscalatorMiddleware) supports different escalation strategies (see [GasEscalator](crate::gas_escalator::GasEscalator)) and bump frequencies (see [Frequency](crate::gas_escalator::Frequency)). -- [`Gas Oracle`](./gas_oracle/struct.GasOracleMiddleware.html): Allows getting - your gas price estimates from places other than `eth_gasPrice`, including REST based gas stations (i.e. Etherscan, ETH Gas Station etc.). -- [`Transformer`](./transformer/trait.Transformer.html): Allows intercepting and - transforming a transaction to be broadcasted via a proxy wallet, e.g. - [`DSProxy`](./transformer/struct.DsProxy.html). +- [`Signer`](./signer/struct.SignerMiddleware.html): Signs transactions locally, with a private key or a hardware wallet. +- [`Nonce Manager`](./nonce_manager/struct.NonceManagerMiddleware.html): Manages nonces locally. Allows to sign multiple consecutive transactions without waiting for them to hit the mempool. +- [`Gas Escalator`](./gas_escalator/struct.GasEscalatorMiddleware.html): Bumps transactions gas price in the background to avoid getting them stuck in the memory pool. A [`GasEscalatorMiddleware`](crate::gas_escalator::GasEscalatorMiddleware) supports different escalation strategies (see [GasEscalator](crate::gas_escalator::GasEscalator)) and bump frequencies (see [Frequency](crate::gas_escalator::Frequency)). +- [`Gas Oracle`](./gas_oracle/struct.GasOracleMiddleware.html): Allows getting + your gas price estimates from places other than `eth_gasPrice`, including REST based gas stations (i.e. Etherscan, ETH Gas Station etc.). +- [`Transformer`](./transformer/trait.Transformer.html): Allows intercepting and + transforming a transaction to be broadcasted via a proxy wallet, e.g. + [`DSProxy`](./transformer/struct.DsProxy.html). -## Stacking middlewares using a builder +## Examples Each [`Middleware`](ethers_providers::Middleware) implements the trait [MiddlewareBuilder](crate::MiddlewareBuilder). This trait helps a developer to compose a custom [`Middleware`](ethers_providers::Middleware) stack. The following example shows how to build a composed [`Middleware`](ethers_providers::Middleware) starting from a [`Provider`](ethers_providers::Provider): ```rust -use ethers_providers::{Middleware, Provider, Http}; -use std::sync::Arc; -use std::convert::TryFrom; -use ethers_signers::{LocalWallet, Signer}; -use ethers_middleware::{gas_oracle::{GasOracle, GasNow}, MiddlewareBuilder}; - -fn builder_example() { - let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169"; - let signer = key.parse::().unwrap(); - let address = signer.address(); - let gas_oracle = GasNow::new(); - - let provider = Provider::::try_from("http://localhost:8545") - .unwrap() - .gas_oracle(gas_oracle) - .with_signer(signer) - .nonce_manager(address); // Outermost layer -} +# use ethers_providers::{Middleware, Provider, Http}; +# use ethers_signers::{LocalWallet, Signer}; +# use ethers_middleware::{gas_oracle::GasNow, MiddlewareBuilder}; +let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169"; +let signer = key.parse::()?; +let address = signer.address(); +let gas_oracle = GasNow::new(); + +let provider = Provider::::try_from("http://localhost:8545")? + .gas_oracle(gas_oracle) + .with_signer(signer) + .nonce_manager(address); // Outermost layer +# Ok::<_, Box>(()) ``` The [wrap_into](crate::MiddlewareBuilder::wrap_into) function can be used to wrap [`Middleware`](ethers_providers::Middleware) layers explicitly. This is useful when pushing [`Middleware`](ethers_providers::Middleware)s not directly handled by the builder interface. -```rust -use ethers_providers::{Middleware, Provider, Http}; -use std::sync::Arc; -use std::convert::TryFrom; -use ethers_signers::{LocalWallet, Signer}; -use ethers_middleware::{*,gas_escalator::*,gas_oracle::*}; - -fn builder_example_wrap_into() { - let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169"; - let signer = key.parse::().unwrap(); - let address = signer.address(); - let escalator = GeometricGasPrice::new(1.125, 60_u64, None::); - - let provider = Provider::::try_from("http://localhost:8545") - .unwrap() - .wrap_into(|p| GasEscalatorMiddleware::new(p, escalator, Frequency::PerBlock)) - .wrap_into(|p| SignerMiddleware::new(p, signer)) - .wrap_into(|p| GasOracleMiddleware::new(p, GasNow::new())) - .wrap_into(|p| NonceManagerMiddleware::new(p, address)); // Outermost layer -} +```rust,no_run +# use ethers_providers::{Middleware, Provider, Http}; +# use std::convert::TryFrom; +# use ethers_signers::{LocalWallet, Signer}; +# use ethers_middleware::{*,gas_escalator::*,gas_oracle::*}; +let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169"; +let signer = key.parse::()?; +let address = signer.address(); +let escalator = GeometricGasPrice::new(1.125, 60_u64, None::); + +let provider = Provider::::try_from("http://localhost:8545")? + .wrap_into(|p| GasEscalatorMiddleware::new(p, escalator, Frequency::PerBlock)) + .wrap_into(|p| SignerMiddleware::new(p, signer)) + .wrap_into(|p| GasOracleMiddleware::new(p, GasNow::new())) + .wrap_into(|p| NonceManagerMiddleware::new(p, address)); // Outermost layer +# Ok::<_, Box>(()) ``` - -## Stacking middlewares manually A [`Middleware`](ethers_providers::Middleware) stack can be also constructed manually. This is achieved by explicitly wrapping layers. -```rust no_run -use ethers_providers::{Provider, Http}; -use ethers_signers::{LocalWallet, Signer}; -use ethers_middleware::{ - gas_escalator::{GasEscalatorMiddleware, GeometricGasPrice, Frequency}, - gas_oracle::{GasOracleMiddleware, GasCategory, GasNow}, - signer::SignerMiddleware, - nonce_manager::NonceManagerMiddleware, -}; -use ethers_core::rand; -use std::convert::TryFrom; - +```rust,no_run +# use ethers_providers::{Provider, Http}; +# use ethers_signers::{LocalWallet, Signer}; +# use ethers_middleware::{ +# gas_escalator::{GasEscalatorMiddleware, GeometricGasPrice, Frequency}, +# gas_oracle::{GasOracleMiddleware, GasCategory, GasNow}, +# signer::SignerMiddleware, +# nonce_manager::NonceManagerMiddleware, +# }; // Start the stack -let provider = Provider::::try_from("http://localhost:8545").unwrap(); +let provider = Provider::::try_from("http://localhost:8545")?; // Escalate gas prices let escalator = GeometricGasPrice::new(1.125, 60u64, None::); let provider = GasEscalatorMiddleware::new(provider, escalator, Frequency::PerBlock); // Sign transactions with a private key -let signer = LocalWallet::new(&mut rand::thread_rng()); +let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169"; +let signer = key.parse::()?; let address = signer.address(); let provider = SignerMiddleware::new(provider, signer); @@ -97,6 +87,5 @@ let provider = GasOracleMiddleware::new(provider, gas_oracle); // Manage nonces locally let provider = NonceManagerMiddleware::new(provider, address); - -// ... do something with the provider +# Ok::<_, Box>(()) ``` diff --git a/ethers-middleware/src/lib.rs b/ethers-middleware/src/lib.rs index 8593a10be..88aa042fe 100644 --- a/ethers-middleware/src/lib.rs +++ b/ethers-middleware/src/lib.rs @@ -1,6 +1,5 @@ #![doc = include_str!("../README.md")] -#![deny(unsafe_code)] -#![deny(rustdoc::broken_intra_doc_links)] +#![deny(unsafe_code, rustdoc::broken_intra_doc_links)] /// The [Gas Escalator middleware](crate::gas_escalator::GasEscalatorMiddleware) /// is used to re-broadcast transactions with an increasing gas price to guarantee diff --git a/ethers-providers/README.md b/ethers-providers/README.md index 7e0a38fe1..820eeb830 100644 --- a/ethers-providers/README.md +++ b/ethers-providers/README.md @@ -1,24 +1,58 @@ -# Clients for interacting with Ethereum nodes +# ethers-providers + +Clients for interacting with Ethereum nodes. This crate provides asynchronous [Ethereum JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) compliant clients. -For more documentation on the available calls, refer to the -[`Provider`](./struct.Provider.html) struct. +For more information, please refer to the [book](https://gakonst.com/ethers-rs). + +## Websockets + +This crate supports for WebSockets via `tokio-tungstenite`. +Please ensure that you have the `ws` feature enabled if you wish to use WebSockets: + +```toml +[dependencies] +ethers-providers = { version = "1.0.2", features = ["ws"] } +``` + +## Interprocess Communication (IPC) + +This crate supports for Interprocess Communication via Unix sockets and Windows named pipes. +Please ensure that you have the `ipc` feature enabled if you wish to use IPC: + +```toml +[dependencies] +ethers-providers = { version = "1.0.2", features = ["ipc"] } +``` + +## Ethereum Name Service + +The provider may also be used to resolve [Ethereum Name Service](https://ens.domains) (ENS) names +to addresses (and vice versa). +The default ENS address is [`0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e`][ens] +and can be overriden with the [`ens`](./struct.Provider.html#method.ens) method on the provider. -# Examples +[ens]: https://etherscan.io/address/0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e -```no_run -use ethers_core::types::Address; -use ethers_providers::{Provider, Http, Middleware}; -use std::convert::TryFrom; +## Examples +```rust,no_run +# use ethers_core::types::Address; +# use ethers_providers::{Provider, Http, Middleware, Ws}; # async fn foo() -> Result<(), Box> { +// HTTP Provider let provider = Provider::::try_from( "https://mainnet.infura.io/v3/YOUR_API_KEY" )?; +// Websocket Provider +let provider = Provider::::connect( + "wss://mainnet.infura.io/v3/YOUR_API_KEY" +).await?; + let block = provider.get_block(100u64).await?; println!("Got block: {}", serde_json::to_string(&block)?); @@ -29,30 +63,10 @@ println!("Got code: {}", serde_json::to_string(&code)?); # } ``` -# Websockets - -The crate has support for WebSockets via Tokio. Please ensure that you have the "ws" and "rustls" / "openssl" features enabled if you wish to use WebSockets. - -``` -# async fn foo() -> Result<(), Box> { -# use ethers_providers::Ws; -let ws = Ws::connect("ws://localhost:8545").await?; -# Ok(()) -# } -``` - -# Ethereum Name Service - -The provider may also be used to resolve -[Ethereum Name Service](https://ens.domains) (ENS) names to addresses (and vice -versa). The default ENS address is -[mainnet](https://etherscan.io/address/0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e) -and can be overriden by calling the [`ens`](./struct.Provider.html#method.ens) -method on the provider. +Using ENS: -```no_run +```rust,no_run # use ethers_providers::{Provider, Http, Middleware}; -# use std::convert::TryFrom; # async fn foo() -> Result<(), Box> { # let provider = Provider::::try_from( # "https://mainnet.infura.io/v3/YOUR_API_KEY" diff --git a/ethers-providers/src/lib.rs b/ethers-providers/src/lib.rs index 50c64bd21..a49a78d65 100644 --- a/ethers-providers/src/lib.rs +++ b/ethers-providers/src/lib.rs @@ -1,9 +1,8 @@ +#![doc = include_str!("../README.md")] #![cfg_attr(docsrs, feature(doc_cfg))] -#![deny(unsafe_code)] -#![deny(rustdoc::broken_intra_doc_links)] #![allow(clippy::type_complexity)] -#![doc = include_str!("../README.md")] #![warn(missing_docs)] +#![deny(unsafe_code, rustdoc::broken_intra_doc_links)] mod ext; pub use ext::*; diff --git a/ethers-signers/README.md b/ethers-signers/README.md index 227d2cb47..a3c45cbdd 100644 --- a/ethers-signers/README.md +++ b/ethers-signers/README.md @@ -1,3 +1,7 @@ +# ethers-signers + +A unified interface for locally signing transactions. + You can implement the `Signer` trait to extend functionality to other signers such as Hardware Security Modules, KMS etc. @@ -13,10 +17,16 @@ Supported signers: - [YubiHSM2](./src/wallet/yubi.rs) - [AWS KMS](./src/aws) -```no_run +For more information, please refer to the [book](https://gakonst.com/ethers-rs). + +[`transaction`]: ethers_core::types::Transaction +[`transactionrequest`]: ethers_core::types::TransactionRequest + +## Examples + +```rust,no_run # use ethers_signers::{LocalWallet, Signer}; # use ethers_core::{k256::ecdsa::SigningKey, types::TransactionRequest}; - # async fn foo() -> Result<(), Box> { // instantiate the wallet let wallet = "dcf2cbdd171a21c480aa7f53d77f31bb102282b3ff099c78e3118b37348c72f7" @@ -37,5 +47,21 @@ signature.verify("hello world", wallet.address()).unwrap(); # } ``` -[`transaction`]: ethers_core::types::Transaction -[`transactionrequest`]: ethers_core::types::TransactionRequest +Sign an Ethereum prefixed message ([eip-712](https://eips.ethereum.org/EIPS/eip-712)): + +```rust,no_run +# use ethers_signers::{Signer, LocalWallet}; +# async fn foo() -> Result<(), Box> { +let message = "Some data"; +let wallet = LocalWallet::new(&mut rand::thread_rng()); + +// Sign the message +let signature = wallet.sign_message(message).await?; + +// Recover the signer from the message +let recovered = signature.recover(message)?; + +assert_eq!(recovered, wallet.address()); +# Ok(()) +# } +``` diff --git a/ethers-signers/src/lib.rs b/ethers-signers/src/lib.rs index 5287999f2..ed9594be5 100644 --- a/ethers-signers/src/lib.rs +++ b/ethers-signers/src/lib.rs @@ -1,6 +1,5 @@ -//! Provides a unified interface for locally signing transactions. -#![deny(unsafe_code)] -#![deny(rustdoc::broken_intra_doc_links)] +#![doc = include_str!("../README.md")] +#![deny(unsafe_code, rustdoc::broken_intra_doc_links)] mod wallet; pub use wallet::{MnemonicBuilder, Wallet, WalletError}; diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs index dfbcaec12..6390e80ed 100644 --- a/ethers-solc/src/lib.rs +++ b/ethers-solc/src/lib.rs @@ -1,3 +1,4 @@ +#![doc = include_str!("../README.md")] #![deny(rustdoc::broken_intra_doc_links)] pub mod artifacts; diff --git a/src/lib.rs b/src/lib.rs index 151575b43..5fd61c2b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,56 +1,50 @@ -#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub)] -#![deny(rustdoc::broken_intra_doc_links)] -#![doc(test( - no_crate_inject, - attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) -))] - -//! # Complete Ethereum & Celo library and wallet implementation. +//! # ethers-rs //! -//! > ethers-rs is a port of [ethers-js](https://github.com/ethers-io/ethers.js) in Rust. +//! A complete Ethereum and Celo Rust library. //! //! ## Quickstart: `prelude` //! //! A prelude is provided which imports all the important data types and traits for you. Use this //! when you want to quickly bootstrap a new project. //! -//! ```no_run -//! # #[allow(unused)] +//! ```rust //! use ethers::prelude::*; //! ``` //! -//! Examples on how you can use the types imported by the prelude can be found in -//! the [`examples` directory of the repository](https://github.com/gakonst/ethers-rs/tree/master/examples) +//! Examples on how you can use the types imported by the prelude can be found in the +//! [`examples` directory of the repository](https://github.com/gakonst/ethers-rs/tree/master/examples) //! and in the `tests/` directories of each crate. //! -//! # Quick explanation of each module in ascending order of abstraction +//! ## Modules +//! +//! The following paragraphs are a quick explanation of each module in ascending order of +//! abstraction. More details can be found in [the book](https://gakonst.com/ethers-rs). //! -//! ## `core` +//! ### `core` //! -//! Contains all the [necessary data structures](core::types) for interacting -//! with Ethereum, along with cryptographic utilities for signing and verifying -//! ECDSA signatures on `secp256k1`. Bindings to the Solidity compiler, Anvil and `ganache-cli` -//! are also provided as helpers. To simplify your imports, consider using the re-exported -//! modules described in the next subsection. +//! Contains all the [necessary data structures](core::types) for interacting with Ethereum, along +//! with cryptographic utilities for signing and verifying ECDSA signatures on `secp256k1`. Bindings +//! to the Solidity compiler, Anvil and Ganace are also provided as helpers. +//! To simplify your imports, consider using the re-exported modules described in the next +//! subsection. //! -//! ## `utils`, `types`, `abi` +//! ### `utils`, `types`, `abi` //! -//! These are re-exports of the [`utils`], [`types`] and [`abi`] modules from the `core` crate +//! These are re-exports of the [`utils`], [`types`] and [`abi`] modules from the [`core`] crate. //! -//! ## `providers` +//! ### `providers` //! -//! Ethereum nodes expose RPC endpoints (by default at `localhost:8545`). You can connect -//! to them by using the [`Provider`]. The provider instance -//! allows you to issue requests to the node which involve querying the state of Ethereum or -//! broadcasting transactions with unlocked accounts on the node. +//! Contains the [`Provider`] struct, an abstraction of a connection to the Ethereum network, which +//! alongside the [`Middleware`] trait provides a concise, consistent interface to standard Ethereum +//! node functionality, //! -//! ## `signers` +//! ### `signers` //! -//! This module provides a [`Signer`] trait which can be used for signing messages -//! or transactions. A [`Wallet`] type is implemented which can be used with a -//! raw private key, or a YubiHSM2. We also provide Ledger support. +//! Provides a [`Signer`] trait which can be used for signing messages or transactions. A [`Wallet`] +//! type is implemented which can be used with a raw private key or a YubiHSM2. Ledger and Trezor +//! support are also provided. //! -//! ## `contract` +//! ### `contract` //! //! Interacting with Ethereum is not restricted to sending or receiving funds. It also involves //! using smart contracts, which can be thought of as programs with persistent storage. @@ -61,9 +55,10 @@ //! selector](https://ethereum.stackexchange.com/questions/72363/what-is-a-function-selector) //! along with the arguments of the called function. This module provides the //! [`Contract`] and [`ContractFactory`] abstractions so that you do not have to worry about that. -//! It also provides typesafe bindings via the [`abigen`] macro and the [`Abigen` builder]. //! -//! ## `middleware` +//! It also provides typesafe bindings via the [`abigen`] macro and the [`Abigen`] builder. +//! +//! ### `middleware` //! //! In order to keep the ethers architecture as modular as possible, providers define a //! [`Middleware`] trait which defines all the methods to interact with an Ethereum node. By @@ -78,56 +73,38 @@ //! [`Signer`]: signers::Signer //! [`ContractFactory`]: contract::ContractFactory //! [`Contract`]: contract::Contract -//! [`abigen`]: ./contract/macro.abigen.html -//! [`Abigen` builder]: contract::Abigen +//! [`abigen`]: contract::abigen +//! [`Abigen`]: contract::Abigen //! [`utils`]: core::utils //! [`abi`]: core::abi //! [`types`]: core::types -/// Address book consisting of frequently used contracts -pub mod addressbook { - pub use ethers_addressbook::*; -} - -#[doc = include_str!("../assets/CONTRACT_README.md")] -pub mod contract { - pub use ethers_contract::*; -} - -#[doc = include_str!("../assets/CORE_README.md")] -pub mod core { - pub use ethers_core::*; -} - -#[doc = include_str!("../assets/PROVIDERS_README.md")] -pub mod providers { - pub use ethers_providers::*; -} - -#[doc = include_str!("../assets/MIDDLEWARE_README.md")] -pub mod middleware { - pub use ethers_middleware::*; -} - -#[doc = include_str!("../assets/SIGNERS_README.md")] -pub mod signers { - pub use ethers_signers::*; -} - +#![warn(missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub)] +#![deny(rustdoc::broken_intra_doc_links)] +#![doc(test(no_crate_inject, attr(deny(rust_2018_idioms), allow(dead_code, unused_variables))))] + +#[doc(inline)] +pub use ethers_addressbook as addressbook; +#[doc(inline)] +pub use ethers_contract as contract; +#[doc(inline)] +pub use ethers_core as core; +#[doc(inline)] +pub use ethers_etherscan as etherscan; +#[doc(inline)] +pub use ethers_middleware as middleware; +#[doc(inline)] +pub use ethers_providers as providers; +#[doc(inline)] +pub use ethers_signers as signers; +#[doc(inline)] #[cfg(feature = "ethers-solc")] -#[doc = include_str!("../assets/SOLC_README.md")] -pub mod solc { - pub use ethers_solc::*; -} +pub use ethers_solc as solc; -/// Etherscan bindings -pub mod etherscan { - pub use ethers_etherscan::*; -} - -pub use crate::core::{abi, types, utils}; +#[doc(inline)] +pub use ethers_core::{abi, types, utils}; -/// Easy imports of frequently used type definitions and traits +/// Easy imports of frequently used type definitions and traits. #[doc(hidden)] pub mod prelude { pub use super::addressbook::*; @@ -136,6 +113,8 @@ pub mod prelude { pub use super::core::{types::*, *}; + pub use super::etherscan::*; + pub use super::middleware::*; pub use super::providers::*; @@ -144,6 +123,4 @@ pub mod prelude { #[cfg(feature = "ethers-solc")] pub use super::solc::*; - - pub use super::etherscan::*; }