Skip to content

Commit

Permalink
feat(providers): adding Berachain provider and Berachain bArtio support
Browse files Browse the repository at this point in the history
  • Loading branch information
geekbrother committed Sep 30, 2024
1 parent cd5a0de commit f8d9483
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 2 deletions.
1 change: 1 addition & 0 deletions SUPPORTED_CHAINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Chain name with associated `chainId` query param to use.
| Avalanche C-Chain | eip155:43114 |
| Linea <sup>[1](#footnote1)</sup> | eip155:59144 |
| Polygon Amoy <sup>[1](#footnote1)</sup> | eip155:80002 |
| Berachain bArtio <sup>[1](#footnote1)</sup> | eip155:80084 |
| Base Sepolia | eip155:84532 |
| Arbitrum Sepolia | eip155:421614 |
| Zora <sup>[1](#footnote1)</sup> | eip155:7777777 |
Expand Down
47 changes: 47 additions & 0 deletions src/env/berachain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use {
super::ProviderConfig,
crate::providers::{Priority, Weight},
std::collections::HashMap,
};

#[derive(Debug)]
pub struct BerachainConfig {
pub supported_chains: HashMap<String, (String, Weight)>,
}

impl Default for BerachainConfig {
fn default() -> Self {
Self {
supported_chains: default_supported_chains(),
}
}
}

impl ProviderConfig for BerachainConfig {
fn supported_chains(self) -> HashMap<String, (String, Weight)> {
self.supported_chains
}

fn supported_ws_chains(self) -> HashMap<String, (String, Weight)> {
HashMap::new()
}

fn provider_kind(&self) -> crate::providers::ProviderKind {
crate::providers::ProviderKind::Berachain
}
}

fn default_supported_chains() -> HashMap<String, (String, Weight)> {
// Keep in-sync with SUPPORTED_CHAINS.md

HashMap::from([
// Berachain bArtio
(
"eip155:80084".into(),
(
"https://bartio.rpc.berachain.com/".into(),
Weight::new(Priority::Normal).unwrap(),
),
),
])
}
5 changes: 3 additions & 2 deletions src/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ use {
std::{collections::HashMap, fmt::Display},
};
pub use {
aurora::*, base::*, binance::*, getblock::*, infura::*, mantle::*, near::*, pokt::*,
publicnode::*, quicknode::*, server::*, zksync::*, zora::*,
aurora::*, base::*, berachain::*, binance::*, getblock::*, infura::*, mantle::*, near::*,
pokt::*, publicnode::*, quicknode::*, server::*, zksync::*, zora::*,
};
mod aurora;
mod base;
mod berachain;
mod binance;
mod getblock;
mod infura;
Expand Down
96 changes: 96 additions & 0 deletions src/providers/berachain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use {
super::{Provider, ProviderKind, RateLimited, RpcProvider, RpcProviderFactory},
crate::{
env::BerachainConfig,
error::{RpcError, RpcResult},
},
async_trait::async_trait,
axum::{
http::HeaderValue,
response::{IntoResponse, Response},
},
hyper::{client::HttpConnector, http, Client, Method},
hyper_tls::HttpsConnector,
std::collections::HashMap,
tracing::debug,
};

#[derive(Debug)]
pub struct BerachainProvider {
pub client: Client<HttpsConnector<HttpConnector>>,
pub supported_chains: HashMap<String, String>,
}

impl Provider for BerachainProvider {
fn supports_caip_chainid(&self, chain_id: &str) -> bool {
self.supported_chains.contains_key(chain_id)
}

fn supported_caip_chains(&self) -> Vec<String> {
self.supported_chains.keys().cloned().collect()
}

fn provider_kind(&self) -> ProviderKind {
ProviderKind::Berachain
}
}

#[async_trait]
impl RateLimited for BerachainProvider {
async fn is_rate_limited(&self, response: &mut Response) -> bool {
response.status() == http::StatusCode::TOO_MANY_REQUESTS
}
}

#[async_trait]
impl RpcProvider for BerachainProvider {
#[tracing::instrument(skip(self, body), fields(provider = %self.provider_kind()), level = "debug")]
async fn proxy(&self, chain_id: &str, body: hyper::body::Bytes) -> RpcResult<Response> {
let uri = self
.supported_chains
.get(chain_id)
.ok_or(RpcError::ChainNotFound)?;

let hyper_request = hyper::http::Request::builder()
.method(Method::POST)
.uri(uri)
.header("Content-Type", "application/json")
.body(hyper::body::Body::from(body))?;

let response = self.client.request(hyper_request).await?;
let status = response.status();
let body = hyper::body::to_bytes(response.into_body()).await?;

if let Ok(response) = serde_json::from_slice::<jsonrpc::Response>(&body) {
if response.error.is_some() && status.is_success() {
debug!(
"Strange: provider returned JSON RPC error, but status {status} is success: \
Berachain: {response:?}"
);
}
}

let mut response = (status, body).into_response();
response
.headers_mut()
.insert("Content-Type", HeaderValue::from_static("application/json"));
Ok(response)
}
}

impl RpcProviderFactory<BerachainConfig> for BerachainProvider {
#[tracing::instrument(level = "debug")]
fn new(provider_config: &BerachainConfig) -> Self {
let forward_proxy_client = Client::builder().build::<_, hyper::Body>(HttpsConnector::new());
let supported_chains: HashMap<String, String> = provider_config
.supported_chains
.iter()
.map(|(k, v)| (k.clone(), v.0.clone()))
.collect();

BerachainProvider {
client: forward_proxy_client,
supported_chains,
}
}
}
5 changes: 5 additions & 0 deletions src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use {

mod aurora;
mod base;
mod berachain;
mod binance;
mod coinbase;
mod getblock;
Expand All @@ -63,6 +64,7 @@ mod zora;
pub use {
aurora::AuroraProvider,
base::BaseProvider,
berachain::BerachainProvider,
binance::BinanceProvider,
getblock::GetBlockProvider,
infura::{InfuraProvider, InfuraWsProvider},
Expand Down Expand Up @@ -448,6 +450,7 @@ pub enum ProviderKind {
Infura,
Pokt,
Binance,
Berachain,
ZKSync,
Publicnode,
Base,
Expand All @@ -472,6 +475,7 @@ impl Display for ProviderKind {
ProviderKind::Infura => "Infura",
ProviderKind::Pokt => "Pokt",
ProviderKind::Binance => "Binance",
ProviderKind::Berachain => "Berachain",
ProviderKind::ZKSync => "zkSync",
ProviderKind::Publicnode => "Publicnode",
ProviderKind::Base => "Base",
Expand All @@ -497,6 +501,7 @@ impl ProviderKind {
"Infura" => Some(Self::Infura),
"Pokt" => Some(Self::Pokt),
"Binance" => Some(Self::Binance),
"Berachain" => Some(Self::Berachain),
"zkSync" => Some(Self::ZKSync),
"Publicnode" => Some(Self::Publicnode),
"Base" => Some(Self::Base),
Expand Down
18 changes: 18 additions & 0 deletions tests/functional/http/berachain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use {
super::check_if_rpc_is_responding_correctly_for_supported_chain, crate::context::ServerContext,
rpc_proxy::providers::ProviderKind, test_context::test_context,
};

#[test_context(ServerContext)]
#[tokio::test]
#[ignore]
async fn berachain_provider_eip155_80084(ctx: &mut ServerContext) {
// Berachain bArtio
check_if_rpc_is_responding_correctly_for_supported_chain(
ctx,
&ProviderKind::Berachain,
"eip155:80084",
"0x138d4",
)
.await;
}
1 change: 1 addition & 0 deletions tests/functional/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use {

pub(crate) mod aurora;
pub(crate) mod base;
pub(crate) mod berachain;
pub(crate) mod binance;
pub(crate) mod getblock;
pub(crate) mod infura;
Expand Down

0 comments on commit f8d9483

Please sign in to comment.