Skip to main content

ave_common/bridge/
response.rs

1//! Response payloads returned by the Ave API.
2
3use crate::{
4    DataToSink, SchemaType,
5    bridge::request::{ApprovalState, EventRequestType},
6};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9use std::{collections::HashMap, fmt::Display};
10
11#[cfg(feature = "openapi")]
12use utoipa::ToSchema;
13
14#[cfg(feature = "typescript")]
15use ts_rs::TS;
16
17/// Approval entry with request data and current state.
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[cfg_attr(feature = "openapi", derive(ToSchema))]
20#[cfg_attr(feature = "typescript", derive(TS))]
21#[cfg_attr(feature = "typescript", ts(export))]
22pub struct ApprovalEntry {
23    /// The approval request details
24    pub request: ApprovalReq,
25    /// Current state of the approval
26    pub state: ApprovalState,
27}
28
29#[derive(
30    Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd,
31)]
32#[cfg_attr(feature = "openapi", derive(ToSchema))]
33#[cfg_attr(feature = "typescript", derive(TS))]
34#[cfg_attr(feature = "typescript", ts(export))]
35pub struct SubjsData {
36    pub subject_id: String,
37    pub schema_id: SchemaType,
38    pub active: bool,
39    pub namespace: String,
40    pub name: Option<String>,
41    pub description: Option<String>,
42}
43
44#[derive(Clone, Debug, Serialize, Deserialize)]
45#[cfg_attr(feature = "openapi", derive(ToSchema))]
46#[cfg_attr(feature = "typescript", derive(TS))]
47#[cfg_attr(feature = "typescript", ts(export))]
48pub struct GovsData {
49    pub governance_id: String,
50    pub active: bool,
51    pub name: Option<String>,
52    pub description: Option<String>,
53}
54
55#[derive(Clone, Debug, Serialize, Deserialize)]
56#[cfg_attr(feature = "openapi", derive(ToSchema))]
57#[cfg_attr(feature = "typescript", derive(TS))]
58#[cfg_attr(feature = "typescript", ts(export))]
59pub struct TransferSubject {
60    pub name: Option<String>,
61    pub subject_id: String,
62    pub new_owner: String,
63    pub actual_owner: String,
64}
65
66#[derive(Clone, Debug, Serialize, Deserialize)]
67#[cfg_attr(feature = "openapi", derive(ToSchema))]
68#[cfg_attr(feature = "typescript", derive(TS))]
69#[cfg_attr(feature = "typescript", ts(export))]
70pub struct ApprovalReq {
71    /// The signed event request.
72    pub subject_id: String,
73    /// The sequence number of the event.
74    pub sn: u64,
75    /// The version of the governance contract.
76    pub gov_version: u64,
77    /// The patch to apply to the state.
78    pub patch: Value,
79
80    pub signer: String,
81}
82
83/// Network status exposed by monitoring endpoints.
84#[derive(Clone, Debug, Serialize, Deserialize, Default, Eq, PartialEq)]
85#[cfg_attr(feature = "openapi", derive(ToSchema))]
86#[cfg_attr(feature = "typescript", derive(TS))]
87#[cfg_attr(feature = "typescript", ts(export))]
88pub enum MonitorNetworkState {
89    /// Connecting to others network nodes
90    #[default]
91    Connecting,
92    /// Connected to others netowrk nodes
93    Running,
94    /// Can not connect to others network nodes
95    Down,
96}
97
98#[derive(Clone, Debug, Serialize, Deserialize)]
99#[cfg_attr(feature = "openapi", derive(ToSchema))]
100#[cfg_attr(feature = "typescript", derive(TS))]
101#[cfg_attr(feature = "typescript", ts(export))]
102pub struct LedgerDB {
103    pub subject_id: String,
104    pub sn: u64,
105    pub event_request_timestamp: u64,
106    pub event_ledger_timestamp: u64,
107    pub sink_timestamp: u64,
108    pub event: RequestEventDB,
109    pub event_type: EventRequestType,
110}
111
112#[derive(Clone, Debug, Serialize, Deserialize)]
113#[cfg_attr(feature = "openapi", derive(ToSchema))]
114#[cfg_attr(feature = "typescript", derive(TS))]
115#[cfg_attr(feature = "typescript", ts(export))]
116pub struct RequestsInManager {
117    pub handling: HashMap<String, String>,
118    pub in_queue: HashMap<String, Vec<String>>,
119}
120
121#[derive(Clone, Debug, Serialize, Deserialize)]
122#[cfg_attr(feature = "openapi", derive(ToSchema))]
123#[cfg_attr(feature = "typescript", derive(TS))]
124#[cfg_attr(feature = "typescript", ts(export))]
125pub struct RequestsInManagerSubject {
126    pub handling: Option<String>,
127    pub in_queue: Option<Vec<String>>,
128}
129
130#[derive(Clone, Debug, Serialize, Deserialize)]
131#[cfg_attr(feature = "openapi", derive(ToSchema))]
132#[cfg_attr(feature = "typescript", derive(TS))]
133#[cfg_attr(feature = "typescript", ts(export))]
134pub struct AbortDB {
135    pub request_id: String,
136    pub subject_id: String,
137    pub sn: Option<u64>,
138    pub error: String,
139    pub who: String,
140    pub abort_type: String,
141}
142
143#[derive(Clone, Debug, Serialize, Deserialize)]
144#[cfg_attr(feature = "openapi", derive(ToSchema))]
145#[cfg_attr(feature = "typescript", derive(TS))]
146#[cfg_attr(feature = "typescript", ts(export))]
147#[serde(tag = "event", content = "data", rename_all = "snake_case")]
148pub enum RequestEventDB {
149    Create {
150        name: Option<String>,
151        description: Option<String>,
152        schema_id: String,
153        namespace: String,
154    },
155    TrackerFact {
156        payload: Value,
157        evaluation_response: EvalResDB,
158    },
159    GovernanceFact {
160        payload: Value,
161        evaluation_response: EvalResDB,
162        approval_success: Option<bool>,
163    },
164    Transfer {
165        evaluation_error: Option<String>,
166        new_owner: String,
167    },
168    TrackerConfirm,
169    GovernanceConfirm {
170        name_old_owner: Option<String>,
171        evaluation_response: EvalResDB,
172    },
173    Reject,
174    EOL,
175}
176
177impl RequestEventDB {
178    pub const fn get_event_type(&self) -> EventRequestType {
179        match self {
180            Self::Create { .. } => EventRequestType::Create,
181            Self::TrackerFact { .. } | Self::GovernanceFact { .. } => {
182                EventRequestType::Fact
183            }
184            Self::Transfer { .. } => EventRequestType::Transfer,
185            Self::TrackerConfirm | Self::GovernanceConfirm { .. } => {
186                EventRequestType::Confirm
187            }
188            Self::Reject => EventRequestType::Reject,
189            Self::EOL => EventRequestType::Eol,
190        }
191    }
192}
193
194#[derive(Clone, Debug, Serialize, Deserialize)]
195#[cfg_attr(feature = "openapi", derive(ToSchema))]
196#[cfg_attr(feature = "typescript", derive(TS))]
197#[cfg_attr(feature = "typescript", ts(export))]
198pub enum EvalResDB {
199    Patch(Value),
200    Error(String),
201}
202
203#[derive(Clone, Debug, Serialize, Deserialize)]
204#[cfg_attr(feature = "openapi", derive(ToSchema))]
205#[cfg_attr(feature = "typescript", derive(TS))]
206#[cfg_attr(feature = "typescript", ts(export))]
207pub struct SubjectDB {
208    pub name: Option<String>,
209    pub description: Option<String>,
210    pub subject_id: String,
211    pub governance_id: String,
212    pub genesis_gov_version: u64,
213    pub prev_ledger_event_hash: Option<String>,
214    pub schema_id: String,
215    pub namespace: String,
216    pub sn: u64,
217    pub creator: String,
218    pub owner: String,
219    pub new_owner: Option<String>,
220    pub active: bool,
221    pub properties: Value,
222}
223
224#[derive(Clone, Debug, Serialize, Deserialize)]
225#[cfg_attr(feature = "openapi", derive(ToSchema))]
226#[cfg_attr(feature = "typescript", derive(TS))]
227#[cfg_attr(feature = "typescript", ts(export))]
228pub struct PaginatorEvents {
229    pub paginator: Paginator,
230    pub events: Vec<LedgerDB>,
231}
232
233#[derive(Clone, Debug, Serialize, Deserialize)]
234#[cfg_attr(feature = "openapi", derive(ToSchema))]
235#[cfg_attr(feature = "typescript", derive(TS))]
236#[cfg_attr(feature = "typescript", ts(export))]
237pub struct SinkEventsPage {
238    pub from_sn: u64,
239    pub to_sn: Option<u64>,
240    pub limit: u64,
241    pub next_sn: Option<u64>,
242    pub has_more: bool,
243    pub events: Vec<DataToSink>,
244}
245
246#[derive(Clone, Debug, Serialize, Deserialize)]
247#[cfg_attr(feature = "openapi", derive(ToSchema))]
248#[cfg_attr(feature = "typescript", derive(TS))]
249#[cfg_attr(feature = "typescript", ts(export))]
250pub struct PaginatorAborts {
251    pub paginator: Paginator,
252    pub events: Vec<AbortDB>,
253}
254
255#[derive(Clone, Debug, Serialize, Deserialize)]
256#[cfg_attr(feature = "openapi", derive(ToSchema))]
257#[cfg_attr(feature = "typescript", derive(TS))]
258#[cfg_attr(feature = "typescript", ts(export))]
259pub struct Paginator {
260    pub pages: u64,
261    pub next: Option<u64>,
262    pub prev: Option<u64>,
263}
264
265#[derive(Clone, Debug, Serialize, Deserialize)]
266#[cfg_attr(feature = "openapi", derive(ToSchema))]
267#[cfg_attr(feature = "typescript", derive(TS))]
268#[cfg_attr(feature = "typescript", ts(export))]
269pub struct RequestInfo {
270    pub state: RequestState,
271    pub version: u64,
272}
273
274#[derive(Clone, Debug, Serialize, Deserialize)]
275#[cfg_attr(feature = "openapi", derive(ToSchema))]
276#[cfg_attr(feature = "typescript", derive(TS))]
277#[cfg_attr(feature = "typescript", ts(export))]
278pub struct RequestInfoExtend {
279    pub request_id: String,
280    pub state: RequestState,
281    pub version: u64,
282}
283
284#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
285#[cfg_attr(feature = "openapi", derive(ToSchema))]
286#[cfg_attr(feature = "typescript", derive(TS))]
287#[cfg_attr(feature = "typescript", ts(export))]
288pub enum RequestState {
289    // Handler
290    InQueue,
291    Handling,
292    Invalid {
293        subject_id: String,
294        who: String,
295        sn: Option<u64>,
296        error: String,
297    },
298    // Manager
299    Abort {
300        subject_id: String,
301        who: String,
302        sn: Option<u64>,
303        error: String,
304    },
305    Reboot,
306    RebootDiff {
307        seconds: u64,
308        count: u64,
309    },
310    RebootTimeOut {
311        seconds: u64,
312        count: u64,
313    },
314    Evaluation,
315    Approval,
316    Validation,
317    Distribution,
318    Finish,
319}
320
321impl Display for RequestState {
322    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
323        match self {
324            Self::Handling => write!(f, "Handling"),
325            Self::Abort {
326                subject_id,
327                who,
328                sn,
329                error,
330            } => {
331                let sn_text = sn
332                    .as_ref()
333                    .map_or_else(|| "None".to_string(), |sn| format!("{sn}"));
334
335                write!(
336                    f,
337                    "Abort, subject_id: {}, who: {}, sn: {}, error: {}",
338                    subject_id, who, sn_text, error
339                )
340            }
341            Self::InQueue => write!(f, "In Queue"),
342            Self::Invalid {
343                subject_id,
344                who,
345                sn,
346                error,
347            } => {
348                let sn_text = sn
349                    .as_ref()
350                    .map_or_else(|| "None".to_string(), |sn| format!("{sn}"));
351
352                write!(
353                    f,
354                    "Abort, subject_id: {}, who: {}, sn: {}, error: {}",
355                    subject_id, who, sn_text, error
356                )
357            }
358            Self::Finish => write!(f, "Finish"),
359            Self::Reboot => write!(f, "Reboot"),
360            Self::RebootDiff { seconds, count } => {
361                write!(f, "Reboot diff, try: {}, seconds: {}", count, seconds)
362            }
363            Self::RebootTimeOut { seconds, count } => write!(
364                f,
365                "Reboot timeout, try: {}, seconds: {}",
366                count, seconds
367            ),
368            Self::Evaluation => write!(f, "Evaluation"),
369            Self::Approval => write!(f, "Approval"),
370            Self::Validation => write!(f, "Validation"),
371            Self::Distribution => write!(f, "Distribution"),
372        }
373    }
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
377#[cfg_attr(feature = "openapi", derive(ToSchema))]
378#[cfg_attr(feature = "typescript", derive(TS))]
379#[cfg_attr(feature = "typescript", ts(export))]
380pub struct RequestData {
381    pub request_id: String,
382    pub subject_id: String,
383}
384
385/// Time range filter for querying events by timestamp.
386/// Both `from` and `to` are optional and should be ISO 8601 strings (e.g., "2024-01-15T14:30:00Z").
387#[derive(Clone, Debug, Default, Serialize, Deserialize)]
388#[cfg_attr(feature = "openapi", derive(ToSchema))]
389#[cfg_attr(feature = "typescript", derive(TS))]
390#[cfg_attr(feature = "typescript", ts(export))]
391pub struct TimeRange {
392    /// Start of the range (inclusive). ISO 8601 format.
393    pub from: Option<String>,
394    /// End of the range (inclusive). ISO 8601 format.
395    pub to: Option<String>,
396}