alloy_rpc_types_eth/
pubsub.rsuse crate::{Filter, Header, Log, Transaction};
use alloc::{boxed::Box, format};
use alloy_primitives::B256;
use alloy_serde::WithOtherFields;
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum SubscriptionResult<T = Transaction> {
Header(Box<WithOtherFields<Header>>),
Log(Box<Log>),
TransactionHash(B256),
FullTransaction(Box<T>),
SyncState(PubSubSyncStatus),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum PubSubSyncStatus {
Simple(bool),
Detailed(SyncStatusMetadata),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct SyncStatusMetadata {
pub syncing: bool,
pub starting_block: u64,
pub current_block: u64,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
pub highest_block: Option<u64>,
}
#[cfg(feature = "serde")]
impl<T> serde::Serialize for SubscriptionResult<T>
where
T: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match *self {
Self::Header(ref header) => header.serialize(serializer),
Self::Log(ref log) => log.serialize(serializer),
Self::TransactionHash(ref hash) => hash.serialize(serializer),
Self::FullTransaction(ref tx) => tx.serialize(serializer),
Self::SyncState(ref sync) => sync.serialize(serializer),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
pub enum SubscriptionKind {
NewHeads,
Logs,
NewPendingTransactions,
Syncing,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum Params {
#[default]
None,
Logs(Box<Filter>),
Bool(bool),
}
impl Params {
#[inline]
pub const fn is_bool(&self) -> bool {
matches!(self, Self::Bool(_))
}
#[inline]
pub const fn is_logs(&self) -> bool {
matches!(self, Self::Logs(_))
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Params {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Self::None => (&[] as &[serde_json::Value]).serialize(serializer),
Self::Logs(logs) => logs.serialize(serializer),
Self::Bool(full) => full.serialize(serializer),
}
}
}
#[cfg(feature = "serde")]
impl<'a> serde::Deserialize<'a> for Params {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'a>,
{
use serde::de::Error;
let v = serde_json::Value::deserialize(deserializer)?;
if v.is_null() {
return Ok(Self::None);
}
if let Some(val) = v.as_bool() {
return Ok(Self::Bool(val));
}
serde_json::from_value(v)
.map(|f| Self::Logs(Box::new(f)))
.map_err(|e| D::Error::custom(format!("Invalid Pub-Sub parameters: {e}")))
}
}
#[cfg(test)]
mod tests {
use super::*;
use similar_asserts::assert_eq;
#[test]
#[cfg(feature = "serde")]
fn params_serde() {
let s: Params = serde_json::from_str("true").unwrap();
assert_eq!(s, Params::Bool(true));
let s: Params = serde_json::from_str("null").unwrap();
assert_eq!(s, Params::None);
}
}