1use crate::didcomm::PlainMessage;
4use crate::error::Result;
5use crate::message::{
6 policy::{Policy, RequireAuthorization, RequirePresentation, RequireProofOfControl},
7 tap_message_trait::{Authorizable, TapMessageBody},
8 Authorize, Participant, Transfer, UpdatePolicies,
9};
10
11use std::collections::HashMap;
12use std::str::FromStr;
13use tap_caip::AssetId;
14
15pub fn create_participant_with_policies_example() -> Result<Participant> {
17 let auth_policy = RequireAuthorization {
19 from: Some(vec!["did:example:alice".to_string()]),
20 from_role: None,
21 from_agent: None,
22 purpose: Some("Authorization required from Alice".to_string()),
23 };
24
25 let presentation_policy = RequirePresentation {
27 context: Some(vec![
28 "https://www.w3.org/2018/credentials/v1".to_string(),
29 "https://w3id.org/security/suites/ed25519-2020/v1".to_string(),
30 ]),
31 from: Some(vec!["did:example:bob".to_string()]),
32 from_role: None,
33 from_agent: None,
34 about_party: Some("originator".to_string()),
35 about_agent: None,
36 purpose: Some("Please provide KYC credentials".to_string()),
37 presentation_definition: Some("https://example.com/presentations/kyc".to_string()),
38 credentials: None,
39 };
40
41 let participant = Participant {
43 id: "did:example:charlie".to_string(),
44 role: Some("beneficiary".to_string()),
45 leiCode: None,
46 name: None,
47 policies: Some(vec![
48 Policy::RequireAuthorization(auth_policy),
49 Policy::RequirePresentation(presentation_policy),
50 ]),
51 };
52
53 Ok(participant)
54}
55
56pub fn update_policies_example(
58 transaction_id: &str,
59 creator_did: &str,
60 recipients: &[&str],
61) -> Result<PlainMessage> {
62 let proof_policy = RequireProofOfControl {
64 from: Some(vec!["did:example:dave".to_string()]),
65 from_role: None,
66 from_agent: None,
67 address_id: "eip155:1:0x1234567890123456789012345678901234567890".to_string(),
68 purpose: Some("Please prove control of your account".to_string()),
69 };
70
71 let update = UpdatePolicies {
73 transaction_id: transaction_id.to_string(),
74 policies: vec![Policy::RequireProofOfControl(proof_policy)],
75 };
76
77 let participants = recipients
79 .iter()
80 .filter(|&&did| did != creator_did)
81 .copied()
82 .collect::<Vec<_>>();
83 let mut message = update.to_didcomm_with_route(creator_did, participants)?;
84
85 message.thid = Some(transaction_id.to_string());
87
88 Ok(message)
89}
90
91pub fn policy_workflow_example() -> Result<()> {
93 println!("=== Starting Policy Workflow Example ===");
94
95 let originator_did = "did:example:originator";
97 let beneficiary_did = "did:example:beneficiary";
98 let sender_vaspd_did = "did:example:sender_vasp";
99 let receiver_vaspd_did = "did:example:receiver_vasp";
100
101 println!("Step 1: Creating beneficiary with policies");
103 let auth_policy = RequireAuthorization {
104 from: Some(vec![originator_did.to_string()]),
105 from_role: None,
106 from_agent: None,
107 purpose: Some("Authorization required from originator".to_string()),
108 };
109
110 let beneficiary = Participant {
111 id: beneficiary_did.to_string(),
112 role: Some("beneficiary".to_string()),
113 leiCode: None,
114 name: 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 mut message = update_message.to_didcomm_with_route(sender_vaspd_did, to)?;
158
159 message.thid = Some(transfer_id.to_string());
161
162 println!(" Created UpdatePolicies message: {:?}", message);
163 println!(" This message will be routed to all participants");
164
165 println!("=== Policy Workflow Example Completed ===");
166 Ok(())
167}
168
169pub fn create_update_policies_using_authorizable_example(
171 original_message: &Result<PlainMessage>,
172 policies: Vec<Policy>,
173 _transaction_id: &str,
174 creator_did: &str,
175 participant_dids: &[String],
176) -> Result<PlainMessage> {
177 let body_json = original_message
179 .as_ref()
180 .map_err(Clone::clone)?
181 .body
182 .clone();
183 let transfer_body: Transfer = serde_json::from_value(body_json.clone())
185 .map_err(|e| crate::error::Error::SerializationError(e.to_string()))?;
186 let transaction_id = transfer_body.transaction_id.clone();
189 let update_policies_message = transfer_body.update_policies(transaction_id, policies);
191
192 let mut update_policies_reply = update_policies_message.to_didcomm(creator_did)?;
194
195 update_policies_reply.thid = Some(original_message.as_ref().map_err(Clone::clone)?.id.clone());
197
198 update_policies_reply.to = participant_dids.iter().map(|s| s.to_string()).collect();
200
201 Ok(update_policies_reply)
202}
203
204pub fn policy_workflow_with_authorizable_example() -> Result<()> {
206 println!("=== Starting Policy Workflow with Authorizable Example ===");
207
208 let originator_did = "did:example:originator";
210 let beneficiary_did = "did:example:beneficiary";
211 let sender_vasp_did = "did:example:sender_vasp";
212 let receiver_vasp_did = "did:example:receiver_vasp";
213
214 let transfer = Transfer {
216 transaction_id: uuid::Uuid::new_v4().to_string(),
217 asset: AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
218 .unwrap(),
219 originator: Participant {
220 id: originator_did.to_string(),
221 role: Some("originator".to_string()),
222 leiCode: None,
223 name: None,
224 policies: None,
225 },
226 beneficiary: Some(Participant {
227 id: beneficiary_did.to_string(),
228 role: Some("beneficiary".to_string()),
229 leiCode: None,
230 name: None,
231 policies: None,
232 }),
233 amount: "100.00".to_string(),
234 memo: None,
235 agents: vec![
236 Participant {
237 id: sender_vasp_did.to_string(),
238 role: Some("sender_vasp".to_string()),
239 leiCode: None,
240 name: None,
241 policies: None,
242 },
243 Participant {
244 id: receiver_vasp_did.to_string(),
245 role: Some("receiver_vasp".to_string()),
246 leiCode: None,
247 name: None,
248 policies: None,
249 },
250 ],
251 settlement_id: None,
252 metadata: HashMap::new(),
253 };
254
255 let transfer_message = transfer.to_didcomm_with_route(
257 originator_did,
258 [beneficiary_did, sender_vasp_did, receiver_vasp_did]
259 .iter()
260 .copied(),
261 )?;
262
263 println!("Transfer message created: {:?}", transfer_message);
264
265 let participants = [
268 originator_did.to_string(),
269 beneficiary_did.to_string(),
270 sender_vasp_did.to_string(),
271 receiver_vasp_did.to_string(),
272 ];
273
274 let cloned_transfer_id = transfer_message.id.clone();
275 let update_policies_message = create_update_policies_using_authorizable_example(
276 &Ok(transfer_message),
277 vec![],
278 &cloned_transfer_id,
279 sender_vasp_did,
280 &participants,
281 )?;
282
283 println!(
284 "Update policies message created: {:?}",
285 update_policies_message
286 );
287
288 let authorize_body =
291 transfer.authorize(Some("Authorization with policy constraints".to_string()));
292
293 let mut authorize_reply = authorize_body.to_didcomm(beneficiary_did)?;
295
296 authorize_reply.thid = Some(update_policies_message.id.clone());
298
299 authorize_reply.to = 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}