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,
14 BridgeEventRequest, BridgeFactRequest, BridgeRejectRequest,
15 BridgeSignedEventRequest, BridgeTransferRequest,
16 },
17 request::{
18 ConfirmRequest, CreateRequest, EOLRequest, EventRequest, FactRequest,
19 RejectRequest, TransferRequest,
20 },
21 signature::BridgeSignature,
22};
23
24#[derive(Debug, Clone)]
26pub enum ConversionError {
27 InvalidSubjectId(String),
28 InvalidGovernanceId(String),
29 InvalidSchemaId(String),
30 InvalidPublicKey(String),
31 InvalidNamespace(String),
32 MissingGovernanceId,
33 MissingNamespace,
34}
35
36impl std::fmt::Display for ConversionError {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 ConversionError::InvalidSubjectId(e) => {
40 write!(f, "Invalid subject identifier: {}", e)
41 }
42 ConversionError::InvalidGovernanceId(e) => {
43 write!(f, "Invalid governance identifier: {}", e)
44 }
45 ConversionError::InvalidSchemaId(e) => {
46 write!(f, "Invalid schema identifier: {}", e)
47 }
48 ConversionError::InvalidPublicKey(e) => {
49 write!(f, "Invalid public key: {}", e)
50 }
51 ConversionError::InvalidNamespace(e) => {
52 write!(f, "Invalid namespace: {}", e)
53 }
54 ConversionError::MissingGovernanceId => {
55 write!(f, "Missing governance identifier")
56 }
57 ConversionError::MissingNamespace => write!(f, "Missing namespace"),
58 }
59 }
60}
61
62impl std::error::Error for ConversionError {}
63
64impl From<Signed<EventRequest>> for BridgeSignedEventRequest {
69 fn from(value: Signed<EventRequest>) -> Self {
70 let request = BridgeEventRequest::from(value.content().clone());
71 let signature = Some(BridgeSignature::from(value.signature().clone()));
72
73 Self { request, signature }
74 }
75}
76
77impl From<EventRequest> for BridgeSignedEventRequest {
78 fn from(value: EventRequest) -> Self {
79 let request = BridgeEventRequest::from(value.clone());
80 let signature = None;
81
82 Self { request, signature }
83 }
84}
85
86impl From<EventRequest> for BridgeEventRequest {
87 fn from(request: EventRequest) -> Self {
88 match request {
89 EventRequest::Create(req) => BridgeEventRequest::Create(req.into()),
90 EventRequest::Fact(req) => BridgeEventRequest::Fact(req.into()),
91 EventRequest::Transfer(req) => {
92 BridgeEventRequest::Transfer(req.into())
93 }
94 EventRequest::EOL(req) => BridgeEventRequest::EOL(req.into()),
95 EventRequest::Confirm(req) => {
96 BridgeEventRequest::Confirm(req.into())
97 }
98 EventRequest::Reject(req) => BridgeEventRequest::Reject(req.into()),
99 }
100 }
101}
102
103impl TryFrom<BridgeEventRequest> for EventRequest {
104 type Error = ConversionError;
105
106 fn try_from(request: BridgeEventRequest) -> Result<Self, Self::Error> {
107 match request {
108 BridgeEventRequest::Create(req) => {
109 Ok(EventRequest::Create(req.try_into()?))
110 }
111 BridgeEventRequest::Fact(req) => {
112 Ok(EventRequest::Fact(req.try_into()?))
113 }
114 BridgeEventRequest::Transfer(req) => {
115 Ok(EventRequest::Transfer(req.try_into()?))
116 }
117 BridgeEventRequest::EOL(req) => {
118 Ok(EventRequest::EOL(req.try_into()?))
119 }
120 BridgeEventRequest::Confirm(req) => {
121 Ok(EventRequest::Confirm(req.try_into()?))
122 }
123 BridgeEventRequest::Reject(req) => {
124 Ok(EventRequest::Reject(req.try_into()?))
125 }
126 }
127 }
128}
129
130impl From<CreateRequest> for BridgeCreateRequest {
135 fn from(request: CreateRequest) -> Self {
136 BridgeCreateRequest {
137 name: request.name,
138 description: request.description,
139 governance_id: Some(request.governance_id.to_string()),
140 schema_id: request.schema_id.to_string(),
141 namespace: Some(request.namespace.to_string()),
142 }
143 }
144}
145
146impl TryFrom<BridgeCreateRequest> for CreateRequest {
147 type Error = ConversionError;
148
149 fn try_from(request: BridgeCreateRequest) -> Result<Self, Self::Error> {
150 let governance_id = request
151 .governance_id
152 .ok_or(ConversionError::MissingGovernanceId)?;
153
154 let governance_id = DigestIdentifier::from_str(&governance_id)
155 .map_err(|e| ConversionError::InvalidGovernanceId(e.to_string()))?;
156
157 let schema_id = SchemaType::from_str(&request.schema_id)
158 .map_err(ConversionError::InvalidSchemaId)?;
159
160 let namespace =
161 request.namespace.ok_or(ConversionError::MissingNamespace)?;
162
163 let namespace = Namespace::from(namespace);
164
165 if !namespace.check() {
166 return Err(ConversionError::InvalidNamespace(
167 "Namespace validation failed".to_string(),
168 ));
169 }
170
171 Ok(CreateRequest {
172 name: request.name,
173 description: request.description,
174 governance_id,
175 schema_id,
176 namespace,
177 })
178 }
179}
180
181impl From<FactRequest> for BridgeFactRequest {
186 fn from(request: FactRequest) -> Self {
187 BridgeFactRequest {
188 subject_id: request.subject_id.to_string(),
189 payload: request.payload.0,
190 }
191 }
192}
193
194impl TryFrom<BridgeFactRequest> for FactRequest {
195 type Error = ConversionError;
196
197 fn try_from(request: BridgeFactRequest) -> 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(FactRequest {
202 subject_id,
203 payload: ValueWrapper(request.payload),
204 })
205 }
206}
207
208impl From<TransferRequest> for BridgeTransferRequest {
213 fn from(request: TransferRequest) -> Self {
214 BridgeTransferRequest {
215 subject_id: request.subject_id.to_string(),
216 new_owner: request.new_owner.to_string(),
217 }
218 }
219}
220
221impl TryFrom<BridgeTransferRequest> for TransferRequest {
222 type Error = ConversionError;
223
224 fn try_from(request: BridgeTransferRequest) -> Result<Self, Self::Error> {
225 let subject_id = DigestIdentifier::from_str(&request.subject_id)
226 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
227
228 let new_owner = PublicKey::from_str(&request.new_owner)
229 .map_err(|e| ConversionError::InvalidPublicKey(e.to_string()))?;
230
231 Ok(TransferRequest {
232 subject_id,
233 new_owner,
234 })
235 }
236}
237
238impl From<EOLRequest> for BridgeEOLRequest {
243 fn from(request: EOLRequest) -> Self {
244 BridgeEOLRequest {
245 subject_id: request.subject_id.to_string(),
246 }
247 }
248}
249
250impl TryFrom<BridgeEOLRequest> for EOLRequest {
251 type Error = ConversionError;
252
253 fn try_from(request: BridgeEOLRequest) -> Result<Self, Self::Error> {
254 let subject_id = DigestIdentifier::from_str(&request.subject_id)
255 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
256
257 Ok(EOLRequest { subject_id })
258 }
259}
260
261impl From<ConfirmRequest> for BridgeConfirmRequest {
266 fn from(request: ConfirmRequest) -> Self {
267 BridgeConfirmRequest {
268 subject_id: request.subject_id.to_string(),
269 name_old_owner: request.name_old_owner,
270 }
271 }
272}
273
274impl TryFrom<BridgeConfirmRequest> for ConfirmRequest {
275 type Error = ConversionError;
276
277 fn try_from(request: BridgeConfirmRequest) -> Result<Self, Self::Error> {
278 let subject_id = DigestIdentifier::from_str(&request.subject_id)
279 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
280
281 Ok(ConfirmRequest {
282 subject_id,
283 name_old_owner: request.name_old_owner,
284 })
285 }
286}
287
288impl From<RejectRequest> for BridgeRejectRequest {
293 fn from(request: RejectRequest) -> Self {
294 BridgeRejectRequest {
295 subject_id: request.subject_id.to_string(),
296 }
297 }
298}
299
300impl TryFrom<BridgeRejectRequest> for RejectRequest {
301 type Error = ConversionError;
302
303 fn try_from(request: BridgeRejectRequest) -> Result<Self, Self::Error> {
304 let subject_id = DigestIdentifier::from_str(&request.subject_id)
305 .map_err(|e| ConversionError::InvalidSubjectId(e.to_string()))?;
306
307 Ok(RejectRequest { subject_id })
308 }
309}
310
311#[cfg(test)]
317mod tests {
318 use super::*;
319 use serde_json::json;
320
321 #[test]
322 fn test_fact_request_conversion() {
323 let bridge_fact = BridgeFactRequest {
324 subject_id: "BKZgYibuHNJjiNS179FUDpLGgdLq0C04TZRGb6AXMd1s"
325 .to_string(),
326 payload: json!({"test": "value"}),
327 };
328
329 let fact: Result<FactRequest, _> = bridge_fact.clone().try_into();
330 assert!(fact.is_ok());
331
332 let fact = fact.unwrap();
333 let bridge_back: BridgeFactRequest = fact.into();
334 assert_eq!(bridge_back.subject_id, bridge_fact.subject_id);
335 }
336
337 #[test]
338 fn test_create_request_conversion() {
339 let bridge_create = BridgeCreateRequest {
340 name: Some("Test".to_string()),
341 description: Some("Test description".to_string()),
342 governance_id: Some(
343 "BKZgYibuHNJjiNS179FUDpLGgdLq0C04TZRGb6AXMd1s".to_string(),
344 ),
345 schema_id: "governance".to_string(),
346 namespace: Some("test.namespace".to_string()),
347 };
348
349 let create: Result<CreateRequest, _> = bridge_create.try_into();
350 assert!(create.is_ok());
351 }
352
353 #[test]
354 fn test_create_request_missing_governance_id() {
355 let bridge_create = BridgeCreateRequest {
356 name: Some("Test".to_string()),
357 description: Some("Test description".to_string()),
358 governance_id: None,
359 schema_id: "governance".to_string(),
360 namespace: Some("test.namespace".to_string()),
361 };
362
363 let create: Result<CreateRequest, _> = bridge_create.try_into();
364 assert!(create.is_err());
365 assert!(matches!(
366 create.unwrap_err(),
367 ConversionError::MissingGovernanceId
368 ));
369 }
370
371 #[test]
372 fn test_invalid_subject_id() {
373 let bridge_fact = BridgeFactRequest {
374 subject_id: "invalid_id".to_string(),
375 payload: json!({"test": "value"}),
376 };
377
378 let fact: Result<FactRequest, _> = bridge_fact.try_into();
379 assert!(fact.is_err());
380 assert!(matches!(
381 fact.unwrap_err(),
382 ConversionError::InvalidSubjectId(_)
383 ));
384 }
385}