Skip to main content

ave_common/bridge/
conversions.rs

1//! Conversions between bridge models and internal domain models.
2
3use std::str::FromStr;
4
5use ave_identity::{DigestIdentifier, PublicKey, Signed};
6
7use crate::{
8    Namespace, SchemaType, ValueWrapper,
9    bridge::request::{
10        BridgeConfirmRequest, BridgeCreateRequest, BridgeEOLRequest,
11        BridgeEventRequest, BridgeFactRequest, BridgeRejectRequest,
12        BridgeSignedEventRequest, BridgeTransferRequest,
13    },
14    error::ConversionError,
15    request::{
16        ConfirmRequest, CreateRequest, EOLRequest, EventRequest, FactRequest,
17        RejectRequest, TransferRequest,
18    },
19    signature::BridgeSignature,
20};
21
22// ============================================================================
23// EventRequest conversions
24// ============================================================================
25
26impl From<Signed<EventRequest>> for BridgeSignedEventRequest {
27    fn from(value: Signed<EventRequest>) -> Self {
28        let request = BridgeEventRequest::from(value.content().clone());
29        let signature = Some(BridgeSignature::from(value.signature().clone()));
30
31        Self { request, signature }
32    }
33}
34
35impl From<EventRequest> for BridgeSignedEventRequest {
36    fn from(value: EventRequest) -> Self {
37        let request = BridgeEventRequest::from(value);
38        let signature = None;
39
40        Self { request, signature }
41    }
42}
43
44impl From<EventRequest> for BridgeEventRequest {
45    fn from(request: EventRequest) -> Self {
46        match request {
47            EventRequest::Create(req) => Self::Create(req.into()),
48            EventRequest::Fact(req) => Self::Fact(req.into()),
49            EventRequest::Transfer(req) => Self::Transfer(req.into()),
50            EventRequest::EOL(req) => Self::Eol(req.into()),
51            EventRequest::Confirm(req) => Self::Confirm(req.into()),
52            EventRequest::Reject(req) => Self::Reject(req.into()),
53        }
54    }
55}
56
57impl TryFrom<BridgeEventRequest> for EventRequest {
58    type Error = ConversionError;
59
60    fn try_from(request: BridgeEventRequest) -> Result<Self, Self::Error> {
61        match request {
62            BridgeEventRequest::Create(req) => {
63                Ok(Self::Create(req.try_into()?))
64            }
65            BridgeEventRequest::Fact(req) => Ok(Self::Fact(req.try_into()?)),
66            BridgeEventRequest::Transfer(req) => {
67                Ok(Self::Transfer(req.try_into()?))
68            }
69            BridgeEventRequest::Eol(req) => Ok(Self::EOL(req.try_into()?)),
70            BridgeEventRequest::Confirm(req) => {
71                Ok(Self::Confirm(req.try_into()?))
72            }
73            BridgeEventRequest::Reject(req) => {
74                Ok(Self::Reject(req.try_into()?))
75            }
76        }
77    }
78}
79
80// ============================================================================
81// CreateRequest conversions
82// ============================================================================
83
84impl From<CreateRequest> for BridgeCreateRequest {
85    fn from(request: CreateRequest) -> Self {
86        Self {
87            name: request.name,
88            description: request.description,
89            governance_id: Some(request.governance_id.to_string()),
90            schema_id: request.schema_id.to_string(),
91            namespace: Some(request.namespace.to_string()),
92        }
93    }
94}
95
96impl TryFrom<BridgeCreateRequest> for CreateRequest {
97    type Error = ConversionError;
98
99    fn try_from(request: BridgeCreateRequest) -> Result<Self, Self::Error> {
100        let governance_id = if let Some(governance_id) = request.governance_id {
101            DigestIdentifier::from_str(&governance_id).map_err(|e| {
102                ConversionError::InvalidGovernanceId(e.to_string())
103            })?
104        } else {
105            DigestIdentifier::default()
106        };
107
108        let schema_id = SchemaType::from_str(&request.schema_id)
109            .map_err(ConversionError::InvalidSchemaId)?;
110
111        let namespace = request
112            .namespace
113            .map_or_else(Namespace::new, Namespace::from);
114
115        Ok(Self {
116            name: request.name,
117            description: request.description,
118            governance_id,
119            schema_id,
120            namespace,
121        })
122    }
123}
124
125// ============================================================================
126// FactRequest conversions
127// ============================================================================
128
129impl From<FactRequest> for BridgeFactRequest {
130    fn from(request: FactRequest) -> Self {
131        Self {
132            subject_id: request.subject_id.to_string(),
133            payload: request.payload.0,
134        }
135    }
136}
137
138impl TryFrom<BridgeFactRequest> for FactRequest {
139    type Error = ConversionError;
140
141    fn try_from(request: BridgeFactRequest) -> Result<Self, Self::Error> {
142        let subject_id = DigestIdentifier::from_str(&request.subject_id)
143            .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
144
145        Ok(Self {
146            subject_id,
147            payload: ValueWrapper(request.payload),
148        })
149    }
150}
151
152// ============================================================================
153// TransferRequest conversions
154// ============================================================================
155
156impl From<TransferRequest> for BridgeTransferRequest {
157    fn from(request: TransferRequest) -> Self {
158        Self {
159            subject_id: request.subject_id.to_string(),
160            new_owner: request.new_owner.to_string(),
161        }
162    }
163}
164
165impl TryFrom<BridgeTransferRequest> for TransferRequest {
166    type Error = ConversionError;
167
168    fn try_from(request: BridgeTransferRequest) -> Result<Self, Self::Error> {
169        let subject_id = DigestIdentifier::from_str(&request.subject_id)
170            .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
171
172        let new_owner = PublicKey::from_str(&request.new_owner)
173            .map_err(|e| ConversionError::InvalidPublicKey(e.to_string()))?;
174
175        Ok(Self {
176            subject_id,
177            new_owner,
178        })
179    }
180}
181
182// ============================================================================
183// EOLRequest conversions
184// ============================================================================
185
186impl From<EOLRequest> for BridgeEOLRequest {
187    fn from(request: EOLRequest) -> Self {
188        Self {
189            subject_id: request.subject_id.to_string(),
190        }
191    }
192}
193
194impl TryFrom<BridgeEOLRequest> for EOLRequest {
195    type Error = ConversionError;
196
197    fn try_from(request: BridgeEOLRequest) -> Result<Self, Self::Error> {
198        let subject_id = DigestIdentifier::from_str(&request.subject_id)
199            .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
200
201        Ok(Self { subject_id })
202    }
203}
204
205// ============================================================================
206// ConfirmRequest conversions
207// ============================================================================
208
209impl From<ConfirmRequest> for BridgeConfirmRequest {
210    fn from(request: ConfirmRequest) -> Self {
211        Self {
212            subject_id: request.subject_id.to_string(),
213            name_old_owner: request.name_old_owner,
214        }
215    }
216}
217
218impl TryFrom<BridgeConfirmRequest> for ConfirmRequest {
219    type Error = ConversionError;
220
221    fn try_from(request: BridgeConfirmRequest) -> Result<Self, Self::Error> {
222        let subject_id = DigestIdentifier::from_str(&request.subject_id)
223            .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
224
225        Ok(Self {
226            subject_id,
227            name_old_owner: request.name_old_owner,
228        })
229    }
230}
231
232// ============================================================================
233// RejectRequest conversions
234// ============================================================================
235
236impl From<RejectRequest> for BridgeRejectRequest {
237    fn from(request: RejectRequest) -> Self {
238        Self {
239            subject_id: request.subject_id.to_string(),
240        }
241    }
242}
243
244impl TryFrom<BridgeRejectRequest> for RejectRequest {
245    type Error = ConversionError;
246
247    fn try_from(request: BridgeRejectRequest) -> 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(Self { subject_id })
252    }
253}
254
255#[cfg(test)]
256mod tests {
257    use super::*;
258    use serde_json::json;
259
260    #[test]
261    fn test_fact_request_conversion() {
262        let bridge_fact = BridgeFactRequest {
263            subject_id: "BKZgYibuHNJjiNS179FUDpLGgdLq0C04TZRGb6AXMd1s"
264                .to_string(),
265            payload: json!({"test": "value"}),
266        };
267
268        let fact: Result<FactRequest, _> = bridge_fact.clone().try_into();
269        assert!(fact.is_ok());
270
271        let fact = fact.unwrap();
272        let bridge_back: BridgeFactRequest = fact.into();
273        assert_eq!(bridge_back.subject_id, bridge_fact.subject_id);
274    }
275
276    #[test]
277    fn test_create_request_conversion() {
278        let bridge_create = BridgeCreateRequest {
279            name: Some("Test".to_string()),
280            description: Some("Test description".to_string()),
281            governance_id: Some(
282                "BKZgYibuHNJjiNS179FUDpLGgdLq0C04TZRGb6AXMd1s".to_string(),
283            ),
284            schema_id: "governance".to_string(),
285            namespace: Some("test.namespace".to_string()),
286        };
287
288        let create: Result<CreateRequest, _> = bridge_create.try_into();
289        assert!(create.is_ok());
290    }
291
292    #[test]
293    fn test_create_request_missing_governance_id() {
294        let bridge_create = BridgeCreateRequest {
295            name: Some("Test".to_string()),
296            description: Some("Test description".to_string()),
297            governance_id: None,
298            schema_id: "governance".to_string(),
299            namespace: Some("test.namespace".to_string()),
300        };
301
302        let create: Result<CreateRequest, _> = bridge_create.try_into();
303        assert!(create.is_ok());
304    }
305
306    #[test]
307    fn test_invalid_subject_id() {
308        let bridge_fact = BridgeFactRequest {
309            subject_id: "invalid_id".to_string(),
310            payload: json!({"test": "value"}),
311        };
312
313        let fact: Result<FactRequest, _> = bridge_fact.try_into();
314        assert!(fact.is_err());
315        assert!(matches!(
316            fact.unwrap_err(),
317            ConversionError::InvalidSubjectId(_)
318        ));
319    }
320}