Skip to content

Commit

Permalink
feat(providers): adding Allnodes RPC endpoint (#934)
Browse files Browse the repository at this point in the history
* feat(providers): adding Allnodes RPC endpoint

* feat: making tthe priority high
  • Loading branch information
geekbrother authored Feb 5, 2025
1 parent 56e42e3 commit 29534c5
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 14 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export RPC_PROXY_PROVIDER_TENDERLY_ACCOUNT_ID=""
export RPC_PROXY_PROVIDER_TENDERLY_PROJECT_ID=""
export RPC_PROXY_PROVIDER_DUNE_API_KEY=""
export RPC_PROXY_PROVIDER_SYNDICA_API_KEY=""
export RPC_PROXY_PROVIDER_ALLNODES_API_KEY=""

# PostgreSQL URI connection string
export RPC_PROXY_POSTGRES_URI="postgres://postgres@localhost/postgres"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/event_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ jobs:
RPC_PROXY_PROVIDER_ZERION_API_KEY: ""
RPC_PROXY_PROVIDER_DUNE_API_KEY: ""
RPC_PROXY_PROVIDER_SYNDICA_API_KEY: ""
RPC_PROXY_PROVIDER_ALLNODES_API_KEY: ""
- run: docker logs mock-bundler-anvil-1
if: failure()
- run: docker logs mock-bundler-alto-1
Expand Down
46 changes: 46 additions & 0 deletions src/env/allnodes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use {
super::ProviderConfig,
crate::providers::{Priority, Weight},
std::collections::HashMap,
};

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

impl AllnodesConfig {
pub fn new(api_key: String) -> Self {
Self {
supported_chains: default_supported_chains(),
api_key,
}
}
}

impl ProviderConfig for AllnodesConfig {
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::Allnodes
}
}

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

HashMap::from([
// Ethereum Mainnet
(
"eip155:1".into(),
("eth30082".into(), Weight::new(Priority::High).unwrap()),
),
])
}
11 changes: 7 additions & 4 deletions src/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ use {
std::{collections::HashMap, fmt::Display},
};
pub use {
arbitrum::*, aurora::*, base::*, berachain::*, binance::*, drpc::*, dune::*, getblock::*,
infura::*, lava::*, mantle::*, morph::*, near::*, odyssey::*, pokt::*, publicnode::*,
quicknode::*, server::*, solscan::*, syndica::*, unichain::*, wemix::*, zerion::*, zksync::*,
zora::*,
allnodes::*, arbitrum::*, aurora::*, base::*, berachain::*, binance::*, drpc::*, dune::*,
getblock::*, infura::*, lava::*, mantle::*, morph::*, near::*, odyssey::*, pokt::*,
publicnode::*, quicknode::*, server::*, solscan::*, syndica::*, unichain::*, wemix::*,
zerion::*, zksync::*, zora::*,
};
mod allnodes;
mod arbitrum;
mod aurora;
mod base;
Expand Down Expand Up @@ -204,6 +205,7 @@ mod test {
),
("RPC_PROXY_PROVIDER_DUNE_API_KEY", "DUNE_API_KEY"),
("RPC_PROXY_PROVIDER_SYNDICA_API_KEY", "SYNDICA_API_KEY"),
("RPC_PROXY_PROVIDER_ALLNODES_API_KEY", "ALLNODES_API_KEY"),
(
"RPC_PROXY_PROVIDER_PROMETHEUS_QUERY_URL",
"PROMETHEUS_QUERY_URL",
Expand Down Expand Up @@ -314,6 +316,7 @@ mod test {
dune_api_key: "DUNE_API_KEY".to_string(),
syndica_api_key: "SYNDICA_API_KEY".to_string(),
override_bundler_urls: None,
allnodes_api_key: "ALLNODES_API_KEY".to_string(),
},
rate_limiting: RateLimitingConfig {
max_tokens: Some(100),
Expand Down
24 changes: 14 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,22 @@ use {
Router,
},
env::{
ArbitrumConfig, AuroraConfig, BaseConfig, BerachainConfig, BinanceConfig, DrpcConfig,
DuneConfig, GetBlockConfig, InfuraConfig, LavaConfig, MantleConfig, MorphConfig,
NearConfig, OdysseyConfig, PoktConfig, PublicnodeConfig, QuicknodeConfig, SolScanConfig,
SyndicaConfig, UnichainConfig, WemixConfig, ZKSyncConfig, ZerionConfig, ZoraConfig,
AllnodesConfig, ArbitrumConfig, AuroraConfig, BaseConfig, BerachainConfig, BinanceConfig,
DrpcConfig, DuneConfig, GetBlockConfig, InfuraConfig, LavaConfig, MantleConfig,
MorphConfig, NearConfig, OdysseyConfig, PoktConfig, PublicnodeConfig, QuicknodeConfig,
SolScanConfig, SyndicaConfig, UnichainConfig, WemixConfig, ZKSyncConfig, ZerionConfig,
ZoraConfig,
},
error::RpcResult,
http::Request,
hyper::{header::HeaderName, http, server::conn::AddrIncoming, Body, Server},
providers::{
ArbitrumProvider, AuroraProvider, BaseProvider, BerachainProvider, BinanceProvider,
DrpcProvider, DuneProvider, GetBlockProvider, InfuraProvider, InfuraWsProvider,
LavaProvider, MantleProvider, MorphProvider, NearProvider, OdysseyProvider, PoktProvider,
ProviderRepository, PublicnodeProvider, QuicknodeProvider, SolScanProvider,
SyndicaProvider, UnichainProvider, WemixProvider, ZKSyncProvider, ZerionProvider,
ZoraProvider, ZoraWsProvider,
AllnodesProvider, ArbitrumProvider, AuroraProvider, BaseProvider, BerachainProvider,
BinanceProvider, DrpcProvider, DuneProvider, GetBlockProvider, InfuraProvider,
InfuraWsProvider, LavaProvider, MantleProvider, MorphProvider, NearProvider,
OdysseyProvider, PoktProvider, ProviderRepository, PublicnodeProvider, QuicknodeProvider,
SolScanProvider, SyndicaProvider, UnichainProvider, WemixProvider, ZKSyncProvider,
ZerionProvider, ZoraProvider, ZoraWsProvider,
},
sqlx::postgres::PgPoolOptions,
std::{
Expand Down Expand Up @@ -531,6 +532,9 @@ fn init_providers(config: &ProvidersConfig) -> ProviderRepository {
providers.add_rpc_provider::<WemixProvider, WemixConfig>(WemixConfig::default());
providers.add_rpc_provider::<DrpcProvider, DrpcConfig>(DrpcConfig::default());
providers.add_rpc_provider::<OdysseyProvider, OdysseyConfig>(OdysseyConfig::default());
providers.add_rpc_provider::<AllnodesProvider, AllnodesConfig>(AllnodesConfig::new(
config.allnodes_api_key.clone(),
));

if let Some(getblock_access_tokens) = &config.getblock_access_tokens {
providers.add_rpc_provider::<GetBlockProvider, GetBlockConfig>(GetBlockConfig::new(
Expand Down
100 changes: 100 additions & 0 deletions src/providers/allnodes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use {
super::{Provider, ProviderKind, RateLimited, RpcProvider, RpcProviderFactory},
crate::{
env::AllnodesConfig,
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 AllnodesProvider {
pub client: Client<HttpsConnector<HttpConnector>>,
pub supported_chains: HashMap<String, String>,
pub api_key: String,
}

impl Provider for AllnodesProvider {
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::Allnodes
}
}

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

#[async_trait]
impl RpcProvider for AllnodesProvider {
#[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 chain = &self
.supported_chains
.get(chain_id)
.ok_or(RpcError::ChainNotFound)?;

let uri = format!("https://{}.allnodes.me:8545/{}", chain, &self.api_key);

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: \
Allnodes: {response:?}"
);
}
}

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

impl RpcProviderFactory<AllnodesConfig> for AllnodesProvider {
#[tracing::instrument(level = "debug")]
fn new(provider_config: &AllnodesConfig) -> 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();

AllnodesProvider {
client: forward_proxy_client,
supported_chains,
api_key: provider_config.api_key.clone(),
}
}
}
7 changes: 7 additions & 0 deletions src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use {
yttrium::chain_abstraction::api::Transaction,
};

mod allnodes;
mod arbitrum;
mod aurora;
mod base;
Expand Down Expand Up @@ -83,6 +84,7 @@ mod zksync;
mod zora;

pub use {
allnodes::AllnodesProvider,
arbitrum::ArbitrumProvider,
aurora::AuroraProvider,
base::BaseProvider,
Expand Down Expand Up @@ -155,6 +157,8 @@ pub struct ProvidersConfig {
pub dune_api_key: String,
/// Syndica API key
pub syndica_api_key: String,
/// Allnodes API key
pub allnodes_api_key: String,

pub override_bundler_urls: Option<MockAltoUrls>,
}
Expand Down Expand Up @@ -645,6 +649,7 @@ pub enum ProviderKind {
Drpc,
Odyssey,
Syndica,
Allnodes,
}

impl Display for ProviderKind {
Expand Down Expand Up @@ -681,6 +686,7 @@ impl Display for ProviderKind {
ProviderKind::Drpc => "Drpc",
ProviderKind::Odyssey => "Odyssey",
ProviderKind::Syndica => "Syndica",
ProviderKind::Allnodes => "Allnodes",
}
)
}
Expand Down Expand Up @@ -718,6 +724,7 @@ impl ProviderKind {
"Drpc" => Some(Self::Drpc),
"Odyssey" => Some(Self::Odyssey),
"Syndica" => Some(Self::Syndica),
"Allnodes" => Some(Self::Allnodes),
_ => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions terraform/ecs/cluster.tf
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ resource "aws_ecs_task_definition" "app_task" {
{ name = "RPC_PROXY_PROVIDER_TENDERLY_PROJECT_ID", value = var.tenderly_project_id },
{ name = "RPC_PROXY_PROVIDER_DUNE_API_KEY", value = var.dune_api_key },
{ name = "RPC_PROXY_PROVIDER_SYNDICA_API_KEY", value = var.syndica_api_key },
{ name = "RPC_PROXY_PROVIDER_ALLNODES_API_KEY", value = var.allnodes_api_key },

{ name = "RPC_PROXY_PROVIDER_PROMETHEUS_QUERY_URL", value = "http://127.0.0.1:${local.prometheus_proxy_port}/workspaces/${var.prometheus_workspace_id}" },
{ name = "RPC_PROXY_PROVIDER_PROMETHEUS_WORKSPACE_HEADER", value = "aps-workspaces.${module.this.region}.amazonaws.com" },
Expand Down
6 changes: 6 additions & 0 deletions terraform/ecs/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ variable "syndica_api_key" {
sensitive = true
}

variable "allnodes_api_key" {
description = "Allnodes API key"
type = string
sensitive = true
}

variable "testing_project_id" {
description = "Project ID used in a testing suite"
type = string
Expand Down
1 change: 1 addition & 0 deletions terraform/res_ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ module "ecs" {
tenderly_project_id = var.tenderly_project_id
dune_api_key = var.dune_api_key
syndica_api_key = var.syndica_api_key
allnodes_api_key = var.allnodes_api_key

# Project Registry
registry_api_endpoint = var.registry_api_endpoint
Expand Down
6 changes: 6 additions & 0 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ variable "testing_project_id" {
sensitive = true
}

variable "allnodes_api_key" {
description = "Allnodes API key"
type = string
sensitive = true
}

#-------------------------------------------------------------------------------
# Analytics

Expand Down

0 comments on commit 29534c5

Please sign in to comment.