ci: mdbook (#2003)
* Applied same book structure as Reth * ci: [WIP] added book workflow * fix warning mdbook version different from template plugin version * ci: added deploy step * Http provider docs * IPC provider docs * RetryClient docs * WebSocket provider docs Co-authored-by: Andrea Simeoni <>
This commit is contained in:
parent
4fd742f8ce
commit
da0363918b
|
@ -0,0 +1,61 @@
|
|||
name: book
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'book/**'
|
||||
- 'book.toml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'book/**'
|
||||
- 'book.toml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install mdbook
|
||||
run: |
|
||||
mkdir mdbook
|
||||
curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.21/mdbook-v0.4.21-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
|
||||
echo `pwd`/mdbook >> $GITHUB_PATH
|
||||
|
||||
- name: Install mdbook-template
|
||||
run: |
|
||||
mkdir mdbook-template
|
||||
curl -sSL https://github.com/sgoudham/mdbook-template/releases/latest/download/mdbook-template-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook-template
|
||||
echo `pwd`/mdbook-template >> $GITHUB_PATH
|
||||
|
||||
- name: Build
|
||||
run: mdbook build
|
||||
|
||||
- name: Save pages artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: target/book
|
||||
|
||||
deploy:
|
||||
# Only deploy if a push to master
|
||||
if: github.ref_name == 'master' && github.event_name == 'push'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
|
||||
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
# reference: https://github.com/actions/deploy-pages
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
|
@ -1684,6 +1684,7 @@ version = "1.0.2"
|
|||
dependencies = [
|
||||
"ethers",
|
||||
"eyre",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
[book]
|
||||
authors = ["The ethers-rs contributors"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "book"
|
||||
title = "Ethers.rs: The Ethereum Library for Rust"
|
||||
description = "A book on all things ethers-rs"
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/gakonst/ethers-rs"
|
||||
default-theme = "ayu"
|
||||
no-section-label = true
|
||||
|
||||
[output.html.fold]
|
||||
enable = true
|
||||
level = 1
|
||||
|
||||
[build]
|
||||
build-dir = "target/book"
|
||||
|
||||
[preprocessor.template]
|
||||
before = [ "links" ]
|
||||
|
||||
[preprocessor.index]
|
||||
|
||||
[preprocessor.links]
|
||||
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
# Reference guide
|
||||
- [Providers]()
|
||||
- [Http]()
|
||||
- [IPC]()
|
||||
- [Http](./providers/http.md)
|
||||
- [IPC](./providers/ipc.md)
|
||||
- [Mock]()
|
||||
- [Quorum]()
|
||||
- [Retry]()
|
||||
- [Retry](./providers/retry.md)
|
||||
- [RW]()
|
||||
- [WS]()
|
||||
- [WebSocket](./providers/ws.md)
|
||||
- [Middleware]()
|
||||
- [Builder]()
|
||||
- [Create custom middleware]()
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
# Comparison and equivalence
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/big-numbers/examples/comparison_equivalence.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Conversion
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/big-numbers/examples/conversion.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Creating instances
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/big-numbers/examples/create_instances.rs}}
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
{{#include ../../examples/big-numbers/README.md}}
|
|
@ -0,0 +1,5 @@
|
|||
# Math operations
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/big-numbers/examples/math_operations.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Utilities
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/big-numbers/examples/utilities.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Http provider
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/providers/examples/http.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# IPC provider
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/providers/examples/ipc.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# Retry client
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/providers/examples/retry.rs}}
|
||||
```
|
|
@ -0,0 +1,5 @@
|
|||
# WebSocket provider
|
||||
|
||||
```rust
|
||||
{{#include ../../examples/providers/examples/ws.rs}}
|
||||
```
|
|
@ -1 +0,0 @@
|
|||
book
|
|
@ -1,6 +0,0 @@
|
|||
[book]
|
||||
authors = ["The ethers-rs contributors"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "Ethers.rs: The Ethereum Library for Rust"
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
# Comparison and equivalence
|
||||
|
||||
```rust
|
||||
{{#include ../../../../examples/big-numbers/examples/comparison_equivalence.rs}}
|
||||
```
|
|
@ -1,5 +0,0 @@
|
|||
# Conversion
|
||||
|
||||
```rust
|
||||
{{#include ../../../../examples/big-numbers/examples/conversion.rs}}
|
||||
```
|
|
@ -1,5 +0,0 @@
|
|||
# Creating instances
|
||||
|
||||
```rust
|
||||
{{#include ../../../../examples/big-numbers/examples/create_instances.rs}}
|
||||
```
|
|
@ -1 +0,0 @@
|
|||
{{#include ../../../../examples/big-numbers/README.md}}
|
|
@ -1,5 +0,0 @@
|
|||
# Math operations
|
||||
|
||||
```rust
|
||||
{{#include ../../../../examples/big-numbers/examples/math_operations.rs}}
|
||||
```
|
|
@ -1,5 +0,0 @@
|
|||
# Utilities
|
||||
|
||||
```rust
|
||||
{{#include ../../../../examples/big-numbers/examples/utilities.rs}}
|
||||
```
|
|
@ -35,13 +35,13 @@
|
|||
- [ ] Time lag
|
||||
- [ ] Transformer
|
||||
- [ ] Providers
|
||||
- [ ] Http
|
||||
- [x] Http
|
||||
- [x] IPC
|
||||
- [ ] Mock
|
||||
- [x] Quorum
|
||||
- [ ] Retry
|
||||
- [x] Retry
|
||||
- [x] RW
|
||||
- [ ] WS
|
||||
- [x] WS
|
||||
- [ ] Queries
|
||||
- [ ] Blocks
|
||||
- [x] Contracts
|
||||
|
|
|
@ -12,6 +12,7 @@ ipc = []
|
|||
ethers = { path = "../..", version = "1.0.0", features = ["abigen", "ipc", "rustls", "ws"] }
|
||||
|
||||
eyre = "0.6"
|
||||
reqwest = { version = "0.11.13", default-features = false }
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
serde_json = "1.0.64"
|
||||
tokio = { version = "1.18", features = ["macros"] }
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
use ethers::prelude::*;
|
||||
use reqwest::header::{HeaderMap, HeaderValue};
|
||||
use std::sync::Arc;
|
||||
|
||||
const RPC_URL: &str = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27";
|
||||
|
||||
/// The Http transport is used to send JSON-RPC requests over Http to an
|
||||
/// Ethereum node. It allows you to perform various actions on the Ethereum blockchain, such as
|
||||
/// reading and writing data, sending transactions, and more. To use the Http transport, you will
|
||||
/// need to create a new `Provider` instance as described in this example.
|
||||
#[tokio::main]
|
||||
async fn main() -> eyre::Result<()> {
|
||||
create_instance().await?;
|
||||
share_providers_across_tasks().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_instance() -> eyre::Result<()> {
|
||||
// An Http provider can be created from an http(s) URI.
|
||||
// In case of https you must add the "rustls" or "openssl" feature
|
||||
// to the ethers library dependency in `Cargo.toml`.
|
||||
let _provider = Provider::<Http>::try_from(RPC_URL)?;
|
||||
|
||||
// Instantiate with auth to append basic authorization headers across requests
|
||||
let url = reqwest::Url::parse(RPC_URL)?;
|
||||
let auth = Authorization::basic("username", "password");
|
||||
let _provider = Http::new_with_auth(url, auth)?;
|
||||
|
||||
// Instantiate from custom Http Client if you need
|
||||
// finer control over the Http client configuration
|
||||
// (TLS, Proxy, Cookies, Headers, etc.)
|
||||
let url = reqwest::Url::parse(RPC_URL)?;
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert("Authorization", HeaderValue::from_static("Bearer my token"));
|
||||
headers.insert("X-MY-HEADERS", HeaderValue::from_static("Some value"));
|
||||
|
||||
let http_client = reqwest::Client::builder()
|
||||
.default_headers(headers)
|
||||
.proxy(reqwest::Proxy::all("http://proxy.example.com:8080")?)
|
||||
.build()?;
|
||||
|
||||
let _provider = Http::new_with_client(url, http_client);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Providers can be easily shared across tasks using `Arc` smart pointers
|
||||
async fn share_providers_across_tasks() -> eyre::Result<()> {
|
||||
let provider: Provider<Http> = Provider::<Http>::try_from(RPC_URL)?;
|
||||
|
||||
let client_1 = Arc::new(provider);
|
||||
let client_2 = Arc::clone(&client_1);
|
||||
|
||||
let handle1 =
|
||||
tokio::spawn(async move { client_1.get_block(BlockNumber::Latest).await.unwrap_or(None) });
|
||||
|
||||
let handle2 =
|
||||
tokio::spawn(async move { client_2.get_block(BlockNumber::Latest).await.unwrap_or(None) });
|
||||
|
||||
let block1: Option<Block<H256>> = handle1.await?;
|
||||
let block2: Option<Block<H256>> = handle2.await?;
|
||||
|
||||
println!("{block1:?} {block2:?}");
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,11 +1,23 @@
|
|||
/// The IPC (Inter-Process Communication) transport is a way for a process to communicate with a
|
||||
/// running Ethereum client over a local Unix domain socket. Using the IPC transport allows the
|
||||
/// ethers library to send JSON-RPC requests to the Ethereum client and receive responses, without
|
||||
/// the need for a network connection or HTTP server. This can be useful for interacting with a
|
||||
/// local Ethereum node that is running on the same machine.
|
||||
#[tokio::main]
|
||||
#[cfg(feature = "ipc")]
|
||||
async fn main() -> eyre::Result<()> {
|
||||
use ethers::prelude::*;
|
||||
|
||||
// We instantiate the provider using the path of a local Unix domain socket
|
||||
// --------------------------------------------------------------------------------
|
||||
// NOTE: The IPC transport supports push notifications, but we still need to specify a polling
|
||||
// interval because only subscribe RPC calls (e.g., transactions, blocks, events) support push
|
||||
// notifications in Ethereum's RPC API. For other calls we must use repeated polling for many
|
||||
// operations even with the IPC transport.
|
||||
let provider = Provider::connect_ipc("~/.ethereum/geth.ipc")
|
||||
.await?
|
||||
.interval(std::time::Duration::from_millis(2000));
|
||||
|
||||
let block = provider.get_block_number().await?;
|
||||
println!("Current block: {block}");
|
||||
let mut stream = provider.watch_blocks().await?.stream();
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
use ethers::prelude::*;
|
||||
use reqwest::Url;
|
||||
use std::time::Duration;
|
||||
|
||||
const RPC_URL: &str = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27";
|
||||
|
||||
/// The RetryClient is a type that wraps around a JsonRpcClient and automatically retries failed
|
||||
/// requests using an exponential backoff and filtering based on a RetryPolicy. It presents as a
|
||||
/// JsonRpcClient, but with additional functionality for retrying requests.
|
||||
///
|
||||
/// The RetryPolicy can be customized for specific applications and endpoints, mainly to handle
|
||||
/// rate-limiting errors. In addition to the RetryPolicy, errors caused by connectivity issues such
|
||||
/// as timed out connections or responses in the 5xx range can also be retried separately.
|
||||
#[tokio::main]
|
||||
async fn main() -> eyre::Result<()> {
|
||||
let provider = Http::new(Url::parse(RPC_URL)?);
|
||||
|
||||
let client = RetryClientBuilder::default()
|
||||
.rate_limit_retries(10)
|
||||
.timeout_retries(3)
|
||||
.initial_backoff(Duration::from_millis(500))
|
||||
.build(provider, Box::new(HttpRateLimitRetryPolicy::default()));
|
||||
|
||||
// Send a JSON-RPC request for the latest block
|
||||
let block_num = "latest".to_string();
|
||||
let txn_details = false;
|
||||
let params = (block_num, txn_details);
|
||||
|
||||
let block: Block<H256> =
|
||||
JsonRpcClient::request(&client, "eth_getBlockByNumber", params).await?;
|
||||
|
||||
println!("{block:?}");
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use ethers::prelude::*;
|
||||
|
||||
const WSS_URL: &str = "wss://mainnet.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27";
|
||||
|
||||
type BoxErr = Box<dyn std::error::Error>;
|
||||
|
||||
/// The Ws transport allows you to send JSON-RPC requests and receive responses over WebSocket
|
||||
/// connections. It is useful for connecting to Ethereum nodes that support WebSockets.
|
||||
/// This allows to interact with the Ethereum network in real-time without the need for HTTP
|
||||
/// polling.
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), BoxErr> {
|
||||
create_instance().await?;
|
||||
watch_blocks().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_instance() -> Result<(), BoxErr> {
|
||||
// An Ws provider can be created from an ws(s) URI.
|
||||
// In case of wss you must add the "rustls" or "openssl" feature
|
||||
// to the ethers library dependency in `Cargo.toml`.
|
||||
//------------------------------------------------------------------------------------------
|
||||
// NOTE: The Ws transport supports push notifications, but we still need to specify a polling
|
||||
// interval because only subscribe RPC calls (e.g., transactions, blocks, events) support push
|
||||
// notifications in Ethereum's RPC API. For other calls we must use repeated polling for many
|
||||
// operations even with the Ws transport.
|
||||
let _provider = Provider::<Ws>::connect(WSS_URL).await?.interval(Duration::from_millis(500));
|
||||
|
||||
// Instantiate with auth to send basic authorization headers on connection.
|
||||
let url = reqwest::Url::parse(WSS_URL)?;
|
||||
let auth = Authorization::basic("username", "password");
|
||||
if let Ok(_provider) = Provider::<Ws>::connect_with_auth(url, auth).await {
|
||||
println!("Create Ws provider with auth");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Let's show how the Ws connection enables listening for blocks using a persistent TCP connection
|
||||
async fn watch_blocks() -> Result<(), BoxErr> {
|
||||
let provider = Provider::<Ws>::connect(WSS_URL).await?;
|
||||
let mut stream = provider.watch_blocks().await?.take(1);
|
||||
|
||||
while let Some(block_hash) = stream.next().await {
|
||||
println!("{block_hash:?}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue