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 pub role: String,
92
93 #[serde(rename = "for")]
96 pub for_parties: ForParties,
97
98 #[serde(skip_serializing_if = "Option::is_none")]
100 #[serde(default)]
101 pub policies: Option<Vec<Policy>>,
102
103 #[serde(flatten)]
106 pub metadata: HashMap<String, serde_json::Value>,
107}
108
109impl TapParticipant for Agent {
110 fn id(&self) -> &str {
111 &self.id
112 }
113}
114
115impl Agent {
116 pub fn new(id: &str, role: &str, for_party: &str) -> Self {
118 Self {
119 id: id.to_string(),
120 role: role.to_string(),
121 for_parties: ForParties(vec![for_party.to_string()]),
122 policies: None,
123 metadata: HashMap::new(),
124 }
125 }
126
127 pub fn new_for_parties(id: &str, role: &str, for_parties: Vec<String>) -> Self {
129 Self {
130 id: id.to_string(),
131 role: role.to_string(),
132 for_parties: ForParties(for_parties),
133 policies: None,
134 metadata: HashMap::new(),
135 }
136 }
137
138 pub fn with_metadata(
140 id: &str,
141 role: &str,
142 for_party: &str,
143 metadata: HashMap<String, serde_json::Value>,
144 ) -> Self {
145 Self {
146 id: id.to_string(),
147 role: role.to_string(),
148 for_parties: ForParties(vec![for_party.to_string()]),
149 policies: None,
150 metadata,
151 }
152 }
153
154 pub fn with_policies(mut self, policies: Vec<Policy>) -> Self {
156 self.policies = Some(policies);
157 self
158 }
159
160 pub fn add_policy(mut self, policy: Policy) -> Self {
162 match &mut self.policies {
163 Some(policies) => policies.push(policy),
164 None => self.policies = Some(vec![policy]),
165 }
166 self
167 }
168
169 pub fn add_metadata(&mut self, key: String, value: serde_json::Value) {
171 self.metadata.insert(key, value);
172 }
173
174 pub fn with_metadata_field(mut self, key: String, value: serde_json::Value) -> Self {
176 self.metadata.insert(key, value);
177 self
178 }
179
180 pub fn get_metadata(&self, key: &str) -> Option<&serde_json::Value> {
182 self.metadata.get(key)
183 }
184
185 pub fn has_role(&self, role: &str) -> bool {
187 self.role == role
188 }
189
190 pub fn acts_for(&self, party_id: &str) -> bool {
192 self.for_parties.0.contains(&party_id.to_string())
193 }
194
195 pub fn for_parties(&self) -> &[String] {
197 &self.for_parties.0
198 }
199
200 pub fn primary_party(&self) -> Option<&str> {
202 self.for_parties.0.first().map(|s| s.as_str())
203 }
204
205 pub fn add_for_party(&mut self, party_id: &str) {
207 if !self.for_parties.0.contains(&party_id.to_string()) {
208 self.for_parties.0.push(party_id.to_string());
209 }
210 }
211
212 pub fn set_for_parties(&mut self, parties: Vec<String>) {
214 self.for_parties.0 = parties;
215 }
216}
217
218pub mod roles {
220 pub const SETTLEMENT_ADDRESS: &str = "SettlementAddress";
222
223 pub const SOURCE_ADDRESS: &str = "SourceAddress";
225
226 pub const CUSTODIAL_SERVICE: &str = "CustodialService";
228
229 pub const WALLET_SERVICE: &str = "WalletService";
231
232 pub const EXCHANGE: &str = "Exchange";
234
235 pub const BRIDGE: &str = "Bridge";
237
238 pub const DEFI_PROTOCOL: &str = "DeFiProtocol";
240}
241
242#[cfg(test)]
243mod tests {
244 use super::*;
245 use serde_json;
246
247 #[test]
248 fn test_agent_creation() {
249 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
250
251 assert_eq!(agent.id, "did:web:example.com");
252 assert_eq!(agent.role, "Exchange");
253 assert_eq!(agent.for_parties.0, vec!["did:example:alice"]);
254 assert!(agent.policies.is_none());
255 assert!(agent.metadata.is_empty());
256 }
257
258 #[test]
259 fn test_agent_with_metadata() {
260 let mut metadata = HashMap::new();
261 metadata.insert(
262 "name".to_string(),
263 serde_json::Value::String("Example Exchange".to_string()),
264 );
265
266 let agent = Agent::with_metadata(
267 "did:web:example.com",
268 "Exchange",
269 "did:example:alice",
270 metadata,
271 );
272
273 assert_eq!(
274 agent.get_metadata("name").unwrap().as_str().unwrap(),
275 "Example Exchange"
276 );
277 }
278
279 #[test]
280 fn test_agent_with_policies() {
281 use crate::message::policy::{Policy, RequireAuthorization};
282
283 let auth_req = RequireAuthorization {
284 from: Some(vec!["did:example:kyc".to_string()]),
285 from_role: None,
286 from_agent: None,
287 purpose: Some("KYC verification".to_string()),
288 };
289 let policy = Policy::RequireAuthorization(auth_req);
290
291 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice")
292 .with_policies(vec![policy]);
293
294 assert!(agent.policies.is_some());
295 assert_eq!(agent.policies.as_ref().unwrap().len(), 1);
296 }
297
298 #[test]
299 fn test_agent_serialization() {
300 let agent = Agent::new(
301 "did:web:example.com",
302 "SettlementAddress",
303 "did:example:alice",
304 )
305 .with_metadata_field(
306 "name".to_string(),
307 serde_json::Value::String("Test Agent".to_string()),
308 );
309
310 let json = serde_json::to_string(&agent).unwrap();
311 let deserialized: Agent = serde_json::from_str(&json).unwrap();
312
313 assert_eq!(agent, deserialized);
314 assert_eq!(deserialized.role, "SettlementAddress");
315 assert_eq!(deserialized.for_parties.0, vec!["did:example:alice"]);
316 }
317
318 #[test]
319 fn test_agent_json_ld_format() {
320 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
321 let json = serde_json::to_value(&agent).unwrap();
322
323 assert_eq!(json["@id"], "did:web:example.com");
324 assert_eq!(json["role"], "Exchange");
325 assert_eq!(json["for"], "did:example:alice"); }
327
328 #[test]
329 fn test_agent_helper_methods() {
330 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
331
332 assert!(agent.has_role("Exchange"));
333 assert!(!agent.has_role("Wallet"));
334 assert!(agent.acts_for("did:example:alice"));
335 assert!(!agent.acts_for("did:example:bob"));
336 }
337
338 #[test]
339 fn test_agent_roles_constants() {
340 assert_eq!(roles::SETTLEMENT_ADDRESS, "SettlementAddress");
341 assert_eq!(roles::SOURCE_ADDRESS, "SourceAddress");
342 assert_eq!(roles::EXCHANGE, "Exchange");
343 }
344
345 #[test]
346 fn test_agent_multiple_parties() {
347 let parties = vec![
348 "did:example:alice".to_string(),
349 "did:example:bob".to_string(),
350 ];
351 let agent = Agent::new_for_parties("did:web:example.com", "Exchange", parties.clone());
352
353 assert_eq!(agent.for_parties.0, parties);
354 assert!(agent.acts_for("did:example:alice"));
355 assert!(agent.acts_for("did:example:bob"));
356 assert!(!agent.acts_for("did:example:charlie"));
357 }
358
359 #[test]
360 fn test_agent_for_parties_serialization_single() {
361 let agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
362 let json = serde_json::to_value(&agent).unwrap();
363
364 assert_eq!(json["for"], "did:example:alice");
366
367 let deserialized: Agent = serde_json::from_value(json).unwrap();
369 assert_eq!(deserialized.for_parties.0, vec!["did:example:alice"]);
370 }
371
372 #[test]
373 fn test_agent_for_parties_serialization_multiple() {
374 let parties = vec![
375 "did:example:alice".to_string(),
376 "did:example:bob".to_string(),
377 ];
378 let agent = Agent::new_for_parties("did:web:example.com", "Exchange", parties.clone());
379 let json = serde_json::to_value(&agent).unwrap();
380
381 assert_eq!(
383 json["for"],
384 serde_json::Value::Array(vec![
385 serde_json::Value::String("did:example:alice".to_string()),
386 serde_json::Value::String("did:example:bob".to_string())
387 ])
388 );
389
390 let deserialized: Agent = serde_json::from_value(json).unwrap();
392 assert_eq!(deserialized.for_parties.0, parties);
393 }
394
395 #[test]
396 fn test_agent_for_parties_deserialization_from_string() {
397 let json = serde_json::json!({
398 "@id": "did:web:example.com",
399 "role": "Exchange",
400 "for": "did:example:alice"
401 });
402
403 let agent: Agent = serde_json::from_value(json).unwrap();
404 assert_eq!(agent.for_parties.0, vec!["did:example:alice"]);
405 }
406
407 #[test]
408 fn test_agent_for_parties_deserialization_from_array() {
409 let json = serde_json::json!({
410 "@id": "did:web:example.com",
411 "role": "Exchange",
412 "for": ["did:example:alice", "did:example:bob"]
413 });
414
415 let agent: Agent = serde_json::from_value(json).unwrap();
416 assert_eq!(
417 agent.for_parties.0,
418 vec!["did:example:alice", "did:example:bob"]
419 );
420 }
421
422 #[test]
423 fn test_agent_for_parties_methods() {
424 let mut agent = Agent::new("did:web:example.com", "Exchange", "did:example:alice");
425
426 assert_eq!(agent.for_parties(), &["did:example:alice"]);
427 assert_eq!(agent.primary_party(), Some("did:example:alice"));
428
429 agent.add_for_party("did:example:bob");
430 assert_eq!(
431 agent.for_parties(),
432 &["did:example:alice", "did:example:bob"]
433 );
434
435 agent.set_for_parties(vec!["did:example:charlie".to_string()]);
436 assert_eq!(agent.for_parties(), &["did:example:charlie"]);
437 assert_eq!(agent.primary_party(), Some("did:example:charlie"));
438 }
439}