2022-05-06 00:25:40 +03:00
|
|
|
use argh::FromArgs;
|
2022-06-14 08:43:28 +03:00
|
|
|
use ethers::prelude::{Block, TxHash};
|
2022-06-16 20:51:49 +03:00
|
|
|
use futures::Future;
|
2022-05-05 22:07:09 +03:00
|
|
|
use serde::Deserialize;
|
2022-05-13 23:50:11 +03:00
|
|
|
use std::collections::HashMap;
|
2022-06-16 20:51:49 +03:00
|
|
|
use std::pin::Pin;
|
2022-05-05 22:07:09 +03:00
|
|
|
use std::sync::Arc;
|
2022-06-29 22:15:05 +03:00
|
|
|
use tokio::sync::broadcast;
|
2022-05-05 22:07:09 +03:00
|
|
|
|
2022-06-16 05:53:37 +03:00
|
|
|
use crate::app::AnyhowJoinHandle;
|
|
|
|
use crate::connection::Web3Connection;
|
|
|
|
use crate::Web3ProxyApp;
|
|
|
|
|
2022-05-22 02:34:05 +03:00
|
|
|
#[derive(Debug, FromArgs)]
|
2022-05-12 08:54:27 +03:00
|
|
|
/// Web3-proxy is a fast caching and load balancing proxy for web3 (Ethereum or similar) JsonRPC servers.
|
2022-05-06 00:25:40 +03:00
|
|
|
pub struct CliConfig {
|
|
|
|
/// what port the proxy should listen on
|
2022-05-06 09:33:29 +03:00
|
|
|
#[argh(option, default = "8544")]
|
2022-05-18 23:28:00 +03:00
|
|
|
pub port: u16,
|
2022-05-06 00:25:40 +03:00
|
|
|
|
2022-06-06 01:39:44 +03:00
|
|
|
/// number of worker threads. Defaults to the number of logical processors
|
2022-05-18 19:35:06 +03:00
|
|
|
#[argh(option, default = "0")]
|
2022-05-18 23:28:00 +03:00
|
|
|
pub workers: usize,
|
2022-05-18 19:35:06 +03:00
|
|
|
|
2022-05-12 08:54:27 +03:00
|
|
|
/// path to a toml of rpc servers
|
2022-05-21 23:40:22 +03:00
|
|
|
#[argh(option, default = "\"./config/development.toml\".to_string()")]
|
2022-05-18 23:28:00 +03:00
|
|
|
pub config: String,
|
2022-05-06 00:25:40 +03:00
|
|
|
}
|
|
|
|
|
2022-05-22 02:34:05 +03:00
|
|
|
#[derive(Debug, Deserialize)]
|
2022-05-06 00:25:40 +03:00
|
|
|
pub struct RpcConfig {
|
2022-05-12 21:49:57 +03:00
|
|
|
pub shared: RpcSharedConfig,
|
2022-05-13 23:50:11 +03:00
|
|
|
pub balanced_rpcs: HashMap<String, Web3ConnectionConfig>,
|
2022-05-06 01:21:27 +03:00
|
|
|
pub private_rpcs: Option<HashMap<String, Web3ConnectionConfig>>,
|
2022-05-05 22:07:09 +03:00
|
|
|
}
|
|
|
|
|
2022-05-12 21:49:57 +03:00
|
|
|
/// shared configuration between Web3Connections
|
2022-05-22 02:34:05 +03:00
|
|
|
#[derive(Debug, Deserialize)]
|
2022-05-12 21:49:57 +03:00
|
|
|
pub struct RpcSharedConfig {
|
|
|
|
/// TODO: what type for chain_id? TODO: this isn't at the right level. this is inside a "Config"
|
|
|
|
pub chain_id: usize,
|
2022-05-22 02:34:05 +03:00
|
|
|
pub rate_limit_redis: Option<String>,
|
2022-07-07 06:22:09 +03:00
|
|
|
// TODO: serde default for development?
|
|
|
|
// TODO: allow no limit?
|
|
|
|
pub public_rate_limit_per_minute: u32,
|
2022-05-12 21:49:57 +03:00
|
|
|
}
|
|
|
|
|
2022-05-22 02:34:05 +03:00
|
|
|
#[derive(Debug, Deserialize)]
|
2022-05-05 22:07:09 +03:00
|
|
|
pub struct Web3ConnectionConfig {
|
|
|
|
url: String,
|
|
|
|
soft_limit: u32,
|
|
|
|
hard_limit: Option<u32>,
|
|
|
|
}
|
|
|
|
|
2022-05-06 00:25:40 +03:00
|
|
|
impl RpcConfig {
|
2022-05-12 08:54:27 +03:00
|
|
|
/// Create a Web3ProxyApp from config
|
2022-05-17 20:15:18 +03:00
|
|
|
// #[instrument(name = "try_build_RpcConfig", skip_all)]
|
2022-06-16 20:51:49 +03:00
|
|
|
pub async fn spawn(
|
|
|
|
self,
|
|
|
|
) -> anyhow::Result<(
|
|
|
|
Arc<Web3ProxyApp>,
|
|
|
|
Pin<Box<dyn Future<Output = anyhow::Result<()>>>>,
|
|
|
|
)> {
|
2022-05-13 23:50:11 +03:00
|
|
|
let balanced_rpcs = self.balanced_rpcs.into_values().collect();
|
2022-05-06 01:21:27 +03:00
|
|
|
|
|
|
|
let private_rpcs = if let Some(private_rpcs) = self.private_rpcs {
|
|
|
|
private_rpcs.into_values().collect()
|
|
|
|
} else {
|
|
|
|
vec![]
|
|
|
|
};
|
2022-05-05 22:07:09 +03:00
|
|
|
|
2022-06-14 07:04:14 +03:00
|
|
|
Web3ProxyApp::spawn(
|
2022-05-22 02:34:05 +03:00
|
|
|
self.shared.chain_id,
|
|
|
|
self.shared.rate_limit_redis,
|
|
|
|
balanced_rpcs,
|
|
|
|
private_rpcs,
|
2022-07-07 06:22:09 +03:00
|
|
|
self.shared.public_rate_limit_per_minute,
|
2022-05-22 02:34:05 +03:00
|
|
|
)
|
|
|
|
.await
|
2022-05-05 22:07:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Web3ConnectionConfig {
|
2022-05-12 08:54:27 +03:00
|
|
|
/// Create a Web3Connection from config
|
2022-05-17 20:15:18 +03:00
|
|
|
// #[instrument(name = "try_build_Web3ConnectionConfig", skip_all)]
|
2022-06-14 08:43:28 +03:00
|
|
|
pub async fn spawn(
|
2022-05-05 22:07:09 +03:00
|
|
|
self,
|
2022-07-07 06:22:09 +03:00
|
|
|
redis_client_pool: Option<&redis_cell_client::RedisClientPool>,
|
2022-05-12 21:49:57 +03:00
|
|
|
chain_id: usize,
|
2022-05-22 02:34:05 +03:00
|
|
|
http_client: Option<&reqwest::Client>,
|
2022-06-29 22:15:05 +03:00
|
|
|
http_interval_sender: Option<Arc<broadcast::Sender<()>>>,
|
2022-06-14 08:43:28 +03:00
|
|
|
block_sender: Option<flume::Sender<(Block<TxHash>, Arc<Web3Connection>)>>,
|
|
|
|
tx_id_sender: Option<flume::Sender<(TxHash, Arc<Web3Connection>)>>,
|
|
|
|
) -> anyhow::Result<(Arc<Web3Connection>, AnyhowJoinHandle<()>)> {
|
2022-07-07 06:22:09 +03:00
|
|
|
let hard_rate_limit = self.hard_limit.map(|x| (x, redis_client_pool.unwrap()));
|
2022-05-22 02:34:05 +03:00
|
|
|
|
2022-06-14 07:04:14 +03:00
|
|
|
Web3Connection::spawn(
|
2022-05-12 21:49:57 +03:00
|
|
|
chain_id,
|
2022-05-05 22:07:09 +03:00
|
|
|
self.url,
|
|
|
|
http_client,
|
2022-06-29 22:15:05 +03:00
|
|
|
http_interval_sender,
|
2022-05-22 02:34:05 +03:00
|
|
|
hard_rate_limit,
|
2022-05-05 22:07:09 +03:00
|
|
|
self.soft_limit,
|
2022-06-14 08:43:28 +03:00
|
|
|
block_sender,
|
|
|
|
tx_id_sender,
|
2022-06-29 22:15:05 +03:00
|
|
|
true,
|
2022-05-05 22:07:09 +03:00
|
|
|
)
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
}
|