alloy_json_rpc/lib.rs
1//! Alloy JSON-RPC data types.
2//!
3//! This crate provides data types for use with the JSON-RPC 2.0 protocol. It
4//! does not provide any functionality for actually sending or receiving
5//! JSON-RPC data.
6//!
7//! If you find yourself importing this crate, and you are not implementing a
8//! JSON-RPC client or transport, you are likely at the wrong layer of
9//! abstraction. If you want to _use_ a JSON-RPC client, consider using the
10//! [`alloy-transport`] crate.
11//!
12//! [`alloy-transport`]: https://docs.rs/alloy-transport/latest/alloy_transport/
13//!
14//! ## Usage
15//!
16//! This crate models the JSON-RPC 2.0 protocol data-types. It is intended to
17//! be used to build JSON-RPC clients or servers. Most users will not need to
18//! import this crate.
19//!
20//! This crate provides the following low-level data types:
21//!
22//! - [`Request`] - A JSON-RPC request.
23//! - [`Response`] - A JSON-RPC response.
24//! - [`ErrorPayload`] - A JSON-RPC error response payload, including code and message.
25//! - [`ResponsePayload`] - The payload of a JSON-RPC response, either a success payload, or an
26//! [`ErrorPayload`].
27//!
28//! For client-side Rust ergonomics, we want to map responses to [`Result`]s.
29//! To that end, we provide the following types:
30//!
31//! - [`RpcError`] - An error that can occur during JSON-RPC communication. This type aggregates
32//! errors that are common to all transports, such as (de)serialization, error responses, and
33//! includes a generic transport error.
34//! - [`RpcResult`] - A result modeling an Rpc outcome as `Result<T,
35//! RpcError<E>>`.
36//!
37//! We recommend that transport implementors use [`RpcResult`] as the return
38//! type for their transport methods, parameterized by their transport error
39//! type. This will allow them to return either a successful response or an
40//! error.
41//!
42//! ## Note On (De)Serialization
43//!
44//! [`Request`], [`Response`], and similar types are generic over the
45//! actual data being passed to and from the RPC. We can achieve partial
46//! (de)serialization by making them generic over a `serde_json::RawValue`.
47//!
48//! - For [`Request`] - [`PartiallySerializedRequest`] is a `Request<Box<RawValue>`. It represents a
49//! `Request` whose parameters have been serialized. [`SerializedRequest`], on the other hand is a
50//! request that has been totally serialized. For client-development purposes, its [`Id`] and
51//! method have been preserved.
52//! - For [`Response`] - [`BorrowedResponse`] is a `Response<&RawValue>`. It represents a Response
53//! whose [`Id`] and return status (success or failure) have been deserialized, but whose payload
54//! has not.
55//!
56//! Allowing partial serialization lets us include many unlike [`Request`]
57//! objects in collections (e.g. in a batch request). This is useful for
58//! implementing a client.
59//!
60//! Allowing partial deserialization lets learn request status, and associate
61//! the raw response data with the corresponding client request before doing
62//! full deserialization work. This is useful for implementing a client.
63//!
64//! In general, partially deserialized responses can be further deserialized.
65//! E.g. an [`BorrowedRpcResult`] may have success responses deserialized
66//! with [`crate::try_deserialize_ok::<U>`], which will transform it to an
67//! [`RpcResult<U>`].
68
69#![doc(
70 html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg",
71 html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico"
72)]
73#![cfg_attr(not(test), warn(unused_crate_dependencies))]
74#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
75
76#[macro_use]
77extern crate tracing;
78
79use serde::{de::DeserializeOwned, Deserialize, Serialize};
80use std::fmt::Debug;
81
82mod common;
83pub use common::Id;
84
85mod error;
86pub use error::RpcError;
87
88mod notification;
89pub use notification::{EthNotification, PubSubItem, SubId};
90
91mod packet;
92pub use packet::{BorrowedResponsePacket, RequestPacket, ResponsePacket};
93
94mod request;
95pub use request::{PartiallySerializedRequest, Request, RequestMeta, SerializedRequest};
96
97mod response;
98pub use response::{
99 BorrowedErrorPayload, BorrowedResponse, BorrowedResponsePayload, ErrorPayload, Response,
100 ResponsePayload,
101};
102
103mod result;
104pub use result::{
105 transform_response, transform_result, try_deserialize_ok, BorrowedRpcResult, RpcResult,
106};
107
108/// An object that can be sent over RPC.
109///
110/// This marker trait is blanket-implemented for every qualifying type. It is
111/// used to indicate that a type can be sent in the body of a JSON-RPC message.
112pub trait RpcSend: Serialize + Clone + Debug + Send + Sync + Unpin {}
113
114impl<T> RpcSend for T where T: Serialize + Clone + Debug + Send + Sync + Unpin {}
115
116/// An object that can be received over RPC.
117///
118/// This marker trait is blanket-implemented for every qualifying type. It is
119/// used to indicate that a type can be received in the body of a JSON-RPC
120/// message.
121///
122/// # Note
123///
124/// We add the `'static` lifetime to the supertraits to indicate that the type
125/// can't borrow. This is a simplification that makes it easier to use the
126/// types in client code. Servers may prefer borrowing, using the [`RpcBorrow`]
127/// trait.
128pub trait RpcRecv: DeserializeOwned + Debug + Send + Sync + Unpin + 'static {}
129
130impl<T> RpcRecv for T where T: DeserializeOwned + Debug + Send + Sync + Unpin + 'static {}
131
132/// An object that can be received over RPC, borrowing from the
133/// deserialization context.
134///
135/// This marker trait is blanket-implemented for every qualifying type. It is
136/// used to indicate that a type can be borrowed from the body of a wholly or
137/// partially serialized JSON-RPC message.
138pub trait RpcBorrow<'de>: Deserialize<'de> + Debug + Send + Sync + Unpin {}
139
140impl<'de, T> RpcBorrow<'de> for T where T: Deserialize<'de> + Debug + Send + Sync + Unpin {}
141
142/// An object that can be both sent and received over RPC.
143///
144/// This marker trait is blanket-implemented for every qualifying type. It is
145/// used to indicate that a type can be both sent and received in the body of a
146/// JSON-RPC message.
147///
148/// # Note
149///
150/// We add the `'static` lifetime to the supertraits to indicate that the type
151/// can't borrow. This is a simplification that makes it easier to use the
152/// types in client code. Servers may prefer borrowing, using the
153/// [`BorrowedRpcObject`] trait.
154pub trait RpcObject: RpcSend + RpcRecv {}
155
156impl<T> RpcObject for T where T: RpcSend + RpcRecv {}
157
158/// An object that can be both sent and received over RPC, borrowing from the
159/// the deserialization context.
160///
161/// This marker trait is blanket-implemented for every qualifying type. It is
162/// used to indicate that a type can be both sent and received in the body of a
163/// JSON-RPC message, and can borrow from the deserialization context.
164pub trait BorrowedRpcObject<'de>: RpcBorrow<'de> + RpcSend {}
165
166impl<'de, T> BorrowedRpcObject<'de> for T where T: RpcBorrow<'de> + RpcSend {}