2023-05-31 07:26:11 +03:00
|
|
|
//! Utlities for logging errors for admins and displaying errors to users.
|
|
|
|
|
2023-11-03 21:51:02 +03:00
|
|
|
use crate::block_number::BlockNumOrHash;
|
2023-05-31 07:26:11 +03:00
|
|
|
use crate::frontend::authorization::Authorization;
|
2023-10-17 09:56:38 +03:00
|
|
|
use crate::jsonrpc::{self, JsonRpcErrorData, ParsedResponse, StreamResponse};
|
2023-10-11 10:12:20 +03:00
|
|
|
use crate::response_cache::ForwardedResponse;
|
2023-10-24 04:46:53 +03:00
|
|
|
use crate::rpcs::blockchain::Web3ProxyBlock;
|
|
|
|
use crate::rpcs::one::Web3Rpc;
|
2023-05-31 21:20:17 +03:00
|
|
|
use crate::rpcs::provider::EthersHttpProvider;
|
2023-07-25 02:25:48 +03:00
|
|
|
use axum::extract::rejection::JsonRejection;
|
2023-06-15 19:50:21 +03:00
|
|
|
use axum::extract::ws::Message;
|
2023-05-31 07:26:11 +03:00
|
|
|
use axum::{
|
|
|
|
headers,
|
|
|
|
http::StatusCode,
|
|
|
|
response::{IntoResponse, Response},
|
|
|
|
Json,
|
|
|
|
};
|
|
|
|
use derive_more::{Display, Error, From};
|
2023-05-31 21:20:17 +03:00
|
|
|
use ethers::prelude::ContractError;
|
2023-06-29 01:04:55 +03:00
|
|
|
use ethers::types::{H256, U64};
|
2023-05-31 07:26:11 +03:00
|
|
|
use http::header::InvalidHeaderValue;
|
2023-06-24 21:11:07 +03:00
|
|
|
use http::uri::InvalidUri;
|
2023-05-31 07:26:11 +03:00
|
|
|
use ipnet::AddrParseError;
|
|
|
|
use migration::sea_orm::DbErr;
|
|
|
|
use redis_rate_limiter::redis::RedisError;
|
2023-06-24 21:11:07 +03:00
|
|
|
use redis_rate_limiter::RedisPoolError;
|
2023-05-31 07:26:11 +03:00
|
|
|
use reqwest::header::ToStrError;
|
2023-05-31 21:20:17 +03:00
|
|
|
use rust_decimal::Error as DecimalError;
|
2023-07-25 02:25:48 +03:00
|
|
|
use serde_json::json;
|
2023-05-31 07:26:11 +03:00
|
|
|
use serde_json::value::RawValue;
|
2023-06-24 19:48:28 +03:00
|
|
|
use siwe::VerificationError;
|
2023-06-08 03:26:38 +03:00
|
|
|
use std::sync::Arc;
|
2023-07-20 08:32:52 +03:00
|
|
|
use std::time::Duration;
|
2023-05-31 21:20:17 +03:00
|
|
|
use std::{borrow::Cow, net::IpAddr};
|
2023-05-31 07:26:11 +03:00
|
|
|
use tokio::{sync::AcquireError, task::JoinError, time::Instant};
|
2023-06-24 02:28:45 +03:00
|
|
|
use tracing::{debug, error, trace, warn};
|
2023-05-31 07:26:11 +03:00
|
|
|
|
|
|
|
pub type Web3ProxyResult<T> = Result<T, Web3ProxyError>;
|
|
|
|
// TODO: take "IntoResponse" instead of Response?
|
|
|
|
pub type Web3ProxyResponse = Web3ProxyResult<Response>;
|
|
|
|
|
|
|
|
impl From<Web3ProxyError> for Web3ProxyResult<()> {
|
|
|
|
fn from(value: Web3ProxyError) -> Self {
|
|
|
|
Err(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Display, Error, From)]
|
|
|
|
pub enum Web3ProxyError {
|
2023-05-31 22:44:02 +03:00
|
|
|
Abi(ethers::abi::Error),
|
2023-06-29 09:00:34 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
|
|
|
AccessDenied(Cow<'static, str>),
|
2023-05-31 07:26:11 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
Anyhow(anyhow::Error),
|
2023-06-08 03:26:38 +03:00
|
|
|
Arc(Arc<Self>),
|
2023-10-10 22:19:54 +03:00
|
|
|
#[from(ignore)]
|
|
|
|
#[display(fmt = "{:?} to {:?}", min, max)]
|
|
|
|
ArchiveRequired {
|
|
|
|
min: Option<U64>,
|
|
|
|
max: Option<U64>,
|
|
|
|
},
|
2023-05-31 07:26:11 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
2023-05-31 09:17:05 +03:00
|
|
|
BadRequest(Cow<'static, str>),
|
2023-05-31 07:26:11 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
2023-06-10 04:31:47 +03:00
|
|
|
BadResponse(Cow<'static, str>),
|
2023-05-31 07:26:11 +03:00
|
|
|
BadRouting,
|
2023-05-31 21:20:17 +03:00
|
|
|
Contract(ContractError<EthersHttpProvider>),
|
2023-05-31 07:26:11 +03:00
|
|
|
Database(DbErr),
|
2023-07-15 04:30:01 +03:00
|
|
|
DatabaseArc(Arc<DbErr>),
|
2023-05-31 21:20:17 +03:00
|
|
|
Decimal(DecimalError),
|
2023-07-15 04:31:00 +03:00
|
|
|
EthersHttpClient(ethers::providers::HttpClientError),
|
2023-05-31 07:26:11 +03:00
|
|
|
EthersProvider(ethers::prelude::ProviderError),
|
|
|
|
EthersWsClient(ethers::prelude::WsClientError),
|
2023-10-16 21:04:02 +03:00
|
|
|
#[display(fmt = "{:?} < {}", head, requested)]
|
2023-10-10 08:21:39 +03:00
|
|
|
#[from(ignore)]
|
|
|
|
FarFutureBlock {
|
2023-10-16 21:04:02 +03:00
|
|
|
head: Option<U64>,
|
2023-10-10 08:21:39 +03:00
|
|
|
requested: U64,
|
|
|
|
},
|
2023-05-31 07:26:11 +03:00
|
|
|
GasEstimateNotU256,
|
2023-06-09 22:21:50 +03:00
|
|
|
HdrRecord(hdrhistogram::errors::RecordError),
|
2023-05-31 07:26:11 +03:00
|
|
|
Headers(headers::Error),
|
|
|
|
HeaderToString(ToStrError),
|
2023-06-24 21:11:07 +03:00
|
|
|
HttpUri(InvalidUri),
|
2023-05-31 07:26:11 +03:00
|
|
|
Hyper(hyper::Error),
|
|
|
|
InfluxDb2Request(influxdb2::RequestError),
|
|
|
|
#[display(fmt = "{} > {}", min, max)]
|
|
|
|
#[from(ignore)]
|
|
|
|
InvalidBlockBounds {
|
|
|
|
min: u64,
|
|
|
|
max: u64,
|
|
|
|
},
|
|
|
|
InvalidHeaderValue(InvalidHeaderValue),
|
|
|
|
InvalidEip,
|
|
|
|
InvalidInviteCode,
|
|
|
|
Io(std::io::Error),
|
|
|
|
UnknownReferralCode,
|
|
|
|
InvalidReferer,
|
|
|
|
InvalidSignatureLength,
|
2023-06-07 19:39:30 +03:00
|
|
|
InvalidUserTier,
|
2023-05-31 07:26:11 +03:00
|
|
|
InvalidUserAgent,
|
|
|
|
InvalidUserKey,
|
|
|
|
IpAddrParse(AddrParseError),
|
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
|
|
|
IpNotAllowed(IpAddr),
|
|
|
|
JoinError(JoinError),
|
2023-07-25 02:25:48 +03:00
|
|
|
JsonRejection(JsonRejection),
|
2023-05-31 07:26:11 +03:00
|
|
|
#[display(fmt = "{:?}", _0)]
|
|
|
|
#[error(ignore)]
|
|
|
|
JsonRpcErrorData(JsonRpcErrorData),
|
2023-10-09 19:38:58 +03:00
|
|
|
#[from(ignore)]
|
|
|
|
#[display(fmt = "{}", _0)]
|
|
|
|
MdbxPanic(String, Cow<'static, str>),
|
2023-05-31 07:26:11 +03:00
|
|
|
NoBlockNumberOrHash,
|
|
|
|
NoBlocksKnown,
|
|
|
|
NoConsensusHeadBlock,
|
2023-07-15 04:30:01 +03:00
|
|
|
NoDatabaseConfigured,
|
2023-05-31 07:26:11 +03:00
|
|
|
NoHandleReady,
|
|
|
|
NoServersSynced,
|
|
|
|
#[display(fmt = "{}/{}", num_known, min_head_rpcs)]
|
|
|
|
#[from(ignore)]
|
|
|
|
NotEnoughRpcs {
|
|
|
|
num_known: usize,
|
|
|
|
min_head_rpcs: usize,
|
|
|
|
},
|
|
|
|
#[display(fmt = "{}/{}", available, needed)]
|
|
|
|
#[from(ignore)]
|
|
|
|
NotEnoughSoftLimit {
|
|
|
|
available: u32,
|
|
|
|
needed: u32,
|
|
|
|
},
|
|
|
|
NotFound,
|
2023-06-29 07:47:06 +03:00
|
|
|
#[error(ignore)]
|
2023-06-29 09:00:34 +03:00
|
|
|
#[from(ignore)]
|
2023-08-18 01:32:22 +03:00
|
|
|
MethodNotFound(Cow<'static, str>),
|
2023-06-24 21:11:07 +03:00
|
|
|
NoVolatileRedisDatabase,
|
2023-10-24 04:46:53 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
|
|
|
#[display(fmt = "{} @ {}", _0, _1)]
|
|
|
|
OldHead(Arc<Web3Rpc>, Web3ProxyBlock),
|
2023-05-31 07:26:11 +03:00
|
|
|
OriginRequired,
|
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
|
|
|
OriginNotAllowed(headers::Origin),
|
|
|
|
#[display(fmt = "{:?}", _0)]
|
|
|
|
#[error(ignore)]
|
|
|
|
ParseBytesError(Option<ethers::types::ParseBytesError>),
|
|
|
|
ParseMsgError(siwe::ParseError),
|
|
|
|
ParseAddressError,
|
2023-11-03 21:51:02 +03:00
|
|
|
#[display(fmt = "{:?} > {:?}", from, to)]
|
|
|
|
RangeInvalid {
|
|
|
|
from: BlockNumOrHash,
|
|
|
|
to: BlockNumOrHash,
|
|
|
|
},
|
|
|
|
#[display(fmt = "{:?} > {:?}", from, to)]
|
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
|
|
|
RangeTooLarge {
|
|
|
|
from: BlockNumOrHash,
|
|
|
|
to: BlockNumOrHash,
|
|
|
|
requested: U64,
|
|
|
|
allowed: U64,
|
|
|
|
},
|
2023-05-31 07:26:11 +03:00
|
|
|
#[display(fmt = "{:?}, {:?}", _0, _1)]
|
|
|
|
RateLimited(Authorization, Option<Instant>),
|
|
|
|
Redis(RedisError),
|
2023-06-24 21:11:07 +03:00
|
|
|
RedisDeadpool(RedisPoolError),
|
2023-05-31 07:26:11 +03:00
|
|
|
RefererRequired,
|
|
|
|
#[display(fmt = "{:?}", _0)]
|
|
|
|
#[error(ignore)]
|
|
|
|
#[from(ignore)]
|
|
|
|
RefererNotAllowed(headers::Referer),
|
2023-10-07 00:51:21 +03:00
|
|
|
Reqwest(reqwest::Error),
|
2023-05-31 07:26:11 +03:00
|
|
|
SemaphoreAcquireError(AcquireError),
|
|
|
|
SerdeJson(serde_json::Error),
|
2023-06-24 19:48:28 +03:00
|
|
|
SiweVerification(VerificationError),
|
2023-05-31 07:26:11 +03:00
|
|
|
/// simple way to return an error message to the user and an anyhow to our logs
|
|
|
|
#[display(fmt = "{}, {}, {:?}", _0, _1, _2)]
|
2023-10-07 00:51:21 +03:00
|
|
|
StatusCode(StatusCode, Cow<'static, str>, Option<serde_json::Value>),
|
2023-10-17 09:56:38 +03:00
|
|
|
#[display(fmt = "streaming response")]
|
|
|
|
#[error(ignore)]
|
|
|
|
StreamResponse(StreamResponse<Arc<RawValue>>),
|
2023-10-07 05:20:38 +03:00
|
|
|
#[cfg(feature = "stripe")]
|
2023-07-03 22:17:30 +03:00
|
|
|
StripeWebhookError(stripe::WebhookError),
|
2023-05-31 07:26:11 +03:00
|
|
|
/// TODO: what should be attached to the timout?
|
|
|
|
#[display(fmt = "{:?}", _0)]
|
|
|
|
#[error(ignore)]
|
2023-07-20 08:32:52 +03:00
|
|
|
Timeout(Option<Duration>),
|
2023-05-31 07:26:11 +03:00
|
|
|
UlidDecode(ulid::DecodeError),
|
2023-06-29 01:04:55 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
UnknownBlockHash(H256),
|
|
|
|
#[display(fmt = "known: {known}, unknown: {unknown}")]
|
|
|
|
#[error(ignore)]
|
|
|
|
UnknownBlockNumber {
|
|
|
|
known: U64,
|
|
|
|
unknown: U64,
|
|
|
|
},
|
2023-05-31 07:26:11 +03:00
|
|
|
UnknownKey,
|
2023-08-09 01:50:34 +03:00
|
|
|
#[error(ignore)]
|
|
|
|
UnhandledMethod(Cow<'static, str>),
|
2023-05-31 07:26:11 +03:00
|
|
|
UserAgentRequired,
|
|
|
|
#[error(ignore)]
|
|
|
|
UserAgentNotAllowed(headers::UserAgent),
|
|
|
|
UserIdZero,
|
|
|
|
PaymentRequired,
|
|
|
|
WatchRecvError(tokio::sync::watch::error::RecvError),
|
|
|
|
WatchSendError,
|
|
|
|
WebsocketOnly,
|
|
|
|
#[display(fmt = "{:?}, {}", _0, _1)]
|
|
|
|
#[error(ignore)]
|
2023-06-10 04:31:47 +03:00
|
|
|
WithContext(Option<Box<Web3ProxyError>>, Cow<'static, str>),
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Web3ProxyError {
|
2023-09-27 04:18:06 +03:00
|
|
|
pub fn as_json_response_parts(
|
|
|
|
&self,
|
|
|
|
id: Box<RawValue>,
|
|
|
|
) -> (StatusCode, jsonrpc::SingleResponse) {
|
|
|
|
let (code, response_data) = self.as_response_parts();
|
|
|
|
let response = jsonrpc::ParsedResponse::from_response_data(response_data, id);
|
|
|
|
(code, response.into())
|
|
|
|
}
|
|
|
|
|
2023-07-25 02:25:48 +03:00
|
|
|
/// turn the error into an axum response.
|
|
|
|
/// <https://www.jsonrpc.org/specification#error_object>
|
2023-10-09 19:38:58 +03:00
|
|
|
/// TODO? change to `to_response_parts(self)`
|
2023-10-11 10:12:20 +03:00
|
|
|
pub fn as_response_parts(&self) -> (StatusCode, ForwardedResponse<Arc<RawValue>>) {
|
2023-05-31 07:26:11 +03:00
|
|
|
// TODO: include a unique request id in the data
|
|
|
|
let (code, err): (StatusCode, JsonRpcErrorData) = match self {
|
2023-05-31 22:44:02 +03:00
|
|
|
Self::Abi(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
warn!(?err, "abi error");
|
2023-05-31 22:44:02 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "abi error".into(),
|
2023-05-31 22:44:02 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 22:44:02 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-29 09:00:34 +03:00
|
|
|
Self::AccessDenied(msg) => {
|
2023-05-31 07:26:11 +03:00
|
|
|
// TODO: attach something to this trace. probably don't include much in the message though. don't want to leak creds by accident
|
2023-06-29 09:00:34 +03:00
|
|
|
trace!(%msg, "access denied");
|
2023-06-25 21:29:54 +03:00
|
|
|
(
|
|
|
|
StatusCode::FORBIDDEN,
|
|
|
|
JsonRpcErrorData {
|
2023-06-29 09:00:34 +03:00
|
|
|
message: format!("FORBIDDEN: {}", msg).into(),
|
2023-06-25 21:29:54 +03:00
|
|
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-10 22:19:54 +03:00
|
|
|
Self::ArchiveRequired { min, max } => {
|
|
|
|
// TODO: attach something to this trace. probably don't include much in the message though. don't want to leak creds by accident
|
|
|
|
trace!(?min, ?max, "archive node required");
|
|
|
|
(
|
|
|
|
StatusCode::OK,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "Archive data required".into(),
|
|
|
|
code: StatusCode::OK.as_u16().into(),
|
|
|
|
data: Some(json!({
|
|
|
|
"min": min,
|
|
|
|
"max": max,
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::Anyhow(err) => {
|
2023-07-26 01:15:03 +03:00
|
|
|
error!(?err, "anyhow: {}", err);
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
// TODO: is it safe to expose all of our anyhow strings?
|
2023-06-27 08:40:00 +03:00
|
|
|
message: "INTERNAL SERVER ERROR".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-08 03:26:38 +03:00
|
|
|
Self::Arc(err) => {
|
2023-10-14 05:41:59 +03:00
|
|
|
return err.as_response_parts();
|
2023-06-08 03:26:38 +03:00
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::BadRequest(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
trace!(?err, "BAD_REQUEST");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "bad request".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::BadResponse(err) => {
|
|
|
|
// TODO: think about this one more. ankr gives us this because ethers fails to parse responses without an id
|
2023-07-10 08:49:29 +03:00
|
|
|
debug!(?err, "BAD_RESPONSE: {}", err);
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "bad response".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::BadRouting => {
|
|
|
|
error!("BadRouting");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "bad routing".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-27 07:38:41 +03:00
|
|
|
Self::Contract(err) => {
|
2023-07-10 08:49:29 +03:00
|
|
|
warn!(?err, "Contract Error: {}", err);
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "contract error".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-27 07:38:41 +03:00
|
|
|
Self::Database(err) => {
|
2023-07-10 08:49:29 +03:00
|
|
|
error!(?err, "database err: {}", err);
|
2023-05-31 21:20:17 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-27 07:38:41 +03:00
|
|
|
message: "database error!".into(),
|
2023-05-31 21:20:17 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 21:20:17 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-07-15 04:30:01 +03:00
|
|
|
Self::DatabaseArc(err) => {
|
|
|
|
error!(?err, "database (arc) err: {}", err);
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "database (arc) error!".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-07-15 04:30:01 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 21:20:17 +03:00
|
|
|
Self::Decimal(err) => {
|
2023-07-10 08:49:29 +03:00
|
|
|
debug!(?err, "Decimal Error: {}", err);
|
2023-05-31 21:20:17 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "decimal error".into(),
|
2023-05-31 21:20:17 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 21:20:17 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-07 00:51:21 +03:00
|
|
|
Self::EthersHttpClient(err) => match JsonRpcErrorData::try_from(err) {
|
|
|
|
Ok(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
trace!(?err, "EthersHttpClient jsonrpc error");
|
|
|
|
(StatusCode::OK, err)
|
2023-10-07 00:51:21 +03:00
|
|
|
}
|
|
|
|
Err(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
warn!(?err, "EthersHttpClient");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "ethers http client error".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-27 08:40:00 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-07 00:51:21 +03:00
|
|
|
},
|
|
|
|
Self::EthersProvider(err) => match JsonRpcErrorData::try_from(err) {
|
|
|
|
Ok(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
trace!(?err, "EthersProvider jsonrpc error");
|
|
|
|
(StatusCode::OK, err)
|
2023-10-07 00:51:21 +03:00
|
|
|
}
|
|
|
|
Err(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
warn!(?err, "EthersProvider");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "ethers provider error".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-27 08:40:00 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-07 00:51:21 +03:00
|
|
|
},
|
|
|
|
Self::EthersWsClient(err) => match JsonRpcErrorData::try_from(err) {
|
|
|
|
Ok(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
trace!(?err, "EthersWsClient jsonrpc error");
|
|
|
|
(StatusCode::OK, err)
|
2023-10-07 00:51:21 +03:00
|
|
|
}
|
|
|
|
Err(err) => {
|
2023-06-27 08:40:00 +03:00
|
|
|
warn!(?err, "EthersWsClient");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "ethers ws client error".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-27 08:40:00 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-07 00:51:21 +03:00
|
|
|
},
|
2023-10-10 08:21:39 +03:00
|
|
|
Self::FarFutureBlock { head, requested } => {
|
|
|
|
trace!(?head, ?requested, "FarFutureBlock");
|
|
|
|
(
|
|
|
|
StatusCode::OK,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "requested block is too far in the future".into(),
|
|
|
|
code: (-32002).into(),
|
|
|
|
data: Some(json!({
|
|
|
|
"head": head,
|
|
|
|
"requested": requested,
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
// Self::JsonRpcForwardedError(x) => (StatusCode::OK, x),
|
|
|
|
Self::GasEstimateNotU256 => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("GasEstimateNotU256");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "gas estimate result is not an U256".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-09 22:21:50 +03:00
|
|
|
Self::HdrRecord(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(?err, "HdrRecord");
|
2023-06-09 22:21:50 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "hdr record error".into(),
|
2023-06-09 22:21:50 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-09 22:21:50 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::Headers(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "HeadersError");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "headers error".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-27 07:38:41 +03:00
|
|
|
Self::HeaderToString(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "HeaderToString");
|
2023-06-27 07:38:41 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "header to string error".into(),
|
2023-06-27 07:38:41 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-27 07:38:41 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-24 21:11:07 +03:00
|
|
|
Self::HttpUri(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "HttpUri");
|
2023-06-24 21:11:07 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: err.to_string().into(),
|
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-24 21:11:07 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::Hyper(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(?err, "hyper");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
// TODO: is it safe to expose these error strings?
|
2023-06-10 04:31:47 +03:00
|
|
|
message: err.to_string().into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InfluxDb2Request(err) => {
|
|
|
|
// TODO: attach a request id to the message and to this error so that if people report problems, we can dig in sentry to find out more
|
2023-06-29 07:30:00 +03:00
|
|
|
error!(?err, "influxdb2");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "influxdb2 error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidBlockBounds { min, max } => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(%min, %max, "InvalidBlockBounds");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "Invalid blocks bounds requested".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(json!({
|
|
|
|
"min": min,
|
|
|
|
"max": max,
|
|
|
|
})),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::IpAddrParse(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
debug!(?err, "IpAddrParse");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: err.to_string().into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::IpNotAllowed(ip) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?ip, "IpNotAllowed");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::FORBIDDEN,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "IP is not allowed!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(ip.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidHeaderValue(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "InvalidHeaderValue");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "invalid header value".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidEip => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("InvalidEip");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "invalid message eip given".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidInviteCode => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("InvalidInviteCode");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::UNAUTHORIZED,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "invalid invite code".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::UNAUTHORIZED.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::Io(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(?err, "std io");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "std io".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
// TODO: is it safe to expose our io error strings?
|
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidReferer => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("InvalidReferer");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "invalid referer!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidSignatureLength => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("InvalidSignatureLength");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "invalid signature length".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidUserAgent => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("InvalidUserAgent");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::FORBIDDEN,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "invalid user agent!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::InvalidUserKey => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("InvalidUserKey");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "UserKey was not a ULID or UUID".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
2023-06-07 19:39:30 +03:00
|
|
|
}
|
|
|
|
Self::InvalidUserTier => {
|
|
|
|
warn!("InvalidUserTier");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "UserTier is not valid!".into(),
|
2023-06-07 19:39:30 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
Self::JoinError(err) => {
|
|
|
|
let code = if err.is_cancelled() {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "JoinError. likely shutting down");
|
2023-05-31 07:26:11 +03:00
|
|
|
StatusCode::BAD_GATEWAY
|
|
|
|
} else {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(?err, "JoinError");
|
2023-05-31 07:26:11 +03:00
|
|
|
StatusCode::INTERNAL_SERVER_ERROR
|
|
|
|
};
|
|
|
|
|
|
|
|
(
|
|
|
|
code,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
// TODO: different messages of cancelled or not?
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "Unable to complete request".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: code.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::JsonRejection(err) => {
|
|
|
|
trace!(?err, "JsonRejection");
|
|
|
|
|
2023-10-07 00:51:21 +03:00
|
|
|
let (message, code): (&str, _) = match &err {
|
2023-07-25 02:25:48 +03:00
|
|
|
JsonRejection::JsonDataError(_) => ("Invalid Request", -32600),
|
|
|
|
JsonRejection::JsonSyntaxError(_) => ("Parse error", -32700),
|
|
|
|
JsonRejection::MissingJsonContentType(_) => ("Invalid Request", -32600),
|
|
|
|
JsonRejection::BytesRejection(_) => ("Invalid Request", -32600),
|
|
|
|
x => {
|
|
|
|
warn!(?x, "what? isn't that all of them?");
|
|
|
|
// TODO: what code should this be?
|
|
|
|
("Parse error", -32700)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO: i feel like this should be a 401, but the spec seems to say its a 200
|
|
|
|
(
|
|
|
|
StatusCode::OK,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: message.into(),
|
|
|
|
code: code.into(),
|
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-08 03:26:38 +03:00
|
|
|
Self::JsonRpcErrorData(jsonrpc_error_data) => {
|
|
|
|
// TODO: do this without clone? the Arc needed it though
|
|
|
|
(StatusCode::OK, jsonrpc_error_data.clone())
|
|
|
|
}
|
2023-10-09 19:38:58 +03:00
|
|
|
Self::MdbxPanic(rpc, msg) => {
|
|
|
|
error!(%msg, "mdbx panic");
|
|
|
|
|
|
|
|
// TODO: this is bad enough that we should send something to pager duty
|
|
|
|
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "mdbx panic".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-10-10 08:21:39 +03:00
|
|
|
data: Some(json!({"rpc": rpc})),
|
2023-10-09 19:38:58 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-08-18 01:32:22 +03:00
|
|
|
Self::MethodNotFound(method) => {
|
|
|
|
warn!("MethodNotFound: {}", method);
|
|
|
|
(
|
|
|
|
StatusCode::OK,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "Method not found".into(),
|
|
|
|
code: -32601,
|
|
|
|
data: Some(json!({
|
|
|
|
"method": method,
|
|
|
|
"extra": "contact us if you need this",
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::NoBlockNumberOrHash => {
|
|
|
|
warn!("NoBlockNumberOrHash");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "Blocks here must have a number or hash".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::NoBlocksKnown => {
|
|
|
|
error!("NoBlocksKnown");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "no blocks known".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_GATEWAY.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::NoConsensusHeadBlock => {
|
|
|
|
error!("NoConsensusHeadBlock");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "no consensus head block".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_GATEWAY.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-07-15 04:30:01 +03:00
|
|
|
Self::NoDatabaseConfigured => {
|
2023-07-14 11:19:09 +03:00
|
|
|
// TODO: this needs more context
|
2023-07-15 04:30:01 +03:00
|
|
|
debug!("no database configured");
|
2023-06-16 10:46:27 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-07-15 04:30:01 +03:00
|
|
|
message: "no database configured! this request needs a database".into(),
|
2023-06-16 10:46:27 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::NoHandleReady => {
|
|
|
|
error!("NoHandleReady");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "unable to retry for request handle".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_GATEWAY.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-24 21:11:07 +03:00
|
|
|
Self::NoVolatileRedisDatabase => {
|
|
|
|
error!("no volatile redis database configured");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "no volatile redis database configured!".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::NoServersSynced => {
|
|
|
|
warn!("NoServersSynced");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "no servers synced".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_GATEWAY.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::NotEnoughRpcs {
|
|
|
|
num_known,
|
|
|
|
min_head_rpcs,
|
|
|
|
} => {
|
2023-07-03 22:17:30 +03:00
|
|
|
error!(%num_known, %min_head_rpcs, "NotEnoughRpcs");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: format!(
|
2023-05-31 07:26:11 +03:00
|
|
|
"not enough rpcs connected {}/{}",
|
|
|
|
num_known, min_head_rpcs
|
2023-06-10 04:31:47 +03:00
|
|
|
)
|
|
|
|
.into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_GATEWAY.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::NotEnoughSoftLimit { available, needed } => {
|
2023-07-03 22:17:30 +03:00
|
|
|
error!(available, needed, "NotEnoughSoftLimit");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "not enough soft limit available".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_GATEWAY.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(json!({
|
|
|
|
"available": available,
|
|
|
|
"needed": needed,
|
|
|
|
})),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::NotFound => {
|
|
|
|
// TODO: emit a stat?
|
|
|
|
// TODO: instead of an error, show a normal html page for 404?
|
|
|
|
(
|
|
|
|
StatusCode::NOT_FOUND,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "not found!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::NOT_FOUND.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-24 04:46:53 +03:00
|
|
|
Self::OldHead(rpc, old_head) => {
|
|
|
|
warn!(?old_head, "{} is lagged", rpc);
|
|
|
|
(
|
|
|
|
StatusCode::BAD_GATEWAY,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "RPC is lagged".into(),
|
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: Some(json!({
|
|
|
|
"rpc": rpc.name,
|
|
|
|
"head": old_head,
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::OriginRequired => {
|
|
|
|
trace!("OriginRequired");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "Origin required".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::OriginNotAllowed(origin) => {
|
2023-07-03 22:17:30 +03:00
|
|
|
trace!(?origin, "OriginNotAllowed");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::FORBIDDEN,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "Origin is not allowed!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(origin.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::ParseBytesError(err) => {
|
2023-07-03 22:17:30 +03:00
|
|
|
trace!(?err, "ParseBytesError");
|
2023-07-25 02:25:48 +03:00
|
|
|
|
|
|
|
let data = err
|
|
|
|
.as_ref()
|
|
|
|
.map(|x| serde_json::Value::String(x.to_string()));
|
|
|
|
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "parse bytes error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data,
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::ParseMsgError(err) => {
|
2023-07-03 22:17:30 +03:00
|
|
|
trace!(?err, "ParseMsgError");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "parse message error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::ParseAddressError => {
|
|
|
|
trace!("ParseAddressError");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "unable to parse address".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::PaymentRequired => {
|
|
|
|
trace!("PaymentRequiredError");
|
|
|
|
(
|
|
|
|
StatusCode::PAYMENT_REQUIRED,
|
|
|
|
JsonRpcErrorData {
|
2023-06-27 07:38:41 +03:00
|
|
|
message: "Payment is required to activate premium".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::PAYMENT_REQUIRED.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-11-03 21:51:02 +03:00
|
|
|
Self::RangeInvalid { from, to } => {
|
|
|
|
trace!(?from, ?to, "RangeInvalid");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "invalid block range given".into(),
|
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: Some(json!({
|
|
|
|
"from": from,
|
|
|
|
"to": to,
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::RangeTooLarge {
|
|
|
|
from,
|
|
|
|
to,
|
|
|
|
requested,
|
|
|
|
allowed,
|
|
|
|
} => {
|
|
|
|
trace!(?from, ?to, %requested, %allowed, "RangeTooLarge");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "invalid block range given".into(),
|
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: Some(json!({
|
|
|
|
"from": from,
|
|
|
|
"to": to,
|
|
|
|
"requested": requested,
|
|
|
|
"allowed": allowed,
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
// TODO: this should actually by the id of the key. multiple users might control one key
|
|
|
|
Self::RateLimited(authorization, retry_at) => {
|
|
|
|
// TODO: emit a stat
|
|
|
|
|
2023-08-24 23:25:14 +03:00
|
|
|
let retry_after = if let Some(retry_at) = retry_at {
|
|
|
|
retry_at.duration_since(Instant::now()).as_secs()
|
2023-05-31 07:26:11 +03:00
|
|
|
} else {
|
2023-08-24 23:25:14 +03:00
|
|
|
// TODO: what should we default to?
|
|
|
|
60
|
2023-05-31 07:26:11 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// create a string with either the IP or the rpc_key_id
|
2023-08-24 23:25:14 +03:00
|
|
|
let retry_data = if authorization.checks.rpc_secret_key_id.is_none() {
|
|
|
|
json!({"retry_after": retry_after, "ip": authorization.ip})
|
2023-05-31 07:26:11 +03:00
|
|
|
} else {
|
2023-08-24 23:25:14 +03:00
|
|
|
json!({"retry_after": retry_after, "ip": authorization.ip, "key_id": authorization.checks.rpc_secret_key_id.unwrap()})
|
2023-05-31 07:26:11 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
(
|
|
|
|
StatusCode::TOO_MANY_REQUESTS,
|
|
|
|
JsonRpcErrorData {
|
2023-08-24 23:25:14 +03:00
|
|
|
message: "too many requests".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::TOO_MANY_REQUESTS.as_u16().into(),
|
2023-08-24 23:25:14 +03:00
|
|
|
data: Some(retry_data),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::Redis(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(?err, "redis");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "redis error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-27 07:38:41 +03:00
|
|
|
Self::RedisDeadpool(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
error!(?err, "redis deadpool");
|
2023-06-27 07:38:41 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
// TODO: is it safe to expose our io error strings?
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "redis pool error".into(),
|
2023-06-27 07:38:41 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-27 07:38:41 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::RefererRequired => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("referer required");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "Referer required".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::RefererNotAllowed(referer) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?referer, "referer not allowed");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::FORBIDDEN,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "Referer is not allowed".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(format!("{:?}", referer))),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-07 00:51:21 +03:00
|
|
|
Self::Reqwest(err) => {
|
|
|
|
warn!(?err, "reqwest");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "reqwest error!".into(),
|
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::SemaphoreAcquireError(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
error!(?err, "semaphore acquire");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
// TODO: is it safe to expose all of our anyhow strings?
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "semaphore acquire error".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::SerdeJson(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "serde json");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "de/serialization error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-06-27 07:38:41 +03:00
|
|
|
Self::SiweVerification(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
trace!(?err, "Siwe Verification");
|
2023-06-27 07:38:41 +03:00
|
|
|
(
|
|
|
|
StatusCode::UNAUTHORIZED,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "siwe verification error".into(),
|
2023-06-27 07:38:41 +03:00
|
|
|
code: StatusCode::UNAUTHORIZED.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-06-27 07:38:41 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-07 00:51:21 +03:00
|
|
|
Self::StatusCode(status_code, err_msg, data) => {
|
2023-05-31 07:26:11 +03:00
|
|
|
// different status codes should get different error levels. 500s should warn. 400s should stat
|
|
|
|
let code = status_code.as_u16();
|
|
|
|
if (500..600).contains(&code) {
|
2023-10-07 00:51:21 +03:00
|
|
|
warn!(?data, "server error {}: {}", code, err_msg);
|
2023-05-31 07:26:11 +03:00
|
|
|
} else {
|
2023-10-07 00:51:21 +03:00
|
|
|
trace!(?data, "user error {}: {}", code, err_msg);
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
|
2023-10-07 00:51:21 +03:00
|
|
|
// TODO: would be great to do this without the cloning! Something blocked that and I didn't write a comment about it though
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
2023-06-08 03:26:38 +03:00
|
|
|
*status_code,
|
2023-05-31 07:26:11 +03:00
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: err_msg.clone(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: code.into(),
|
2023-10-07 00:51:21 +03:00
|
|
|
data: data.clone(),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-17 09:56:38 +03:00
|
|
|
Self::StreamResponse(..) => {
|
|
|
|
// TODO: should it really?
|
|
|
|
unimplemented!("streaming should be handled elsewhere");
|
|
|
|
}
|
2023-10-07 05:20:38 +03:00
|
|
|
#[cfg(feature = "stripe")]
|
2023-07-03 22:17:30 +03:00
|
|
|
Self::StripeWebhookError(err) => {
|
|
|
|
trace!(?err, "StripeWebhookError");
|
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "stripe webhook error".into(),
|
2023-07-03 22:17:30 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
// TODO: include the stripe signature? anything else?
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::Timeout(x) => {
|
|
|
|
let data = x.as_ref().map(|x| json!(x.as_secs_f32()));
|
|
|
|
|
|
|
|
(
|
|
|
|
StatusCode::REQUEST_TIMEOUT,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "request timed out".into(),
|
|
|
|
code: StatusCode::REQUEST_TIMEOUT.as_u16().into(),
|
|
|
|
// TODO: prettier message
|
|
|
|
// TODO: include the actual id!
|
|
|
|
data,
|
2023-07-03 22:17:30 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::UlidDecode(err) => {
|
2023-07-03 22:17:30 +03:00
|
|
|
trace!(?err, "UlidDecodeError");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "ulid decode error".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-08-09 01:50:34 +03:00
|
|
|
Self::UnhandledMethod(method) => {
|
|
|
|
unimplemented!(
|
|
|
|
"unhandled method ({}) should never be shown to a user",
|
|
|
|
method
|
|
|
|
);
|
|
|
|
}
|
2023-06-29 01:04:55 +03:00
|
|
|
Self::UnknownBlockHash(hash) => {
|
|
|
|
debug!(%hash, "UnknownBlockHash");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
2023-06-29 01:04:55 +03:00
|
|
|
StatusCode::OK,
|
2023-05-31 07:26:11 +03:00
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "block hash not found".into(),
|
2023-06-29 03:42:43 +03:00
|
|
|
code: -32000,
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(json!({
|
|
|
|
"hash": hash,
|
|
|
|
})),
|
2023-06-29 01:04:55 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::UnknownBlockNumber { known, unknown } => {
|
|
|
|
debug!(%known, %unknown, "UnknownBlockNumber");
|
|
|
|
(
|
|
|
|
StatusCode::OK,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "block number not found".into(),
|
2023-06-29 03:42:43 +03:00
|
|
|
code: -32000,
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(json!({
|
|
|
|
"unknown": unknown,
|
|
|
|
"known": known,
|
|
|
|
})),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::UnknownKey => (
|
|
|
|
StatusCode::UNAUTHORIZED,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "unknown api key!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::UNAUTHORIZED.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
),
|
2023-06-27 07:38:41 +03:00
|
|
|
Self::UnknownReferralCode => {
|
|
|
|
trace!("UnknownReferralCode");
|
|
|
|
(
|
|
|
|
StatusCode::UNAUTHORIZED,
|
|
|
|
JsonRpcErrorData {
|
|
|
|
message: "invalid referral code".into(),
|
|
|
|
code: StatusCode::UNAUTHORIZED.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
Self::UserAgentRequired => {
|
2023-06-16 10:46:27 +03:00
|
|
|
trace!("UserAgentRequired");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
2023-06-27 07:38:41 +03:00
|
|
|
StatusCode::UNAUTHORIZED,
|
2023-05-31 07:26:11 +03:00
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "User agent required".into(),
|
2023-06-27 07:38:41 +03:00
|
|
|
code: StatusCode::UNAUTHORIZED.as_u16().into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::UserAgentNotAllowed(ua) => {
|
2023-07-03 22:17:30 +03:00
|
|
|
trace!(%ua, "UserAgentNotAllowed");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::FORBIDDEN,
|
|
|
|
JsonRpcErrorData {
|
2023-07-25 02:25:48 +03:00
|
|
|
message: "User agent is not allowed!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::FORBIDDEN.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(ua.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::UserIdZero => {
|
|
|
|
warn!("UserIdZero");
|
|
|
|
// TODO: this might actually be an application error and not a BAD_REQUEST
|
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "user ids should always be non-zero".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::WatchRecvError(err) => {
|
2023-07-03 22:17:30 +03:00
|
|
|
error!(?err, "WatchRecvError");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "watch recv error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
2023-07-25 02:25:48 +03:00
|
|
|
data: Some(serde_json::Value::String(err.to_string())),
|
2023-05-31 07:26:11 +03:00
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::WatchSendError => {
|
|
|
|
error!("WatchSendError");
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: "watch send error!".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::WebsocketOnly => {
|
2023-06-29 01:04:55 +03:00
|
|
|
trace!("WebsocketOnly. redirect_public_url not set");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::BAD_REQUEST,
|
|
|
|
JsonRpcErrorData {
|
2023-06-29 01:04:55 +03:00
|
|
|
message: "only websockets work here".into(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::BAD_REQUEST.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
Self::WithContext(err, msg) => match err {
|
|
|
|
Some(err) => {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(?err, %msg, "error w/ context");
|
2023-06-08 03:26:38 +03:00
|
|
|
return err.as_response_parts();
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
None => {
|
2023-06-29 07:30:00 +03:00
|
|
|
warn!(%msg, "error w/ context");
|
2023-05-31 07:26:11 +03:00
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
JsonRpcErrorData {
|
2023-06-10 04:31:47 +03:00
|
|
|
message: msg.clone(),
|
2023-05-31 07:26:11 +03:00
|
|
|
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(),
|
|
|
|
data: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2023-10-11 10:12:20 +03:00
|
|
|
(code, ForwardedResponse::from(err))
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
|
2023-06-13 07:51:08 +03:00
|
|
|
#[inline]
|
|
|
|
pub fn into_response_with_id(self, id: Option<Box<RawValue>>) -> Response {
|
2023-06-08 03:26:38 +03:00
|
|
|
let (status_code, response_data) = self.as_response_parts();
|
2023-05-31 07:26:11 +03:00
|
|
|
|
2023-06-13 07:51:08 +03:00
|
|
|
let id = id.unwrap_or_default();
|
|
|
|
|
2023-10-11 10:12:20 +03:00
|
|
|
let response = ParsedResponse::from_response_data(response_data, id);
|
2023-05-31 07:26:11 +03:00
|
|
|
|
|
|
|
(status_code, Json(response)).into_response()
|
|
|
|
}
|
2023-07-15 04:30:01 +03:00
|
|
|
|
|
|
|
/// some things should keep going even if the db is down
|
|
|
|
pub fn split_db_errors(&self) -> Result<&Self, &Self> {
|
|
|
|
match self {
|
|
|
|
Web3ProxyError::NoDatabaseConfigured => Ok(self),
|
|
|
|
Web3ProxyError::Database(err) => {
|
|
|
|
warn!(?err, "db error while checking rpc key authorization");
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
Web3ProxyError::DatabaseArc(err) => {
|
|
|
|
warn!(?err, "db arc error while checking rpc key authorization");
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
Web3ProxyError::Arc(x) => {
|
|
|
|
// errors from inside moka cache helpers are wrapped in an Arc
|
|
|
|
x.split_db_errors()
|
|
|
|
}
|
|
|
|
_ => Err(self),
|
|
|
|
}
|
|
|
|
}
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ethers::types::ParseBytesError> for Web3ProxyError {
|
|
|
|
fn from(err: ethers::types::ParseBytesError) -> Self {
|
|
|
|
Self::ParseBytesError(Some(err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<tokio::time::error::Elapsed> for Web3ProxyError {
|
2023-07-20 08:32:52 +03:00
|
|
|
fn from(_: tokio::time::error::Elapsed) -> Self {
|
|
|
|
Self::Timeout(None)
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoResponse for Web3ProxyError {
|
|
|
|
#[inline]
|
|
|
|
fn into_response(self) -> Response {
|
|
|
|
self.into_response_with_id(Default::default())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Web3ProxyErrorContext<T> {
|
2023-06-10 04:31:47 +03:00
|
|
|
fn web3_context<S: Into<Cow<'static, str>>>(self, msg: S) -> Result<T, Web3ProxyError>;
|
2023-05-31 07:26:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Web3ProxyErrorContext<T> for Option<T> {
|
2023-06-10 04:31:47 +03:00
|
|
|
fn web3_context<S: Into<Cow<'static, str>>>(self, msg: S) -> Result<T, Web3ProxyError> {
|
2023-05-31 07:26:11 +03:00
|
|
|
self.ok_or(Web3ProxyError::WithContext(None, msg.into()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T, E> Web3ProxyErrorContext<T> for Result<T, E>
|
|
|
|
where
|
|
|
|
E: Into<Web3ProxyError>,
|
|
|
|
{
|
2023-06-10 04:31:47 +03:00
|
|
|
fn web3_context<S: Into<Cow<'static, str>>>(self, msg: S) -> Result<T, Web3ProxyError> {
|
2023-05-31 07:26:11 +03:00
|
|
|
self.map_err(|err| Web3ProxyError::WithContext(Some(Box::new(err.into())), msg.into()))
|
|
|
|
}
|
|
|
|
}
|
2023-06-15 19:50:21 +03:00
|
|
|
|
|
|
|
impl Web3ProxyError {
|
|
|
|
pub fn into_message(self, id: Option<Box<RawValue>>) -> Message {
|
|
|
|
let (_, err) = self.as_response_parts();
|
|
|
|
|
|
|
|
let id = id.unwrap_or_default();
|
|
|
|
|
2023-10-11 10:12:20 +03:00
|
|
|
let err = ParsedResponse::from_response_data(err, id);
|
2023-06-15 19:50:21 +03:00
|
|
|
|
|
|
|
let msg = serde_json::to_string(&err).expect("errors should always serialize to json");
|
|
|
|
|
|
|
|
// TODO: what about a binary message?
|
|
|
|
Message::Text(msg)
|
|
|
|
}
|
|
|
|
}
|