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