docs: fix broken links, update documentation (#2203)
* docs: fix broken links * docs: update READMEs and module-level documentation
This commit is contained in:
parent
620300f357
commit
203e350940
|
@ -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
|
||||
|
||||
|
|
|
@ -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 = [
|
||||
|
|
104
README.md
104
README.md
|
@ -1,6 +1,6 @@
|
|||
# <h1 align="center"> ethers.rs </h1>
|
||||
# <h1 align="center"> ethers-rs </h1>
|
||||
|
||||
**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
|
||||
|
||||
## Quickstart
|
||||
|
||||
Add this to your Cargo.toml:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
ethers = "1.0.2"
|
||||
```
|
||||
|
||||
And this to your code:
|
||||
|
||||
```rust
|
||||
use ethers::prelude::*;
|
||||
```
|
||||
|
||||
## 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`
|
||||
View the API reference [here](https://docs.rs/ethers) or the online book [here](https://gakonst.com/ethers-rs).
|
||||
|
||||
Examples are organized into individual crates under the `/examples` folder.
|
||||
You can run any of the examples by executing:
|
||||
You can run any of the examples by executing:
|
||||
|
||||
```bash
|
||||
# cargo run -p <example-crate-name> --example <name>
|
||||
cargo run -p examples-big-numbers --example math_operations
|
||||
```
|
||||
|
||||
## Add ethers-rs to your repository
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
|
||||
ethers = "1.0.0"
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Running the tests
|
||||
|
||||
Tests require the following installed:
|
||||
|
||||
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)
|
||||
|
||||
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).
|
||||
|
||||
### 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.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../ethers-contract/README.md
|
|
@ -1 +0,0 @@
|
|||
../ethers-core/README.md
|
|
@ -1 +0,0 @@
|
|||
../ethers-middleware/README.md
|
|
@ -1 +0,0 @@
|
|||
../ethers-providers/README.md
|
|
@ -1 +0,0 @@
|
|||
../ethers-signers/README.md
|
|
@ -1 +0,0 @@
|
|||
../ethers-solc/README.md
|
|
@ -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" }
|
||||
|
|
|
@ -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());
|
||||
```
|
|
@ -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<HashMap<String, Contract>> =
|
||||
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<Chain, Address>,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<BTreeMap<String, MethodAlias>> {
|
||||
let mut aliases = self.method_aliases.clone();
|
||||
|
||||
|
|
|
@ -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 <explorer>:<address> or <explorer_url>/.../<address>
|
||||
/// The URL can be either `<explorer>:<address>` or `<explorer_url>/.../<address>`
|
||||
fn from_explorer(s: &str, url: &Url) -> Result<Self> {
|
||||
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}"))?;
|
||||
|
|
|
@ -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
|
||||
For more information, please refer to the [book](https://gakonst.com/ethers-rs).
|
||||
|
||||
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.
|
||||
## Feature flags
|
||||
|
||||
```rust,ignore
|
||||
# async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
use ethers::signers::{Signer, LocalWallet};
|
||||
- `eip712`: Provides the `Eip712` trait and derive procedural macro for EIP-712 encoding of typed data.
|
||||
|
||||
let message = "Some data";
|
||||
let wallet = LocalWallet::new(&mut rand::thread_rng());
|
||||
## ABI
|
||||
|
||||
// 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(())
|
||||
# }
|
||||
```
|
||||
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<dyn std::error::Error>>(())
|
||||
```
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Ethereum data types.
|
||||
|
||||
pub type Selector = [u8; 4];
|
||||
|
||||
// Re-export common ethereum datatypes with more specific names
|
||||
|
|
|
@ -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<dyn std::error::Error>> {
|
||||
let client = Client::new(Chain::Mainnet, "<your_api_key>")?;
|
||||
// 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(())
|
||||
# }
|
||||
```
|
|
@ -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<dyn std::error::Error>> {
|
||||
/// let client = Client::new(Chain::Mainnet, "<your_api_key>")?;
|
||||
/// 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<ContractMetadata> {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
# 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::<LocalWallet>()?;
|
||||
let address = signer.address();
|
||||
let gas_oracle = GasNow::new();
|
||||
|
||||
fn builder_example() {
|
||||
let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169";
|
||||
let signer = key.parse::<LocalWallet>().unwrap();
|
||||
let address = signer.address();
|
||||
let gas_oracle = GasNow::new();
|
||||
|
||||
let provider = Provider::<Http>::try_from("http://localhost:8545")
|
||||
.unwrap()
|
||||
.gas_oracle(gas_oracle)
|
||||
.with_signer(signer)
|
||||
.nonce_manager(address); // Outermost layer
|
||||
}
|
||||
let provider = Provider::<Http>::try_from("http://localhost:8545")?
|
||||
.gas_oracle(gas_oracle)
|
||||
.with_signer(signer)
|
||||
.nonce_manager(address); // Outermost layer
|
||||
# Ok::<_, Box<dyn std::error::Error>>(())
|
||||
```
|
||||
|
||||
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::*};
|
||||
```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::<LocalWallet>()?;
|
||||
let address = signer.address();
|
||||
let escalator = GeometricGasPrice::new(1.125, 60_u64, None::<u64>);
|
||||
|
||||
fn builder_example_wrap_into() {
|
||||
let key = "fdb33e2105f08abe41a8ee3b758726a31abdd57b7a443f470f23efce853af169";
|
||||
let signer = key.parse::<LocalWallet>().unwrap();
|
||||
let address = signer.address();
|
||||
let escalator = GeometricGasPrice::new(1.125, 60_u64, None::<u64>);
|
||||
|
||||
let provider = Provider::<Http>::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
|
||||
}
|
||||
let provider = Provider::<Http>::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<dyn std::error::Error>>(())
|
||||
```
|
||||
|
||||
|
||||
## 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::<Http>::try_from("http://localhost:8545").unwrap();
|
||||
let provider = Provider::<Http>::try_from("http://localhost:8545")?;
|
||||
|
||||
// Escalate gas prices
|
||||
let escalator = GeometricGasPrice::new(1.125, 60u64, None::<u64>);
|
||||
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::<LocalWallet>()?;
|
||||
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<dyn std::error::Error>>(())
|
||||
```
|
||||
|
|
|
@ -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 <https://en.wikipedia.org/wiki/Percentile#The_weighted_percentile_method>
|
||||
/// See: <https://en.wikipedia.org/wiki/Percentile#The_weighted_percentile_method>
|
||||
///
|
||||
/// # 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)],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
||||
# Examples
|
||||
## Websockets
|
||||
|
||||
```no_run
|
||||
use ethers_core::types::Address;
|
||||
use ethers_providers::{Provider, Http, Middleware};
|
||||
use std::convert::TryFrom;
|
||||
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.
|
||||
|
||||
[ens]: https://etherscan.io/address/0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
|
||||
|
||||
## Examples
|
||||
|
||||
```rust,no_run
|
||||
# use ethers_core::types::Address;
|
||||
# use ethers_providers::{Provider, Http, Middleware, Ws};
|
||||
# async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// HTTP Provider
|
||||
let provider = Provider::<Http>::try_from(
|
||||
"https://mainnet.infura.io/v3/YOUR_API_KEY"
|
||||
)?;
|
||||
|
||||
// Websocket Provider
|
||||
let provider = Provider::<Ws>::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
|
||||
Using ENS:
|
||||
|
||||
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<dyn std::error::Error>> {
|
||||
# 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.
|
||||
|
||||
```no_run
|
||||
```rust,no_run
|
||||
# use ethers_providers::{Provider, Http, Middleware};
|
||||
# use std::convert::TryFrom;
|
||||
# async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
# let provider = Provider::<Http>::try_from(
|
||||
# "https://mainnet.infura.io/v3/YOUR_API_KEY"
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unsafe_code, rustdoc::broken_intra_doc_links)]
|
||||
|
||||
mod ext;
|
||||
pub use ext::*;
|
||||
|
|
|
@ -24,9 +24,10 @@ pub struct JsonRpcError {
|
|||
pub data: Option<Value>,
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// <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<Bytes> {
|
||||
match value {
|
||||
Value::String(s) => s.parse().ok(),
|
||||
|
|
|
@ -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<dyn std::error::Error>> {
|
||||
// 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<dyn std::error::Error>> {
|
||||
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(())
|
||||
# }
|
||||
```
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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<Artifact: DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<BTreeMap<String, Vec<ArtifactFile<Artifact>>>> {
|
||||
|
@ -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<T::Artifact>,
|
||||
/// relationship between all the files
|
||||
|
||||
/// Relationship between all the files.
|
||||
pub edges: GraphEdges,
|
||||
/// the project
|
||||
|
||||
/// The project.
|
||||
pub project: &'a Project<T>,
|
||||
/// all files that were filtered because they haven't changed
|
||||
|
||||
/// All the files that were filtered because they haven't changed.
|
||||
pub filtered: HashMap<PathBuf, (Source, HashSet<Version>)>,
|
||||
/// 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<PathBuf, (CacheEntry, HashSet<Version>)>,
|
||||
/// the file hashes
|
||||
|
||||
/// The file hashes.
|
||||
pub content_hashes: HashMap<PathBuf, String>,
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
///
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![allow(rustdoc::private_intra_doc_links)]
|
||||
|
||||
pub mod artifacts;
|
||||
pub mod sourcemap;
|
||||
|
@ -24,7 +24,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 +280,7 @@ impl<T: ArtifactOutput> Project<T> {
|
|||
///
|
||||
/// 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
|
||||
///
|
||||
|
|
|
@ -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<Path>) -> HashSet<&PathBuf> {
|
||||
let mut link_references = HashSet::new();
|
||||
for import in self.all_imported_nodes(self.node_id(file)) {
|
||||
|
|
133
src/lib.rs
133
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
|
||||
//!
|
||||
//! ## `core`
|
||||
//! 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).
|
||||
//!
|
||||
//! 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.
|
||||
//! ### `core`
|
||||
//!
|
||||
//! ## `utils`, `types`, `abi`
|
||||
//! 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.
|
||||
//!
|
||||
//! These are re-exports of the [`utils`], [`types`] and [`abi`] modules from the `core` crate
|
||||
//! ### `utils`, `types`, `abi`
|
||||
//!
|
||||
//! ## `providers`
|
||||
//! These are re-exports of the [`utils`], [`types`] and [`abi`] modules from the [`core`] crate.
|
||||
//!
|
||||
//! 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.
|
||||
//! ### `providers`
|
||||
//!
|
||||
//! ## `signers`
|
||||
//! 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,
|
||||
//!
|
||||
//! 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.
|
||||
//! ### `signers`
|
||||
//!
|
||||
//! ## `contract`
|
||||
//! 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`
|
||||
//!
|
||||
//! 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::*;
|
||||
}
|
||||
#[doc(inline)]
|
||||
pub use ethers_core::{abi, types, utils};
|
||||
|
||||
pub use crate::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::*;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue