add optional display name

This commit is contained in:
Bryan Stitt 2022-11-13 21:05:37 +00:00
parent 46c598515a
commit 96a486866c
5 changed files with 55 additions and 12 deletions

View File

@ -41,48 +41,57 @@ response_cache_max_bytes = 10_000_000_000
[balanced_rpcs] [balanced_rpcs]
[balanced_rpcs.ankr] [balanced_rpcs.ankr]
display_name = "Ankr"
url = "https://rpc.ankr.com/eth" url = "https://rpc.ankr.com/eth"
soft_limit = 1_000 soft_limit = 1_000
weight = 0 weight = 0
[balanced_rpcs.cloudflare] [balanced_rpcs.cloudflare]
display_name = "Cloudflare"
url = "https://cloudflare-eth.com" url = "https://cloudflare-eth.com"
soft_limit = 1_000 soft_limit = 1_000
weight = 10 weight = 10
[balanced_rpcs.blastapi] [balanced_rpcs.blastapi]
display_name = "Blast"
url = "https://eth-mainnet.public.blastapi.io" url = "https://eth-mainnet.public.blastapi.io"
soft_limit = 1_000 soft_limit = 1_000
weight = 10 weight = 10
[balanced_rpcs.mycryptoapi] [balanced_rpcs.mycryptoapi]
display_name = "MyCrypto"
disabled = true disabled = true
url = "https://api.mycryptoapi.com/eth" url = "https://api.mycryptoapi.com/eth"
soft_limit = 1_000 soft_limit = 1_000
weight = 25 weight = 25
[balanced_rpcs.pokt-v1] [balanced_rpcs.pokt-v1]
display_name = "Pokt #1"
url = "https://eth-mainnet.gateway.pokt.network/v1/5f3453978e354ab992c4da79" url = "https://eth-mainnet.gateway.pokt.network/v1/5f3453978e354ab992c4da79"
soft_limit = 500 soft_limit = 500
weight = 25 weight = 25
[balanced_rpcs.pokt] [balanced_rpcs.pokt]
display_name = "Pokt #2"
url = "https://eth-rpc.gateway.pokt.network" url = "https://eth-rpc.gateway.pokt.network"
soft_limit = 500 soft_limit = 500
weight = 50 weight = 50
[balanced_rpcs.runonflux] [balanced_rpcs.runonflux]
display_name = "Run on Flux (light)"
url = "https://ethereumnodelight.app.runonflux.io" url = "https://ethereumnodelight.app.runonflux.io"
soft_limit = 1_000 soft_limit = 1_000
weight = 75 weight = 75
[balanced_rpcs.linkpool] [balanced_rpcs.linkpool]
display_name = "Linkpool"
url = "https://main-rpc.linkpool.io" url = "https://main-rpc.linkpool.io"
soft_limit = 500 soft_limit = 500
weight = 75 weight = 75
# load balanced light nodes are not very reliable # load balanced light nodes are not very reliable
[balanced_rpcs.linkpool-light] [balanced_rpcs.linkpool-light]
display_name = "Linkpool (light)"
disabled = true disabled = true
url = "https://main-light.eth.linkpool.io" url = "https://main-light.eth.linkpool.io"
soft_limit = 100 soft_limit = 100
@ -94,30 +103,35 @@ response_cache_max_bytes = 10_000_000_000
[private_rpcs.eden] [private_rpcs.eden]
disabled = true disabled = true
display_name = "Eden network"
url = "https://api.edennetwork.io/v1/" url = "https://api.edennetwork.io/v1/"
soft_limit = 1_805 soft_limit = 1_805
weight = 0 weight = 0
[private_rpcs.eden_beta] [private_rpcs.eden_beta]
disabled = true disabled = true
display_name = "Eden network beta"
url = "https://api.edennetwork.io/v1/beta" url = "https://api.edennetwork.io/v1/beta"
soft_limit = 5_861 soft_limit = 5_861
weight = 0 weight = 0
[private_rpcs.ethermine] [private_rpcs.ethermine]
disabled = true disabled = true
display_name = "Ethermine"
url = "https://rpc.ethermine.org" url = "https://rpc.ethermine.org"
soft_limit = 5_861 soft_limit = 5_861
weight = 0 weight = 0
[private_rpcs.flashbots] [private_rpcs.flashbots]
disabled = true disabled = true
display_name = "Flashbots Fast"
url = "https://rpc.flashbots.net/fast" url = "https://rpc.flashbots.net/fast"
soft_limit = 7_074 soft_limit = 7_074
weight = 0 weight = 0
[private_rpcs.securerpc] [private_rpcs.securerpc]
disabled = true disabled = true
display_name = "SecureRPC"
url = "https://gibson.securerpc.com/v1" url = "https://gibson.securerpc.com/v1"
soft_limit = 4_560 soft_limit = 4_560
weight = 0 weight = 0

View File

@ -275,11 +275,27 @@ mod tests {
balanced_rpcs: HashMap::from([ balanced_rpcs: HashMap::from([
( (
"anvil".to_string(), "anvil".to_string(),
Web3ConnectionConfig::new(false, anvil.endpoint(), 100, None, 1, Some(false)), Web3ConnectionConfig::new(
false,
None,
anvil.endpoint(),
100,
None,
1,
Some(false),
),
), ),
( (
"anvil_ws".to_string(), "anvil_ws".to_string(),
Web3ConnectionConfig::new(false, anvil.ws_endpoint(), 100, None, 0, Some(true)), Web3ConnectionConfig::new(
false,
None,
anvil.ws_endpoint(),
100,
None,
0,
Some(true),
),
), ),
]), ]),
private_rpcs: None, private_rpcs: None,

View File

@ -182,6 +182,8 @@ pub struct Web3ConnectionConfig {
/// simple way to disable a connection without deleting the row /// simple way to disable a connection without deleting the row
#[serde(default)] #[serde(default)]
pub disabled: bool, pub disabled: bool,
/// a name used in /status and other user facing messages
pub display_name: Option<String>,
/// websocket (or http if no websocket) /// websocket (or http if no websocket)
pub url: String, pub url: String,
/// the requests per second at which the server starts slowing down /// the requests per second at which the server starts slowing down
@ -189,6 +191,7 @@ pub struct Web3ConnectionConfig {
/// the requests per second at which the server throws errors (rate limit or otherwise) /// the requests per second at which the server throws errors (rate limit or otherwise)
pub hard_limit: Option<u64>, pub hard_limit: Option<u64>,
/// All else equal, a server with a lower weight receives more requests. Ranges 0-100 /// All else equal, a server with a lower weight receives more requests. Ranges 0-100
#[serde(default = "default_weight")]
pub weight: u32, pub weight: u32,
/// Subscribe to the firehose of pending transactions /// Subscribe to the firehose of pending transactions
/// Don't do this with free rpcs /// Don't do this with free rpcs
@ -196,9 +199,13 @@ pub struct Web3ConnectionConfig {
pub subscribe_txs: Option<bool>, pub subscribe_txs: Option<bool>,
} }
fn default_weight() -> u32 {
0
}
impl Web3ConnectionConfig { impl Web3ConnectionConfig {
/// Create a Web3Connection from config /// Create a Web3Connection from config
/// TODO: move this into Web3Connection (just need to make things pub(crate)) /// TODO: move this into Web3Connection? (just need to make things pub(crate))
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub async fn spawn( pub async fn spawn(
self, self,
@ -232,6 +239,7 @@ impl Web3ConnectionConfig {
Web3Connection::spawn( Web3Connection::spawn(
name, name,
self.display_name,
chain_id, chain_id,
db_conn, db_conn,
self.url, self.url,

View File

@ -501,7 +501,7 @@ impl Web3Connections {
if consensus_head_block_id.hash == old_block_id.hash { if consensus_head_block_id.hash == old_block_id.hash {
// no change in hash. no need to use head_block_sender // no change in hash. no need to use head_block_sender
debug!( debug!(
"con {}/{}/{}. con head={}. rpc={}. rpc head={}", "con {}/{}/{} con_head={} rpc={} rpc_head={}",
num_consensus_rpcs, num_consensus_rpcs,
num_connection_heads, num_connection_heads,
total_conns, total_conns,
@ -512,7 +512,7 @@ impl Web3Connections {
} else { } else {
// hash changed // hash changed
debug!( debug!(
"unc {}/{}/{} con_head={}. old={}. rpc_head={}. rpc={}", "unc {}/{}/{} con_head={} old={} rpc_head={} rpc={}",
num_consensus_rpcs, num_consensus_rpcs,
num_connection_heads, num_connection_heads,
total_conns, total_conns,
@ -534,7 +534,7 @@ impl Web3Connections {
Ordering::Less => { Ordering::Less => {
// this is unlikely but possible // this is unlikely but possible
// TODO: better log // TODO: better log
warn!("chain rolled back {}/{}/{}. con_head={} old_head={}. rpc_head={}. rpc={}", num_consensus_rpcs, num_connection_heads, total_conns, consensus_head_block_id, old_block_id, rpc_head_str, rpc); warn!("chain rolled back {}/{}/{} con_head={} old_head={} rpc_head={} rpc={}", num_consensus_rpcs, num_connection_heads, total_conns, consensus_head_block_id, old_block_id, rpc_head_str, rpc);
// TODO: tell save_block to remove any higher block numbers from the cache. not needed because we have other checks on requested blocks being > head, but still seems slike a good idea // TODO: tell save_block to remove any higher block numbers from the cache. not needed because we have other checks on requested blocks being > head, but still seems slike a good idea
self.save_block(&consensus_head_block, true).await.context( self.save_block(&consensus_head_block, true).await.context(
@ -547,7 +547,7 @@ impl Web3Connections {
} }
Ordering::Greater => { Ordering::Greater => {
debug!( debug!(
"new {}/{}/{} conn_head={}. rpc_head={}. rpc={}", "new {}/{}/{} con head={} rpc_head={} rpc={}",
num_consensus_rpcs, num_consensus_rpcs,
num_connection_heads, num_connection_heads,
total_conns, total_conns,

View File

@ -30,6 +30,7 @@ use tokio::time::{interval, sleep, sleep_until, Duration, Instant, MissedTickBeh
/// An active connection to a Web3 RPC server like geth or erigon. /// An active connection to a Web3 RPC server like geth or erigon.
pub struct Web3Connection { pub struct Web3Connection {
pub name: String, pub name: String,
pub display_name: Option<String>,
/// TODO: can we get this from the provider? do we even need it? /// TODO: can we get this from the provider? do we even need it?
url: String, url: String,
/// Some connections use an http_client. we keep a clone for reconnecting /// Some connections use an http_client. we keep a clone for reconnecting
@ -62,6 +63,7 @@ impl Web3Connection {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub async fn spawn( pub async fn spawn(
name: String, name: String,
display_name: Option<String>,
chain_id: u64, chain_id: u64,
db_conn: Option<DatabaseConnection>, db_conn: Option<DatabaseConnection>,
url_str: String, url_str: String,
@ -95,6 +97,7 @@ impl Web3Connection {
let new_connection = Self { let new_connection = Self {
name, name,
display_name,
http_client, http_client,
url: url_str, url: url_str,
active_requests: 0.into(), active_requests: 0.into(),
@ -737,7 +740,7 @@ impl Web3Connection {
authorization: Arc<Authorization>, authorization: Arc<Authorization>,
tx_id_sender: flume::Sender<(TxHash, Arc<Self>)>, tx_id_sender: flume::Sender<(TxHash, Arc<Self>)>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
info!( "watching pending transactions on {}", self); info!("watching pending transactions on {}", self);
// TODO: is a RwLock of an Option<Arc> the right thing here? // TODO: is a RwLock of an Option<Arc> the right thing here?
if let Some(provider) = self.provider.read().await.clone() { if let Some(provider) = self.provider.read().await.clone() {
@ -790,7 +793,7 @@ impl Web3Connection {
// TODO: is this always an error? // TODO: is this always an error?
// TODO: we probably don't want a warn and to return error // TODO: we probably don't want a warn and to return error
warn!( "pending_transactions subscription ended on {}", self); warn!("pending_transactions subscription ended on {}", self);
return Err(anyhow::anyhow!("pending_transactions subscription ended")); return Err(anyhow::anyhow!("pending_transactions subscription ended"));
} }
} }
@ -859,7 +862,7 @@ impl Web3Connection {
// save the smallest retry_after. if nothing succeeds, return an Err with retry_after in it // save the smallest retry_after. if nothing succeeds, return an Err with retry_after in it
// TODO: use tracing better // TODO: use tracing better
// TODO: i'm seeing "Exhausted rate limit on moralis: 0ns". How is it getting 0? // TODO: i'm seeing "Exhausted rate limit on moralis: 0ns". How is it getting 0?
warn!( "Exhausted rate limit on {}. Retry at {:?}", self, retry_at); warn!("Exhausted rate limit on {}. Retry at {:?}", self, retry_at);
return Ok(OpenRequestResult::RetryAt(retry_at)); return Ok(OpenRequestResult::RetryAt(retry_at));
} }
@ -915,10 +918,12 @@ impl Serialize for Web3Connection {
S: Serializer, S: Serializer,
{ {
// 3 is the number of fields in the struct. // 3 is the number of fields in the struct.
let mut state = serializer.serialize_struct("Web3Connection", 7)?; let mut state = serializer.serialize_struct("Web3Connection", 8)?;
// the url is excluded because it likely includes private information. just show the name // the url is excluded because it likely includes private information. just show the name that we use in keys
state.serialize_field("name", &self.name)?; state.serialize_field("name", &self.name)?;
// a longer name for display to users
state.serialize_field("display_name", &self.display_name)?;
let block_data_limit = self.block_data_limit.load(atomic::Ordering::Relaxed); let block_data_limit = self.block_data_limit.load(atomic::Ordering::Relaxed);
if block_data_limit == u64::MAX { if block_data_limit == u64::MAX {