tap_msg/message/
presentation.rs1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9use crate::error::Result;
10use crate::impl_tap_message;
11use crate::message::tap_message_trait::TapMessageBody;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct RequestPresentation {
16 pub transaction_id: String,
18
19 pub presentation_definition: String,
21
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub description: Option<String>,
25
26 pub challenge: String,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub for_originator: Option<bool>,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub for_beneficiary: Option<bool>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub note: Option<String>,
40
41 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
43 pub metadata: HashMap<String, serde_json::Value>,
44}
45
46impl TapMessageBody for RequestPresentation {
47 fn message_type() -> &'static str {
48 "https://tap.rsvp/schema/1.0#request-presentation"
49 }
50
51 fn validate(&self) -> Result<()> {
52 if self.transaction_id.is_empty() {
53 return Err(crate::error::Error::Validation(
54 "Transaction ID is required in RequestPresentation".to_string(),
55 ));
56 }
57
58 if self.presentation_definition.is_empty() {
59 return Err(crate::error::Error::Validation(
60 "Presentation definition is required in RequestPresentation".to_string(),
61 ));
62 }
63
64 if self.challenge.is_empty() {
65 return Err(crate::error::Error::Validation(
66 "Challenge is required in RequestPresentation".to_string(),
67 ));
68 }
69
70 Ok(())
71 }
72}
73
74impl_tap_message!(RequestPresentation);
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct Presentation {
79 pub challenge: String,
81
82 pub credentials: Vec<serde_json::Value>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub transaction_id: Option<String>,
88
89 pub id: String,
91
92 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
94 pub metadata: HashMap<String, serde_json::Value>,
95}
96
97impl Presentation {
98 pub fn new(
100 challenge: String,
101 credentials: Vec<serde_json::Value>,
102 transaction_id: Option<String>,
103 ) -> Self {
104 Self {
105 challenge,
106 credentials,
107 transaction_id,
108 id: uuid::Uuid::new_v4().to_string(),
109 metadata: HashMap::new(),
110 }
111 }
112
113 pub fn with_metadata(mut self, key: &str, value: serde_json::Value) -> Self {
115 self.metadata.insert(key.to_string(), value);
116 self
117 }
118}
119
120impl TapMessageBody for Presentation {
121 fn message_type() -> &'static str {
122 "https://didcomm.org/present-proof/3.0/presentation"
123 }
124
125 fn validate(&self) -> Result<()> {
126 if self.challenge.is_empty() {
127 return Err(crate::error::Error::Validation(
128 "Challenge is required in Presentation".to_string(),
129 ));
130 }
131
132 if self.credentials.is_empty() {
133 return Err(crate::error::Error::Validation(
134 "Credentials are required in Presentation".to_string(),
135 ));
136 }
137
138 Ok(())
139 }
140}
141
142impl_tap_message!(Presentation, optional_transaction_id);