1use std::str::FromStr;
7
8use ave_identity::{DigestIdentifier, PublicKey, Signed};
9
10use crate::{
11 Namespace, SchemaType, ValueWrapper,
12 bridge::request::{
13 BridgeConfirmRequest, BridgeCreateRequest, BridgeEOLRequest, BridgeEventRequest, BridgeFactRequest, BridgeRejectRequest, BridgeSignedEventRequest, BridgeTransferRequest
14 },
15 request::{
16 ConfirmRequest, CreateRequest, EOLRequest, EventRequest, FactRequest, RejectRequest,
17 TransferRequest,
18 }, signature::BridgeSignature,
19};
20
21#[derive(Debug, Clone)]
23pub enum ConversionError {
24 InvalidSubjectId(String),
25 InvalidGovernanceId(String),
26 InvalidSchemaId(String),
27 InvalidPublicKey(String),
28 InvalidNamespace(String),
29 MissingGovernanceId,
30 MissingNamespace,
31}
32
33impl std::fmt::Display for ConversionError {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 ConversionError::InvalidSubjectId(e) => write!(f, "Invalid subject identifier: {}", e),
37 ConversionError::InvalidGovernanceId(e) => write!(f, "Invalid governance identifier: {}", e),
38 ConversionError::InvalidSchemaId(e) => write!(f, "Invalid schema identifier: {}", e),
39 ConversionError::InvalidPublicKey(e) => write!(f, "Invalid public key: {}", e),
40 ConversionError::InvalidNamespace(e) => write!(f, "Invalid namespace: {}", e),
41 ConversionError::MissingGovernanceId => write!(f, "Missing governance identifier"),
42 ConversionError::MissingNamespace => write!(f, "Missing namespace"),
43 }
44 }
45}
46
47impl std::error::Error for ConversionError {}
48
49impl From<Signed<EventRequest>> for BridgeSignedEventRequest {
54 fn from(value: Signed<EventRequest>) -> Self {
55 let request = BridgeEventRequest::from(value.content().clone());
56 let signature = Some(BridgeSignature::from(value.signature().clone()));
57
58 Self { request, signature }
59 }
60}
61
62impl From<EventRequest> for BridgeSignedEventRequest {
63 fn from(value: EventRequest) -> Self {
64 let request = BridgeEventRequest::from(value.clone());
65 let signature = None;
66
67 Self { request, signature }
68 }
69}
70
71impl From<EventRequest> for BridgeEventRequest {
72 fn from(request: EventRequest) -> Self {
73 match request {
74 EventRequest::Create(req) => BridgeEventRequest::Create(req.into()),
75 EventRequest::Fact(req) => BridgeEventRequest::Fact(req.into()),
76 EventRequest::Transfer(req) => BridgeEventRequest::Transfer(req.into()),
77 EventRequest::EOL(req) => BridgeEventRequest::EOL(req.into()),
78 EventRequest::Confirm(req) => BridgeEventRequest::Confirm(req.into()),
79 EventRequest::Reject(req) => BridgeEventRequest::Reject(req.into()),
80 }
81 }
82}
83
84impl TryFrom<BridgeEventRequest> for EventRequest {
85 type Error = ConversionError;
86
87 fn try_from(request: BridgeEventRequest) -> Result<Self, Self::Error> {
88 match request {
89 BridgeEventRequest::Create(req) => Ok(EventRequest::Create(req.try_into()?)),
90 BridgeEventRequest::Fact(req) => Ok(EventRequest::Fact(req.try_into()?)),
91 BridgeEventRequest::Transfer(req) => Ok(EventRequest::Transfer(req.try_into()?)),
92 BridgeEventRequest::EOL(req) => Ok(EventRequest::EOL(req.try_into()?)),
93 BridgeEventRequest::Confirm(req) => Ok(EventRequest::Confirm(req.try_into()?)),
94 BridgeEventRequest::Reject(req) => Ok(EventRequest::Reject(req.try_into()?)),
95 }
96 }
97}
98
99impl From<CreateRequest> for BridgeCreateRequest {
104 fn from(request: CreateRequest) -> Self {
105 BridgeCreateRequest {
106 name: request.name,
107 description: request.description,
108 governance_id: Some(request.governance_id.to_string()),
109 schema_id: request.schema_id.to_string(),
110 namespace: Some(request.namespace.to_string()),
111 }
112 }
113}
114
115impl TryFrom<BridgeCreateRequest> for CreateRequest {
116 type Error = ConversionError;
117
118 fn try_from(request: BridgeCreateRequest) -> Result<Self, Self::Error> {
119 let governance_id = request
120 .governance_id
121 .ok_or(ConversionError::MissingGovernanceId)?;
122
123 let governance_id = DigestIdentifier::from_str(&governance_id)
124 .map_err(|e| ConversionError::InvalidGovernanceId(e.to_string()))?;
125
126 let schema_id = SchemaType::from_str(&request.schema_id)
127 .map_err(|e| ConversionError::InvalidSchemaId(e))?;
128
129 let namespace = request
130 .namespace
131 .ok_or(ConversionError::MissingNamespace)?;
132
133 let namespace = Namespace::from(namespace);
134
135 if !namespace.check() {
136 return Err(ConversionError::InvalidNamespace(
137 "Namespace validation failed".to_string()
138 ));
139 }
140
141 Ok(CreateRequest {
142 name: request.name,
143 description: request.description,
144 governance_id,
145 schema_id,
146 namespace,
147 })
148 }
149}
150
151impl From<FactRequest> for BridgeFactRequest {
156 fn from(request: FactRequest) -> Self {
157 BridgeFactRequest {
158 subject_id: request.subject_id.to_string(),
159 payload: request.payload.0,
160 }
161 }
162}
163
164impl TryFrom<BridgeFactRequest> for FactRequest {
165 type Error = ConversionError;
166
167 fn try_from(request: BridgeFactRequest) -> Result<Self, Self::Error> {
168 let subject_id = DigestIdentifier::from_str(&request.subject_id)
169 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
170
171 Ok(FactRequest {
172 subject_id,
173 payload: ValueWrapper(request.payload),
174 })
175 }
176}
177
178impl From<TransferRequest> for BridgeTransferRequest {
183 fn from(request: TransferRequest) -> Self {
184 BridgeTransferRequest {
185 subject_id: request.subject_id.to_string(),
186 new_owner: request.new_owner.to_string(),
187 }
188 }
189}
190
191impl TryFrom<BridgeTransferRequest> for TransferRequest {
192 type Error = ConversionError;
193
194 fn try_from(request: BridgeTransferRequest) -> Result<Self, Self::Error> {
195 let subject_id = DigestIdentifier::from_str(&request.subject_id)
196 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
197
198 let new_owner = PublicKey::from_str(&request.new_owner)
199 .map_err(|e| ConversionError::InvalidPublicKey(e.to_string()))?;
200
201 Ok(TransferRequest {
202 subject_id,
203 new_owner,
204 })
205 }
206}
207
208impl From<EOLRequest> for BridgeEOLRequest {
213 fn from(request: EOLRequest) -> Self {
214 BridgeEOLRequest {
215 subject_id: request.subject_id.to_string(),
216 }
217 }
218}
219
220impl TryFrom<BridgeEOLRequest> for EOLRequest {
221 type Error = ConversionError;
222
223 fn try_from(request: BridgeEOLRequest) -> Result<Self, Self::Error> {
224 let subject_id = DigestIdentifier::from_str(&request.subject_id)
225 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
226
227 Ok(EOLRequest { subject_id })
228 }
229}
230
231impl From<ConfirmRequest> for BridgeConfirmRequest {
236 fn from(request: ConfirmRequest) -> Self {
237 BridgeConfirmRequest {
238 subject_id: request.subject_id.to_string(),
239 name_old_owner: request.name_old_owner,
240 }
241 }
242}
243
244impl TryFrom<BridgeConfirmRequest> for ConfirmRequest {
245 type Error = ConversionError;
246
247 fn try_from(request: BridgeConfirmRequest) -> Result<Self, Self::Error> {
248 let subject_id = DigestIdentifier::from_str(&request.subject_id)
249 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
250
251 Ok(ConfirmRequest {
252 subject_id,
253 name_old_owner: request.name_old_owner,
254 })
255 }
256}
257
258impl From<RejectRequest> for BridgeRejectRequest {
263 fn from(request: RejectRequest) -> Self {
264 BridgeRejectRequest {
265 subject_id: request.subject_id.to_string(),
266 }
267 }
268}
269
270impl TryFrom<BridgeRejectRequest> for RejectRequest {
271 type Error = ConversionError;
272
273 fn try_from(request: BridgeRejectRequest) -> Result<Self, Self::Error> {
274 let subject_id = DigestIdentifier::from_str(&request.subject_id)
275 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
276
277 Ok(RejectRequest { subject_id })
278 }
279}
280
281#[cfg(test)]
287mod tests {
288 use super::*;
289 use serde_json::json;
290
291 #[test]
292 fn test_fact_request_conversion() {
293 let bridge_fact = BridgeFactRequest {
294 subject_id: "BKZgYibuHNJjiNS179FUDpLGgdLq0C04TZRGb6AXMd1s".to_string(),
295 payload: json!({"test": "value"}),
296 };
297
298 let fact: Result<FactRequest, _> = bridge_fact.clone().try_into();
299 assert!(fact.is_ok());
300
301 let fact = fact.unwrap();
302 let bridge_back: BridgeFactRequest = fact.into();
303 assert_eq!(bridge_back.subject_id, bridge_fact.subject_id);
304 }
305
306 #[test]
307 fn test_create_request_conversion() {
308 let bridge_create = BridgeCreateRequest {
309 name: Some("Test".to_string()),
310 description: Some("Test description".to_string()),
311 governance_id: Some("BKZgYibuHNJjiNS179FUDpLGgdLq0C04TZRGb6AXMd1s".to_string()),
312 schema_id: "governance".to_string(),
313 namespace: Some("test.namespace".to_string()),
314 };
315
316 let create: Result<CreateRequest, _> = bridge_create.try_into();
317 assert!(create.is_ok());
318 }
319
320 #[test]
321 fn test_create_request_missing_governance_id() {
322 let bridge_create = BridgeCreateRequest {
323 name: Some("Test".to_string()),
324 description: Some("Test description".to_string()),
325 governance_id: None,
326 schema_id: "governance".to_string(),
327 namespace: Some("test.namespace".to_string()),
328 };
329
330 let create: Result<CreateRequest, _> = bridge_create.try_into();
331 assert!(create.is_err());
332 assert!(matches!(create.unwrap_err(), ConversionError::MissingGovernanceId));
333 }
334
335 #[test]
336 fn test_invalid_subject_id() {
337 let bridge_fact = BridgeFactRequest {
338 subject_id: "invalid_id".to_string(),
339 payload: json!({"test": "value"}),
340 };
341
342 let fact: Result<FactRequest, _> = bridge_fact.try_into();
343 assert!(fact.is_err());
344 assert!(matches!(fact.unwrap_err(), ConversionError::InvalidSubjectId(_)));
345 }
346}