add backend nodes to the rpc response headers
only do this in dev?
This commit is contained in:
parent
f27c764a07
commit
82eb449e96
@ -108,7 +108,7 @@ impl RedisRateLimiter {
|
|||||||
// do the query
|
// do the query
|
||||||
.query_async(&mut *conn)
|
.query_async(&mut *conn)
|
||||||
.await
|
.await
|
||||||
.context("increment rate limit and set expiration")?;
|
.context("cannot increment rate limit or set expiration")?;
|
||||||
|
|
||||||
let new_count: u64 = *x.first().expect("check redis");
|
let new_count: u64 = *x.first().expect("check redis");
|
||||||
|
|
||||||
|
@ -5,11 +5,13 @@ use crate::app_stats::{ProxyResponseStat, StatEmitter, Web3ProxyStat};
|
|||||||
use crate::block_number::{block_needed, BlockNeeded};
|
use crate::block_number::{block_needed, BlockNeeded};
|
||||||
use crate::config::{AppConfig, TopConfig};
|
use crate::config::{AppConfig, TopConfig};
|
||||||
use crate::frontend::authorization::{Authorization, RequestMetadata};
|
use crate::frontend::authorization::{Authorization, RequestMetadata};
|
||||||
|
use crate::frontend::errors::FrontendErrorResponse;
|
||||||
use crate::jsonrpc::JsonRpcForwardedResponse;
|
use crate::jsonrpc::JsonRpcForwardedResponse;
|
||||||
use crate::jsonrpc::JsonRpcForwardedResponseEnum;
|
use crate::jsonrpc::JsonRpcForwardedResponseEnum;
|
||||||
use crate::jsonrpc::JsonRpcRequest;
|
use crate::jsonrpc::JsonRpcRequest;
|
||||||
use crate::jsonrpc::JsonRpcRequestEnum;
|
use crate::jsonrpc::JsonRpcRequestEnum;
|
||||||
use crate::rpcs::blockchain::{ArcBlock, SavedBlock};
|
use crate::rpcs::blockchain::{ArcBlock, SavedBlock};
|
||||||
|
use crate::rpcs::connection::Web3Connection;
|
||||||
use crate::rpcs::connections::Web3Connections;
|
use crate::rpcs::connections::Web3Connections;
|
||||||
use crate::rpcs::request::OpenRequestHandleMetrics;
|
use crate::rpcs::request::OpenRequestHandleMetrics;
|
||||||
use crate::rpcs::transactions::TxStatus;
|
use crate::rpcs::transactions::TxStatus;
|
||||||
@ -21,11 +23,10 @@ use derive_more::From;
|
|||||||
use entities::sea_orm_active_enums::LogLevel;
|
use entities::sea_orm_active_enums::LogLevel;
|
||||||
use ethers::core::utils::keccak256;
|
use ethers::core::utils::keccak256;
|
||||||
use ethers::prelude::{Address, Block, Bytes, TxHash, H256, U64};
|
use ethers::prelude::{Address, Block, Bytes, TxHash, H256, U64};
|
||||||
use ethers::types::U256;
|
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use futures::stream::FuturesUnordered;
|
use futures::stream::FuturesUnordered;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::{HashMap, HashSet};
|
||||||
use ipnet::IpNet;
|
use ipnet::IpNet;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use metered::{metered, ErrorCount, HitCount, ResponseTime, Throughput};
|
use metered::{metered, ErrorCount, HitCount, ResponseTime, Throughput};
|
||||||
@ -708,7 +709,8 @@ impl Web3ProxyApp {
|
|||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
authorization: Arc<Authorization>,
|
authorization: Arc<Authorization>,
|
||||||
request: JsonRpcRequestEnum,
|
request: JsonRpcRequestEnum,
|
||||||
) -> anyhow::Result<JsonRpcForwardedResponseEnum> {
|
) -> Result<(JsonRpcForwardedResponseEnum, Vec<Arc<Web3Connection>>), FrontendErrorResponse>
|
||||||
|
{
|
||||||
// TODO: this should probably be trace level
|
// TODO: this should probably be trace level
|
||||||
// // trace!(?request, "proxy_web3_rpc");
|
// // trace!(?request, "proxy_web3_rpc");
|
||||||
|
|
||||||
@ -718,24 +720,25 @@ impl Web3ProxyApp {
|
|||||||
let max_time = Duration::from_secs(120);
|
let max_time = Duration::from_secs(120);
|
||||||
|
|
||||||
let response = match request {
|
let response = match request {
|
||||||
JsonRpcRequestEnum::Single(request) => JsonRpcForwardedResponseEnum::Single(
|
JsonRpcRequestEnum::Single(request) => {
|
||||||
timeout(
|
let (response, rpcs) = timeout(
|
||||||
max_time,
|
max_time,
|
||||||
self.proxy_web3_rpc_request(&authorization, request),
|
self.proxy_web3_rpc_request(&authorization, request),
|
||||||
)
|
)
|
||||||
.await??,
|
.await??;
|
||||||
),
|
|
||||||
JsonRpcRequestEnum::Batch(requests) => JsonRpcForwardedResponseEnum::Batch(
|
(JsonRpcForwardedResponseEnum::Single(response), rpcs)
|
||||||
timeout(
|
}
|
||||||
|
JsonRpcRequestEnum::Batch(requests) => {
|
||||||
|
let (responses, rpcs) = timeout(
|
||||||
max_time,
|
max_time,
|
||||||
self.proxy_web3_rpc_requests(&authorization, requests),
|
self.proxy_web3_rpc_requests(&authorization, requests),
|
||||||
)
|
)
|
||||||
.await??,
|
.await??;
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: this should probably be trace level
|
(JsonRpcForwardedResponseEnum::Batch(responses), rpcs)
|
||||||
// // trace!(?response, "Forwarding");
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
@ -746,12 +749,12 @@ impl Web3ProxyApp {
|
|||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
authorization: &Arc<Authorization>,
|
authorization: &Arc<Authorization>,
|
||||||
requests: Vec<JsonRpcRequest>,
|
requests: Vec<JsonRpcRequest>,
|
||||||
) -> anyhow::Result<Vec<JsonRpcForwardedResponse>> {
|
) -> anyhow::Result<(Vec<JsonRpcForwardedResponse>, Vec<Arc<Web3Connection>>)> {
|
||||||
// TODO: we should probably change ethers-rs to support this directly
|
// TODO: we should probably change ethers-rs to support this directly. they pushed this off to v2 though
|
||||||
let num_requests = requests.len();
|
let num_requests = requests.len();
|
||||||
|
|
||||||
// TODO: spawn so the requests go in parallel
|
// TODO: spawn so the requests go in parallel? need to think about rate limiting more if we do that
|
||||||
// TODO: i think we will need to flatten
|
// TODO: improve flattening
|
||||||
let responses = join_all(
|
let responses = join_all(
|
||||||
requests
|
requests
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -760,14 +763,21 @@ impl Web3ProxyApp {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// TODO: i'm sure this could be done better with iterators. we could return the error earlier then, too
|
// TODO: i'm sure this could be done better with iterators
|
||||||
// TODO: stream the response?
|
// TODO: stream the response?
|
||||||
let mut collected: Vec<JsonRpcForwardedResponse> = Vec::with_capacity(num_requests);
|
let mut collected: Vec<JsonRpcForwardedResponse> = Vec::with_capacity(num_requests);
|
||||||
|
let mut collected_rpcs: HashSet<Arc<Web3Connection>> = HashSet::new();
|
||||||
for response in responses {
|
for response in responses {
|
||||||
collected.push(response?);
|
// TODO: any way to attach the tried rpcs to the error? it is likely helpful
|
||||||
|
let (response, rpcs) = response?;
|
||||||
|
|
||||||
|
collected.push(response);
|
||||||
|
collected_rpcs.extend(rpcs.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(collected)
|
let collected_rpcs: Vec<_> = collected_rpcs.into_iter().collect();
|
||||||
|
|
||||||
|
Ok((collected, collected_rpcs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: i don't think we want or need this. just use app.db_conn, or maybe app.db_conn.clone() or app.db_conn.as_ref()
|
/// TODO: i don't think we want or need this. just use app.db_conn, or maybe app.db_conn.clone() or app.db_conn.as_ref()
|
||||||
@ -795,7 +805,7 @@ impl Web3ProxyApp {
|
|||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
authorization: &Arc<Authorization>,
|
authorization: &Arc<Authorization>,
|
||||||
mut request: JsonRpcRequest,
|
mut request: JsonRpcRequest,
|
||||||
) -> anyhow::Result<JsonRpcForwardedResponse> {
|
) -> anyhow::Result<(JsonRpcForwardedResponse, Vec<Arc<Web3Connection>>)> {
|
||||||
// trace!("Received request: {:?}", request);
|
// trace!("Received request: {:?}", request);
|
||||||
|
|
||||||
let request_metadata = Arc::new(RequestMetadata::new(REQUEST_PERIOD, request.num_bytes())?);
|
let request_metadata = Arc::new(RequestMetadata::new(REQUEST_PERIOD, request.num_bytes())?);
|
||||||
@ -917,6 +927,8 @@ impl Web3ProxyApp {
|
|||||||
// no stats on this. its cheap
|
// no stats on this. its cheap
|
||||||
json!(Address::zero())
|
json!(Address::zero())
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
// erigon was giving bad estimates. but now it doesn't need it
|
||||||
"eth_estimateGas" => {
|
"eth_estimateGas" => {
|
||||||
// TODO: eth_estimateGas using anvil?
|
// TODO: eth_estimateGas using anvil?
|
||||||
// TODO: modify the block requested?
|
// TODO: modify the block requested?
|
||||||
@ -937,15 +949,18 @@ impl Web3ProxyApp {
|
|||||||
parsed_gas_estimate
|
parsed_gas_estimate
|
||||||
} else {
|
} else {
|
||||||
// i think this is always an error response
|
// i think this is always an error response
|
||||||
return Ok(response);
|
let rpcs = request_metadata.backend_requests.lock().clone();
|
||||||
|
|
||||||
|
return Ok((response, rpcs));
|
||||||
};
|
};
|
||||||
|
|
||||||
// increase by 10.01%
|
// increase by 1.01%
|
||||||
let parsed_gas_estimate =
|
let parsed_gas_estimate =
|
||||||
parsed_gas_estimate * U256::from(110_010) / U256::from(100_000);
|
parsed_gas_estimate * U256::from(101_010) / U256::from(100_000);
|
||||||
|
|
||||||
json!(parsed_gas_estimate)
|
json!(parsed_gas_estimate)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// TODO: eth_gasPrice that does awesome magic to predict the future
|
// TODO: eth_gasPrice that does awesome magic to predict the future
|
||||||
"eth_hashrate" => {
|
"eth_hashrate" => {
|
||||||
// no stats on this. its cheap
|
// no stats on this. its cheap
|
||||||
@ -959,16 +974,24 @@ impl Web3ProxyApp {
|
|||||||
// broadcast transactions to all private rpcs at once
|
// broadcast transactions to all private rpcs at once
|
||||||
"eth_sendRawTransaction" => {
|
"eth_sendRawTransaction" => {
|
||||||
// emit stats
|
// emit stats
|
||||||
let rpcs = self.private_rpcs.as_ref().unwrap_or(&self.balanced_rpcs);
|
let private_rpcs = self.private_rpcs.as_ref().unwrap_or(&self.balanced_rpcs);
|
||||||
|
|
||||||
return rpcs
|
let mut response = private_rpcs
|
||||||
.try_send_all_upstream_servers(
|
.try_send_all_upstream_servers(
|
||||||
authorization,
|
authorization,
|
||||||
request,
|
request,
|
||||||
Some(request_metadata),
|
Some(request_metadata.clone()),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await;
|
.await?;
|
||||||
|
|
||||||
|
response.id = request_id;
|
||||||
|
|
||||||
|
let rpcs = request_metadata.backend_requests.lock().clone();
|
||||||
|
|
||||||
|
// TODO! STATS!
|
||||||
|
|
||||||
|
return Ok((response, rpcs));
|
||||||
}
|
}
|
||||||
"eth_syncing" => {
|
"eth_syncing" => {
|
||||||
// no stats on this. its cheap
|
// no stats on this. its cheap
|
||||||
@ -1134,6 +1157,9 @@ impl Web3ProxyApp {
|
|||||||
// replace the id with our request's id.
|
// replace the id with our request's id.
|
||||||
response.id = request_id;
|
response.id = request_id;
|
||||||
|
|
||||||
|
// TODO: DRY!
|
||||||
|
let rpcs = request_metadata.backend_requests.lock().clone();
|
||||||
|
|
||||||
if let Some(stat_sender) = self.stat_sender.as_ref() {
|
if let Some(stat_sender) = self.stat_sender.as_ref() {
|
||||||
let response_stat = ProxyResponseStat::new(
|
let response_stat = ProxyResponseStat::new(
|
||||||
method.to_string(),
|
method.to_string(),
|
||||||
@ -1148,12 +1174,15 @@ impl Web3ProxyApp {
|
|||||||
.context("stat_sender sending response_stat")?;
|
.context("stat_sender sending response_stat")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(response);
|
return Ok((response, rpcs));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = JsonRpcForwardedResponse::from_value(partial_response, request_id);
|
let response = JsonRpcForwardedResponse::from_value(partial_response, request_id);
|
||||||
|
|
||||||
|
// TODO: DRY
|
||||||
|
let rpcs = request_metadata.backend_requests.lock().clone();
|
||||||
|
|
||||||
if let Some(stat_sender) = self.stat_sender.as_ref() {
|
if let Some(stat_sender) = self.stat_sender.as_ref() {
|
||||||
let response_stat = ProxyResponseStat::new(
|
let response_stat = ProxyResponseStat::new(
|
||||||
request_method,
|
request_method,
|
||||||
@ -1168,9 +1197,7 @@ impl Web3ProxyApp {
|
|||||||
.context("stat_sender sending response stat")?;
|
.context("stat_sender sending response stat")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!("attach a header here");
|
Ok((response, rpcs))
|
||||||
|
|
||||||
Ok(response)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ use log::{trace, warn};
|
|||||||
use migration::sea_orm::DbErr;
|
use migration::sea_orm::DbErr;
|
||||||
use redis_rate_limiter::redis::RedisError;
|
use redis_rate_limiter::redis::RedisError;
|
||||||
use reqwest::header::ToStrError;
|
use reqwest::header::ToStrError;
|
||||||
use std::error::Error;
|
|
||||||
use tokio::{sync::AcquireError, task::JoinError, time::Instant};
|
use tokio::{sync::AcquireError, task::JoinError, time::Instant};
|
||||||
|
|
||||||
// TODO: take "IntoResponse" instead of Response?
|
// TODO: take "IntoResponse" instead of Response?
|
||||||
@ -27,7 +26,6 @@ pub enum FrontendErrorResponse {
|
|||||||
AccessDenied,
|
AccessDenied,
|
||||||
Anyhow(anyhow::Error),
|
Anyhow(anyhow::Error),
|
||||||
SemaphoreAcquireError(AcquireError),
|
SemaphoreAcquireError(AcquireError),
|
||||||
Box(Box<dyn Error>),
|
|
||||||
Database(DbErr),
|
Database(DbErr),
|
||||||
HeadersError(headers::Error),
|
HeadersError(headers::Error),
|
||||||
HeaderToString(ToStrError),
|
HeaderToString(ToStrError),
|
||||||
@ -40,6 +38,8 @@ pub enum FrontendErrorResponse {
|
|||||||
Response(Response),
|
Response(Response),
|
||||||
/// simple way to return an error message to the user and an anyhow to our logs
|
/// simple way to return an error message to the user and an anyhow to our logs
|
||||||
StatusCode(StatusCode, String, Option<anyhow::Error>),
|
StatusCode(StatusCode, String, Option<anyhow::Error>),
|
||||||
|
/// TODO: what should be attached to the timout?
|
||||||
|
Timeout(tokio::time::error::Elapsed),
|
||||||
UlidDecodeError(ulid::DecodeError),
|
UlidDecodeError(ulid::DecodeError),
|
||||||
UnknownKey,
|
UnknownKey,
|
||||||
}
|
}
|
||||||
@ -74,18 +74,18 @@ impl IntoResponse for FrontendErrorResponse {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Self::Box(err) => {
|
// Self::(err) => {
|
||||||
warn!("boxed err={:?}", err);
|
// warn!("boxed err={:?}", err);
|
||||||
(
|
// (
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
// StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
JsonRpcForwardedResponse::from_str(
|
// JsonRpcForwardedResponse::from_str(
|
||||||
// TODO: make this better. maybe include the error type?
|
// // TODO: make this better. maybe include the error type?
|
||||||
"boxed error!",
|
// "boxed error!",
|
||||||
Some(StatusCode::INTERNAL_SERVER_ERROR.as_u16().into()),
|
// Some(StatusCode::INTERNAL_SERVER_ERROR.as_u16().into()),
|
||||||
None,
|
// None,
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
Self::Database(err) => {
|
Self::Database(err) => {
|
||||||
warn!("database err={:?}", err);
|
warn!("database err={:?}", err);
|
||||||
(
|
(
|
||||||
@ -131,12 +131,20 @@ impl IntoResponse for FrontendErrorResponse {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Self::JoinError(err) => {
|
Self::JoinError(err) => {
|
||||||
warn!("JoinError. likely shutting down. err={:?}", err);
|
let code = if err.is_cancelled() {
|
||||||
|
trace!("JoinError. likely shutting down. err={:?}", err);
|
||||||
|
StatusCode::BAD_GATEWAY
|
||||||
|
} else {
|
||||||
|
warn!("JoinError. err={:?}", err);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
code,
|
||||||
JsonRpcForwardedResponse::from_str(
|
JsonRpcForwardedResponse::from_str(
|
||||||
|
// TODO: different messages, too?
|
||||||
"Unable to complete request",
|
"Unable to complete request",
|
||||||
Some(StatusCode::INTERNAL_SERVER_ERROR.as_u16().into()),
|
Some(code.as_u16().into()),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -226,8 +234,17 @@ impl IntoResponse for FrontendErrorResponse {
|
|||||||
JsonRpcForwardedResponse::from_str(&err_msg, Some(code.into()), None),
|
JsonRpcForwardedResponse::from_str(&err_msg, Some(code.into()), None),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Self::Timeout(x) => (
|
||||||
|
StatusCode::REQUEST_TIMEOUT,
|
||||||
|
JsonRpcForwardedResponse::from_str(
|
||||||
|
&format!("request timed out: {:?}", x),
|
||||||
|
Some(StatusCode::REQUEST_TIMEOUT.as_u16().into()),
|
||||||
|
// TODO: include the actual id!
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
),
|
||||||
Self::HeaderToString(err) => {
|
Self::HeaderToString(err) => {
|
||||||
// // trace!(?err, "HeaderToString");
|
// trace!(?err, "HeaderToString");
|
||||||
(
|
(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
JsonRpcForwardedResponse::from_str(
|
JsonRpcForwardedResponse::from_str(
|
||||||
@ -238,7 +255,7 @@ impl IntoResponse for FrontendErrorResponse {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Self::UlidDecodeError(err) => {
|
Self::UlidDecodeError(err) => {
|
||||||
// // trace!(?err, "UlidDecodeError");
|
// trace!(?err, "UlidDecodeError");
|
||||||
(
|
(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
JsonRpcForwardedResponse::from_str(
|
JsonRpcForwardedResponse::from_str(
|
||||||
|
@ -9,6 +9,7 @@ use axum::TypedHeader;
|
|||||||
use axum::{response::IntoResponse, Extension, Json};
|
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 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.
|
||||||
@ -24,16 +25,30 @@ pub async fn proxy_web3_rpc(
|
|||||||
// TODO: do we care about keeping the TypedHeader wrapper?
|
// TODO: do we care about keeping the TypedHeader wrapper?
|
||||||
let origin = origin.map(|x| x.0);
|
let origin = origin.map(|x| x.0);
|
||||||
|
|
||||||
|
// TODO: move ip_is_authorized/key_is_authorized into proxy_web3_rpc
|
||||||
|
let f = tokio::spawn(async move {
|
||||||
let (authorization, _semaphore) = ip_is_authorized(&app, ip, origin).await?;
|
let (authorization, _semaphore) = ip_is_authorized(&app, ip, origin).await?;
|
||||||
|
|
||||||
let authorization = Arc::new(authorization);
|
let authorization = Arc::new(authorization);
|
||||||
|
|
||||||
// TODO: spawn earlier? i think we want ip_is_authorized in this future
|
app.proxy_web3_rpc(authorization, payload).await
|
||||||
let f = tokio::spawn(async move { app.proxy_web3_rpc(authorization, payload).await });
|
});
|
||||||
|
|
||||||
let response = f.await??;
|
let (response, rpcs) = f.await??;
|
||||||
|
|
||||||
Ok(Json(&response).into_response())
|
let mut response = Json(&response).into_response();
|
||||||
|
|
||||||
|
let headers = response.headers_mut();
|
||||||
|
|
||||||
|
// TODO: special string if no rpcs were used (cache hit)?
|
||||||
|
let rpcs: String = rpcs.into_iter().map(|x| x.name.clone()).join(",");
|
||||||
|
|
||||||
|
headers.insert(
|
||||||
|
"W3P-RPCs",
|
||||||
|
rpcs.parse().expect("W3P-RPCS should always parse"),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Authenticated entrypoint for HTTP JSON-RPC requests. Web3 wallets use this.
|
/// Authenticated entrypoint for HTTP JSON-RPC requests. Web3 wallets use this.
|
||||||
|
@ -180,7 +180,6 @@ async fn handle_socket_payload(
|
|||||||
// TODO: do any clients send batches over websockets?
|
// TODO: do any clients send batches over websockets?
|
||||||
let (id, response) = match serde_json::from_str::<JsonRpcRequest>(payload) {
|
let (id, response) = match serde_json::from_str::<JsonRpcRequest>(payload) {
|
||||||
Ok(json_request) => {
|
Ok(json_request) => {
|
||||||
// TODO: should we use this id for the subscription id? it should be unique and means we dont need an atomic
|
|
||||||
let id = json_request.id.clone();
|
let id = json_request.id.clone();
|
||||||
|
|
||||||
let response: anyhow::Result<JsonRpcForwardedResponseEnum> = match &json_request.method
|
let response: anyhow::Result<JsonRpcForwardedResponseEnum> = match &json_request.method
|
||||||
@ -251,8 +250,13 @@ async fn handle_socket_payload(
|
|||||||
Ok(response.into())
|
Ok(response.into())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
app.proxy_web3_rpc(authorization.clone(), json_request.into())
|
let (response, _) = app
|
||||||
|
.proxy_web3_rpc(authorization.clone(), json_request.into())
|
||||||
.await
|
.await
|
||||||
|
// TODO: DO NOT UNWRAP HERE! ANY FAILING MESSAGES WILL KEPP THE CONNECTION!
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -266,15 +270,16 @@ async fn handle_socket_payload(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let response_str = match response {
|
let response_str = match response {
|
||||||
Ok(x) => serde_json::to_string(&x),
|
Ok(x) => serde_json::to_string(&x).expect("to_string should always work here"),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// we have an anyhow error. turn it into a response
|
// we have an anyhow error. turn it into a response
|
||||||
let response = JsonRpcForwardedResponse::from_anyhow_error(err, None, Some(id));
|
let response = JsonRpcForwardedResponse::from_anyhow_error(err, None, Some(id));
|
||||||
serde_json::to_string(&response)
|
|
||||||
}
|
serde_json::to_string(&response).expect("to_string should always work here")
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: what error should this be?
|
// TODO: what error should this be?
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Message::Text(response_str)
|
Message::Text(response_str)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use crate::rpcs::connection::Web3Connection;
|
|
||||||
use derive_more::From;
|
use derive_more::From;
|
||||||
use ethers::prelude::{HttpClientError, ProviderError, WsClientError};
|
use ethers::prelude::{HttpClientError, ProviderError, WsClientError};
|
||||||
use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
|
use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::value::RawValue;
|
use serde_json::value::RawValue;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
// this is used by serde
|
// this is used by serde
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
Loading…
Reference in New Issue
Block a user