Skip to main content

tycho_client/feed/
dto.rs

1//! Serializable wrappers for the client feed pipeline types.
2//!
3//! [`FeedMessage`], [`StateSyncMessage`], etc. mirror the structures of their
4//! model-based counterparts but use [`tycho_common::dto`] types that carry full
5//! `Serialize` / `Deserialize` support. The JSON format produced here matches the
6//! wire format (dto field names such as `contract_ids` and `state_updates`), which
7//! keeps the CLI output backwards-compatible with existing tooling and preserves the
8//! existing test fixture files.
9//!
10//! Conversion to and from the model-based pipeline types is provided via `From` impls.
11//! When both names are in scope use the module path to disambiguate, e.g.
12//! `feed::dto::ComponentWithState` vs `feed::synchronizer::ComponentWithState`.
13
14use std::collections::HashMap;
15
16use serde::{Deserialize, Serialize};
17use tycho_common::{
18    dto::{self, BlockAggregatedChanges, ResponseAccount, ResponseProtocolState},
19    Bytes,
20};
21
22use crate::feed::{self as feed_model, synchronizer, BlockHeader, HeaderLike, SynchronizerState};
23
24/// Serializable counterpart of [`crate::feed::synchronizer::ComponentWithState`].
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct ComponentWithState {
27    pub state: ResponseProtocolState,
28    pub component: dto::ProtocolComponent,
29    pub component_tvl: Option<f64>,
30    pub entrypoints: Vec<(dto::EntryPointWithTracingParams, dto::TracingResult)>,
31}
32
33/// Serializable counterpart of [`crate::feed::synchronizer::Snapshot`].
34#[derive(Debug, Clone, Serialize, Deserialize, Default)]
35pub struct Snapshot {
36    pub states: HashMap<String, ComponentWithState>,
37    #[serde(with = "tycho_common::serde_primitives::hex_hashmap_key")]
38    pub vm_storage: HashMap<Bytes, ResponseAccount>,
39}
40
41/// Serializable counterpart of [`crate::feed::synchronizer::StateSyncMessage`].
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct StateSyncMessage<H = BlockHeader> {
44    pub header: H,
45    pub snapshots: Snapshot,
46    pub deltas: Option<BlockAggregatedChanges>,
47    pub removed_components: HashMap<String, dto::ProtocolComponent>,
48}
49
50/// Serializable counterpart of [`crate::feed::FeedMessage`].
51#[derive(Debug, Clone, Serialize, Deserialize, Default)]
52pub struct FeedMessage<H = BlockHeader> {
53    pub state_msgs: HashMap<String, StateSyncMessage<H>>,
54    pub sync_states: HashMap<String, SynchronizerState>,
55}
56
57// ── dto types → model types ───────────────────────────────────────────────────
58
59impl From<ComponentWithState> for synchronizer::ComponentWithState {
60    fn from(value: ComponentWithState) -> Self {
61        Self {
62            state: value.state.into(),
63            component: value.component.into(),
64            component_tvl: value.component_tvl,
65            entrypoints: value
66                .entrypoints
67                .into_iter()
68                .map(|(ep, tr)| (ep.into(), tr.into()))
69                .collect(),
70        }
71    }
72}
73
74impl From<Snapshot> for synchronizer::Snapshot {
75    fn from(value: Snapshot) -> Self {
76        Self {
77            states: value
78                .states
79                .into_iter()
80                .map(|(k, v)| (k, v.into()))
81                .collect(),
82            vm_storage: value
83                .vm_storage
84                .into_iter()
85                .map(|(k, v)| (k, v.into()))
86                .collect(),
87        }
88    }
89}
90
91impl<H: HeaderLike> From<StateSyncMessage<H>> for synchronizer::StateSyncMessage<H> {
92    fn from(value: StateSyncMessage<H>) -> Self {
93        Self {
94            header: value.header,
95            snapshots: value.snapshots.into(),
96            deltas: value.deltas.map(Into::into),
97            removed_components: value
98                .removed_components
99                .into_iter()
100                .map(|(k, v)| (k, v.into()))
101                .collect(),
102        }
103    }
104}
105
106impl<H: HeaderLike> From<FeedMessage<H>> for feed_model::FeedMessage<H> {
107    fn from(value: FeedMessage<H>) -> Self {
108        Self {
109            state_msgs: value
110                .state_msgs
111                .into_iter()
112                .map(|(k, v)| (k, v.into()))
113                .collect(),
114            sync_states: value.sync_states,
115        }
116    }
117}
118
119// ── model types → dto types ───────────────────────────────────────────────────
120
121impl From<synchronizer::ComponentWithState> for ComponentWithState {
122    fn from(value: synchronizer::ComponentWithState) -> Self {
123        Self {
124            state: value.state.into(),
125            component: value.component.into(),
126            component_tvl: value.component_tvl,
127            entrypoints: value
128                .entrypoints
129                .into_iter()
130                .map(|(ep, tr)| (ep.into(), tr.into()))
131                .collect(),
132        }
133    }
134}
135
136impl From<synchronizer::Snapshot> for Snapshot {
137    fn from(value: synchronizer::Snapshot) -> Self {
138        Self {
139            states: value
140                .states
141                .into_iter()
142                .map(|(k, v)| (k, v.into()))
143                .collect(),
144            vm_storage: value
145                .vm_storage
146                .into_iter()
147                .map(|(k, v)| (k, v.into()))
148                .collect(),
149        }
150    }
151}
152
153impl<H: HeaderLike> From<synchronizer::StateSyncMessage<H>> for StateSyncMessage<H> {
154    fn from(value: synchronizer::StateSyncMessage<H>) -> Self {
155        Self {
156            header: value.header,
157            snapshots: value.snapshots.into(),
158            deltas: value.deltas.map(Into::into),
159            removed_components: value
160                .removed_components
161                .into_iter()
162                .map(|(k, v)| (k, v.into()))
163                .collect(),
164        }
165    }
166}
167
168impl<H: HeaderLike> From<feed_model::FeedMessage<H>> for FeedMessage<H> {
169    fn from(value: feed_model::FeedMessage<H>) -> Self {
170        Self {
171            state_msgs: value
172                .state_msgs
173                .into_iter()
174                .map(|(k, v)| (k, v.into()))
175                .collect(),
176            sync_states: value.sync_states,
177        }
178    }
179}