web3-proxy/web3_proxy/src/rpcs/provider.rs

76 lines
2.5 KiB
Rust
Raw Normal View History

2022-09-14 05:11:48 +03:00
use anyhow::Context;
use derive_more::From;
2022-09-14 05:11:48 +03:00
use std::time::Duration;
// TODO: our own structs for these that handle streaming large responses
type EthersHttpProvider = ethers::providers::Provider<ethers::providers::Http>;
type EthersWsProvider = ethers::providers::Provider<ethers::providers::Ws>;
/// Use HTTP and WS providers.
// TODO: instead of an enum, I tried to use Box<dyn Provider>, but hit <https://github.com/gakonst/ethers-rs/issues/592>
// TODO: custom types that let us stream JSON responses
#[derive(From)]
pub enum Web3Provider {
Both(EthersHttpProvider, EthersWsProvider),
Http(EthersHttpProvider),
// TODO: deadpool? custom tokio-tungstenite
Ws(EthersWsProvider),
#[cfg(test)]
Mock,
}
2022-08-24 03:11:49 +03:00
impl Web3Provider {
pub fn ready(&self) -> bool {
match self {
Self::Both(_, ws) => ws.as_ref().ready(),
Self::Http(_) => true,
Self::Ws(ws) => ws.as_ref().ready(),
#[cfg(test)]
Self::Mock => true,
}
}
pub fn http(&self) -> Option<&EthersHttpProvider> {
match self {
Self::Http(x) => Some(x),
_ => None,
}
}
pub fn ws(&self) -> Option<&EthersWsProvider> {
match self {
Self::Both(_, x) | Self::Ws(x) => Some(x),
_ => None,
}
}
2022-08-24 03:11:49 +03:00
pub async fn from_str(
url_str: &str,
http_client: Option<reqwest::Client>,
) -> anyhow::Result<Self> {
let provider = if url_str.starts_with("http") {
let url: url::Url = url_str.parse()?;
2022-09-14 05:11:48 +03:00
let http_client = http_client.context("no http_client")?;
2022-08-24 03:11:49 +03:00
let provider = ethers::providers::Http::new_with_client(url, http_client);
// TODO: dry this up (needs https://github.com/gakonst/ethers-rs/issues/592)
// TODO: i don't think this interval matters for our uses, but we should probably set it to like `block time / 2`
ethers::providers::Provider::new(provider)
2023-01-03 22:37:42 +03:00
.interval(Duration::from_secs(12))
2022-08-24 03:11:49 +03:00
.into()
} else if url_str.starts_with("ws") {
2022-11-12 11:24:32 +03:00
let provider = ethers::providers::Ws::connect(url_str).await?;
2022-08-24 03:11:49 +03:00
// TODO: dry this up (needs https://github.com/gakonst/ethers-rs/issues/592)
// TODO: i don't think this interval matters
ethers::providers::Provider::new(provider).into()
} else {
return Err(anyhow::anyhow!("only http and ws servers are supported"));
};
Ok(provider)
}
}