1use crate::error::Result;
4use crate::message::{
5 policy::{Policy, RequireAuthorization, RequirePresentation, RequireProofOfControl},
6 tap_message_trait::TapMessageBody,
7 types::{Authorizable, Authorize, Participant, Transfer, UpdatePolicies},
8};
9use didcomm::Message;
10use std::collections::HashMap;
11use std::str::FromStr;
12use tap_caip::AssetId;
13
14pub fn create_participant_with_policies_example() -> Result<Participant> {
16 let auth_policy = RequireAuthorization {
18 from: Some(vec!["did:example:alice".to_string()]),
19 from_role: None,
20 from_agent: None,
21 purpose: Some("Authorization required from Alice".to_string()),
22 };
23
24 let presentation_policy = RequirePresentation {
26 context: Some(vec![
27 "https://www.w3.org/2018/credentials/v1".to_string(),
28 "https://w3id.org/security/suites/ed25519-2020/v1".to_string(),
29 ]),
30 from: Some(vec!["did:example:bob".to_string()]),
31 from_role: None,
32 from_agent: None,
33 about_party: Some("originator".to_string()),
34 about_agent: None,
35 purpose: Some("Please provide KYC credentials".to_string()),
36 presentation_definition: Some("https://example.com/presentations/kyc".to_string()),
37 credentials: None,
38 };
39
40 let participant = Participant {
42 id: "did:example:charlie".to_string(),
43 role: Some("beneficiary".to_string()),
44 leiCode: None,
45 policies: Some(vec![
46 Policy::RequireAuthorization(auth_policy),
47 Policy::RequirePresentation(presentation_policy),
48 ]),
49 };
50
51 Ok(participant)
52}
53
54pub fn update_policies_example(
56 transaction_id: &str,
57 creator_did: &str,
58 recipients: &[&str],
59) -> Result<Message> {
60 let proof_policy = RequireProofOfControl {
62 from: Some(vec!["did:example:dave".to_string()]),
63 from_role: None,
64 from_agent: None,
65 address_id: "eip155:1:0x1234567890123456789012345678901234567890".to_string(),
66 purpose: Some("Please prove control of your account".to_string()),
67 };
68
69 let update = UpdatePolicies {
71 transaction_id: transaction_id.to_string(),
72 policies: vec![Policy::RequireProofOfControl(proof_policy)],
73 };
74
75 let participants = recipients
77 .iter()
78 .filter(|&&did| did != creator_did)
79 .copied()
80 .collect::<Vec<_>>();
81 let message = update.to_didcomm_with_route(Some(creator_did), participants)?;
82
83 let message_with_thread = Message {
85 thid: Some(transaction_id.to_string()),
86 ..message
87 };
88
89 Ok(message_with_thread)
90}
91
92pub fn policy_workflow_example() -> Result<()> {
94 println!("=== Starting Policy Workflow Example ===");
95
96 let originator_did = "did:example:originator";
98 let beneficiary_did = "did:example:beneficiary";
99 let sender_vaspd_did = "did:example:sender_vasp";
100 let receiver_vaspd_did = "did:example:receiver_vasp";
101
102 println!("Step 1: Creating beneficiary with policies");
104 let auth_policy = RequireAuthorization {
105 from: Some(vec![originator_did.to_string()]),
106 from_role: None,
107 from_agent: None,
108 purpose: Some("Authorization required from originator".to_string()),
109 };
110
111 let beneficiary = Participant {
112 id: beneficiary_did.to_string(),
113 role: Some("beneficiary".to_string()),
114 leiCode: None,
115 policies: Some(vec![Policy::RequireAuthorization(auth_policy)]),
116 };
117 println!(" Created beneficiary with policies: {:?}", beneficiary);
118
119 let transfer_id = "transfer_12345";
121 println!("Step 2: Created transfer ID: {}", transfer_id);
122
123 println!("Step 3: Sender VASP adds a presentation requirement");
125 let presentation_policy = RequirePresentation {
126 context: Some(vec!["https://www.w3.org/2018/credentials/v1".to_string()]),
127 from: Some(vec![beneficiary_did.to_string()]),
128 from_role: None,
129 from_agent: None,
130 about_party: Some("beneficiary".to_string()),
131 about_agent: None,
132 purpose: Some("Please provide identity credentials".to_string()),
133 presentation_definition: None,
134 credentials: Some(HashMap::from([(
135 "type".to_string(),
136 vec!["IdentityCredential".to_string()],
137 )])),
138 };
139
140 let update_message = UpdatePolicies {
141 transaction_id: transfer_id.to_string(),
142 policies: vec![Policy::RequirePresentation(presentation_policy)],
143 };
144
145 let participants = [
147 originator_did,
148 beneficiary_did,
149 sender_vaspd_did,
150 receiver_vaspd_did,
151 ];
152 let to = participants
153 .iter()
154 .filter(|&&did| did != sender_vaspd_did)
155 .copied()
156 .collect::<Vec<_>>();
157 let message = update_message.to_didcomm_with_route(Some(sender_vaspd_did), to)?;
158
159 let message_with_thread = Message {
161 thid: Some(transfer_id.to_string()),
162 ..message
163 };
164
165 println!(
166 " Created UpdatePolicies message: {:?}",
167 message_with_thread
168 );
169 println!(" This message will be routed to all participants");
170
171 println!("=== Policy Workflow Example Completed ===");
172 Ok(())
173}
174
175pub fn create_update_policies_using_authorizable_example(
177 original_message: &Result<Message>,
178 policies: Vec<Policy>,
179 _transaction_id: &str,
180 creator_did: &str,
181 participant_dids: &[String],
182) -> Result<Message> {
183 let body_json = original_message
185 .as_ref()
186 .map_err(Clone::clone)?
187 .body
188 .clone();
189 let transfer_body: Transfer = serde_json::from_value(body_json.clone())
191 .map_err(|e| crate::error::Error::SerializationError(e.to_string()))?;
192 let transaction_id = transfer_body.transaction_id.clone();
195 let update_policies_message = transfer_body.update_policies(transaction_id, policies);
196
197 let mut update_policies_reply = update_policies_message.to_didcomm(Some(creator_did))?;
199
200 update_policies_reply.thid = Some(original_message.as_ref().map_err(Clone::clone)?.id.clone());
202
203 update_policies_reply.to = Some(participant_dids.iter().map(|s| s.to_string()).collect());
205
206 Ok(update_policies_reply)
207}
208
209pub fn policy_workflow_with_authorizable_example() -> Result<()> {
211 println!("=== Starting Policy Workflow with Authorizable Example ===");
212
213 let originator_did = "did:example:originator";
215 let beneficiary_did = "did:example:beneficiary";
216 let sender_vasp_did = "did:example:sender_vasp";
217 let receiver_vasp_did = "did:example:receiver_vasp";
218
219 let transfer = Transfer {
221 transaction_id: uuid::Uuid::new_v4().to_string(),
222 asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
223 .unwrap(),
224 originator: Participant {
225 id: originator_did.to_string(),
226 role: Some("originator".to_string()),
227 leiCode: None,
228 policies: None,
229 },
230 beneficiary: Some(Participant {
231 id: beneficiary_did.to_string(),
232 role: Some("beneficiary".to_string()),
233 leiCode: None,
234 policies: None,
235 }),
236 amount: "100.00".to_string(),
237 memo: None,
238 agents: vec![
239 Participant {
240 id: sender_vasp_did.to_string(),
241 role: Some("sender_vasp".to_string()),
242 leiCode: None,
243 policies: None,
244 },
245 Participant {
246 id: receiver_vasp_did.to_string(),
247 role: Some("receiver_vasp".to_string()),
248 leiCode: None,
249 policies: None,
250 },
251 ],
252 settlement_id: None,
253 metadata: HashMap::new(),
254 };
255
256 let transfer_message = transfer.to_didcomm_with_route(
258 Some(originator_did),
259 [beneficiary_did, sender_vasp_did, receiver_vasp_did]
260 .iter()
261 .copied(),
262 )?;
263
264 println!("Transfer message created: {:?}", transfer_message);
265
266 let participants = [
269 originator_did.to_string(),
270 beneficiary_did.to_string(),
271 sender_vasp_did.to_string(),
272 receiver_vasp_did.to_string(),
273 ];
274
275 let cloned_transfer_id = transfer_message.id.clone();
276 let update_policies_message = create_update_policies_using_authorizable_example(
277 &Ok(transfer_message),
278 vec![],
279 &cloned_transfer_id,
280 sender_vasp_did,
281 &participants,
282 )?;
283
284 println!(
285 "Update policies message created: {:?}",
286 update_policies_message
287 );
288
289 let authorize_body =
291 transfer.authorize(Some("Authorization with policy constraints".to_string()));
292
293 let mut authorize_reply = authorize_body.to_didcomm(Some(beneficiary_did))?;
295
296 authorize_reply.thid = Some(update_policies_message.id.clone());
298
299 authorize_reply.to = Some(participants.iter().map(|s| s.to_string()).collect());
301
302 println!("Authorization message created: {:?}", authorize_reply);
303
304 Ok(())
305}
306
307pub fn create_authorize_example() -> Result<()> {
309 let authorize_message = Authorize {
311 transaction_id: "transfer_12345".to_string(),
312 note: Some("Authorized with policy constraints".to_string()),
313 };
314
315 println!("Authorize message: {:#?}", authorize_message);
316
317 Ok(())
318}