Skip to content

Commit

Permalink
Bundle Multiple EVM Providers (#531)
Browse files Browse the repository at this point in the history
* bundle multiple providers in retry client

* update doc

* undo quorum changes

* multi provider client

* use multi provider client

* error handling and update readme doc

* update docs in config files and incorporate review feedback
  • Loading branch information
salman01zp authored Jun 7, 2023
1 parent b90d392 commit a16b308
Show file tree
Hide file tree
Showing 31 changed files with 325 additions and 158 deletions.
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.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ api-key = "$POLYGONSCAN_MAINNET_API_KEY"

| Field | Description | Optionality |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `http-endpoint` | Http(s) Endpoint for quick Req/Res | Required |
| `http-endpoint` | Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints. | Required |
| `ws-endpoint` | Websocket Endpoint for long living connections | Required |
| `name` | The Chain/Node name | Required |
| `explorer` | Block explorer, used for generating clickable links for transactions that happens on this chain. | Optional |
Expand Down
12 changes: 9 additions & 3 deletions config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,18 +320,24 @@ chain-id = 1

#### http-endpoint

The HTTP(s) RPC endpoint for this chain, used for watching events, and sending transactions.
The HTTP(s) RPC endpoint for this chain, used for watching events, and sending transactions. Input can be single http-endpoint or array of multiple http-endpoints.

- Type: `string`
- Type: `string | string[]`
- Required: `true`
- env: `WEBB_EVM_<CHAIN_NAME>_HTTP_ENDPOINT`

Example:

- Single Endpoint
```toml
http-endpoint = "https://mainnet.infura.io/v3/<project-id>"
```

- Multiple Endpoints
```toml
http-endpoint = ["https://mainnet.infura.io/v3/<project-id>","https://rpc.testnet.network"]
```


#### ws-endpoint

The WebSocket RPC endpoint for this chain, used for watching events, and sending transactions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
enabled = false
# The name that the chain is indexed on, for linkable anchors
name = "ethereum-mainnet"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$ETHEREUM_MAINNET_HTTP_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$ETHEREUM_MAINNET_WS_URL"
Expand Down
2 changes: 1 addition & 1 deletion config/block-header-relay/eth2-networks/sepolia.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
enabled = true
# The name that the chain is indexed on, for linkable anchors
name = "sepolia-testnet"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$SEPOLIA_HTTP_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$SEPOLIA_WS_URL"
Expand Down
2 changes: 1 addition & 1 deletion config/development/evm-blanknet/athena.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[evm.athena]
# The name that the chain is indexed on, for linkable anchors
name = "athena"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "http://localhost:5002"
# Websocket Endpoint for long living connections
ws-endpoint = "ws://localhost:5002"
Expand Down
2 changes: 1 addition & 1 deletion config/development/evm-blanknet/demeter.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[evm.demeter]
# The name that the chain is indexed on, for linkable anchors
name = "demeter"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "http://localhost:5003"
# Websocket Endpoint for long living connections
ws-endpoint = "ws://localhost:5003"
Expand Down
2 changes: 1 addition & 1 deletion config/development/evm-blanknet/hermes.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[evm.hermes]
# The name that the chain is indexed on, for linkable anchors
name = "hermes"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "http://localhost:5001"
# Websocket Endpoint for long living connections
ws-endpoint = "ws://localhost:5001"
Expand Down
2 changes: 1 addition & 1 deletion config/example/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private-tx-relay = true
# The following block defines an EVM network (in this case, Goerli) that the relayer will connect to.
[evm.goerli]
name = "goerli"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
# env: WEBB_EVM_GOERLI_HTTP_ENDPOINT
http-endpoint = "https://rpc.ankr.com/eth_goerli"
# Websocket Endpoint for long living connections
Expand Down
2 changes: 1 addition & 1 deletion config/exclusive-strategies/data-querying/goerli.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[evm.goerli]
name = "goerli"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$GOERLI_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$GOERLI_WSS_URL"
Expand Down
2 changes: 1 addition & 1 deletion config/exclusive-strategies/data-querying/sepolia.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[evm.sepolia]
name = "sepolia"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$SEPOLIA_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$SEPOLIA_WSS_URL"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Block which represents properties for a network
[evm.goerli]
name = "goerli"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$GOERLI_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$GOERLI_WSS_URL"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Block which represents properties for a network
[evm.sepolia]
name = "sepolia"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$SEPOLIA_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$SEPOLIA_WSS_URL"
Expand Down
2 changes: 1 addition & 1 deletion config/exclusive-strategies/signature-relaying/goerli.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Block which represents properties for a network
[evm.goerli]
name = "goerli"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$GOERLI_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$GOERLI_WSS_URL"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Block which represents properties for a network
[evm.optimismtestnet]
name = "optimismtestnet"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$OPTIMISM_TESTNET_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$OPTIMISM_TESTNET_WSS_URL"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Block which represents properties for a network
[evm.sepolia]
name = "sepolia"
# Http(s) Endpoint for quick Req/Res
# Http(s) Endpoint for quick Req/Res. Input can be single http-endpoint or array of multiple http-endpoints.
http-endpoint = "$SEPOLIA_HTTPS_URL"
# Websocket Endpoint for long living connections
ws-endpoint = "$SEPOLIA_WSS_URL"
Expand Down
13 changes: 9 additions & 4 deletions crates/event-watcher-traits/src/evm/event_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@

use tokio::sync::Mutex;
use webb::evm::ethers::prelude::TimeLag;
use webb_relayer_utils::retry;
use webb_relayer_utils::{multi_provider::MultiProvider, retry};

use super::*;

/// Ethereum client using Ethers, that includes a retry strategy.
pub type EthersClient =
providers::Provider<providers::RetryClient<providers::Http>>;
providers::Provider<providers::RetryClient<MultiProvider<providers::Http>>>;

/// Ethereum TimeLag client using Ethers, that includes a retry strategy.
pub type EthersTimeLagClient =
TimeLag<Arc<providers::Provider<providers::RetryClient<providers::Http>>>>;
pub type EthersTimeLagClient = TimeLag<
Arc<
providers::Provider<
providers::RetryClient<MultiProvider<providers::Http>>,
>,
>,
>;

/// A watchable contract is a contract used in the [EventWatcher]
pub trait WatchableContract: Send + Sync {
Expand Down
34 changes: 33 additions & 1 deletion crates/relayer-config/src/evm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use core::fmt;

use ethereum_types::Address;
use url::Url;
use webb_relayer_types::{private_key::PrivateKey, rpc_url::RpcUrl};

use crate::{
Expand All @@ -20,7 +23,7 @@ pub struct EvmChainConfig {
pub enabled: bool,
/// Http(s) Endpoint for quick Req/Res
#[serde(skip_serializing)]
pub http_endpoint: RpcUrl,
pub http_endpoint: HttpEndpoint,
/// Websocket Endpoint for long living connections
#[serde(skip_serializing)]
pub ws_endpoint: RpcUrl,
Expand Down Expand Up @@ -73,6 +76,35 @@ pub struct EvmChainConfig {
pub block_poller: Option<BlockPollerConfig>,
}

/// configuration for adding http endpoints.
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum HttpEndpoint {
/// Single http endpoint
Single(RpcUrl),
/// Multiple http endpoints
Multiple(Vec<RpcUrl>),
}

impl fmt::Display for HttpEndpoint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HttpEndpoint::Single(url) => write!(f, "{}", url),
HttpEndpoint::Multiple(urls) => {
let urls: Vec<String> =
urls.iter().map(ToString::to_string).collect();
write!(f, "{}", urls.join(", "))
}
}
}
}

impl From<Url> for HttpEndpoint {
fn from(url: Url) -> Self {
HttpEndpoint::Single(url.into())
}
}

/// Linked anchor config for Evm based target system
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all(serialize = "camelCase", deserialize = "kebab-case"))]
Expand Down
Loading

0 comments on commit a16b308

Please sign in to comment.