1use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10use crate::message::policy::Policy;
11
12pub trait TapParticipant {
14 fn id(&self) -> &str;
16}
17
18#[derive(Debug, Clone, PartialEq)]
20pub struct ForParties(pub Vec<String>);
21
22impl Serialize for ForParties {
23 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
24 where
25 S: serde::Serializer,
26 {
27 if self.0.len() == 1 {
28 self.0[0].serialize(serializer)
30 } else {
31 self.0.serialize(serializer)
33 }
34 }
35}
36
37impl<'de> Deserialize<'de> for ForParties {
38 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39 where
40 D: serde::Deserializer<'de>,
41 {
42 use serde::de::{self, Visitor};
43 use std::fmt;
44
45 struct ForPartiesVisitor;
46
47 impl<'de> Visitor<'de> for ForPartiesVisitor {
48 type Value = ForParties;
49
50 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
51 formatter.write_str("a string or an array of strings")
52 }
53
54 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
55 where
56 E: de::Error,
57 {
58 Ok(ForParties(vec![value.to_string()]))
59 }
60
61 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
62 where
63 A: de::SeqAccess<'de>,
64 {
65 let mut parties = Vec::new();
66 while let Some(party) = seq.next_element::<String>()? {
67 parties.push(party);
68 }
69 Ok(ForParties(parties))
70 }
71 }
72
73 deserializer.deserialize_any(ForPartiesVisitor)
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
84pub struct Agent {
85 #[serde(rename = "@id")]
87 pub id: String,
88
89 #[serde(skip_serializing_if = "Option::is_none")]
92 pub role: Option<String>,
93
94 #[serde(rename = "for")]
97 pub for_parties: ForParties,
98
99 #[serde(skip_serializing_if = "Option::is_none")]
101 #[serde(default)]
102 pub policies: Option<Vec<Policy>>,
103
104 #[serde(flatten)]
107 pub metadata: HashMap<String, serde_json::Value>,
108}
109
110impl TapParticipant for Agent {
111 fn id(&self) -> &str {
112 &self.id
113 }
114}
115
116impl Agent {
117 pub fn new(id: &str, role: &str, for_party: &str) -> Self {
119 Self {
120 id: id.to_string(),
121 role: Some(role.to_string()),
122 for_parties: ForParties(vec![for_party.to_string()]),
123 policies: None,
124 metadata: HashMap::new(),
125 }
126 }
127
128 pub fn new_for_parties(id: &str, role: &str, for_parties: Vec<String>) -> Self {
130 Self {
131 id: id.to_string(),
132 role: Some(role.to_string()),
133 for_parties: ForParties(for_parties),
134 policies: None,
135 metadata: HashMap::new(),
136 }
137 }
138
139 pub fn new_without_role(id: &str, for_party: &str) -> Self {
141 Self {
142 id: id.to_string(),
143 role: None,
144 for_parties: ForParties(vec![for_party.to_string()]),
145 policies: None,
146 metadata: HashMap::new(),
147 }
148 }
149
150 pub fn with_metadata(
152 id: &str,
153 role: &str,
154 for_party: &str,
155 metadata: HashMap<String, serde_json::Value>,
156 ) -> Self {
157 Self {
158 id: id.to_string(),
159 role: Some(role.to_string()),
160 for_parties: ForParties(vec![for_party.to_string()]),
161 policies: None,
162 metadata,
163 }
164 }
165
166 pub fn with_policies(mut self, policies: Vec<Policy>) -> Self {
168 self.policies = Some(policies);
169 self
170 }
171
172 pub fn add_policy(mut self, policy: Policy) -> Self {
174 match &mut self.policies {
175 Some(policies) => policies.push(policy),
176 None => self.policies = Some(vec![policy]),
177 }
178 self
179 }
180
181 pub fn add_metadata(&mut self, key: String, value: serde_json::Value) {
183 self.metadata.insert(key, value);
184 }
185
186 pub fn with_metadata_field(mut self, key: String, value: serde_json::Value) -> Self {
188 self.metadata.insert(key, value);
189 self
190 }
191
192 pub fn get_metadata(&self, key: &str) -> Option<&serde_json::Value> {
194 self.metadata.get(key)
195 }
196
197 pub fn has_role(&self, role: &str) -> bool {
199 self.role.as_ref().is_some_and(|r| r == role)
200 }
201
202 pub fn acts_for(&self, party_id: &str) -> bool {
204 self.for_parties.0.contains(&party_id.to_string())
205 }
206
207 pub fn for_parties(&self) -> &[String] {
209 &self.for_parties.0
210 }
211
212 pub fn primary_party(&self) -> Option<&str> {
214 self.for_parties.0.first().map(|s| s.as_str())
215 }
216
217 pub fn add_for_party(&mut self, party_id: &str) {
219 if !self.for_parties.0.contains(&party_id.to_string()) {
220 self.for_parties.0.push(party_id.to_string());
221 }
222 }
223
224 pub fn set_for_parties(&mut self, parties: Vec<String>) {
226 self.for_parties.0 = parties;
227 }
228
229 pub fn with_name(mut self, name: &str) -> Self {
233 self.metadata.insert(
234 "name".to_string(),
235 serde_json::Value::String(name.to_string()),
236 );
237 self
238 }
239
240 pub fn name(&self) -> Option<&str> {
242 self.metadata.get("name").and_then(|v| v.as_str())
243 }
244
245 pub fn with_url(mut self, url: &str) -> Self {
247 self.metadata.insert(
248 "url".to_string(),
249 serde_json::Value::String(url.to_string()),
250 );
251 self
252 }
253
254 pub fn url(&self) -> Option<&str> {
256 self.metadata.get("url").and_then(|v| v.as_str())
257 }
258
259 pub fn with_logo(mut self, logo: &str) -> Self {
261 self.metadata.insert(
262 "logo".to_string(),
263 serde_json::Value::String(logo.to_string()),
264 );
265 self
266 }
267
268 pub fn logo(&self) -> Option<&str> {
270 self.metadata.get("logo").and_then(|v| v.as_str())
271 }
272
273 pub fn with_description(mut self, description: &str) -> Self {
275 self.metadata.insert(
276 "description".to_string(),
277 serde_json::Value::String(description.to_string()),
278 );
279 self
280 }
281
282 pub fn description(&self) -> Option<&str> {
284 self.metadata.get("description").and_then(|v| v.as_str())
285 }
286
287 pub fn with_email(mut self, email: &str) -> Self {
289 self.metadata.insert(
290 "email".to_string(),
291 serde_json::Value::String(email.to_string()),
292 );
293 self
294 }
295
296 pub fn email(&self) -> Option<&str> {
298 self.metadata.get("email").and_then(|v| v.as_str())
299 }
300
301 pub fn with_telephone(mut self, telephone: &str) -> Self {
303 self.metadata.insert(
304 "telephone".to_string(),
305 serde_json::Value::String(telephone.to_string()),
306 );
307 self
308 }
309
310 pub fn telephone(&self) -> Option<&str> {
312 self.metadata.get("telephone").and_then(|v| v.as_str())
313 }
314
315 pub fn with_service_url(mut self, service_url: &str) -> Self {
317 self.metadata.insert(
318 "serviceUrl".to_string(),
319 serde_json::Value::String(service_url.to_string()),
320 );
321 self
322 }
323
324 pub fn service_url(&self) -> Option<&str> {
326 self.metadata.get("serviceUrl").and_then(|v| v.as_str())
327 }
328}
329
330pub mod roles {
332 pub const SETTLEMENT_ADDRESS: &str = "SettlementAddress";
334
335 pub const SOURCE_ADDRESS: &str = "SourceAddress";
337
338 pub const CUSTODIAL_SERVICE: &str = "CustodialService";
340
341 pub const WALLET_SERVICE: &str = "WalletService";
343
344 pub const EXCHANGE: &str = "Exchange";
346
347 pub const BRIDGE: &str = "Bridge";
349
350 pub const DEFI_PROTOCOL: &str = "DeFiProtocol";
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357 use serde_json;
358
359 #[test]
360 fn test_agent_creation() {
361 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
362
363 assert_eq!(agent.id, "did:web:example.com");
364 assert_eq!(agent.role, Some("Exchange".to_string()));
365 assert_eq!(agent.for_parties.0, vec!["did:example:alice"]);
366 assert!(agent.policies.is_none());
367 assert!(agent.metadata.is_empty());
368 }
369
370 #[test]
371 fn test_agent_with_metadata() {
372 let mut metadata = HashMap::new();
373 metadata.insert(
374 "name".to_string(),
375 serde_json::Value::String("Example Exchange".to_string()),
376 );
377
378 let agent = Agent::with_metadata(
379 "did:web:example.com",
380 "Exchange",
381 "did:example:alice",
382 metadata,
383 );
384
385 assert_eq!(
386 agent.get_metadata("name").unwrap().as_str().unwrap(),
387 "Example Exchange"
388 );
389 }
390
391 #[test]
392 fn test_agent_with_policies() {
393 use crate::message::policy::{Policy, RequireAuthorization};
394
395 let auth_req = RequireAuthorization {
396 from: Some(vec!["did:example:kyc".to_string()]),
397 from_role: None,
398 from_agent: None,
399 purpose: Some("KYC verification".to_string()),
400 };
401 let policy = Policy::RequireAuthorization(auth_req);
402
403 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
404 .with_policies(vec![policy]);
405
406 assert!(agent.policies.is_some());
407 assert_eq!(agent.policies.as_ref().unwrap().len(), 1);
408 }
409
410 #[test]
411 fn test_agent_serialization() {
412 let agent = Agent::new(
413 "did:web:example.com",
414 "SettlementAddress",
415 "did:example:alice",
416 )
417 .with_metadata_field(
418 "name".to_string(),
419 serde_json::Value::String("Test Agent".to_string()),
420 );
421
422 let json = serde_json::to_string(&agent).unwrap();
423 let deserialized: Agent = serde_json::from_str(&json).unwrap();
424
425 assert_eq!(agent, deserialized);
426 assert_eq!(deserialized.role, Some("SettlementAddress".to_string()));
427 assert_eq!(deserialized.for_parties.0, vec!["did:example:alice"]);
428 }
429
430 #[test]
431 fn test_agent_json_ld_format() {
432 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
433 let json = serde_json::to_value(&agent).unwrap();
434
435 assert_eq!(json["@id"], "did:web:example.com");
436 assert_eq!(json["role"], "Exchange");
437 assert_eq!(json["for"], "did:example:alice"); }
439
440 #[test]
441 fn test_agent_helper_methods() {
442 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
443
444 assert!(agent.has_role("Exchange"));
445 assert!(!agent.has_role("Wallet"));
446 assert!(agent.acts_for("did:example:alice"));
447 assert!(!agent.acts_for("did:example:bob"));
448 }
449
450 #[test]
451 fn test_agent_roles_constants() {
452 assert_eq!(roles::SETTLEMENT_ADDRESS, "SettlementAddress");
453 assert_eq!(roles::SOURCE_ADDRESS, "SourceAddress");
454 assert_eq!(roles::EXCHANGE, "Exchange");
455 }
456
457 #[test]
458 fn test_agent_multiple_parties() {
459 let parties = vec![
460 "did:example:alice".to_string(),
461 "did:example:bob".to_string(),
462 ];
463 let agent = Agent::new_for_parties("did:web:example.com", "Exchange", parties.clone());
464
465 assert_eq!(agent.for_parties.0, parties);
466 assert!(agent.acts_for("did:example:alice"));
467 assert!(agent.acts_for("did:example:bob"));
468 assert!(!agent.acts_for("did:example:charlie"));
469 }
470
471 #[test]
472 fn test_agent_for_parties_serialization_single() {
473 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
474 let json = serde_json::to_value(&agent).unwrap();
475
476 assert_eq!(json["for"], "did:example:alice");
478
479 let deserialized: Agent = serde_json::from_value(json).unwrap();
481 assert_eq!(deserialized.for_parties.0, vec!["did:example:alice"]);
482 }
483
484 #[test]
485 fn test_agent_for_parties_serialization_multiple() {
486 let parties = vec![
487 "did:example:alice".to_string(),
488 "did:example:bob".to_string(),
489 ];
490 let agent = Agent::new_for_parties("did:web:example.com", "Exchange", parties.clone());
491 let json = serde_json::to_value(&agent).unwrap();
492
493 assert_eq!(
495 json["for"],
496 serde_json::Value::Array(vec![
497 serde_json::Value::String("did:example:alice".to_string()),
498 serde_json::Value::String("did:example:bob".to_string())
499 ])
500 );
501
502 let deserialized: Agent = serde_json::from_value(json).unwrap();
504 assert_eq!(deserialized.for_parties.0, parties);
505 }
506
507 #[test]
508 fn test_agent_for_parties_deserialization_from_string() {
509 let json = serde_json::json!({
510 "@id": "did:web:example.com",
511 "role": "Exchange",
512 "for": "did:example:alice"
513 });
514
515 let agent: Agent = serde_json::from_value(json).unwrap();
516 assert_eq!(agent.for_parties.0, vec!["did:example:alice"]);
517 }
518
519 #[test]
520 fn test_agent_for_parties_deserialization_from_array() {
521 let json = serde_json::json!({
522 "@id": "did:web:example.com",
523 "role": "Exchange",
524 "for": ["did:example:alice", "did:example:bob"]
525 });
526
527 let agent: Agent = serde_json::from_value(json).unwrap();
528 assert_eq!(
529 agent.for_parties.0,
530 vec!["did:example:alice", "did:example:bob"]
531 );
532 }
533
534 #[test]
535 fn test_agent_for_parties_methods() {
536 let mut agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
537
538 assert_eq!(agent.for_parties(), &["did:example:alice"]);
539 assert_eq!(agent.primary_party(), Some("did:example:alice"));
540
541 agent.add_for_party("did:example:bob");
542 assert_eq!(
543 agent.for_parties(),
544 &["did:example:alice", "did:example:bob"]
545 );
546
547 agent.set_for_parties(vec!["did:example:charlie".to_string()]);
548 assert_eq!(agent.for_parties(), &["did:example:charlie"]);
549 assert_eq!(agent.primary_party(), Some("did:example:charlie"));
550 }
551
552 #[test]
555 fn test_agent_with_name_field() {
556 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
557 .with_name("Example Exchange Inc.");
558
559 assert_eq!(agent.name(), Some("Example Exchange Inc."));
560
561 let json = serde_json::to_value(&agent).unwrap();
563 assert_eq!(json["name"], "Example Exchange Inc.");
564
565 let deserialized: Agent = serde_json::from_value(json).unwrap();
567 assert_eq!(deserialized.name(), Some("Example Exchange Inc."));
568 }
569
570 #[test]
571 fn test_agent_with_url_field() {
572 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
573 .with_url("https://example.com");
574
575 assert_eq!(agent.url(), Some("https://example.com"));
576
577 let json = serde_json::to_value(&agent).unwrap();
578 assert_eq!(json["url"], "https://example.com");
579 }
580
581 #[test]
582 fn test_agent_with_logo_field() {
583 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
584 .with_logo("https://example.com/logo.png");
585
586 assert_eq!(agent.logo(), Some("https://example.com/logo.png"));
587
588 let json = serde_json::to_value(&agent).unwrap();
589 assert_eq!(json["logo"], "https://example.com/logo.png");
590 }
591
592 #[test]
593 fn test_agent_with_description_field() {
594 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
595 .with_description("A leading cryptocurrency exchange");
596
597 assert_eq!(
598 agent.description(),
599 Some("A leading cryptocurrency exchange")
600 );
601
602 let json = serde_json::to_value(&agent).unwrap();
603 assert_eq!(json["description"], "A leading cryptocurrency exchange");
604 }
605
606 #[test]
607 fn test_agent_with_email_field() {
608 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
609 .with_email("support@example.com");
610
611 assert_eq!(agent.email(), Some("support@example.com"));
612
613 let json = serde_json::to_value(&agent).unwrap();
614 assert_eq!(json["email"], "support@example.com");
615 }
616
617 #[test]
618 fn test_agent_with_telephone_field() {
619 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
620 .with_telephone("+1-555-0100");
621
622 assert_eq!(agent.telephone(), Some("+1-555-0100"));
623
624 let json = serde_json::to_value(&agent).unwrap();
625 assert_eq!(json["telephone"], "+1-555-0100");
626 }
627
628 #[test]
629 fn test_agent_with_service_url_field() {
630 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
631 .with_service_url("https://example.com/didcomm");
632
633 assert_eq!(agent.service_url(), Some("https://example.com/didcomm"));
634
635 let json = serde_json::to_value(&agent).unwrap();
636 assert_eq!(json["serviceUrl"], "https://example.com/didcomm");
637 }
638
639 #[test]
640 fn test_agent_with_multiple_organization_fields() {
641 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
642 .with_name("Example Exchange Inc.")
643 .with_url("https://example.com")
644 .with_logo("https://example.com/logo.png")
645 .with_description("A leading cryptocurrency exchange")
646 .with_email("support@example.com")
647 .with_telephone("+1-555-0100")
648 .with_service_url("https://example.com/didcomm");
649
650 assert_eq!(agent.name(), Some("Example Exchange Inc."));
651 assert_eq!(agent.url(), Some("https://example.com"));
652 assert_eq!(agent.logo(), Some("https://example.com/logo.png"));
653 assert_eq!(
654 agent.description(),
655 Some("A leading cryptocurrency exchange")
656 );
657 assert_eq!(agent.email(), Some("support@example.com"));
658 assert_eq!(agent.telephone(), Some("+1-555-0100"));
659 assert_eq!(agent.service_url(), Some("https://example.com/didcomm"));
660
661 let json = serde_json::to_value(&agent).unwrap();
663 assert_eq!(json["@id"], "did:web:example.com");
664 assert_eq!(json["role"], "Exchange");
665 assert_eq!(json["for"], "did:example:alice");
666 assert_eq!(json["name"], "Example Exchange Inc.");
667 assert_eq!(json["url"], "https://example.com");
668 assert_eq!(json["logo"], "https://example.com/logo.png");
669 assert_eq!(json["description"], "A leading cryptocurrency exchange");
670 assert_eq!(json["email"], "support@example.com");
671 assert_eq!(json["telephone"], "+1-555-0100");
672 assert_eq!(json["serviceUrl"], "https://example.com/didcomm");
673
674 let deserialized: Agent = serde_json::from_value(json).unwrap();
676 assert_eq!(deserialized.name(), Some("Example Exchange Inc."));
677 assert_eq!(deserialized.url(), Some("https://example.com"));
678 assert_eq!(
679 deserialized.service_url(),
680 Some("https://example.com/didcomm")
681 );
682 }
683
684 #[test]
685 fn test_agent_json_ld_compliance_with_organization_fields() {
686 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
687 .with_name("Example Exchange")
688 .with_metadata_field(
689 "lei:leiCode".to_string(),
690 serde_json::Value::String("123456789012345678".to_string()),
691 );
692
693 let json = serde_json::to_value(&agent).unwrap();
694
695 assert_eq!(json["@id"], "did:web:example.com");
697 assert_eq!(json["name"], "Example Exchange");
698 assert_eq!(json["lei:leiCode"], "123456789012345678");
699
700 assert!(json.get("metadata").is_none());
702 }
703}