1use std::{
8 collections::{BTreeSet, HashSet},
9 hash::Hash,
10};
11
12use serde::{Deserialize, Serialize, Serializer};
13use serde_json::Value;
14
15#[cfg(feature = "typescript")]
16use ts_rs::TS;
17
18use crate::identity::PublicKey;
19use crate::{Namespace, SchemaType};
20
21fn default_witnesses_creator() -> BTreeSet<String> {
22 BTreeSet::from(["Witnesses".to_owned()])
23}
24
25pub type MemberName = String;
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29#[cfg_attr(feature = "typescript", derive(TS))]
30#[cfg_attr(feature = "typescript", ts(export))]
31pub struct GovernanceEvent {
32 pub members: Option<MemberEvent>,
33 pub roles: Option<RolesEvent>,
34 pub schemas: Option<SchemasEvent>,
35 pub policies: Option<PoliciesEvent>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
41#[cfg_attr(feature = "typescript", derive(TS))]
42#[cfg_attr(feature = "typescript", ts(export))]
43pub struct MemberEvent {
44 pub add: Option<HashSet<NewMember>>,
45 pub remove: Option<HashSet<MemberName>>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
50#[cfg_attr(feature = "typescript", derive(TS))]
51#[cfg_attr(feature = "typescript", ts(export))]
52pub struct NewMember {
53 pub name: MemberName,
54 #[cfg_attr(feature = "typescript", ts(type = "string"))]
55 pub key: PublicKey,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
61#[cfg_attr(feature = "typescript", derive(TS))]
62#[cfg_attr(feature = "typescript", ts(export))]
63pub struct RolesEvent {
64 pub governance: Option<GovRoleEvent>,
65 pub tracker_schemas: Option<TrackerSchemasRoleEvent>,
66 pub schema: Option<HashSet<SchemaIdRole>>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
70#[cfg_attr(feature = "typescript", derive(TS))]
71#[cfg_attr(feature = "typescript", ts(export))]
72pub struct GovRoleEvent {
73 pub add: Option<GovRolesEvent>,
74 pub remove: Option<GovRolesEvent>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
78#[cfg_attr(feature = "typescript", derive(TS))]
79#[cfg_attr(feature = "typescript", ts(export))]
80pub struct SchemaIdRole {
81 pub schema_id: SchemaType,
82 pub add: Option<SchemaRolesAddEvent>,
83 pub remove: Option<SchemaRolesRemoveEvent>,
84 pub change: Option<SchemaRolesChangeEvent>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
88#[cfg_attr(feature = "typescript", derive(TS))]
89#[cfg_attr(feature = "typescript", ts(export))]
90pub struct TrackerSchemasRoleEvent {
91 pub add: Option<TrackerSchemasRolesAddEvent>,
92 pub remove: Option<TrackerSchemasRolesRemoveEvent>,
93 pub change: Option<TrackerSchemasRolesChangeEvent>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
97#[cfg_attr(feature = "typescript", derive(TS))]
98#[cfg_attr(feature = "typescript", ts(export))]
99pub struct GovRolesEvent {
100 pub approver: Option<BTreeSet<MemberName>>,
101 pub evaluator: Option<BTreeSet<MemberName>>,
102 pub validator: Option<BTreeSet<MemberName>>,
103 pub witness: Option<BTreeSet<MemberName>>,
104 pub issuer: Option<BTreeSet<MemberName>>,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
108#[cfg_attr(feature = "typescript", derive(TS))]
109#[cfg_attr(feature = "typescript", ts(export))]
110pub struct TrackerSchemasRolesAddEvent {
111 pub evaluator: Option<BTreeSet<Role>>,
112 pub validator: Option<BTreeSet<Role>>,
113 pub witness: Option<BTreeSet<Role>>,
114 pub issuer: Option<BTreeSet<Role>>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
118#[cfg_attr(feature = "typescript", derive(TS))]
119#[cfg_attr(feature = "typescript", ts(export))]
120pub struct SchemaRolesAddEvent {
121 pub evaluator: Option<BTreeSet<Role>>,
122 pub validator: Option<BTreeSet<Role>>,
123 pub witness: Option<BTreeSet<Role>>,
124 pub creator: Option<BTreeSet<RoleCreator>>,
125 pub issuer: Option<BTreeSet<Role>>,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
129#[cfg_attr(feature = "typescript", derive(TS))]
130#[cfg_attr(feature = "typescript", ts(export))]
131pub struct TrackerSchemasRolesRemoveEvent {
132 pub evaluator: Option<BTreeSet<Role>>,
133 pub validator: Option<BTreeSet<Role>>,
134 pub witness: Option<BTreeSet<Role>>,
135 pub issuer: Option<BTreeSet<Role>>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
139#[cfg_attr(feature = "typescript", derive(TS))]
140#[cfg_attr(feature = "typescript", ts(export))]
141pub struct SchemaRolesRemoveEvent {
142 pub evaluator: Option<BTreeSet<Role>>,
143 pub validator: Option<BTreeSet<Role>>,
144 pub witness: Option<BTreeSet<Role>>,
145 pub creator: Option<BTreeSet<Role>>,
146 pub issuer: Option<BTreeSet<Role>>,
147}
148
149#[derive(
150 Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord,
151)]
152#[cfg_attr(feature = "typescript", derive(TS))]
153#[cfg_attr(feature = "typescript", ts(export))]
154pub struct TrackerSchemasRolesChangeEvent {
155 pub evaluator: Option<BTreeSet<RoleChange>>,
156 pub validator: Option<BTreeSet<RoleChange>>,
157 pub witness: Option<BTreeSet<RoleChange>>,
158 pub issuer: Option<BTreeSet<RoleChange>>,
159}
160
161#[derive(
162 Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord,
163)]
164#[cfg_attr(feature = "typescript", derive(TS))]
165#[cfg_attr(feature = "typescript", ts(export))]
166pub struct SchemaRolesChangeEvent {
167 pub evaluator: Option<BTreeSet<RoleChange>>,
168 pub validator: Option<BTreeSet<RoleChange>>,
169 pub witness: Option<BTreeSet<RoleChange>>,
170 pub creator: Option<BTreeSet<RoleCreatorChange>>,
171 pub issuer: Option<BTreeSet<RoleChange>>,
172}
173
174#[derive(
175 Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord,
176)]
177#[cfg_attr(feature = "typescript", derive(TS))]
178#[cfg_attr(feature = "typescript", ts(export))]
179pub struct RoleCreatorChange {
180 pub actual_name: MemberName,
181 pub actual_namespace: Namespace,
182 pub new_namespace: Option<Namespace>,
183 pub new_witnesses: Option<BTreeSet<String>>,
184 pub new_quantity: Option<CreatorQuantity>,
185}
186
187#[derive(
188 Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord,
189)]
190#[cfg_attr(feature = "typescript", derive(TS))]
191#[cfg_attr(feature = "typescript", ts(export))]
192pub struct RoleChange {
193 pub actual_name: MemberName,
194 pub actual_namespace: Namespace,
195 pub new_namespace: Namespace,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200#[cfg_attr(feature = "typescript", derive(TS))]
201#[cfg_attr(feature = "typescript", ts(export))]
202pub struct SchemasEvent {
203 pub add: Option<HashSet<SchemaAdd>>,
204 pub remove: Option<HashSet<SchemaType>>,
205 pub change: Option<HashSet<SchemaChange>>,
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
209#[cfg_attr(feature = "typescript", derive(TS))]
210#[cfg_attr(feature = "typescript", ts(export))]
211pub struct SchemaAdd {
212 pub id: SchemaType,
213 pub contract: String,
214 pub initial_value: Value,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
218#[cfg_attr(feature = "typescript", derive(TS))]
219#[cfg_attr(feature = "typescript", ts(export))]
220pub struct SchemaChange {
221 pub actual_id: SchemaType,
222 pub new_contract: Option<String>,
223 pub new_initial_value: Option<Value>,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
228#[cfg_attr(feature = "typescript", derive(TS))]
229#[cfg_attr(feature = "typescript", ts(export))]
230pub struct PoliciesEvent {
231 pub governance: Option<GovPolicieEvent>,
232 pub schema: Option<HashSet<SchemaIdPolicie>>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
236#[cfg_attr(feature = "typescript", derive(TS))]
237#[cfg_attr(feature = "typescript", ts(export))]
238pub struct SchemaIdPolicie {
239 pub schema_id: SchemaType,
240 pub change: SchemaPolicieChange,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize)]
244#[cfg_attr(feature = "typescript", derive(TS))]
245#[cfg_attr(feature = "typescript", ts(export))]
246pub struct GovPolicieEvent {
247 pub change: GovPolicieChange,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
251#[cfg_attr(feature = "typescript", derive(TS))]
252#[cfg_attr(feature = "typescript", ts(export))]
253pub struct GovPolicieChange {
254 pub approve: Option<Quorum>,
255 pub evaluate: Option<Quorum>,
256 pub validate: Option<Quorum>,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
260#[cfg_attr(feature = "typescript", derive(TS))]
261#[cfg_attr(feature = "typescript", ts(export))]
262pub struct SchemaPolicieChange {
263 pub evaluate: Option<Quorum>,
264 pub validate: Option<Quorum>,
265}
266
267#[derive(
270 Debug, Clone, Default, Serialize, Deserialize, PartialEq, Hash, Eq,
271)]
272#[cfg_attr(feature = "typescript", derive(TS))]
273#[cfg_attr(feature = "typescript", ts(export))]
274#[serde(rename_all = "lowercase")]
275pub enum Quorum {
276 #[default]
277 Majority,
278 Fixed(u32),
279 Percentage(u8),
280}
281
282#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
283#[cfg_attr(feature = "typescript", derive(TS))]
284#[cfg_attr(feature = "typescript", ts(export, type = "number | \"infinity\""))]
285pub enum CreatorQuantity {
286 Quantity(u32),
287 Infinity,
288}
289
290impl<'de> Deserialize<'de> for CreatorQuantity {
291 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
292 where
293 D: serde::Deserializer<'de>,
294 {
295 let value = serde_json::Value::deserialize(deserializer)?;
296
297 match value {
298 serde_json::Value::String(s) if s == "infinity" => {
299 Ok(Self::Infinity)
300 }
301 serde_json::Value::Number(n) if n.is_u64() => {
302 Ok(Self::Quantity(n.as_u64().ok_or_else(|| {
303 serde::de::Error::custom(
304 "Quantity must be a number or 'infinity'",
305 )
306 })? as u32))
307 }
308 _ => Err(serde::de::Error::custom(
309 "Quantity must be a number or 'infinity'",
310 )),
311 }
312 }
313}
314
315impl Serialize for CreatorQuantity {
316 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
317 where
318 S: Serializer,
319 {
320 match self {
321 Self::Quantity(n) => serializer.serialize_u32(*n),
322 Self::Infinity => serializer.serialize_str("infinity"),
323 }
324 }
325}
326
327#[derive(
328 Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq, PartialOrd, Ord,
329)]
330#[cfg_attr(feature = "typescript", derive(TS))]
331#[cfg_attr(feature = "typescript", ts(export))]
332pub struct Role {
333 pub name: String,
334 pub namespace: Namespace,
335}
336
337#[derive(Debug, Serialize, Deserialize, Clone)]
338#[cfg_attr(feature = "typescript", derive(TS))]
339#[cfg_attr(feature = "typescript", ts(export))]
340pub struct RoleCreator {
341 pub name: String,
342 pub namespace: Namespace,
343 #[serde(default = "default_witnesses_creator")]
344 pub witnesses: BTreeSet<String>,
345 pub quantity: CreatorQuantity,
346}
347
348impl Hash for RoleCreator {
349 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
350 self.name.hash(state);
351 self.namespace.hash(state);
352 }
353}
354
355impl PartialOrd for RoleCreator {
356 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
357 Some(self.cmp(other))
358 }
359}
360
361impl Ord for RoleCreator {
362 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
363 (self.name.clone(), self.namespace.clone())
364 .cmp(&(other.name.clone(), other.namespace.clone()))
365 }
366}
367
368impl PartialEq for RoleCreator {
369 fn eq(&self, other: &Self) -> bool {
370 self.name == other.name && self.namespace == other.namespace
371 }
372}
373
374impl Eq for RoleCreator {}