use jsonrpsee::{
server::middleware::rpc::{layer::ResponseFuture, RpcServiceT},
MethodResponse,
};
use jsonrpsee_types::ErrorObject;
#[derive(Clone)]
pub struct FixRpcResponseMiddleware<S> {
service: S,
}
impl<S> FixRpcResponseMiddleware<S> {
pub fn new(service: S) -> Self {
Self { service }
}
}
impl<'a, S> RpcServiceT<'a> for FixRpcResponseMiddleware<S>
where
S: RpcServiceT<'a> + Send + Sync + Clone + 'static,
{
type Future = ResponseFuture<futures::future::BoxFuture<'a, jsonrpsee::MethodResponse>>;
fn call(&self, request: jsonrpsee::types::Request<'a>) -> Self::Future {
let service = self.service.clone();
ResponseFuture::future(Box::pin(async move {
let response = service.call(request).await;
if response.is_error() {
let original_error_code = response
.as_error_code()
.expect("response should have an error code");
if original_error_code == jsonrpsee_types::ErrorCode::InvalidParams.code() {
let new_error_code = crate::server::error::LegacyCode::Misc.into();
tracing::debug!(
"Replacing RPC error: {original_error_code} with {new_error_code}"
);
let json: serde_json::Value =
serde_json::from_str(response.into_parts().0.as_str())
.expect("response string should be valid json");
let id = match &json["id"] {
serde_json::Value::Null => Some(jsonrpsee::types::Id::Null),
serde_json::Value::Number(n) => {
n.as_u64().map(jsonrpsee::types::Id::Number)
}
serde_json::Value::String(s) => Some(jsonrpsee::types::Id::Str(s.into())),
_ => None,
}
.expect("response json should have an id");
return MethodResponse::error(
id,
ErrorObject::borrowed(
new_error_code,
json.get("error")
.and_then(|v| v.get("message"))
.and_then(|m| m.as_str())
.unwrap_or("Invalid params"),
None,
),
);
}
}
response
}))
}
}