Skip to content

Commit d1b308c

Browse files
authored
feat(providers): adding Wemix RPC endpoints (#895)
1 parent 16342fe commit d1b308c

File tree

9 files changed

+196
-5
lines changed

9 files changed

+196
-5
lines changed

SUPPORTED_CHAINS.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Chain name with associated `chainId` query param to use.
1717
| zkSync Era Sepolia Testnet <sup>[1](#footnote1)</sup> | eip155:300 |
1818
| zkSync Era | eip155:324 |
1919
| Polygon Zkevm | eip155:1101 |
20+
| Wemix Mainnet <sup>[1](#footnote1)</sup> | eip155:1111 |
21+
| Wemix Testnet <sup>[1](#footnote1)</sup> | eip155:1112 |
2022
| Unichain Sepolia <sup>[1](#footnote1)</sup> | eip155:1301 |
2123
| Sei Network <sup>[1](#footnote1)</sup> | eip155:1329 |
2224
| Morph Holesky <sup>[1](#footnote1)</sup> | eip155:2810 |

src/env/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use {
1616
pub use {
1717
arbitrum::*, aurora::*, base::*, berachain::*, binance::*, dune::*, getblock::*, infura::*,
1818
lava::*, mantle::*, morph::*, near::*, pokt::*, publicnode::*, quicknode::*, server::*,
19-
solscan::*, unichain::*, zerion::*, zksync::*, zora::*,
19+
solscan::*, unichain::*, wemix::*, zerion::*, zksync::*, zora::*,
2020
};
2121
mod arbitrum;
2222
mod aurora;
@@ -36,6 +36,7 @@ mod quicknode;
3636
mod server;
3737
pub mod solscan;
3838
mod unichain;
39+
mod wemix;
3940
pub mod zerion;
4041
mod zksync;
4142
mod zora;

src/env/wemix.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use {
2+
super::ProviderConfig,
3+
crate::providers::{Priority, Weight},
4+
std::collections::HashMap,
5+
};
6+
7+
#[derive(Debug)]
8+
pub struct WemixConfig {
9+
pub supported_chains: HashMap<String, (String, Weight)>,
10+
}
11+
12+
impl Default for WemixConfig {
13+
fn default() -> Self {
14+
Self {
15+
supported_chains: default_supported_chains(),
16+
}
17+
}
18+
}
19+
20+
impl ProviderConfig for WemixConfig {
21+
fn supported_chains(self) -> HashMap<String, (String, Weight)> {
22+
self.supported_chains
23+
}
24+
25+
fn supported_ws_chains(self) -> HashMap<String, (String, Weight)> {
26+
HashMap::new()
27+
}
28+
29+
fn provider_kind(&self) -> crate::providers::ProviderKind {
30+
crate::providers::ProviderKind::Wemix
31+
}
32+
}
33+
34+
fn default_supported_chains() -> HashMap<String, (String, Weight)> {
35+
// Keep in-sync with SUPPORTED_CHAINS.md
36+
37+
HashMap::from([
38+
// Wemix Mainnet
39+
(
40+
"eip155:1111".into(),
41+
(
42+
"https://api.wemix.com/".into(),
43+
Weight::new(Priority::Normal).unwrap(),
44+
),
45+
),
46+
// Wemix Testnet
47+
(
48+
"eip155:1112".into(),
49+
(
50+
"https://api.test.wemix.com".into(),
51+
Weight::new(Priority::Normal).unwrap(),
52+
),
53+
),
54+
])
55+
}

src/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use {
2020
env::{
2121
ArbitrumConfig, AuroraConfig, BaseConfig, BerachainConfig, BinanceConfig, DuneConfig,
2222
GetBlockConfig, InfuraConfig, LavaConfig, MantleConfig, MorphConfig, NearConfig,
23-
PoktConfig, PublicnodeConfig, QuicknodeConfig, SolScanConfig, UnichainConfig, ZKSyncConfig,
24-
ZerionConfig, ZoraConfig,
23+
PoktConfig, PublicnodeConfig, QuicknodeConfig, SolScanConfig, UnichainConfig, WemixConfig,
24+
ZKSyncConfig, ZerionConfig, ZoraConfig,
2525
},
2626
error::RpcResult,
2727
http::Request,
@@ -30,8 +30,8 @@ use {
3030
ArbitrumProvider, AuroraProvider, BaseProvider, BerachainProvider, BinanceProvider,
3131
DuneProvider, GetBlockProvider, InfuraProvider, InfuraWsProvider, LavaProvider,
3232
MantleProvider, MorphProvider, NearProvider, PoktProvider, ProviderRepository,
33-
PublicnodeProvider, QuicknodeProvider, SolScanProvider, UnichainProvider, ZKSyncProvider,
34-
ZerionProvider, ZoraProvider, ZoraWsProvider,
33+
PublicnodeProvider, QuicknodeProvider, SolScanProvider, UnichainProvider, WemixProvider,
34+
ZKSyncProvider, ZerionProvider, ZoraProvider, ZoraWsProvider,
3535
},
3636
sqlx::postgres::PgPoolOptions,
3737
std::{
@@ -511,6 +511,7 @@ fn init_providers(config: &ProvidersConfig) -> ProviderRepository {
511511
providers
512512
.add_rpc_provider::<LavaProvider, LavaConfig>(LavaConfig::new(config.lava_api_key.clone()));
513513
providers.add_rpc_provider::<MorphProvider, MorphConfig>(MorphConfig::default());
514+
providers.add_rpc_provider::<WemixProvider, WemixConfig>(WemixConfig::default());
514515

515516
if let Some(getblock_access_tokens) = &config.getblock_access_tokens {
516517
providers.add_rpc_provider::<GetBlockProvider, GetBlockConfig>(GetBlockConfig::new(

src/providers/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ mod solscan;
7272
pub mod tenderly;
7373
mod unichain;
7474
mod weights;
75+
mod wemix;
7576
pub mod zerion;
7677
mod zksync;
7778
mod zora;
@@ -98,6 +99,7 @@ pub use {
9899
solscan::SolScanProvider,
99100
tenderly::TenderlyProvider,
100101
unichain::UnichainProvider,
102+
wemix::WemixProvider,
101103
zerion::ZerionProvider,
102104
zksync::ZKSyncProvider,
103105
zora::{ZoraProvider, ZoraWsProvider},
@@ -627,6 +629,7 @@ pub enum ProviderKind {
627629
Morph,
628630
Tenderly,
629631
Dune,
632+
Wemix,
630633
}
631634

632635
impl Display for ProviderKind {
@@ -641,6 +644,7 @@ impl Display for ProviderKind {
641644
ProviderKind::Pokt => "Pokt",
642645
ProviderKind::Binance => "Binance",
643646
ProviderKind::Berachain => "Berachain",
647+
ProviderKind::Wemix => "Wemix",
644648
ProviderKind::Bungee => "Bungee",
645649
ProviderKind::ZKSync => "zkSync",
646650
ProviderKind::Publicnode => "Publicnode",
@@ -692,6 +696,7 @@ impl ProviderKind {
692696
"Morph" => Some(Self::Morph),
693697
"Tenderly" => Some(Self::Tenderly),
694698
"Dune" => Some(Self::Dune),
699+
"Wemix" => Some(Self::Wemix),
695700
_ => None,
696701
}
697702
}

src/providers/wemix.rs

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use {
2+
super::{Provider, ProviderKind, RateLimited, RpcProvider, RpcProviderFactory},
3+
crate::{
4+
env::WemixConfig,
5+
error::{RpcError, RpcResult},
6+
},
7+
async_trait::async_trait,
8+
axum::{
9+
http::HeaderValue,
10+
response::{IntoResponse, Response},
11+
},
12+
hyper::{client::HttpConnector, http, Client, Method},
13+
hyper_tls::HttpsConnector,
14+
std::collections::HashMap,
15+
tracing::debug,
16+
};
17+
18+
#[derive(Debug)]
19+
pub struct WemixProvider {
20+
pub client: Client<HttpsConnector<HttpConnector>>,
21+
pub supported_chains: HashMap<String, String>,
22+
}
23+
24+
impl Provider for WemixProvider {
25+
fn supports_caip_chainid(&self, chain_id: &str) -> bool {
26+
self.supported_chains.contains_key(chain_id)
27+
}
28+
29+
fn supported_caip_chains(&self) -> Vec<String> {
30+
self.supported_chains.keys().cloned().collect()
31+
}
32+
33+
fn provider_kind(&self) -> ProviderKind {
34+
ProviderKind::Wemix
35+
}
36+
}
37+
38+
#[async_trait]
39+
impl RateLimited for WemixProvider {
40+
async fn is_rate_limited(&self, response: &mut Response) -> bool {
41+
response.status() == http::StatusCode::TOO_MANY_REQUESTS
42+
}
43+
}
44+
45+
#[async_trait]
46+
impl RpcProvider for WemixProvider {
47+
#[tracing::instrument(skip(self, body), fields(provider = %self.provider_kind()), level = "debug")]
48+
async fn proxy(&self, chain_id: &str, body: hyper::body::Bytes) -> RpcResult<Response> {
49+
let uri = self
50+
.supported_chains
51+
.get(chain_id)
52+
.ok_or(RpcError::ChainNotFound)?;
53+
54+
let hyper_request = hyper::http::Request::builder()
55+
.method(Method::POST)
56+
.uri(uri)
57+
.header("Content-Type", "application/json")
58+
.body(hyper::body::Body::from(body))?;
59+
60+
let response = self.client.request(hyper_request).await?;
61+
let status = response.status();
62+
let body = hyper::body::to_bytes(response.into_body()).await?;
63+
64+
if let Ok(response) = serde_json::from_slice::<jsonrpc::Response>(&body) {
65+
if response.error.is_some() && status.is_success() {
66+
debug!(
67+
"Strange: provider returned JSON RPC error, but status {status} is success: \
68+
Wemix: {response:?}"
69+
);
70+
}
71+
}
72+
73+
let mut response = (status, body).into_response();
74+
response
75+
.headers_mut()
76+
.insert("Content-Type", HeaderValue::from_static("application/json"));
77+
Ok(response)
78+
}
79+
}
80+
81+
impl RpcProviderFactory<WemixConfig> for WemixProvider {
82+
#[tracing::instrument(level = "debug")]
83+
fn new(provider_config: &WemixConfig) -> Self {
84+
let forward_proxy_client = Client::builder().build::<_, hyper::Body>(HttpsConnector::new());
85+
let supported_chains: HashMap<String, String> = provider_config
86+
.supported_chains
87+
.iter()
88+
.map(|(k, v)| (k.clone(), v.0.clone()))
89+
.collect();
90+
91+
WemixProvider {
92+
client: forward_proxy_client,
93+
supported_chains,
94+
}
95+
}
96+
}

terraform/monitoring/dashboard.jsonnet

+3
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ dashboard.new(
8686
panels.usage.provider(ds, vars, 'Unichain') { gridPos: pos._4 },
8787
panels.usage.provider(ds, vars, 'Lava') { gridPos: pos._4 },
8888
panels.usage.provider(ds, vars, 'Morph') { gridPos: pos._4 },
89+
panels.usage.provider(ds, vars, 'Wemix') { gridPos: pos._4 },
8990

9091
row.new('RPC Proxy provider Weights'),
9192
panels.weights.provider(ds, vars, 'Aurora') { gridPos: pos._4 },
@@ -105,6 +106,7 @@ dashboard.new(
105106
panels.weights.provider(ds, vars, 'Unichain') { gridPos: pos._4 },
106107
panels.weights.provider(ds, vars, 'Lava') { gridPos: pos._4 },
107108
panels.weights.provider(ds, vars, 'Morph') { gridPos: pos._4 },
109+
panels.weights.provider(ds, vars, 'Wemix') { gridPos: pos._4 },
108110

109111
row.new('RPC Proxy providers Status Codes'),
110112
panels.status.provider(ds, vars, 'Aurora') { gridPos: pos._4 },
@@ -124,6 +126,7 @@ dashboard.new(
124126
panels.status.provider(ds, vars, 'Unichain') { gridPos: pos._4 },
125127
panels.status.provider(ds, vars, 'Lava') { gridPos: pos._4 },
126128
panels.status.provider(ds, vars, 'Morph') { gridPos: pos._4 },
129+
panels.status.provider(ds, vars, 'Wemix') { gridPos: pos._4 },
127130

128131
row.new('RPC Proxy Metrics'),
129132
panels.proxy.calls(ds, vars) { gridPos: pos._3 },

tests/functional/http/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub(crate) mod pokt;
2121
pub(crate) mod publicnode;
2222
pub(crate) mod quicknode;
2323
pub(crate) mod unichain;
24+
pub(crate) mod wemix;
2425
pub(crate) mod zksync;
2526
pub(crate) mod zora;
2627

tests/functional/http/wemix.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use {
2+
super::check_if_rpc_is_responding_correctly_for_supported_chain, crate::context::ServerContext,
3+
rpc_proxy::providers::ProviderKind, test_context::test_context,
4+
};
5+
6+
#[test_context(ServerContext)]
7+
#[tokio::test]
8+
#[ignore]
9+
async fn wemix_provider(ctx: &mut ServerContext) {
10+
// Wemix Mainnet
11+
check_if_rpc_is_responding_correctly_for_supported_chain(
12+
ctx,
13+
&ProviderKind::Wemix,
14+
"eip155:1111",
15+
"0x457",
16+
)
17+
.await;
18+
19+
// Wemix Testnet
20+
check_if_rpc_is_responding_correctly_for_supported_chain(
21+
ctx,
22+
&ProviderKind::Wemix,
23+
"eip155:1112",
24+
"0x458",
25+
)
26+
.await;
27+
}

0 commit comments

Comments
 (0)