fi_common/
did.rs

1use crate::{
2    error::Error,
3    keys::{KeyPair, VerificationKey},
4};
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use wasm_bindgen::prelude::wasm_bindgen;
8#[cfg(feature = "wasm")]
9use wasm_bindgen::JsValue;
10
11pub const DID_CONTEXT_URL: &str = "https://www.w3.org/ns/did/v1";
12
13#[derive(Serialize, Deserialize, Clone)]
14#[wasm_bindgen]
15pub struct DidDocument {
16    #[serde(rename = "@context")]
17    #[wasm_bindgen(skip)]
18    pub context: Vec<Value>,
19    #[wasm_bindgen(skip)]
20    pub id: String,
21    #[wasm_bindgen(skip)]
22    #[serde(rename = "verificationMethod")]
23    pub verification_method: Option<Vec<KeyPair>>,
24    #[wasm_bindgen(skip)]
25    pub authentication: Option<Vec<String>>,
26    #[wasm_bindgen(skip)]
27    #[serde(rename = "assertionMethod")]
28    pub assertion_method: Option<Vec<String>>,
29    #[wasm_bindgen(skip)]
30    #[serde(rename = "capabilityDelegation")]
31    pub capability_delegation: Option<Vec<String>>,
32    #[wasm_bindgen(skip)]
33    #[serde(rename = "capabilityInvocation")]
34    pub capability_invocation: Option<Vec<String>>,
35    #[serde(rename = "keyAgreement")]
36    #[wasm_bindgen(skip)]
37    pub key_agreement: Option<Vec<KeyPair>>,
38    #[wasm_bindgen(skip)]
39    pub services: Option<Vec<Service>>,
40}
41
42pub trait KeyPairToDidDocument {
43    fn key_pair_to_did_doc(
44        key_pair: &Box<dyn VerificationKey>,
45        fingerprint: &str,
46    ) -> Result<DidDocument, Error>;
47}
48
49#[wasm_bindgen]
50impl DidDocument {
51    #[wasm_bindgen(js_name = "getKeyPair")]
52    pub fn get_key_pair(&self, key_id_fragment: &str) -> Result<KeyPair, Error> {
53        let key_id = format!("{}#{}", self.id, key_id_fragment);
54
55        if self
56            .verification_method
57            .as_ref()
58            .is_some_and(|val| val.len() > 0)
59            || self.key_agreement.as_ref().is_some_and(|val| val.len() > 0)
60        {
61            let verification_method = self.verification_method.as_ref().unwrap();
62            let key_agreement = self.key_agreement.as_ref().unwrap();
63
64            let public_key: KeyPair;
65            if verification_method.len() > 0
66                && verification_method[0]
67                    .id
68                    .as_ref()
69                    .is_some_and(|val| val.eq(&key_id))
70            {
71                public_key = verification_method[0].clone();
72            } else {
73                public_key = key_agreement[0].clone();
74            }
75            return Ok(public_key);
76        }
77
78        return Err(Error::new("No key pair could be found."));
79    }
80
81    #[cfg(feature = "wasm")]
82    #[wasm_bindgen(js_name = "toObject")]
83    pub fn to_object(&self) -> Result<JsValue, serde_wasm_bindgen::Error> {
84        serde_wasm_bindgen::to_value(self)
85    }
86
87    #[cfg(feature = "wasm")]
88    #[wasm_bindgen(getter)]
89    pub fn context(&self) -> JsValue {
90        use wasm_bindgen::JsValue;
91
92        match serde_wasm_bindgen::to_value(&self.context) {
93            Ok(val) => val,
94            Err(_error) => JsValue::NULL,
95        }
96    }
97
98    #[cfg(feature = "wasm")]
99    #[wasm_bindgen(setter)]
100    pub fn set_context(&mut self, context: JsValue) {
101        self.context = match serde_wasm_bindgen::from_value(context) {
102            Ok(val) => val,
103            Err(_error) => Vec::new(),
104        };
105    }
106
107    #[cfg(feature = "wasm")]
108    #[wasm_bindgen(getter)]
109    pub fn id(&self) -> String {
110        self.id.clone()
111    }
112
113    #[cfg(feature = "wasm")]
114    #[wasm_bindgen(setter)]
115    pub fn set_id(&mut self, id: String) {
116        self.id = id;
117    }
118
119    #[cfg(feature = "wasm")]
120    #[wasm_bindgen(setter, js_name = "verificationMethod")]
121    pub fn set_verification_method(&mut self, verification_method: Option<Vec<KeyPair>>) {
122        self.verification_method = verification_method;
123    }
124
125    #[cfg(feature = "wasm")]
126    #[wasm_bindgen(getter, js_name = "verificationMethod")]
127    pub fn verification_method(&self) -> Option<Vec<KeyPair>> {
128        self.verification_method.clone()
129    }
130
131    #[cfg(feature = "wasm")]
132    #[wasm_bindgen(setter)]
133    pub fn set_authentication(&mut self, authentication: Option<Vec<String>>) {
134        self.authentication = authentication;
135    }
136
137    #[cfg(feature = "wasm")]
138    #[wasm_bindgen(getter)]
139    pub fn authentication(&self) -> Option<Vec<String>> {
140        self.authentication.clone()
141    }
142
143    #[cfg(feature = "wasm")]
144    #[wasm_bindgen(setter, js_name = "assertionMethod")]
145    pub fn set_assertion_method(&mut self, assertion_method: Option<Vec<String>>) {
146        self.assertion_method = assertion_method;
147    }
148
149    #[cfg(feature = "wasm")]
150    #[wasm_bindgen(getter, js_name = "assertionMethod")]
151    pub fn assertion_method(&self) -> Option<Vec<String>> {
152        self.assertion_method.clone()
153    }
154
155    #[cfg(feature = "wasm")]
156    #[wasm_bindgen(setter, js_name = "capabilityDelegation")]
157    pub fn set_capability_delegation(&mut self, capability_delegation: Option<Vec<String>>) {
158        self.capability_delegation = capability_delegation;
159    }
160
161    #[cfg(feature = "wasm")]
162    #[wasm_bindgen(getter, js_name = "capabilityDelegation")]
163    pub fn capability_delegation(&self) -> Option<Vec<String>> {
164        self.capability_delegation.clone()
165    }
166
167    #[cfg(feature = "wasm")]
168    #[wasm_bindgen(setter, js_name = "capabilityInvocation")]
169    pub fn set_capability_invocation(&mut self, capability_invocation: Option<Vec<String>>) {
170        self.capability_invocation = capability_invocation;
171    }
172
173    #[cfg(feature = "wasm")]
174    #[wasm_bindgen(getter, js_name = "capabilityInvocation")]
175    pub fn capability_invocation(&self) -> Option<Vec<String>> {
176        self.capability_invocation.clone()
177    }
178
179    #[cfg(feature = "wasm")]
180    #[wasm_bindgen(setter, js_name = "keyAgreement")]
181    pub fn set_key_agreement(&mut self, key_agreement: Option<Vec<KeyPair>>) {
182        self.key_agreement = key_agreement;
183    }
184
185    #[cfg(feature = "wasm")]
186    #[wasm_bindgen(getter, js_name = "keyAgreement")]
187    pub fn key_agreement(&self) -> Option<Vec<KeyPair>> {
188        self.key_agreement.clone()
189    }
190
191    #[cfg(feature = "wasm")]
192    pub fn set_services(&mut self, services: Option<Vec<Service>>) {
193        self.services = services;
194    }
195
196    #[cfg(feature = "wasm")]
197    pub fn services(&self) -> Option<Vec<Service>> {
198        self.services.clone()
199    }
200}
201
202#[derive(Serialize, Deserialize, Debug, Clone)]
203#[wasm_bindgen]
204pub struct Service {
205    #[wasm_bindgen(skip)]
206    pub id: String,
207    #[serde(rename = "type")]
208    #[wasm_bindgen(skip)]
209    pub _type: String,
210    #[wasm_bindgen(skip)]
211    pub service_endpoint: Value,
212}
213
214#[wasm_bindgen]
215impl Service {
216    #[cfg(feature = "wasm")]
217    #[wasm_bindgen(setter)]
218    pub fn set_id(&mut self, id: String) {
219        self.id = id;
220    }
221
222    #[cfg(feature = "wasm")]
223    #[wasm_bindgen(getter)]
224    pub fn id(&self) -> String {
225        self.id.clone()
226    }
227
228    #[cfg(feature = "wasm")]
229    #[wasm_bindgen(setter, js_name = "type")]
230    pub fn set_type(&mut self, _type: String) {
231        self._type = _type;
232    }
233
234    #[cfg(feature = "wasm")]
235    #[wasm_bindgen(getter, js_name = "type")]
236    pub fn _type(&self) -> String {
237        self._type.clone()
238    }
239
240    #[cfg(feature = "wasm")]
241    #[wasm_bindgen(setter, js_name = "serviceEndpoint")]
242    pub fn set_service_endpoint(
243        &mut self,
244        service_endpoint: JsValue,
245    ) -> Result<(), serde_wasm_bindgen::Error> {
246        self.service_endpoint = match serde_wasm_bindgen::from_value(service_endpoint) {
247            Ok(val) => val,
248            Err(error) => return Err(error),
249        };
250
251        Ok(())
252    }
253
254    #[cfg(feature = "wasm")]
255    #[wasm_bindgen(getter, js_name = "serviceEndpoint")]
256    pub fn service_endpoint(&self) -> Result<JsValue, serde_wasm_bindgen::Error> {
257        match serde_wasm_bindgen::to_value(&self.service_endpoint) {
258            Err(error) => Err(error),
259            Ok(val) => Ok(val),
260        }
261    }
262}