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
230pub mod roles {
232 pub const SETTLEMENT_ADDRESS: &str = "SettlementAddress";
234
235 pub const SOURCE_ADDRESS: &str = "SourceAddress";
237
238 pub const CUSTODIAL_SERVICE: &str = "CustodialService";
240
241 pub const WALLET_SERVICE: &str = "WalletService";
243
244 pub const EXCHANGE: &str = "Exchange";
246
247 pub const BRIDGE: &str = "Bridge";
249
250 pub const DEFI_PROTOCOL: &str = "DeFiProtocol";
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257 use serde_json;
258
259 #[test]
260 fn test_agent_creation() {
261 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
262
263 assert_eq!(agent.id, "did:web:example.com");
264 assert_eq!(agent.role, Some("Exchange".to_string()));
265 assert_eq!(agent.for_parties.0, vec!["did:example:alice"]);
266 assert!(agent.policies.is_none());
267 assert!(agent.metadata.is_empty());
268 }
269
270 #[test]
271 fn test_agent_with_metadata() {
272 let mut metadata = HashMap::new();
273 metadata.insert(
274 "name".to_string(),
275 serde_json::Value::String("Example Exchange".to_string()),
276 );
277
278 let agent = Agent::with_metadata(
279 "did:web:example.com",
280 "Exchange",
281 "did:example:alice",
282 metadata,
283 );
284
285 assert_eq!(
286 agent.get_metadata("name").unwrap().as_str().unwrap(),
287 "Example Exchange"
288 );
289 }
290
291 #[test]
292 fn test_agent_with_policies() {
293 use crate::message::policy::{Policy, RequireAuthorization};
294
295 let auth_req = RequireAuthorization {
296 from: Some(vec!["did:example:kyc".to_string()]),
297 from_role: None,
298 from_agent: None,
299 purpose: Some("KYC verification".to_string()),
300 };
301 let policy = Policy::RequireAuthorization(auth_req);
302
303 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
304 .with_policies(vec![policy]);
305
306 assert!(agent.policies.is_some());
307 assert_eq!(agent.policies.as_ref().unwrap().len(), 1);
308 }
309
310 #[test]
311 fn test_agent_serialization() {
312 let agent = Agent::new(
313 "did:web:example.com",
314 "SettlementAddress",
315 "did:example:alice",
316 )
317 .with_metadata_field(
318 "name".to_string(),
319 serde_json::Value::String("Test Agent".to_string()),
320 );
321
322 let json = serde_json::to_string(&agent).unwrap();
323 let deserialized: Agent = serde_json::from_str(&json).unwrap();
324
325 assert_eq!(agent, deserialized);
326 assert_eq!(deserialized.role, Some("SettlementAddress".to_string()));
327 assert_eq!(deserialized.for_parties.0, vec!["did:example:alice"]);
328 }
329
330 #[test]
331 fn test_agent_json_ld_format() {
332 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
333 let json = serde_json::to_value(&agent).unwrap();
334
335 assert_eq!(json["@id"], "did:web:example.com");
336 assert_eq!(json["role"], "Exchange");
337 assert_eq!(json["for"], "did:example:alice"); }
339
340 #[test]
341 fn test_agent_helper_methods() {
342 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
343
344 assert!(agent.has_role("Exchange"));
345 assert!(!agent.has_role("Wallet"));
346 assert!(agent.acts_for("did:example:alice"));
347 assert!(!agent.acts_for("did:example:bob"));
348 }
349
350 #[test]
351 fn test_agent_roles_constants() {
352 assert_eq!(roles::SETTLEMENT_ADDRESS, "SettlementAddress");
353 assert_eq!(roles::SOURCE_ADDRESS, "SourceAddress");
354 assert_eq!(roles::EXCHANGE, "Exchange");
355 }
356
357 #[test]
358 fn test_agent_multiple_parties() {
359 let parties = vec![
360 "did:example:alice".to_string(),
361 "did:example:bob".to_string(),
362 ];
363 let agent = Agent::new_for_parties("did:web:example.com", "Exchange", parties.clone());
364
365 assert_eq!(agent.for_parties.0, parties);
366 assert!(agent.acts_for("did:example:alice"));
367 assert!(agent.acts_for("did:example:bob"));
368 assert!(!agent.acts_for("did:example:charlie"));
369 }
370
371 #[test]
372 fn test_agent_for_parties_serialization_single() {
373 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
374 let json = serde_json::to_value(&agent).unwrap();
375
376 assert_eq!(json["for"], "did:example:alice");
378
379 let deserialized: Agent = serde_json::from_value(json).unwrap();
381 assert_eq!(deserialized.for_parties.0, vec!["did:example:alice"]);
382 }
383
384 #[test]
385 fn test_agent_for_parties_serialization_multiple() {
386 let parties = vec![
387 "did:example:alice".to_string(),
388 "did:example:bob".to_string(),
389 ];
390 let agent = Agent::new_for_parties("did:web:example.com", "Exchange", parties.clone());
391 let json = serde_json::to_value(&agent).unwrap();
392
393 assert_eq!(
395 json["for"],
396 serde_json::Value::Array(vec![
397 serde_json::Value::String("did:example:alice".to_string()),
398 serde_json::Value::String("did:example:bob".to_string())
399 ])
400 );
401
402 let deserialized: Agent = serde_json::from_value(json).unwrap();
404 assert_eq!(deserialized.for_parties.0, parties);
405 }
406
407 #[test]
408 fn test_agent_for_parties_deserialization_from_string() {
409 let json = serde_json::json!({
410 "@id": "did:web:example.com",
411 "role": "Exchange",
412 "for": "did:example:alice"
413 });
414
415 let agent: Agent = serde_json::from_value(json).unwrap();
416 assert_eq!(agent.for_parties.0, vec!["did:example:alice"]);
417 }
418
419 #[test]
420 fn test_agent_for_parties_deserialization_from_array() {
421 let json = serde_json::json!({
422 "@id": "did:web:example.com",
423 "role": "Exchange",
424 "for": ["did:example:alice", "did:example:bob"]
425 });
426
427 let agent: Agent = serde_json::from_value(json).unwrap();
428 assert_eq!(
429 agent.for_parties.0,
430 vec!["did:example:alice", "did:example:bob"]
431 );
432 }
433
434 #[test]
435 fn test_agent_for_parties_methods() {
436 let mut agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
437
438 assert_eq!(agent.for_parties(), &["did:example:alice"]);
439 assert_eq!(agent.primary_party(), Some("did:example:alice"));
440
441 agent.add_for_party("did:example:bob");
442 assert_eq!(
443 agent.for_parties(),
444 &["did:example:alice", "did:example:bob"]
445 );
446
447 agent.set_for_parties(vec!["did:example:charlie".to_string()]);
448 assert_eq!(agent.for_parties(), &["did:example:charlie"]);
449 assert_eq!(agent.primary_party(), Some("did:example:charlie"));
450 }
451}