Skip to main content

ave_common/
governance.rs

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