1use crate::error::{Error, Result};
4use crate::message::policy::{Policy, RequireProofOfControl};
5use crate::message::tap_message_trait::TapMessageBody;
6use crate::message::types::{
7 AddAgents, Authorizable, Authorize, Participant, RemoveAgent, ReplaceAgent, Settle, Transfer,
8};
9
10use didcomm::Message;
11use serde_json;
12use std::collections::HashMap;
13use std::str::FromStr;
14use tap_caip::AssetId;
15
16pub fn create_reply_to_transfer_example() -> Result<Message> {
18 let alice_did = "did:example:alice";
19 let bob_did = "did:example:bob";
20
21 let transfer = Transfer {
23 transaction_id: uuid::Uuid::new_v4().to_string(),
24 asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
25 .unwrap(),
26 originator: Participant {
27 id: alice_did.to_string(),
28 role: Some("originator".to_string()),
29 policies: None,
30 leiCode: None,
31 },
32 beneficiary: Some(Participant {
33 id: bob_did.to_string(),
34 role: Some("beneficiary".to_string()),
35 policies: None,
36 leiCode: None,
37 }),
38 amount: "100.00".to_string(),
39 agents: vec![],
40 settlement_id: None,
41 memo: None,
42 metadata: HashMap::new(),
43 };
44
45 let transfer_message =
47 transfer.to_didcomm_with_route(Some(alice_did), [bob_did].iter().copied())?;
48
49 let authorize = Authorize {
51 transaction_id: transfer_message.id.clone(),
52 note: Some("I authorize this transfer".to_string()),
53 };
54
55 let mut authorize_reply = authorize.to_didcomm(Some(alice_did))?;
57
58 authorize_reply.thid = Some(transfer_message.id.clone());
60
61 let recipients: Vec<String> = [alice_did, bob_did]
63 .iter()
64 .filter(|&did| **did != *alice_did)
65 .map(|s| s.to_string())
66 .collect();
67
68 authorize_reply.to = Some(recipients);
69
70 Ok(authorize_reply)
71}
72
73pub fn create_reply_using_message_trait_example(
75 original_message: &Message,
76 creator_did: &str,
77) -> Result<Message> {
78 let authorize = Authorize {
80 transaction_id: original_message.id.clone(),
81 note: Some("Transfer authorized".to_string()),
82 };
83
84 let mut response_message = authorize.to_didcomm(Some(creator_did))?;
87
88 response_message.thid = original_message.thid.clone();
90
91 let recipients: Vec<String> = original_message
93 .to
94 .as_ref()
95 .unwrap()
96 .iter()
97 .filter(|did| **did != creator_did)
98 .map(|s| s.to_string())
99 .collect();
100
101 response_message.to = Some(recipients);
102
103 Ok(response_message)
104}
105
106pub fn create_add_agents_example() -> Result<Message> {
108 let originator_did = "did:example:originator";
109 let beneficiary_did = "did:example:beneficiary";
110 let sender_vasp_did = "did:example:sender_vasp";
111 let receiver_vasp_did = "did:example:receiver_vasp";
112 let new_agent_did = "did:example:new_agent";
113
114 let transfer = Transfer {
116 transaction_id: uuid::Uuid::new_v4().to_string(),
117 asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
118 .unwrap(),
119 originator: Participant {
120 id: originator_did.to_string(),
121 role: Some("originator".to_string()),
122 policies: None,
123 leiCode: None,
124 },
125 beneficiary: Some(Participant {
126 id: beneficiary_did.to_string(),
127 role: Some("beneficiary".to_string()),
128 policies: None,
129 leiCode: None,
130 }),
131 amount: "100.00".to_string(),
132 memo: None,
133 agents: vec![
134 Participant {
135 id: sender_vasp_did.to_string(),
136 role: Some("sender_vasp".to_string()),
137 policies: None,
138 leiCode: None,
139 },
140 Participant {
141 id: receiver_vasp_did.to_string(),
142 role: Some("receiver_vasp".to_string()),
143 policies: None,
144 leiCode: None,
145 },
146 ],
147 settlement_id: None,
148 metadata: HashMap::new(),
149 };
150
151 let transfer_message =
153 transfer.to_didcomm_with_route(Some(originator_did), [beneficiary_did].iter().copied())?;
154
155 let authorize = Authorize {
157 transaction_id: transfer_message.id.clone(),
158 note: Some("I authorize this transfer".to_string()),
159 };
160
161 let mut authorize_message = authorize.to_didcomm(Some(originator_did))?;
163
164 authorize_message.thid = Some(transfer_message.id.clone());
166
167 let recipients: Vec<String> = [originator_did, beneficiary_did]
169 .iter()
170 .filter(|did| **did != originator_did)
171 .map(|s| s.to_string())
172 .collect();
173
174 authorize_message.to = Some(recipients);
175
176 let add_agents = AddAgents {
178 transaction_id: transfer_message.id.clone(),
179 agents: vec![Participant {
180 id: new_agent_did.to_string(),
181 role: Some("compliance".to_string()),
182 policies: None,
183 leiCode: None,
184 }],
185 };
186
187 let mut response = add_agents.to_didcomm(Some(originator_did))?;
189
190 response.thid = Some(transfer_message.id.clone());
192
193 let recipients: Vec<String> = [originator_did, beneficiary_did, new_agent_did]
195 .iter()
196 .filter(|did| **did != originator_did)
197 .map(|s| s.to_string())
198 .collect();
199
200 response.to = Some(recipients);
201
202 Ok(response)
203}
204
205pub fn create_replace_agent_example(
207 original_message: &Message,
208 creator_did: &str,
209 original_agent_id: &str,
210 replacement_agent_id: &str,
211 replacement_agent_role: Option<&str>,
212) -> Result<Message> {
213 let original_body_json = original_message.body.clone();
215 let original_transfer: Transfer = serde_json::from_value(original_body_json)
216 .map_err(|e| Error::SerializationError(e.to_string()))?;
217
218 let replacement = Participant {
220 id: replacement_agent_id.to_string(),
221 role: replacement_agent_role.map(ToString::to_string),
222 policies: None, leiCode: None,
224 };
225
226 let replace_agent_body = original_transfer.replace_agent(
228 original_message.id.clone(),
229 original_agent_id.to_string(),
230 replacement,
231 );
232
233 let mut response = replace_agent_body.to_didcomm(Some(creator_did))?;
235
236 response.thid = original_message.thid.clone();
238
239 let recipients: Vec<String> = original_message
241 .to
242 .as_ref()
243 .unwrap()
244 .iter()
245 .filter(|did| **did != creator_did)
246 .map(|s| s.to_string())
247 .collect();
248
249 response.to = Some(recipients);
250
251 Ok(response)
252}
253
254pub fn create_remove_agent_example(
256 original_message: &Message,
257 creator_did: &str,
258 agent_to_remove: &str,
259) -> Result<Message> {
260 let original_body_json = original_message.body.clone();
262 let original_transfer: Transfer = serde_json::from_value(original_body_json)
263 .map_err(|e| Error::SerializationError(e.to_string()))?;
264
265 let remove_agent_body =
267 original_transfer.remove_agent(original_message.id.clone(), agent_to_remove.to_string());
268
269 let mut response = remove_agent_body.to_didcomm(Some(creator_did))?;
271
272 response.thid = original_message.thid.clone();
274
275 let recipients: Vec<String> = original_message
277 .to
278 .as_ref()
279 .unwrap()
280 .iter()
281 .filter(|did| **did != creator_did)
282 .map(|s| s.to_string())
283 .collect();
284
285 response.to = Some(recipients);
286
287 Ok(response)
288}
289
290pub fn create_update_policies_example(
292 original_message: &Message,
293 creator_did: &str,
294 _recipients: &[&str],
295) -> Result<Message> {
296 let original_body_json = original_message.body.clone();
298 let original_transfer: Transfer = serde_json::from_value(original_body_json)
299 .map_err(|e| Error::SerializationError(e.to_string()))?;
300
301 let proof_policy = RequireProofOfControl {
303 from: Some(vec!["did:example:dave".to_string()]),
304 from_role: None,
305 from_agent: None,
306 address_id: "eip155:1:0x1234567890123456789012345678901234567890".to_string(),
307 purpose: Some("Please prove control of your account".to_string()),
308 };
309
310 let update_policies_body = original_transfer.update_policies(
312 original_message.id.clone(),
313 vec![Policy::RequireProofOfControl(proof_policy)],
314 );
315
316 let mut response = update_policies_body.to_didcomm(Some(creator_did))?;
318
319 response.thid = original_message.thid.clone();
321
322 let recipients: Vec<String> = original_message
324 .to
325 .as_ref()
326 .unwrap()
327 .iter()
328 .filter(|did| **did != creator_did)
329 .map(|s| s.to_string())
330 .collect();
331
332 response.to = Some(recipients);
333
334 Ok(response)
335}
336
337pub fn settle_example(
349 transaction_id: String,
350 settlement_id: String,
351 amount: Option<String>,
352) -> Result<Message> {
353 let settle = Settle {
355 transaction_id,
356 settlement_id,
357 amount,
358 };
359
360 let settle_message = settle.to_didcomm(Some("did:example:dave"))?;
362
363 Ok(settle_message)
364}
365
366pub fn thread_participant_workflow_example() -> Result<()> {
368 let alice_did = "did:example:alice";
370 let bob_did = "did:example:bob";
371 let charlie_did = "did:example:charlie";
372 let dave_did = "did:example:dave";
373
374 let transfer = Transfer {
376 transaction_id: uuid::Uuid::new_v4().to_string(),
377 asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
378 .unwrap(),
379 originator: Participant {
380 id: alice_did.to_string(),
381 role: Some("originator".to_string()),
382 policies: None,
383 leiCode: None,
384 },
385 memo: None,
386 beneficiary: Some(Participant {
387 id: bob_did.to_string(),
388 role: Some("beneficiary".to_string()),
389 policies: None,
390 leiCode: None,
391 }),
392 amount: "10.00".to_string(),
393 agents: vec![],
394 settlement_id: None,
395 metadata: HashMap::new(),
396 };
397
398 let transfer_message =
400 transfer.to_didcomm_with_route(Some(alice_did), [bob_did].iter().copied())?;
401
402 println!("Created initial transfer message: {:?}", transfer_message);
403
404 let transfer_id = transfer_message.id.clone();
406
407 let authorize = Authorize {
409 transaction_id: transfer_message.id.clone(),
410 note: Some("Transfer approved".to_string()),
411 };
412
413 let mut authorize_message = authorize.to_didcomm(Some(bob_did))?;
415
416 authorize_message.thid = Some(transfer_message.id.clone());
418
419 let recipients: Vec<String> = [alice_did, bob_did]
421 .iter()
422 .filter(|did| **did != bob_did)
423 .map(|s| s.to_string())
424 .collect();
425
426 authorize_message.to = Some(recipients);
427
428 println!("Created authorize message: {:?}", authorize_message);
429
430 let add_agents = AddAgents {
433 transaction_id: transfer_id.clone(),
434 agents: vec![Participant {
435 id: charlie_did.to_string(),
436 role: Some("observer".to_string()),
437 policies: None,
438 leiCode: None,
439 }],
440 };
441
442 let mut add_agents_message = add_agents.to_didcomm(Some(alice_did))?;
444
445 add_agents_message.thid = Some(transfer_id.clone());
447
448 let recipients: Vec<String> = [alice_did, bob_did, charlie_did]
450 .iter()
451 .filter(|did| **did != alice_did)
452 .map(|s| s.to_string())
453 .collect();
454
455 add_agents_message.to = Some(recipients);
456
457 println!("Created add agents message: {:?}", add_agents_message);
458
459 let replace_agent = ReplaceAgent {
461 transaction_id: transfer_id.clone(),
462 original: bob_did.to_string(),
463 replacement: Participant {
464 id: dave_did.to_string(),
465 role: Some("beneficiary".to_string()),
466 policies: None,
467 leiCode: None,
468 },
469 };
470
471 let mut replace_agent_message = replace_agent.to_didcomm(Some(bob_did))?;
473
474 replace_agent_message.thid = Some(transfer_id.clone());
476
477 let recipients: Vec<String> = [alice_did, dave_did, charlie_did]
479 .iter()
480 .filter(|did| **did != bob_did)
481 .map(|s| s.to_string())
482 .collect();
483
484 replace_agent_message.to = Some(recipients);
485
486 println!("Created replace agent message: {:?}", replace_agent_message);
487
488 let remove_agent = RemoveAgent {
490 transaction_id: transfer_id.clone(),
491 agent: charlie_did.to_string(),
492 };
493
494 let mut remove_agent_message = remove_agent.to_didcomm(Some(alice_did))?;
496
497 remove_agent_message.thid = Some(transfer_id.clone());
499
500 let recipients: Vec<String> = [alice_did, dave_did, charlie_did]
502 .iter()
503 .filter(|did| **did != alice_did)
504 .map(|s| s.to_string())
505 .collect();
506
507 remove_agent_message.to = Some(recipients);
508
509 println!("Created remove agent message: {:?}", remove_agent_message);
510
511 println!("Step 5: Settling the transfer");
513 let settle_message = settle_example(
514 transfer_id.clone(),
515 "tx123456".to_string(),
516 Some("100.0".to_string()),
517 )?;
518
519 if let Some(to) = &settle_message.to {
521 assert!(to.contains(&alice_did.to_string()));
522 assert!(!to.contains(&dave_did.to_string())); println!("Verified that the settle message is addressed correctly");
524 }
525
526 Ok(())
527}