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

docs: update providers book and examples #2098

Merged
merged 10 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

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

21 changes: 21 additions & 0 deletions book/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The ethers-rs book

Everything about `ethers-rs`. Work-in-progress. View online here: <https://www.gakonst.com/ethers-rs>

## Contributing

The book is built with [mdbook](https://github.com/rust-lang/mdBook), which you can install by running `cargo install mdbook`.

To view changes live, run:

```sh
mdbook serve
```

Or with docker:

```sh
docker run -p 3000:3000 -v `pwd`:/book peaceiris/mdbook serve
```

To add a new section (file) to the book, add it to [`SUMMARY.md`](./SUMMARY.md).
3 changes: 1 addition & 2 deletions book/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- [Quorum](./providers/quorum.md)
- [Retry](./providers/retry.md)
- [RW](./providers/rw.md)
- [WebSocket](./providers/ws.md)
- [Custom](./providers/custom.md)
- [Advanced Usage](./providers/advanced_usage.md)
- [Middleware](./middleware/middleware.md)
- [Builder](./middleware/builder.md)
Expand Down Expand Up @@ -88,4 +88,3 @@
- [Deploy contracts]()
- [Fork]()
- [Testing]()

12 changes: 7 additions & 5 deletions book/getting-started/connect_to_an_ethereum_node.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Connect to an Ethereum node

Ethers-rs allows application to connect the blockchain using web3 providers. Providers act as an interface between applications and an Ethereum node, allowing you to send requests and receive responses via JSON-RPC messages.

Some common actions you can perform using a provider include:
Expand All @@ -13,11 +14,12 @@ Some common actions you can perform using a provider include:
Providers are an important part of web3 libraries because they allow you to easily interact with the Ethereum blockchain without having to manage the underlying connection to the node yourself.

Code below shows a basic setup to connect a provider to a node:

```rust
/// The `prelude` module provides a convenient way to import a number
/// of common dependencies at once. This can be useful if you are working
/// with multiple parts of the library and want to avoid having
/// to import each dependency individually.
// The `prelude` module provides a convenient way to import a number
// of common dependencies at once. This can be useful if you are working
// with multiple parts of the library and want to avoid having
// to import each dependency individually.
use ethers::prelude::*;

const RPC_URL: &str = "https://mainnet.infura.io/v3/your-project-id";
Expand All @@ -30,4 +32,4 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

Ok(())
}
```
```
10 changes: 6 additions & 4 deletions book/getting-started/intro.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
# Intro

Welcome to the hands-on guide for the ethers-rs library!

This documentation contains a collection of examples demonstrating how to use the library to build Ethereum-based applications in Rust. The examples cover a range of topics, from basic smart contract interactions to more advanced usage of ethers-rs.

```admonish info
```admonish info
You can find the official ethers-rs documentation on docs.rs - [here](https://docs.rs/ethers/0.5.0/ethers/).
```

Each example includes a detailed description of the functionality being demonstrated, as well as complete code snippets that you can use as a starting point for your own projects.

We hope that these docs will help you get started with ethers-rs and give you a better understanding of how to use the library to build your own web3 applications in Rust. If you have any questions or need further assistance, please don't hesitate to reach out to the ethers-rs community.

The following is a brief overview diagram of the topis covered in this guide.
The following is a brief overview diagram of the topics covered in this guide.

```mermaid
{{#include ../mermaid-style.txt}}

graph LR
graph LR
A[Ethers-rs <br> Manual] --> A1[Providers]
A --> A2[Middleware]
A --> A3[Contracts]
Expand All @@ -28,6 +29,7 @@ graph LR
A --> A9[Big numbers]
A --> A10[Anvil]
```
```admonish bug

```admonish bug
This diagram is incomplete and will undergo continuous changes.
```
49 changes: 27 additions & 22 deletions book/getting-started/start_a_new_project.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
# Start a new project
To set up a new project with ethers-rs, you will need to install the Rust programming language and the cargo package manager on your system.

To set up a new project with ethers-rs, you will need to install the Rust programming language toolchain and the Cargo package manager on your system.

1. Install Rust by following the instructions at [https://www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install).
2. Once Rust is installed, create a new Rust project by running the following command:

```bash
cargo new my-project
```
This will create a new directory called my-project with the necessary files for a new Rust project.

This will create a new directory called my-project with the necessary files for a new Rust project.

3. Navigate to the project directory and add ethers-rs as a dependency in your `Cargo.toml` file:
```toml
[dependencies]
ethers = "1.0.0"

# Most of ethers-rs features rely upon an async Rust runtime.
# Since Rust doesn't provide an async runtime itself, you can
# include the excellent tokio library
tokio = { version = "1.23.0", features = ["macros"] }
```
```toml
[dependencies]
ethers = "1.0.0"

# Most of ethers-rs features rely upon an async Rust runtime.
# Since Rust doesn't provide an async runtime itself, you can
# include the excellent tokio library
tokio = { version = "1.23.0", features = ["macros"] }
```

If you want to make experiments and/or play around with early ethers-rs features link our GitHub repo in the `Cargo.toml`.
If you want to make experiments and/or play around with early ethers-rs features link our GitHub repo in the `Cargo.toml`.

```toml
[dependencies]
Expand All @@ -33,33 +37,34 @@ To set up a new project with ethers-rs, you will need to install the Rust progra
[dependencies]
ethers = { git = "https://github.com/gakonst/ethers-rs", rev = "1.0.2" }
```
> **Note:** using a Git repository as a dependency is generally not recommended
> for production projects, as it can make it difficult to ensure that you are using
> a specific and stable version of the dependency.
> It is usually better to specify a version number or range to ensure that your project
> is reproducible.

> **Note:** using a Git repository as a dependency is generally not recommended
> for production projects, as it can make it difficult to ensure that you are using
> a specific and stable version of the dependency.
> It is usually better to specify a version number or range to ensure that your project
> is reproducible.

## Enable transports

Ethers-rs enables interactions with Ethereum nodes through different "transport" types, or communication protocols.
The following transport types are currently supported by ethers.rs:

* **HTTP(S):** The HTTP(S) transport is used to communicate with Ethereum nodes over the HTTP or HTTPS protocols. This is the most common way to interact with Ethereum nodes. If you are looking to connect to a HTTPS endpoint, then you need to enable the `rustls` or `openssl` features:
- **HTTP(S):** The HTTP(S) transport is used to communicate with Ethereum nodes over the HTTP or HTTPS protocols. This is the most common way to interact with Ethereum nodes. If you are looking to connect to a HTTPS endpoint, then you need to enable the `rustls` or `openssl` features:

```toml
[dependencies]
ethers = { version = "1.0.0", features = ["rustls"] }
```

* **WebSocket:** The WebSocket transport is used to communicate with Ethereum nodes over the WebSocket protocol, which is a widely-supported standard for establishing a bi-directional communication channel between a client and a server. This can be used for a variety of purposes, including receiving real-time updates from an Ethereum node, or submitting transactions to the Ethereum network. Websockets support is turned on via the feature-flag ws:
- **WebSocket:** The WebSocket transport is used to communicate with Ethereum nodes over the WebSocket protocol, which is a widely-supported standard for establishing a bi-directional communication channel between a client and a server. This can be used for a variety of purposes, including receiving real-time updates from an Ethereum node, or submitting transactions to the Ethereum network. Websockets support is turned on via the feature-flag ws:

```toml
[dependencies]
ethers = { version = "1.0.0", features = ["ws"] }
```

* **IPC (Interprocess Communication):** The IPC transport is used to communicate with a local Ethereum node using the IPC protocol, which is a way for processes to communicate with each other on a single computer. This is commonly used in Ethereum development to allow applications to communicate with a local Ethereum node, such as geth or parity. IPC support is turned on via the feature-flag `ipc`:
- **IPC (Interprocess Communication):** The IPC transport is used to communicate with a local Ethereum node using the IPC protocol, which is a way for processes to communicate with each other on a single computer. This is commonly used in Ethereum development to allow applications to communicate with a local Ethereum node, such as geth or parity. IPC support is turned on via the feature-flag `ipc`:
```toml
[dependencies]
ethers = { version = "1.0.0", features = ["ipc"] }
```



6 changes: 2 additions & 4 deletions book/providers/advanced_usage.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Advanced Usage


## `CallBuilder`

The `CallBuilder` is an enum to help create complex calls. `CallBuilder` implements `[RawCall](https://docs.rs/ethers/latest/ethers/providers/call_raw/trait.RawCall.html)` methods for overriding parameters to the `eth_call`rpc method.
The `CallBuilder` is an enum to help create complex calls. `CallBuilder` implements [`RawCall`](https://docs.rs/ethers/latest/ethers/providers/call_raw/trait.RawCall.html) methods for overriding parameters to the `eth_call` rpc method.

Lets take a quick look at how to use the `CallBuilder`.

Expand Down Expand Up @@ -73,7 +72,6 @@ async fn main() -> eyre::Result<()> {

Let's look at how to use the state override set. In short, the state override set is an optional address-to-state mapping, where each entry specifies some state to be ephemerally overridden prior to executing the call. The state override set allows you to override an account's balance, an account's nonce, the code at a given address, the entire state of an account's storage or an individual slot in an account's storage. Note that the state override set is not a default feature and is not available on every node.


```rust
use ethers::{
providers::{
Expand Down Expand Up @@ -113,4 +111,4 @@ async fn main() -> eyre::Result<()> {
}
```

In this example, the account balance and nonce for the `from_adr` is overridden. The state override set is a very powerful tool that you can use to simulate complicated transactions without undergoing any actual state changes.
In this example, the account balance and nonce for the `from_adr` is overridden. The state override set is a very powerful tool that you can use to simulate complicated transactions without undergoing any actual state changes.
9 changes: 9 additions & 0 deletions book/providers/custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Custom data transport

As [we've previously seen](./providers.md#data-transports), a transport must implement [`JsonRpcClient`](https://docs.rs/ethers/latest/ethers/providers/trait.JsonRpcClient.html), and can also optionally implement [`PubsubClient`](https://docs.rs/ethers/latest/ethers/providers/trait.PubsubClient.html).

Let's see how we can create a custom data transport by implementing one that stores either a `Ws` or an `Ipc` transport:

```rust
{{#include ../../examples/providers/examples/custom.rs}}
```
27 changes: 15 additions & 12 deletions book/providers/http.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Http

The `Http` provider establishes an Http connection with a node, allowing you to send RPC requests to the node to fetch data, simulate calls, send transactions and much more.
The `Http` provider establishes an HTTP connection with a node, allowing you to send RPC requests to the node to fetch data, simulate calls, send transactions and much more.

## Initializing an Http Provider
Lets take a quick look at few ways to create a new `Http` provider. Since the `Http` provider implements the [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) one of the easiest ways to initialize a new provider is by using the `from_str()` method.

Lets take a quick look at few ways to create a new `Http` provider. One of the easiest ways to initialize a new `Provider<Http>` is by using the [`TryFrom`](https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html) trait's `try_from` method.

```rust
use ethers::providers::{Http, Middleware, Provider};
Expand All @@ -21,18 +22,20 @@ async fn main() -> eyre::Result<()> {
The `Http` provider also supplies a way to initialize a new authorized connection.

```rust
// Initializes a new HTTP Client with authentication
use ethers::providers::{Authorization, Http};
use url::Url;

#[tokio::main]
async fn main() -> eyre::Result<()> {
// Initialize a new HTTP Client with authentication
let url = Url::parse("http://localhost:8545")?;
let provider = Http::new_with_auth(url, Authorization::basic("admin", "good_password"));

Ok(())
}
```

Additionally, you can initialize a new provider with your own custom `reqwest::Client`.
Additionally, you can initialize a new provider with your own custom `reqwest::Client`.

```rust
use ethers::providers::Http;
Expand All @@ -43,6 +46,7 @@ async fn main() -> eyre::Result<()> {
let url = Url::parse("http://localhost:8545")?;
let client = reqwest::Client::builder().build()?;
let provider = Http::new_with_client(url, client);

Ok(())
}
```
Expand All @@ -67,16 +71,15 @@ async fn main() -> eyre::Result<()> {
}
```

You can also use the provider to interact with smart contracts. The snippet below uses the provider to establish a new instance of a UniswapV2Pool and uses the `get_reserves()` method from the smart contract to fetch the current state of the pool's reserves.
You can also use the provider to interact with smart contracts. The snippet below uses the provider to establish a new instance of a UniswapV2Pool and uses the `get_reserves()` method from the smart contract to fetch the current state of the pool's reserves.

```rust
use std::{str::FromStr, sync::Arc};

use ethers::{
prelude::abigen,
providers::{Http, Provider},
types::H160,
types::Address,
};
use std::sync::Arc;

abigen!(
IUniswapV2Pair,
Expand All @@ -89,7 +92,7 @@ async fn main() -> eyre::Result<()> {
let provider = Arc::new(Provider::try_from(rpc_url)?);

// Initialize a new instance of the Weth/Dai Uniswap V2 pair contract
let pair_address = H160::from_str("0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11")?;
let pair_address: Address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11".parse()?;
let uniswap_v2_pair = IUniswapV2Pair::new(pair_address, provider);

// Use the get_reserves() function to fetch the pool reserves
Expand All @@ -100,9 +103,9 @@ async fn main() -> eyre::Result<()> {
}
```

This example is a little more complicated, so lets walk through what is going on. The `IUniswapV2Pair` is a struct that is generated from the `abigen!()` macro. The `IUniswapV2Pair::new()` function is used to create a new instance of the contract, taking in an `Address` and an `Arc<M>` as arguments, where `M` is any type that implements the `Middleware` trait. Note that the provider is wrapped in an [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) when being passed into the `new()` function.
This example is a little more complicated, so let's walk through what is going on. The `IUniswapV2Pair` is a struct that is generated from the `abigen!()` macro. The `IUniswapV2Pair::new()` function is used to create a new instance of the contract, taking in an `Address` and an `Arc<M>` as arguments, where `M` is any type that implements the `Middleware` trait. Note that the provider is wrapped in an [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) when being passed into the `new()` function.

It is very common to wrap a provider in an `Arc` to share the provider across threads. Lets look at another example where the provider is used asynchronously across two tokio threads. In the next example, a new provider is initialized and used to asynchronously fetch the number of Ommer blocks from the most recent block, as well as the previous block.
It is very common to wrap a provider in an `Arc` to share the provider across threads. Let's look at another example where the provider is used asynchronously across two tokio threads. In the next example, a new provider is initialized and used to asynchronously fetch the number of Ommer blocks from the most recent block, as well as the previous block.

```rust
use std::sync::Arc;
Expand Down Expand Up @@ -138,4 +141,4 @@ async fn main() -> eyre::Result<()> {

<br>

Before heading to the next chapter, feel free to check out the docs for the [`Http` provider](https://docs.rs/ethers/latest/ethers/providers/struct.Http.html). Keep in mind that we will cover advanced usage of providers at the end of this chapter. Now that we have the basics covered, lets move on to the next Provider, Websockets!
Before heading to the next chapter, feel free to check out the docs for the [`Http` provider](https://docs.rs/ethers/latest/ethers/providers/struct.Http.html). Keep in mind that we will cover advanced usage of providers at the end of this chapter. Now that we have the basics covered, let's move on to the next provider, Websockets!
Loading