richat_shared/jsonrpc/
helpers.rs

1use {
2    http_body_util::{combinators::BoxBody, BodyExt, Full as BodyFull},
3    hyper::{body::Bytes, header::CONTENT_TYPE, http::Result as HttpResult, HeaderMap, StatusCode},
4    jsonrpsee_types::{
5        ErrorCode, ErrorObject, ErrorObjectOwned, Id, Response, ResponsePayload, TwoPointZero,
6    },
7    serde::Serialize,
8    solana_rpc_client_api::custom_error::RpcCustomError,
9    std::{fmt, sync::Arc},
10};
11
12pub const X_SUBSCRIPTION_ID: &str = "x-subscription-id";
13pub const X_BIGTABLE: &str = "x-bigtable"; // https://github.com/anza-xyz/agave/blob/v2.2.10/rpc/src/rpc_service.rs#L554
14
15pub type RpcResponse = hyper::Response<BoxBody<Bytes, std::convert::Infallible>>;
16
17pub fn get_x_subscription_id(headers: &HeaderMap) -> Arc<str> {
18    headers
19        .get(X_SUBSCRIPTION_ID)
20        .and_then(|value| value.to_str().ok().map(ToOwned::to_owned))
21        .unwrap_or_default()
22        .into()
23}
24
25pub fn get_x_bigtable_disabled(headers: &HeaderMap) -> bool {
26    headers.get(X_BIGTABLE).is_some_and(|v| v == "disabled")
27}
28
29pub fn response_200<D: Into<Bytes>>(data: D) -> HttpResult<RpcResponse> {
30    hyper::Response::builder()
31        .header(CONTENT_TYPE, "application/json; charset=utf-8")
32        .body(BodyFull::from(data.into()).boxed())
33}
34
35pub fn response_400<E: fmt::Display>(error: E) -> HttpResult<RpcResponse> {
36    hyper::Response::builder()
37        .status(StatusCode::BAD_REQUEST)
38        .body(format!("{error}\n").boxed())
39}
40
41pub fn response_500<E: fmt::Display>(error: E) -> HttpResult<RpcResponse> {
42    hyper::Response::builder()
43        .status(StatusCode::INTERNAL_SERVER_ERROR)
44        .body(format!("{error}\n").boxed())
45}
46
47pub fn jsonrpc_response_success<T: Clone + Serialize>(id: Id<'_>, payload: T) -> Vec<u8> {
48    to_vec(&Response {
49        jsonrpc: Some(TwoPointZero),
50        payload: ResponsePayload::success(payload),
51        id,
52    })
53}
54
55pub fn jsonrpc_response_error(id: Id<'_>, error: ErrorObjectOwned) -> Vec<u8> {
56    to_vec(&Response {
57        jsonrpc: Some(TwoPointZero),
58        payload: ResponsePayload::<()>::error(error),
59        id,
60    })
61}
62
63pub fn jsonrpc_response_error_custom(id: Id<'_>, error: RpcCustomError) -> Vec<u8> {
64    let error = jsonrpc_core::Error::from(error);
65    jsonrpc_response_error(
66        id,
67        ErrorObject::owned(error.code.code() as i32, error.message, error.data),
68    )
69}
70
71pub fn jsonrpc_error_invalid_params<S: Serialize>(
72    message: impl Into<String>,
73    data: Option<S>,
74) -> ErrorObjectOwned {
75    ErrorObject::owned(ErrorCode::InvalidParams.code(), message, data)
76}
77
78pub fn to_vec<T: Serialize>(value: &T) -> Vec<u8> {
79    serde_json::to_vec(value).expect("json serialization never fail")
80}