1use ave_identity::{DigestIdentifier, PublicKey};
7use borsh::{BorshDeserialize, BorshSerialize};
8use serde::{Deserialize, Deserializer, Serialize};
9use std::collections::BTreeSet;
10
11use crate::{Namespace, SchemaType, ValueWrapper};
12
13#[derive(
15 Debug,
16 Clone,
17 Serialize,
18 Deserialize,
19 Eq,
20 PartialEq,
21 BorshSerialize,
22 BorshDeserialize,
23)]
24pub enum EventRequest {
25 Create(CreateRequest),
27 Fact(FactRequest),
29 Transfer(TransferRequest),
31 Confirm(ConfirmRequest),
33 Reject(RejectRequest),
35 EOL(EOLRequest),
37}
38
39impl EventRequest {
40 pub fn check_request_signature(
42 &self,
43 signer: &PublicKey,
44 owner: &PublicKey,
45 new_owner: &Option<PublicKey>,
46 ) -> bool {
47 match self {
48 Self::Create(..) | Self::Transfer(..) | Self::EOL(..) => {
49 signer == owner
50 }
51 Self::Confirm(..) | Self::Reject(..) => {
52 new_owner.as_ref() == Some(signer)
53 }
54 Self::Fact(..) => true,
55 }
56 }
57
58 pub const fn is_create_event(&self) -> bool {
60 matches!(self, Self::Create(_create_request))
61 }
62
63 pub const fn is_fact_event(&self) -> bool {
65 matches!(self, Self::Fact(_fact_request))
66 }
67
68 pub fn get_subject_id(&self) -> DigestIdentifier {
73 match self {
74 Self::Create(_create_request) => DigestIdentifier::default(),
75 Self::Fact(fact_request) => fact_request.subject_id.clone(),
76 Self::Transfer(transfer_request) => {
77 transfer_request.subject_id.clone()
78 }
79 Self::Confirm(confirm_request) => {
80 confirm_request.subject_id.clone()
81 }
82 Self::Reject(reject_request) => reject_request.subject_id.clone(),
83 Self::EOL(eolrequest) => eolrequest.subject_id.clone(),
84 }
85 }
86}
87
88#[derive(
90 Debug,
91 Clone,
92 Serialize,
93 Deserialize,
94 Eq,
95 PartialEq,
96 BorshSerialize,
97 BorshDeserialize,
98)]
99pub struct CreateRequest {
100 pub name: Option<String>,
102 pub description: Option<String>,
104 pub governance_id: DigestIdentifier,
106 pub schema_id: SchemaType,
108 pub namespace: Namespace,
110}
111
112#[derive(
114 Debug,
115 Clone,
116 Serialize,
117 Deserialize,
118 Eq,
119 PartialEq,
120 BorshSerialize,
121 BorshDeserialize,
122)]
123pub struct FactRequest {
124 pub subject_id: DigestIdentifier,
126 pub payload: ValueWrapper,
128 #[serde(default)]
132 #[serde(deserialize_with = "deserialize_unique_viewpoints")]
133 pub viewpoints: BTreeSet<String>,
134}
135
136fn deserialize_unique_viewpoints<'de, D>(
137 deserializer: D,
138) -> Result<BTreeSet<String>, D::Error>
139where
140 D: Deserializer<'de>,
141{
142 let viewpoints =
143 <Vec<String> as serde::Deserialize>::deserialize(deserializer)?;
144 let mut unique: BTreeSet<String> = BTreeSet::new();
145
146 for viewpoint in viewpoints {
147 if !unique.insert(viewpoint.clone()) {
148 return Err(serde::de::Error::custom(format!(
149 "duplicated viewpoint '{viewpoint}'"
150 )));
151 }
152 }
153
154 Ok(unique)
155}
156
157#[derive(
159 Debug,
160 Clone,
161 Serialize,
162 Deserialize,
163 Eq,
164 PartialEq,
165 BorshSerialize,
166 BorshDeserialize,
167)]
168pub struct TransferRequest {
169 pub subject_id: DigestIdentifier,
171 pub new_owner: PublicKey,
173}
174
175#[derive(
177 Debug,
178 Clone,
179 Serialize,
180 Deserialize,
181 Eq,
182 PartialEq,
183 BorshSerialize,
184 BorshDeserialize,
185)]
186pub struct ConfirmRequest {
187 pub subject_id: DigestIdentifier,
188 pub name_old_owner: Option<String>,
190}
191
192#[derive(
194 Debug,
195 Clone,
196 Serialize,
197 Deserialize,
198 Eq,
199 PartialEq,
200 BorshSerialize,
201 BorshDeserialize,
202)]
203pub struct EOLRequest {
204 pub subject_id: DigestIdentifier,
206}
207
208#[derive(
210 Debug,
211 Clone,
212 Serialize,
213 Deserialize,
214 Eq,
215 PartialEq,
216 BorshSerialize,
217 BorshDeserialize,
218)]
219pub struct RejectRequest {
220 pub subject_id: DigestIdentifier,
221}
222
223#[cfg(test)]
224mod tests {
225 use super::FactRequest;
226 use ave_identity::DigestIdentifier;
227 use serde_json::json;
228 use std::collections::BTreeSet;
229
230 #[test]
231 fn test_fact_request_defaults_missing_viewpoints_to_empty() {
232 let subject_id = DigestIdentifier::default().to_string();
233 let request = serde_json::from_value::<FactRequest>(json!({
234 "subject_id": subject_id,
235 "payload": { "ModOne": { "data": 1 } }
236 }))
237 .unwrap();
238
239 assert_eq!(request.viewpoints, BTreeSet::new());
240 }
241
242 #[test]
243 fn test_fact_request_rejects_duplicated_viewpoints() {
244 let subject_id = DigestIdentifier::default().to_string();
245 let error = serde_json::from_value::<FactRequest>(json!({
246 "subject_id": subject_id,
247 "payload": { "ModOne": { "data": 1 } },
248 "viewpoints": ["agua", "agua"]
249 }))
250 .unwrap_err();
251
252 assert!(error.to_string().contains("duplicated viewpoint"));
253 }
254}