2022-08-24 02:56:47 +03:00
|
|
|
//! Helper functions for turning ether's BlockNumber into numbers and updating incoming queries to match.
|
2023-07-13 20:58:22 +03:00
|
|
|
use crate::rpcs::many::Web3Rpcs;
|
2023-06-29 03:42:43 +03:00
|
|
|
use crate::{
|
|
|
|
errors::{Web3ProxyError, Web3ProxyResult},
|
|
|
|
rpcs::blockchain::Web3ProxyBlock,
|
|
|
|
};
|
2022-09-22 02:50:55 +03:00
|
|
|
use anyhow::Context;
|
2023-06-29 03:42:43 +03:00
|
|
|
use derive_more::From;
|
2022-09-21 07:48:21 +03:00
|
|
|
use ethers::{
|
|
|
|
prelude::{BlockNumber, U64},
|
|
|
|
types::H256,
|
|
|
|
};
|
2022-12-17 07:05:01 +03:00
|
|
|
use serde_json::json;
|
2023-07-10 08:52:18 +03:00
|
|
|
use tracing::{error, trace, warn};
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2022-12-20 02:59:01 +03:00
|
|
|
#[allow(non_snake_case)]
|
2023-06-29 03:42:43 +03:00
|
|
|
pub fn BlockNumber_to_U64(block_num: BlockNumber, latest_block: &U64) -> (U64, bool) {
|
2022-08-10 05:37:34 +03:00
|
|
|
match block_num {
|
2023-01-31 19:30:24 +03:00
|
|
|
BlockNumber::Earliest => (U64::zero(), false),
|
2022-10-27 01:29:38 +03:00
|
|
|
BlockNumber::Finalized => {
|
|
|
|
warn!("finalized block requested! not yet implemented!");
|
2023-06-29 03:42:43 +03:00
|
|
|
(*latest_block - 10, false)
|
2022-10-27 01:29:38 +03:00
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
BlockNumber::Latest => {
|
|
|
|
// change "latest" to a number
|
2023-06-29 03:42:43 +03:00
|
|
|
(*latest_block, true)
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
2022-08-23 23:45:00 +03:00
|
|
|
BlockNumber::Number(x) => {
|
|
|
|
// we already have a number
|
2023-01-31 19:30:24 +03:00
|
|
|
(x, false)
|
2022-08-23 23:45:00 +03:00
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
BlockNumber::Pending => {
|
2023-01-31 19:30:24 +03:00
|
|
|
// modified is false because we want the backend to see "pending"
|
2022-08-10 05:37:34 +03:00
|
|
|
// TODO: think more about how to handle Pending
|
2023-06-29 03:42:43 +03:00
|
|
|
(*latest_block, false)
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
2022-10-27 01:29:38 +03:00
|
|
|
BlockNumber::Safe => {
|
2023-06-29 03:42:43 +03:00
|
|
|
warn!("safe block requested! not yet implemented!");
|
|
|
|
(*latest_block - 3, false)
|
2022-10-27 01:29:38 +03:00
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
#[derive(Clone, Debug, Eq, From, PartialEq)]
|
|
|
|
pub struct BlockNumAndHash(U64, H256);
|
|
|
|
|
|
|
|
impl BlockNumAndHash {
|
|
|
|
pub fn num(&self) -> &U64 {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
pub fn hash(&self) -> &H256 {
|
|
|
|
&self.1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&Web3ProxyBlock> for BlockNumAndHash {
|
|
|
|
fn from(value: &Web3ProxyBlock) -> Self {
|
|
|
|
let n = *value.number();
|
|
|
|
let h = *value.hash();
|
2022-11-12 11:24:32 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
Self(n, h)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-08 01:28:24 +03:00
|
|
|
/// modify params to always have a block hash and not "latest"
|
|
|
|
/// TODO: this should replace all block numbers with hashes, not just "latest"
|
2022-09-22 02:50:55 +03:00
|
|
|
pub async fn clean_block_number(
|
2022-08-10 05:37:34 +03:00
|
|
|
params: &mut serde_json::Value,
|
|
|
|
block_param_id: usize,
|
2023-06-29 03:42:43 +03:00
|
|
|
latest_block: &Web3ProxyBlock,
|
2023-02-06 20:55:27 +03:00
|
|
|
rpcs: &Web3Rpcs,
|
2023-07-11 09:08:06 +03:00
|
|
|
) -> Web3ProxyResult<BlockNumAndHash> {
|
2022-08-10 05:37:34 +03:00
|
|
|
match params.as_array_mut() {
|
2022-09-10 03:58:33 +03:00
|
|
|
None => {
|
|
|
|
// TODO: this needs the correct error code in the response
|
2023-07-11 09:08:06 +03:00
|
|
|
Err(anyhow::anyhow!("params not an array").into())
|
2022-09-10 03:58:33 +03:00
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
Some(params) => match params.get_mut(block_param_id) {
|
|
|
|
None => {
|
2022-12-24 03:15:48 +03:00
|
|
|
if params.len() == block_param_id {
|
|
|
|
// add the latest block number to the end of the params
|
2023-01-31 20:47:19 +03:00
|
|
|
params.push(json!(latest_block));
|
2022-12-24 03:15:48 +03:00
|
|
|
} else {
|
|
|
|
// don't modify the request. only cache with current block
|
|
|
|
// TODO: more useful log that include the
|
|
|
|
warn!("unexpected params length");
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
|
|
|
|
2022-12-24 03:15:48 +03:00
|
|
|
// don't modify params, just cache with the current block
|
2023-06-29 03:42:43 +03:00
|
|
|
Ok(latest_block.into())
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
|
|
|
Some(x) => {
|
|
|
|
// convert the json value to a BlockNumber
|
2023-06-29 03:42:43 +03:00
|
|
|
let (block, change) = if let Some(obj) = x.as_object_mut() {
|
2022-09-22 02:50:55 +03:00
|
|
|
// it might be a Map like `{"blockHash": String("0xa5626dc20d3a0a209b1de85521717a3e859698de8ce98bca1b16822b7501f74b")}`
|
2023-02-25 10:31:10 +03:00
|
|
|
if let Some(block_hash) = obj.get("blockHash").cloned() {
|
2022-09-22 02:50:55 +03:00
|
|
|
let block_hash: H256 =
|
|
|
|
serde_json::from_value(block_hash).context("decoding blockHash")?;
|
|
|
|
|
2023-01-31 20:47:19 +03:00
|
|
|
let block = rpcs
|
2023-07-13 20:58:22 +03:00
|
|
|
.block(&block_hash, None, Some(3), None)
|
2023-01-31 20:47:19 +03:00
|
|
|
.await
|
|
|
|
.context("fetching block number from hash")?;
|
2022-09-21 07:48:21 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
(BlockNumAndHash::from(&block), false)
|
2022-09-21 07:48:21 +03:00
|
|
|
} else {
|
2023-07-11 09:08:06 +03:00
|
|
|
return Err(anyhow::anyhow!("blockHash missing").into());
|
2022-09-21 07:48:21 +03:00
|
|
|
}
|
|
|
|
} else {
|
2023-06-29 03:42:43 +03:00
|
|
|
// it might be a string like "latest" or a block number or a block hash
|
2022-09-22 02:50:55 +03:00
|
|
|
// TODO: "BlockNumber" needs a better name
|
2023-06-29 03:42:43 +03:00
|
|
|
// TODO: move this to a helper function?
|
2023-07-08 01:28:24 +03:00
|
|
|
if let Ok(block_num) = serde_json::from_value::<U64>(x.clone()) {
|
|
|
|
let (block_hash, _) = rpcs
|
2023-07-13 20:58:22 +03:00
|
|
|
.block_hash(&block_num)
|
2023-07-08 01:28:24 +03:00
|
|
|
.await
|
|
|
|
.context("fetching block hash from number")?;
|
|
|
|
|
|
|
|
let block = rpcs
|
2023-07-13 20:58:22 +03:00
|
|
|
.block(&block_hash, None, Some(3), None)
|
2023-07-08 01:28:24 +03:00
|
|
|
.await
|
|
|
|
.context("fetching block from hash")?;
|
|
|
|
|
|
|
|
// TODO: do true here? will that work for **all** methods on **all** chains? if not we need something smarter
|
|
|
|
(BlockNumAndHash::from(&block), false)
|
|
|
|
} else if let Ok(block_number) =
|
|
|
|
serde_json::from_value::<BlockNumber>(x.clone())
|
|
|
|
{
|
2023-06-29 03:42:43 +03:00
|
|
|
let (block_num, change) =
|
|
|
|
BlockNumber_to_U64(block_number, latest_block.number());
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 10:06:58 +03:00
|
|
|
if block_num == *latest_block.number() {
|
|
|
|
(latest_block.into(), change)
|
|
|
|
} else {
|
|
|
|
let (block_hash, _) = rpcs
|
2023-07-13 20:58:22 +03:00
|
|
|
.block_hash(&block_num)
|
2023-06-29 10:06:58 +03:00
|
|
|
.await
|
|
|
|
.context("fetching block hash from number")?;
|
2023-06-29 03:42:43 +03:00
|
|
|
|
2023-06-29 10:06:58 +03:00
|
|
|
let block = rpcs
|
2023-07-13 20:58:22 +03:00
|
|
|
.block(&block_hash, None, Some(3), None)
|
2023-06-29 10:06:58 +03:00
|
|
|
.await
|
|
|
|
.context("fetching block from hash")?;
|
2023-06-29 03:42:43 +03:00
|
|
|
|
2023-06-29 10:06:58 +03:00
|
|
|
(BlockNumAndHash::from(&block), change)
|
|
|
|
}
|
2023-06-29 03:42:43 +03:00
|
|
|
} else if let Ok(block_hash) = serde_json::from_value::<H256>(x.clone()) {
|
|
|
|
let block = rpcs
|
2023-07-13 20:58:22 +03:00
|
|
|
.block(&block_hash, None, Some(3), None)
|
2023-06-29 03:42:43 +03:00
|
|
|
.await
|
|
|
|
.context("fetching block number from hash")?;
|
|
|
|
|
|
|
|
(BlockNumAndHash::from(&block), false)
|
|
|
|
} else {
|
|
|
|
return Err(anyhow::anyhow!(
|
|
|
|
"param not a block identifier, block number, or block hash"
|
2023-07-11 09:08:06 +03:00
|
|
|
)
|
|
|
|
.into());
|
2023-06-29 03:42:43 +03:00
|
|
|
}
|
2022-09-22 02:50:55 +03:00
|
|
|
};
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-07-08 01:28:24 +03:00
|
|
|
// if we changed "latest" to a hash, update the params to match
|
2023-01-31 19:30:24 +03:00
|
|
|
if change {
|
2023-06-29 03:42:43 +03:00
|
|
|
trace!(old=%x, new=%block.hash(), "changing block number");
|
|
|
|
*x = json!(block.hash());
|
2022-12-20 00:53:38 +03:00
|
|
|
}
|
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
Ok(block)
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-17 07:05:01 +03:00
|
|
|
/// TODO: change this to also return the hash needed?
|
2023-06-29 03:42:43 +03:00
|
|
|
pub enum CacheMode {
|
2022-12-17 07:05:01 +03:00
|
|
|
CacheSuccessForever,
|
|
|
|
CacheNever,
|
2023-01-31 19:30:24 +03:00
|
|
|
Cache {
|
2023-06-29 03:42:43 +03:00
|
|
|
block: BlockNumAndHash,
|
|
|
|
/// cache jsonrpc errors (server errors are never cached)
|
2023-01-31 19:30:24 +03:00
|
|
|
cache_errors: bool,
|
|
|
|
},
|
|
|
|
CacheRange {
|
2023-06-29 03:42:43 +03:00
|
|
|
from_block: BlockNumAndHash,
|
|
|
|
to_block: BlockNumAndHash,
|
|
|
|
/// cache jsonrpc errors (server errors are never cached)
|
2023-01-31 19:30:24 +03:00
|
|
|
cache_errors: bool,
|
|
|
|
},
|
2022-12-17 07:05:01 +03:00
|
|
|
}
|
2022-11-12 11:24:32 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
impl CacheMode {
|
|
|
|
pub async fn new(
|
|
|
|
method: &str,
|
|
|
|
params: &mut serde_json::Value,
|
|
|
|
head_block: &Web3ProxyBlock,
|
|
|
|
rpcs: &Web3Rpcs,
|
|
|
|
) -> Self {
|
2023-07-13 20:58:22 +03:00
|
|
|
match Self::try_new(method, params, head_block, rpcs).await {
|
2023-06-29 03:42:43 +03:00
|
|
|
Ok(x) => x,
|
|
|
|
Err(err) => {
|
|
|
|
warn!(?err, "unable to determine cache mode from params");
|
|
|
|
Self::CacheNever
|
|
|
|
}
|
|
|
|
}
|
2023-05-31 02:32:34 +03:00
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
pub async fn try_new(
|
|
|
|
method: &str,
|
|
|
|
params: &mut serde_json::Value,
|
|
|
|
head_block: &Web3ProxyBlock,
|
|
|
|
rpcs: &Web3Rpcs,
|
|
|
|
) -> Web3ProxyResult<Self> {
|
|
|
|
// some requests have potentially very large responses
|
|
|
|
// TODO: only skip caching if the response actually is large
|
|
|
|
if method.starts_with("trace_") || method == "debug_traceTransaction" {
|
|
|
|
return Ok(Self::CacheNever);
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
2023-06-29 03:42:43 +03:00
|
|
|
|
|
|
|
if matches!(params, serde_json::Value::Null) {
|
|
|
|
// no params given
|
|
|
|
return Ok(Self::Cache {
|
|
|
|
block: head_block.into(),
|
2022-12-17 07:05:01 +03:00
|
|
|
cache_errors: true,
|
|
|
|
});
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
// get the index for the BlockNumber
|
|
|
|
// The BlockNumber is usually the last element.
|
|
|
|
// TODO: double check these. i think some of the getBlock stuff will never need archive
|
|
|
|
let block_param_id = match method {
|
|
|
|
"eth_call" => 1,
|
|
|
|
"eth_estimateGas" => 1,
|
|
|
|
"eth_getBalance" => 1,
|
|
|
|
"eth_getBlockByHash" => {
|
|
|
|
// TODO: double check that any node can serve this
|
|
|
|
// TODO: can a block change? like what if it gets orphaned?
|
2023-07-28 20:38:12 +03:00
|
|
|
// TODO: make sure re-orgs work properly!
|
2023-06-29 03:42:43 +03:00
|
|
|
return Ok(CacheMode::CacheSuccessForever);
|
|
|
|
}
|
|
|
|
"eth_getBlockByNumber" => {
|
|
|
|
// TODO: double check that any node can serve this
|
|
|
|
// TODO: CacheSuccessForever if the block is old enough
|
2023-07-28 20:38:12 +03:00
|
|
|
// TODO: make sure re-orgs work properly!
|
2023-06-29 03:42:43 +03:00
|
|
|
return Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
|
|
|
cache_errors: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
"eth_getBlockReceipts" => 0,
|
|
|
|
"eth_getBlockTransactionCountByHash" => {
|
|
|
|
// TODO: double check that any node can serve this
|
|
|
|
return Ok(CacheMode::CacheSuccessForever);
|
|
|
|
}
|
|
|
|
"eth_getBlockTransactionCountByNumber" => 0,
|
|
|
|
"eth_getCode" => 1,
|
|
|
|
"eth_getLogs" => {
|
|
|
|
// TODO: think about this more
|
|
|
|
// TODO: jsonrpc has a specific code for this
|
|
|
|
let obj = params
|
|
|
|
.get_mut(0)
|
|
|
|
.ok_or_else(|| Web3ProxyError::BadRequest("invalid format. no params".into()))?
|
|
|
|
.as_object_mut()
|
|
|
|
.ok_or_else(|| {
|
|
|
|
Web3ProxyError::BadRequest("invalid format. params not object".into())
|
|
|
|
})?;
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
if obj.contains_key("blockHash") {
|
|
|
|
return Ok(CacheMode::CacheSuccessForever);
|
|
|
|
} else {
|
|
|
|
let from_block = if let Some(x) = obj.get_mut("fromBlock") {
|
|
|
|
// TODO: use .take instead of clone
|
|
|
|
// what if its a hash?
|
|
|
|
let block_num: BlockNumber = serde_json::from_value(x.clone())?;
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
let (block_num, change) =
|
|
|
|
BlockNumber_to_U64(block_num, head_block.number());
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
if change {
|
|
|
|
// TODO: include the hash instead of the number?
|
|
|
|
trace!("changing fromBlock in eth_getLogs. {} -> {}", x, block_num);
|
|
|
|
*x = json!(block_num);
|
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-07-13 20:58:22 +03:00
|
|
|
let (block_hash, _) = rpcs.block_hash(&block_num).await?;
|
2023-06-29 04:36:17 +03:00
|
|
|
|
|
|
|
BlockNumAndHash(block_num, block_hash)
|
2023-06-29 03:42:43 +03:00
|
|
|
} else {
|
2023-07-06 09:13:32 +03:00
|
|
|
BlockNumAndHash(U64::zero(), H256::zero())
|
2023-06-29 03:42:43 +03:00
|
|
|
};
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
let to_block = if let Some(x) = obj.get_mut("toBlock") {
|
|
|
|
// TODO: use .take instead of clone
|
|
|
|
// what if its a hash?
|
|
|
|
let block_num: BlockNumber = serde_json::from_value(x.clone())?;
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
let (block_num, change) =
|
|
|
|
BlockNumber_to_U64(block_num, head_block.number());
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
if change {
|
|
|
|
trace!("changing toBlock in eth_getLogs. {} -> {}", x, block_num);
|
|
|
|
*x = json!(block_num);
|
|
|
|
}
|
2023-01-31 02:47:17 +03:00
|
|
|
|
2023-07-13 20:58:22 +03:00
|
|
|
let (block_hash, _) = rpcs.block_hash(&block_num).await?;
|
2023-06-29 04:36:17 +03:00
|
|
|
|
|
|
|
BlockNumAndHash(block_num, block_hash)
|
2023-06-29 03:42:43 +03:00
|
|
|
} else {
|
|
|
|
head_block.into()
|
|
|
|
};
|
2023-01-31 19:30:24 +03:00
|
|
|
|
2023-06-29 03:42:43 +03:00
|
|
|
return Ok(CacheMode::CacheRange {
|
|
|
|
from_block,
|
|
|
|
to_block,
|
|
|
|
cache_errors: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"eth_getStorageAt" => 2,
|
|
|
|
"eth_getTransactionByHash" => {
|
|
|
|
// TODO: not sure how best to look these up
|
|
|
|
// try full nodes first. retry will use archive
|
|
|
|
return Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
2022-12-17 07:05:01 +03:00
|
|
|
cache_errors: true,
|
|
|
|
});
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
2023-06-29 03:42:43 +03:00
|
|
|
"eth_getTransactionByBlockHashAndIndex" => {
|
|
|
|
// TODO: check a Cache of recent hashes
|
|
|
|
// try full nodes first. retry will use archive
|
|
|
|
return Ok(CacheMode::CacheSuccessForever);
|
|
|
|
}
|
|
|
|
"eth_getTransactionByBlockNumberAndIndex" => 0,
|
|
|
|
"eth_getTransactionCount" => 1,
|
|
|
|
"eth_getTransactionReceipt" => {
|
|
|
|
// TODO: not sure how best to look these up
|
|
|
|
// try full nodes first. retry will use archive
|
|
|
|
return Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
|
|
|
cache_errors: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
"eth_getUncleByBlockHashAndIndex" => {
|
|
|
|
// TODO: check a Cache of recent hashes
|
|
|
|
// try full nodes first. retry will use archive
|
|
|
|
// TODO: what happens if this block is uncled later?
|
|
|
|
return Ok(CacheMode::CacheSuccessForever);
|
|
|
|
}
|
|
|
|
"eth_getUncleByBlockNumberAndIndex" => 0,
|
|
|
|
"eth_getUncleCountByBlockHash" => {
|
|
|
|
// TODO: check a Cache of recent hashes
|
|
|
|
// try full nodes first. retry will use archive
|
|
|
|
// TODO: what happens if this block is uncled later?
|
|
|
|
return Ok(CacheMode::CacheSuccessForever);
|
|
|
|
}
|
|
|
|
"eth_getUncleCountByBlockNumber" => 0,
|
2023-07-28 20:38:12 +03:00
|
|
|
"eth_maxPriorityFeePerGas" => {
|
|
|
|
// TODO: this might be too aggressive. i think it can change before a block is mined
|
|
|
|
return Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
|
|
|
cache_errors: false,
|
|
|
|
});
|
|
|
|
}
|
2023-06-29 03:42:43 +03:00
|
|
|
_ => {
|
|
|
|
// some other command that doesn't take block numbers as an argument
|
|
|
|
// since we are caching with the head block, it should be safe to cache_errors
|
|
|
|
return Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
|
|
|
cache_errors: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2022-08-10 05:37:34 +03:00
|
|
|
|
2023-07-13 20:58:22 +03:00
|
|
|
match clean_block_number(params, block_param_id, head_block, rpcs).await {
|
2023-06-29 03:42:43 +03:00
|
|
|
Ok(block) => Ok(CacheMode::Cache {
|
|
|
|
block,
|
2022-12-17 07:05:01 +03:00
|
|
|
cache_errors: true,
|
2023-06-29 03:42:43 +03:00
|
|
|
}),
|
2023-07-11 09:08:06 +03:00
|
|
|
Err(Web3ProxyError::NoBlocksKnown) => {
|
|
|
|
warn!(%method, ?params, "no servers available to get block from params");
|
|
|
|
Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
|
|
|
cache_errors: true,
|
|
|
|
})
|
|
|
|
}
|
2023-06-29 03:42:43 +03:00
|
|
|
Err(err) => {
|
2023-07-10 08:52:18 +03:00
|
|
|
error!(%method, ?params, ?err, "could not get block from params");
|
2023-06-29 03:42:43 +03:00
|
|
|
Ok(CacheMode::Cache {
|
|
|
|
block: head_block.into(),
|
|
|
|
cache_errors: true,
|
|
|
|
})
|
|
|
|
}
|
2022-08-10 05:37:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|