move allowed_lag around
This commit is contained in:
parent
c0fc999e02
commit
045065986a
@ -54,50 +54,50 @@ response_cache_max_bytes = 10_000_000_000
|
|||||||
display_name = "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
|
tier = 0
|
||||||
|
|
||||||
[balanced_rpcs.cloudflare]
|
[balanced_rpcs.cloudflare]
|
||||||
display_name = "Cloudflare"
|
display_name = "Cloudflare"
|
||||||
url = "https://cloudflare-eth.com"
|
url = "https://cloudflare-eth.com"
|
||||||
soft_limit = 1_000
|
soft_limit = 1_000
|
||||||
weight = 10
|
tier = 1
|
||||||
|
|
||||||
[balanced_rpcs.blastapi]
|
[balanced_rpcs.blastapi]
|
||||||
display_name = "Blast"
|
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
|
tier = 1
|
||||||
|
|
||||||
[balanced_rpcs.mycryptoapi]
|
[balanced_rpcs.mycryptoapi]
|
||||||
display_name = "MyCrypto"
|
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
|
tier = 2
|
||||||
|
|
||||||
[balanced_rpcs.pokt-v1]
|
[balanced_rpcs.pokt-v1]
|
||||||
display_name = "Pokt #1"
|
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
|
tier = 2
|
||||||
|
|
||||||
[balanced_rpcs.pokt]
|
[balanced_rpcs.pokt]
|
||||||
display_name = "Pokt #2"
|
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
|
tier = 3
|
||||||
|
|
||||||
[balanced_rpcs.runonflux]
|
|
||||||
display_name = "Run on Flux (light)"
|
|
||||||
url = "https://ethereumnodelight.app.runonflux.io"
|
|
||||||
soft_limit = 1_000
|
|
||||||
weight = 75
|
|
||||||
|
|
||||||
[balanced_rpcs.linkpool]
|
[balanced_rpcs.linkpool]
|
||||||
display_name = "Linkpool"
|
display_name = "Linkpool"
|
||||||
url = "https://main-rpc.linkpool.io"
|
url = "https://main-rpc.linkpool.io"
|
||||||
soft_limit = 500
|
soft_limit = 500
|
||||||
weight = 75
|
tier = 4
|
||||||
|
|
||||||
|
[balanced_rpcs.runonflux]
|
||||||
|
display_name = "Run on Flux (light)"
|
||||||
|
url = "https://ethereumnodelight.app.runonflux.io"
|
||||||
|
soft_limit = 1_000
|
||||||
|
tier = 5
|
||||||
|
|
||||||
# load balanced light nodes are not very reliable
|
# load balanced light nodes are not very reliable
|
||||||
[balanced_rpcs.linkpool-light]
|
[balanced_rpcs.linkpool-light]
|
||||||
@ -105,7 +105,7 @@ response_cache_max_bytes = 10_000_000_000
|
|||||||
disabled = true
|
disabled = true
|
||||||
url = "https://main-light.eth.linkpool.io"
|
url = "https://main-light.eth.linkpool.io"
|
||||||
soft_limit = 100
|
soft_limit = 100
|
||||||
weight = 75
|
tier = 5
|
||||||
|
|
||||||
[private_rpcs]
|
[private_rpcs]
|
||||||
|
|
||||||
@ -116,32 +116,32 @@ response_cache_max_bytes = 10_000_000_000
|
|||||||
display_name = "Eden network"
|
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
|
tier = 0
|
||||||
|
|
||||||
[private_rpcs.eden_beta]
|
[private_rpcs.eden_beta]
|
||||||
disabled = true
|
disabled = true
|
||||||
display_name = "Eden network beta"
|
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
|
tier = 0
|
||||||
|
|
||||||
[private_rpcs.ethermine]
|
[private_rpcs.ethermine]
|
||||||
disabled = true
|
disabled = true
|
||||||
display_name = "Ethermine"
|
display_name = "Ethermine"
|
||||||
url = "https://rpc.ethermine.org"
|
url = "https://rpc.ethermine.org"
|
||||||
soft_limit = 5_861
|
soft_limit = 5_861
|
||||||
weight = 0
|
tier = 0
|
||||||
|
|
||||||
[private_rpcs.flashbots]
|
[private_rpcs.flashbots]
|
||||||
disabled = true
|
disabled = true
|
||||||
display_name = "Flashbots Fast"
|
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
|
tier = 0
|
||||||
|
|
||||||
[private_rpcs.securerpc]
|
[private_rpcs.securerpc]
|
||||||
disabled = true
|
disabled = true
|
||||||
display_name = "SecureRPC"
|
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
|
tier = 0
|
||||||
|
@ -221,6 +221,7 @@ impl Web3ConnectionConfig {
|
|||||||
pub async fn spawn(
|
pub async fn spawn(
|
||||||
self,
|
self,
|
||||||
name: String,
|
name: String,
|
||||||
|
allowed_lag: u64,
|
||||||
db_conn: Option<DatabaseConnection>,
|
db_conn: Option<DatabaseConnection>,
|
||||||
redis_pool: Option<redis_rate_limiter::RedisPool>,
|
redis_pool: Option<redis_rate_limiter::RedisPool>,
|
||||||
chain_id: u64,
|
chain_id: u64,
|
||||||
@ -257,6 +258,7 @@ impl Web3ConnectionConfig {
|
|||||||
|
|
||||||
Web3Connection::spawn(
|
Web3Connection::spawn(
|
||||||
name,
|
name,
|
||||||
|
allowed_lag,
|
||||||
self.display_name,
|
self.display_name,
|
||||||
chain_id,
|
chain_id,
|
||||||
db_conn,
|
db_conn,
|
||||||
|
@ -10,6 +10,7 @@ use axum::{response::IntoResponse, Extension, Json};
|
|||||||
use axum_client_ip::ClientIp;
|
use axum_client_ip::ClientIp;
|
||||||
use axum_macros::debug_handler;
|
use axum_macros::debug_handler;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use log::debug;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// POST /rpc -- Public entrypoint for HTTP JSON-RPC requests. Web3 wallets use this.
|
/// POST /rpc -- Public entrypoint for HTTP JSON-RPC requests. Web3 wallets use this.
|
||||||
@ -90,7 +91,7 @@ pub async fn proxy_web3_rpc_with_key(
|
|||||||
|
|
||||||
let headers = response.headers_mut();
|
let headers = response.headers_mut();
|
||||||
|
|
||||||
// TODO: special string if no rpcs were used (cache hit)?
|
// TODO: special string if no rpcs were used (cache hit)? or is an empty string fine? maybe the rpc name + "cached"
|
||||||
let rpcs: String = rpcs.into_iter().map(|x| x.name.clone()).join(",");
|
let rpcs: String = rpcs.into_iter().map(|x| x.name.clone()).join(",");
|
||||||
|
|
||||||
headers.insert(
|
headers.insert(
|
||||||
|
@ -29,7 +29,7 @@ pub type BlockHashesCache = Cache<H256, ArcBlock, hashbrown::hash_map::DefaultHa
|
|||||||
pub struct SavedBlock {
|
pub struct SavedBlock {
|
||||||
pub block: ArcBlock,
|
pub block: ArcBlock,
|
||||||
/// number of seconds this block was behind the current time when received
|
/// number of seconds this block was behind the current time when received
|
||||||
pub lag: u64,
|
pub age: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for SavedBlock {
|
impl PartialEq for SavedBlock {
|
||||||
@ -45,11 +45,11 @@ impl PartialEq for SavedBlock {
|
|||||||
|
|
||||||
impl SavedBlock {
|
impl SavedBlock {
|
||||||
pub fn new(block: ArcBlock) -> Self {
|
pub fn new(block: ArcBlock) -> Self {
|
||||||
let mut x = Self { block, lag: 0 };
|
let mut x = Self { block, age: 0 };
|
||||||
|
|
||||||
// no need to recalulate lag every time
|
// no need to recalulate lag every time
|
||||||
// if the head block gets too old, a health check restarts this connection
|
// if the head block gets too old, a health check restarts this connection
|
||||||
x.lag = x.lag();
|
x.age = x.lag();
|
||||||
|
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ impl SavedBlock {
|
|||||||
|
|
||||||
/// When the block was received, this node was still syncing
|
/// When the block was received, this node was still syncing
|
||||||
pub fn syncing(&self, allowed_lag: u64) -> bool {
|
pub fn syncing(&self, allowed_lag: u64) -> bool {
|
||||||
self.lag > allowed_lag
|
self.age > allowed_lag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,13 +93,7 @@ impl From<ArcBlock> for SavedBlock {
|
|||||||
|
|
||||||
impl Display for SavedBlock {
|
impl Display for SavedBlock {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{} ({})", self.number(), self.hash())?;
|
write!(f, "{} ({}, {}s old)", self.number(), self.hash(), self.age)
|
||||||
|
|
||||||
if self.syncing(0) {
|
|
||||||
write!(f, " (behind by {} seconds)", self.lag)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +314,7 @@ impl Web3Connections {
|
|||||||
// TODO: don't default to 60. different chains are differen
|
// TODO: don't default to 60. different chains are differen
|
||||||
if rpc_head_block.syncing(60) {
|
if rpc_head_block.syncing(60) {
|
||||||
if connection_heads.remove(&rpc.name).is_some() {
|
if connection_heads.remove(&rpc.name).is_some() {
|
||||||
warn!("{} is behind by {} seconds", &rpc.name, rpc_head_block.lag);
|
warn!("{} is behind by {} seconds", &rpc.name, rpc_head_block.age);
|
||||||
} else {
|
} else {
|
||||||
// we didn't remove anything and this block is old. exit early
|
// we didn't remove anything and this block is old. exit early
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -63,6 +63,7 @@ pub struct Web3Connection {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub display_name: Option<String>,
|
pub display_name: Option<String>,
|
||||||
pub db_conn: Option<DatabaseConnection>,
|
pub db_conn: Option<DatabaseConnection>,
|
||||||
|
pub(super) allowed_lag: u64,
|
||||||
/// 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?
|
||||||
pub(super) url: String,
|
pub(super) 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
|
||||||
@ -98,6 +99,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,
|
||||||
|
allowed_lag: u64,
|
||||||
display_name: Option<String>,
|
display_name: Option<String>,
|
||||||
chain_id: u64,
|
chain_id: u64,
|
||||||
db_conn: Option<DatabaseConnection>,
|
db_conn: Option<DatabaseConnection>,
|
||||||
@ -135,6 +137,7 @@ impl Web3Connection {
|
|||||||
|
|
||||||
let new_connection = Self {
|
let new_connection = Self {
|
||||||
name,
|
name,
|
||||||
|
allowed_lag,
|
||||||
db_conn: db_conn.clone(),
|
db_conn: db_conn.clone(),
|
||||||
display_name,
|
display_name,
|
||||||
http_client,
|
http_client,
|
||||||
@ -587,6 +590,8 @@ impl Web3Connection {
|
|||||||
reconnect: bool,
|
reconnect: bool,
|
||||||
tx_id_sender: Option<flume::Sender<(TxHash, Arc<Self>)>>,
|
tx_id_sender: Option<flume::Sender<(TxHash, Arc<Self>)>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let allowed_lag = self.allowed_lag;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let http_interval_receiver = http_interval_sender.as_ref().map(|x| x.subscribe());
|
let http_interval_receiver = http_interval_sender.as_ref().map(|x| x.subscribe());
|
||||||
|
|
||||||
@ -641,10 +646,10 @@ impl Web3Connection {
|
|||||||
if let Some(x) = &*conn.head_block.read() {
|
if let Some(x) = &*conn.head_block.read() {
|
||||||
// if this block is too old, return an error so we reconnect
|
// if this block is too old, return an error so we reconnect
|
||||||
let current_lag = x.lag();
|
let current_lag = x.lag();
|
||||||
if current_lag > 0 {
|
if current_lag > allowed_lag {
|
||||||
let level = if warned == 0 {
|
let level = if warned == 0 {
|
||||||
log::Level::Warn
|
log::Level::Warn
|
||||||
} else if current_lag % 1000 == 0 {
|
} else if warned % 100 == 0 {
|
||||||
log::Level::Debug
|
log::Level::Debug
|
||||||
} else {
|
} else {
|
||||||
log::Level::Trace
|
log::Level::Trace
|
||||||
@ -1208,6 +1213,7 @@ mod tests {
|
|||||||
|
|
||||||
let x = Web3Connection {
|
let x = Web3Connection {
|
||||||
name: "name".to_string(),
|
name: "name".to_string(),
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com".to_string(),
|
url: "ws://example.com".to_string(),
|
||||||
@ -1255,6 +1261,7 @@ mod tests {
|
|||||||
// TODO: this is getting long. have a `impl Default`
|
// TODO: this is getting long. have a `impl Default`
|
||||||
let x = Web3Connection {
|
let x = Web3Connection {
|
||||||
name: "name".to_string(),
|
name: "name".to_string(),
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com".to_string(),
|
url: "ws://example.com".to_string(),
|
||||||
@ -1306,6 +1313,7 @@ mod tests {
|
|||||||
|
|
||||||
let x = Web3Connection {
|
let x = Web3Connection {
|
||||||
name: "name".to_string(),
|
name: "name".to_string(),
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com".to_string(),
|
url: "ws://example.com".to_string(),
|
||||||
|
@ -88,6 +88,9 @@ impl Web3Connections {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: this might be too aggressive. think about this more
|
||||||
|
let allowed_lag = ((expected_block_time_ms * 3) as f64 / 1000.0).round() as u64;
|
||||||
|
|
||||||
let http_interval_sender = if http_client.is_some() {
|
let http_interval_sender = if http_client.is_some() {
|
||||||
let (sender, receiver) = broadcast::channel(1);
|
let (sender, receiver) = broadcast::channel(1);
|
||||||
|
|
||||||
@ -151,6 +154,7 @@ impl Web3Connections {
|
|||||||
server_config
|
server_config
|
||||||
.spawn(
|
.spawn(
|
||||||
server_name,
|
server_name,
|
||||||
|
allowed_lag,
|
||||||
db_conn,
|
db_conn,
|
||||||
redis_pool,
|
redis_pool,
|
||||||
chain_id,
|
chain_id,
|
||||||
@ -428,7 +432,7 @@ impl Web3Connections {
|
|||||||
match x_head_block {
|
match x_head_block {
|
||||||
None => continue,
|
None => continue,
|
||||||
Some(x_head) => {
|
Some(x_head) => {
|
||||||
let key = (x_head.number(), u64::MAX - x.tier);
|
let key = (Some(x_head.number()), u64::MAX - x.tier);
|
||||||
|
|
||||||
m.entry(key).or_insert_with(Vec::new).push(x);
|
m.entry(key).or_insert_with(Vec::new).push(x);
|
||||||
}
|
}
|
||||||
@ -450,8 +454,6 @@ impl Web3Connections {
|
|||||||
return Ok(OpenRequestResult::NotReady);
|
return Ok(OpenRequestResult::NotReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
let head_num = head_block.number();
|
|
||||||
|
|
||||||
let mut m = BTreeMap::new();
|
let mut m = BTreeMap::new();
|
||||||
|
|
||||||
for x in synced_connections
|
for x in synced_connections
|
||||||
@ -459,7 +461,7 @@ impl Web3Connections {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|x| !skip.contains(x))
|
.filter(|x| !skip.contains(x))
|
||||||
{
|
{
|
||||||
let key = (head_num, u64::MAX - x.tier);
|
let key = (None, u64::MAX - x.tier);
|
||||||
|
|
||||||
m.entry(key).or_insert_with(Vec::new).push(x.clone());
|
m.entry(key).or_insert_with(Vec::new).push(x.clone());
|
||||||
}
|
}
|
||||||
@ -472,6 +474,7 @@ impl Web3Connections {
|
|||||||
for usable_rpcs in usable_rpcs_by_head_num_and_weight.into_values().rev() {
|
for usable_rpcs in usable_rpcs_by_head_num_and_weight.into_values().rev() {
|
||||||
// under heavy load, it is possible for even our best server to be negative
|
// under heavy load, it is possible for even our best server to be negative
|
||||||
let mut minimum = f64::MAX;
|
let mut minimum = f64::MAX;
|
||||||
|
let mut maximum = f64::MIN;
|
||||||
|
|
||||||
// we sort on a combination of values. cache them here so that we don't do this math multiple times.
|
// we sort on a combination of values. cache them here so that we don't do this math multiple times.
|
||||||
let mut available_request_map: HashMap<_, f64> = usable_rpcs
|
let mut available_request_map: HashMap<_, f64> = usable_rpcs
|
||||||
@ -487,13 +490,20 @@ impl Web3Connections {
|
|||||||
|
|
||||||
trace!("available requests on {}: {}", rpc, available_requests);
|
trace!("available requests on {}: {}", rpc, available_requests);
|
||||||
|
|
||||||
minimum = available_requests.min(minimum);
|
minimum = minimum.min(available_requests);
|
||||||
|
maximum = maximum.max(available_requests);
|
||||||
|
|
||||||
(rpc, available_requests)
|
(rpc, available_requests)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
trace!("minimum available requests: {}", minimum);
|
trace!("minimum available requests: {}", minimum);
|
||||||
|
trace!("maximum available requests: {}", minimum);
|
||||||
|
|
||||||
|
if maximum < 0.0 {
|
||||||
|
// TODO: if maximum < 0 and there are other tiers on the same block, we should include them now
|
||||||
|
warn!("soft limits overloaded: {} to {}", minimum, maximum)
|
||||||
|
}
|
||||||
|
|
||||||
// choose_multiple_weighted can't have negative numbers. shift up if any are negative
|
// choose_multiple_weighted can't have negative numbers. shift up if any are negative
|
||||||
// TODO: is this a correct way to shift?
|
// TODO: is this a correct way to shift?
|
||||||
@ -513,7 +523,7 @@ impl Web3Connections {
|
|||||||
|
|
||||||
let sorted_rpcs = {
|
let sorted_rpcs = {
|
||||||
if usable_rpcs.len() == 1 {
|
if usable_rpcs.len() == 1 {
|
||||||
// TODO: return now instead?
|
// TODO: return now instead? we shouldn't need another alloc
|
||||||
vec![usable_rpcs.get(0).expect("there should be 1")]
|
vec![usable_rpcs.get(0).expect("there should be 1")]
|
||||||
} else {
|
} else {
|
||||||
let mut rng = thread_fast_rng::thread_fast_rng();
|
let mut rng = thread_fast_rng::thread_fast_rng();
|
||||||
@ -935,6 +945,8 @@ mod tests {
|
|||||||
|
|
||||||
let head_rpc = Web3Connection {
|
let head_rpc = Web3Connection {
|
||||||
name: "synced".to_string(),
|
name: "synced".to_string(),
|
||||||
|
// TODO: what should this be?
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com/synced".to_string(),
|
url: "ws://example.com/synced".to_string(),
|
||||||
@ -954,6 +966,7 @@ mod tests {
|
|||||||
|
|
||||||
let lagged_rpc = Web3Connection {
|
let lagged_rpc = Web3Connection {
|
||||||
name: "lagged".to_string(),
|
name: "lagged".to_string(),
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com/lagged".to_string(),
|
url: "ws://example.com/lagged".to_string(),
|
||||||
@ -1157,6 +1170,7 @@ mod tests {
|
|||||||
|
|
||||||
let pruned_rpc = Web3Connection {
|
let pruned_rpc = Web3Connection {
|
||||||
name: "pruned".to_string(),
|
name: "pruned".to_string(),
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com/pruned".to_string(),
|
url: "ws://example.com/pruned".to_string(),
|
||||||
@ -1176,6 +1190,7 @@ mod tests {
|
|||||||
|
|
||||||
let archive_rpc = Web3Connection {
|
let archive_rpc = Web3Connection {
|
||||||
name: "archive".to_string(),
|
name: "archive".to_string(),
|
||||||
|
allowed_lag: 10,
|
||||||
db_conn: None,
|
db_conn: None,
|
||||||
display_name: None,
|
display_name: None,
|
||||||
url: "ws://example.com/archive".to_string(),
|
url: "ws://example.com/archive".to_string(),
|
||||||
|
Loading…
Reference in New Issue
Block a user