did_peer/
lib.rs

1//! # DID Peer Method
2//!
3//! The `did-peer` method is a DID method that is designed to be used for peer-to-peer communication.
4//! It is based on did:key which can be used for Verification (V) and Encryption (E) purposes.
5//! It also supports services (S) which can be used to define endpoints for communication.
6//!
7//! Example:
8//! ```ignore
9//! let peer = DIDPeer;
10//! match peer.resolve(DID::new::<str>("did:peer:2.Vabc...").unwrap()).await {
11//!    Ok(res) => {
12//!        println!("DID DOcument: {:#?}", res.document.into_document()),
13//!    },
14//!    Err(e) => {
15//!      println!("Error: {:?}", e);
16//!   }
17//! }
18//! ```
19//!
20use base64::prelude::*;
21use iref::UriBuf;
22use serde::{Deserialize, Serialize};
23use serde_json::Value;
24use service::convert_service;
25use ssi::{
26    OneOrMany,
27    dids::{
28        DID, DIDBuf, DIDKey, DIDMethod, DIDMethodResolver, DIDURL, DIDURLBuf, DIDURLReferenceBuf,
29        Document, RelativeDIDURLBuf,
30        document::{
31            self, DIDVerificationMethod, Resource, Service, VerificationRelationships,
32            representation::{self, MediaType},
33            service::Endpoint,
34            verification_method,
35        },
36        key::VerificationMethodType,
37        resolution::{self, Content, Error, Options, Output, Parameters},
38    },
39    jwk::Params,
40    prelude::*,
41};
42use std::{collections::BTreeMap, fmt};
43use thiserror::Error;
44use wasm_bindgen::prelude::*;
45
46pub mod service;
47
48#[derive(Error, Debug)]
49pub enum DIDPeerError {
50    #[error("Unsupported key type")]
51    UnsupportedKeyType,
52    #[error("Unsupported curve: {0}")]
53    UnsupportedCurve(String),
54    #[error("Unsupported source")]
55    UnsupportedSource,
56    #[error("Syntax error on Service definition: {0}")]
57    SyntaxErrorServiceDefinition(String),
58    #[error("Unsupported Method. Must be method 2")]
59    MethodNotSupported,
60    #[error("Key Parsing error {0}")]
61    KeyParsingError(String),
62    #[error("DID Document doesn't contain any verificationMethod items")]
63    MissingVerificationMethods,
64    #[error("JSON Parsing error: {0}")]
65    JsonParsingError(String),
66    #[error("Internal error: {0}")]
67    InternalError(String),
68}
69
70// Converts DIDPeerError to JsValue which is required for propagating errors to WASM
71impl From<DIDPeerError> for JsValue {
72    fn from(err: DIDPeerError) -> JsValue {
73        JsValue::from(err.to_string())
74    }
75}
76
77pub struct DIDPeer;
78
79/// DID Peer Service supports two formats:
80/// 1. Short format - uses `a` and `r` for accept and routing keys
81/// 2. Long format - uses `accept` and `routing_keys` for accept and routing keys
82#[derive(Debug, Serialize, Deserialize)]
83#[serde(untagged)]
84pub enum PeerServiceEndPoint {
85    Short(PeerServiceEndPointShort),
86    Long(PeerServiceEndPointLong),
87}
88
89impl PeerServiceEndPoint {
90    pub fn to_short(&self) -> PeerServiceEndPointShort {
91        match self {
92            PeerServiceEndPoint::Short(short) => short.clone(),
93            PeerServiceEndPoint::Long(long) => match long {
94                PeerServiceEndPointLong::URI(uri) => PeerServiceEndPointShort::URI(uri.to_string()),
95                PeerServiceEndPointLong::Map(map) => match map {
96                    OneOrMany::One(single) => {
97                        PeerServiceEndPointShort::Map(OneOrMany::One(PeerServiceEndPointShortMap {
98                            uri: single.uri.to_string(),
99                            a: single.accept.clone(),
100                            r: single.routing_keys.clone(),
101                        }))
102                    }
103                    OneOrMany::Many(many) => PeerServiceEndPointShort::Map(OneOrMany::Many(
104                        many.iter()
105                            .map(|m| PeerServiceEndPointShortMap {
106                                uri: m.uri.to_string(),
107                                a: m.accept.clone(),
108                                r: m.routing_keys.clone(),
109                            })
110                            .collect(),
111                    )),
112                },
113            },
114        }
115    }
116
117    pub fn to_long(&self) -> PeerServiceEndPointLong {
118        match self {
119            PeerServiceEndPoint::Short(short) => PeerServiceEndPointLong::from(short.clone()),
120            PeerServiceEndPoint::Long(long) => long.clone(),
121        }
122    }
123}
124
125/// DID serviceEndPoint structure in short format
126#[derive(Debug, Clone, Serialize, Deserialize)]
127#[serde(untagged)]
128pub enum PeerServiceEndPointShort {
129    URI(String),
130    Map(OneOrMany<PeerServiceEndPointShortMap>),
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct PeerServiceEndPointShortMap {
135    pub uri: String,
136    pub a: Vec<String>,
137    pub r: Vec<String>,
138}
139
140/// DID serviceEndPoint structure in long format
141#[derive(Debug, Clone, Serialize, Deserialize)]
142#[serde(untagged)]
143pub enum PeerServiceEndPointLong {
144    URI(String),
145    Map(OneOrMany<PeerServiceEndPointLongMap>),
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct PeerServiceEndPointLongMap {
150    pub uri: String,
151    pub accept: Vec<String>,
152    pub routing_keys: Vec<String>,
153}
154
155impl From<PeerServiceEndPointShort> for PeerServiceEndPointLong {
156    fn from(service: PeerServiceEndPointShort) -> Self {
157        match service {
158            PeerServiceEndPointShort::URI(uri) => PeerServiceEndPointLong::URI(uri),
159            PeerServiceEndPointShort::Map(map) => match map {
160                OneOrMany::One(single) => {
161                    PeerServiceEndPointLong::Map(OneOrMany::One(PeerServiceEndPointLongMap {
162                        uri: single.uri,
163                        accept: single.a,
164                        routing_keys: single.r,
165                    }))
166                }
167                OneOrMany::Many(many) => PeerServiceEndPointLong::Map(OneOrMany::Many(
168                    many.iter()
169                        .map(|m| PeerServiceEndPointLongMap {
170                            uri: m.uri.clone(),
171                            accept: m.a.clone(),
172                            routing_keys: m.r.clone(),
173                        })
174                        .collect(),
175                )),
176            },
177        }
178    }
179}
180/// DID Service structure in abbreviated format
181#[derive(Debug, Serialize, Deserialize)]
182pub struct DIDPeerService {
183    #[serde(rename = "t")]
184    #[serde(alias = "t")]
185    pub _type: String,
186    #[serde(rename = "s")]
187    #[serde(alias = "s")]
188    pub service_end_point: PeerServiceEndPoint, // serviceEndPoint
189
190    /// id is optional, if not provided, it will be set to #service, #service-1, #service-2, etc
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub id: Option<String>,
193}
194
195impl DIDPeerService {
196    fn convert(did: &str, service: DIDPeerService) -> Result<Service, DIDPeerError> {
197        let service_endpoint = match serde_json::to_value(PeerServiceEndPoint::to_long(
198            &service.service_end_point,
199        )) {
200            Ok(value) => {
201                if value.is_string() {
202                    if let Some(value) = value.as_str() {
203                        if let Ok(uri) = UriBuf::new(value.as_bytes().to_vec()) {
204                            Some(OneOrMany::One(Endpoint::Uri(uri)))
205                        } else {
206                            return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
207                                "Couldn't convert ServiceEndPoint to a valid URI: {}",
208                                value
209                            )));
210                        }
211                    } else {
212                        return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
213                            "Service URI appears to be a string, but can't parse as a string: {}",
214                            value
215                        )));
216                    }
217                } else {
218                    Some(OneOrMany::One(Endpoint::Map(value)))
219                }
220            }
221            Err(err) => {
222                return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
223                    "Couldn't convert ServiceEndPoint to a valid representation. Reason: {}",
224                    err
225                )));
226            }
227        };
228
229        let id = if let Some(id) = service.id {
230            [did, &id].concat()
231        } else {
232            [did, "#service"].concat()
233        };
234
235        let id = match UriBuf::new(id.as_bytes().to_vec()) {
236            Ok(uri) => uri,
237            Err(e) => {
238                return Err(DIDPeerError::SyntaxErrorServiceDefinition(format!(
239                    "Error parsing service id: {}. Reason: {:?}",
240                    id, e
241                )));
242            }
243        };
244
245        Ok(Service {
246            id,
247            type_: OneOrMany::One("DIDCommMessaging".into()),
248            service_endpoint,
249            property_set: BTreeMap::new(),
250        })
251    }
252}
253
254#[derive(Clone)]
255#[wasm_bindgen]
256/// DID Peer Key Purpose (used to create a new did:peer: string)
257///   Verification: Keys are referenced in the authentication and assertionMethod fields
258///   Encryption: Keys are referenced in the keyAgreement field
259pub enum DIDPeerKeys {
260    Verification,
261    Encryption,
262}
263
264impl fmt::Display for DIDPeerKeys {
265    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266        match *self {
267            DIDPeerKeys::Verification => write!(f, "verification"),
268            DIDPeerKeys::Encryption => write!(f, "encryption"),
269        }
270    }
271}
272
273#[derive(Clone)]
274#[wasm_bindgen]
275/// Supported DID Peer Key Types (used to create a new did:peer: string)
276pub enum DIDPeerKeyType {
277    Ed25519,
278    Secp256k1,
279    P256,
280}
281
282impl fmt::Display for DIDPeerKeyType {
283    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
284        match *self {
285            DIDPeerKeyType::Ed25519 => write!(f, "ed25519"),
286            DIDPeerKeyType::Secp256k1 => write!(f, "secp256k1"),
287            DIDPeerKeyType::P256 => write!(f, "p256"),
288        }
289    }
290}
291
292#[derive(Clone)]
293#[wasm_bindgen(getter_with_clone)]
294/// Structure to help with creating a new did:peer: string
295///    purpose: ENUM (DIDPeerKeys) - Verification or Encryption
296///    public_key_multibase: String - Optional: Multibase encoded public key (did:key:(.*))
297///                                   If None, then auto-create and return the private key
298pub struct DIDPeerCreateKeys {
299    pub purpose: DIDPeerKeys,
300    pub type_: Option<DIDPeerKeyType>,
301    pub public_key_multibase: Option<String>,
302}
303
304#[wasm_bindgen]
305impl DIDPeerCreateKeys {
306    #[wasm_bindgen(constructor)]
307    pub fn new(
308        purpose: DIDPeerKeys,
309        type_: Option<DIDPeerKeyType>,
310        public_key_multibase: Option<String>,
311    ) -> Self {
312        DIDPeerCreateKeys {
313            purpose,
314            type_,
315            public_key_multibase,
316        }
317    }
318}
319
320/// DIDPeerCreatedKeys, contains information related to any keys that were created
321///
322/// key_multibase: `String`, the multibase_58 encoded key value (e.g. did:key:(.*))
323/// curve: `String`, the elliptic curve method used
324/// d: `String`, private key value in Base64URL_NOPAD
325/// x: `String`, public key value in Base64URL_NOPAD
326/// y: `Option<String>`, Optional: Y coordinate for EC keys in Base64URL_NOPAD
327#[derive(Clone, Debug, Serialize, Deserialize)]
328#[wasm_bindgen(getter_with_clone)]
329pub struct DIDPeerCreatedKeys {
330    pub key_multibase: String,
331    pub curve: String,
332    pub d: String,
333    pub x: String,
334    pub y: Option<String>,
335}
336
337/// Converts a public key into a DID VerificationMethod
338fn process_key(did: &str, id: &str, public_key: &str) -> Result<DIDVerificationMethod, Error> {
339    let mut properties = BTreeMap::new();
340
341    properties.insert(
342        "publicKeyMultibase".to_string(),
343        Value::String(public_key.to_string()),
344    );
345
346    Ok(DIDVerificationMethod {
347        id: DIDURLBuf::from_string(["did:peer:", did, id].concat()).unwrap(),
348        type_: "Multikey".to_string(),
349        controller: DIDBuf::from_string(["did:peer:", did].concat()).unwrap(),
350        properties,
351    })
352}
353
354impl DIDMethodResolver for DIDPeer {
355    async fn resolve_method_representation<'a>(
356        &'a self,
357        method_specific_id: &'a str,
358        options: Options,
359    ) -> Result<Output<Vec<u8>>, Error> {
360        let did = ["did:peer:", method_specific_id].concat();
361
362        // If did:peer is type 0, then treat it as a did:key
363        if let Some(id) = method_specific_id.strip_prefix('0') {
364            return DIDKey.resolve_method_representation(id, options).await;
365        }
366
367        // Only supports method 2 for did:peer
368        if !method_specific_id.starts_with('2') {
369            return Err(Error::MethodNotSupported(
370                "did:peer version 2 supported only".to_string(),
371            ));
372        }
373
374        let mut context = BTreeMap::new();
375        context.insert("@base".to_string(), serde_json::json!(method_specific_id));
376
377        let mut verification_methods: Vec<DIDVerificationMethod> = Vec::new();
378        let mut verification_relationships: VerificationRelationships =
379            VerificationRelationships::default();
380
381        //let mut key_agreements: Vec<DIDVerificationMethod> = Vec::new();
382        //let mut key_authentications: Vec<DIDVerificationMethod> = Vec::new();
383        //let mut key_assertion_methods: Vec<DIDVerificationMethod> = Vec::new();
384        let mut services: Vec<Service> = Vec::new();
385
386        // Split the DID for peer on '.'s, we skip the first one
387        // did:peer:2.(process from here)
388        let parts: Vec<&str> = method_specific_id[2..].split('.').collect();
389        let mut key_count: u32 = 1;
390        let mut service_idx: u32 = 0;
391
392        for part in parts {
393            let ch = part.chars().next();
394            match ch {
395                Some(e) => {
396                    match e {
397                        'A' => {
398                            // Assertion Method
399                            verification_methods.push(process_key(
400                                method_specific_id,
401                                &["#key-", &key_count.to_string()].concat(),
402                                &part[1..],
403                            )?);
404
405                            verification_relationships.assertion_method.push(
406                                verification_method::ValueOrReference::Reference(
407                                    DIDURLReferenceBuf::Relative(
408                                        RelativeDIDURLBuf::new(
409                                            ["#key-", &key_count.to_string()]
410                                                .concat()
411                                                .as_bytes()
412                                                .to_vec(),
413                                        )
414                                        .unwrap(),
415                                    ),
416                                ),
417                            );
418                            key_count += 1;
419                        }
420                        'D' => {
421                            // Capability Delegation
422                            verification_methods.push(process_key(
423                                method_specific_id,
424                                &["#key-", &key_count.to_string()].concat(),
425                                &part[1..],
426                            )?);
427
428                            verification_relationships.capability_delegation.push(
429                                verification_method::ValueOrReference::Reference(
430                                    DIDURLReferenceBuf::Relative(
431                                        RelativeDIDURLBuf::new(
432                                            ["#key-", &key_count.to_string()]
433                                                .concat()
434                                                .as_bytes()
435                                                .to_vec(),
436                                        )
437                                        .unwrap(),
438                                    ),
439                                ),
440                            );
441                            key_count += 1;
442                        }
443                        'E' => {
444                            // Key Agreement (Encryption)
445                            verification_methods.push(process_key(
446                                method_specific_id,
447                                &["#key-", &key_count.to_string()].concat(),
448                                &part[1..],
449                            )?);
450                            verification_relationships.key_agreement.push(
451                                verification_method::ValueOrReference::Reference(
452                                    DIDURLReferenceBuf::Relative(
453                                        RelativeDIDURLBuf::new(
454                                            ["#key-", &key_count.to_string()]
455                                                .concat()
456                                                .as_bytes()
457                                                .to_vec(),
458                                        )
459                                        .unwrap(),
460                                    ),
461                                ),
462                            );
463                            key_count += 1;
464                        }
465                        'I' => {
466                            // Capability Invocation
467                            verification_methods.push(process_key(
468                                method_specific_id,
469                                &["#key-", &key_count.to_string()].concat(),
470                                &part[1..],
471                            )?);
472
473                            verification_relationships.capability_invocation.push(
474                                verification_method::ValueOrReference::Reference(
475                                    DIDURLReferenceBuf::Relative(
476                                        RelativeDIDURLBuf::new(
477                                            ["#key-", &key_count.to_string()]
478                                                .concat()
479                                                .as_bytes()
480                                                .to_vec(),
481                                        )
482                                        .unwrap(),
483                                    ),
484                                ),
485                            );
486                            key_count += 1;
487                        }
488                        'V' => {
489                            // Authentication (Verification)
490                            verification_methods.push(process_key(
491                                method_specific_id,
492                                &["#key-", &key_count.to_string()].concat(),
493                                &part[1..],
494                            )?);
495
496                            verification_relationships.authentication.push(
497                                verification_method::ValueOrReference::Reference(
498                                    DIDURLReferenceBuf::Relative(
499                                        RelativeDIDURLBuf::new(
500                                            ["#key-", &key_count.to_string()]
501                                                .concat()
502                                                .as_bytes()
503                                                .to_vec(),
504                                        )
505                                        .unwrap(),
506                                    ),
507                                ),
508                            );
509                            verification_relationships.assertion_method.push(
510                                verification_method::ValueOrReference::Reference(
511                                    DIDURLReferenceBuf::Relative(
512                                        RelativeDIDURLBuf::new(
513                                            ["#key-", &key_count.to_string()]
514                                                .concat()
515                                                .as_bytes()
516                                                .to_vec(),
517                                        )
518                                        .unwrap(),
519                                    ),
520                                ),
521                            );
522
523                            key_count += 1;
524                        }
525                        'S' => {
526                            // Service
527                            let service = convert_service(&did, part, service_idx)
528                                .map_err(|e| Error::Internal(e.to_string()))?;
529                            services.push(service);
530                            service_idx += 1;
531                        }
532                        other => {
533                            return Err(Error::RepresentationNotSupported(format!(
534                                "An invalid Purpose Code ({}) was found in the DID",
535                                other
536                            )));
537                        }
538                    }
539                }
540                None => {
541                    // We shouldn't really get here
542                    // But it is ok if we do, we just skip it
543                }
544            }
545        }
546
547        let vm_type = match options.parameters.public_key_format {
548            Some(name) => VerificationMethodType::from_name(&name).ok_or_else(|| {
549                Error::Internal(format!(
550                    "verification method type `{name}` unsupported by did:peer"
551                ))
552            })?,
553            None => VerificationMethodType::Multikey,
554        };
555
556        let mut doc =
557            Document::new(DIDBuf::from_string(["did:peer:", method_specific_id].concat()).unwrap());
558        doc.verification_method = verification_methods;
559        doc.verification_relationships = verification_relationships;
560        doc.service = services;
561
562        let mut json_ld_context = Vec::new();
563        if let Some(context) = vm_type.context_entry() {
564            json_ld_context.push(context)
565        }
566
567        let content_type = options.accept.unwrap_or(MediaType::JsonLd);
568
569        let represented = doc.into_representation(representation::Options::from_media_type(
570            content_type,
571            move || representation::json_ld::Options {
572                context: representation::json_ld::Context::array(
573                    representation::json_ld::DIDContext::V1,
574                    json_ld_context,
575                ),
576            },
577        ));
578
579        Ok(resolution::Output::new(
580            represented.to_bytes(),
581            document::Metadata::default(),
582            resolution::Metadata::from_content_type(Some(content_type.to_string())),
583        ))
584    }
585}
586
587impl DIDMethod for DIDPeer {
588    const DID_METHOD_NAME: &'static str = "peer";
589}
590
591impl DIDPeer {
592    /// Creates a new did:peer DID
593    ///
594    /// This will preserve the order of the keys and services in creating the did:peer string
595    ///
596    /// # Examples
597    /// ```ignore
598    ///
599    /// // Create a did:peer with pre-existing encryption key (Multibase base58-btc e.g: z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK)
600    /// let keys = vec![DIDPeerCreateKeys {
601    ///     type_: Some(DIDPeerKeyType::Ed25519),
602    ///     purpose: DIDPeerKeys::Encryption,
603    ///     public_key_multibase: Some("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK".into()),
604    /// }];
605    /// let did_peer = DIDPeer::create_peer_did(&keys, None).expect("Failed to create did:peer");
606    ///
607    /// // Create a random did:peer with services
608    /// let keys = vec![DIDPeerCreateKeys {
609    ///    type_: Some(DIDPeerKeyType::Secp256k1),
610    ///    purpose: DIDPeerKeys::Encryption,
611    ///    public_key_multibase: Some("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK".into()),
612    ///  }];
613    /// let services: Vec<DIDPeerService> = vec![DIDPeerService {
614    ///    _type: "dm".into(),
615    ///    id: None,
616    ///    service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong {
617    ///        uri: "http://example.com/didcomm".into(),
618    ///        accept: vec!["didcomm/v2".into()],
619    ///        routing_keys: vec!["did:example:123456789abcdefghi#key-1".into()],
620    ///    }),
621    /// }];
622    ///
623    /// let did_peer =
624    ///    DIDPeer::create_peer_did(&keys, Some(&services)).expect("Failed to create did:peer");
625    ///
626    /// // How to create a key prior to creating a did:peer
627    /// let did =
628    ///     DIDKey::generate(&JWK::generate_ed25519().unwrap()).expect("Failed to create did:key");
629    ///
630    /// let keys = vec![DIDPeerCreateKeys {
631    ///     type_: Some(DIDPeerKeyType::Ed25519),
632    ///     purpose: DIDPeerKeys::Verification,
633    ///     public_key_multibase: Some(did[8..].to_string()),
634    /// }];
635    ///
636    /// let did_peer = DIDPeer::create_peer_did(&keys, None).expect("Failed to create did:peer");
637    /// ```
638    pub fn create_peer_did(
639        keys: &Vec<DIDPeerCreateKeys>,
640        services: Option<&Vec<DIDPeerService>>,
641    ) -> Result<(String, Vec<DIDPeerCreatedKeys>), DIDPeerError> {
642        let mut result = String::from("did:peer:2");
643
644        let mut private_keys: Vec<DIDPeerCreatedKeys> = vec![];
645        for key in keys {
646            // Create new keys if not provided
647            let public_key = if let Some(key) = key.public_key_multibase.as_ref() {
648                key.clone()
649            } else {
650                let jwk = match &key.type_ {
651                    Some(type_) => match type_ {
652                        DIDPeerKeyType::Ed25519 => match JWK::generate_ed25519() {
653                            Ok(k) => k,
654                            Err(e) => {
655                                return Err(DIDPeerError::InternalError(format!(
656                                    "Failed to generate ed25519 key. Reason: {}",
657                                    e
658                                )));
659                            }
660                        },
661                        DIDPeerKeyType::Secp256k1 => JWK::generate_secp256k1(),
662                        DIDPeerKeyType::P256 => JWK::generate_p256(),
663                    },
664                    None => return Err(DIDPeerError::UnsupportedKeyType),
665                };
666                let did = if let Ok(output) = ssi::dids::DIDKey::generate(&jwk) {
667                    output.to_string()
668                } else {
669                    return Err(DIDPeerError::InternalError(
670                        "Couldn't create did:key".to_string(),
671                    ));
672                };
673
674                match jwk.params {
675                    Params::OKP(map) => {
676                        let d = if let Some(d) = &map.private_key {
677                            d
678                        } else {
679                            return Err(DIDPeerError::KeyParsingError(
680                                "Missing private key".to_string(),
681                            ));
682                        };
683                        private_keys.push(DIDPeerCreatedKeys {
684                            key_multibase: did[8..].to_string(),
685                            curve: map.curve.clone(),
686                            d: String::from(d),
687                            x: String::from(map.public_key.clone()),
688                            y: None,
689                        })
690                    }
691                    Params::EC(map) => {
692                        let curve = if let Some(curve) = &map.curve {
693                            curve
694                        } else {
695                            return Err(DIDPeerError::KeyParsingError("Missing curve".to_string()));
696                        };
697                        let d = if let Some(d) = &map.ecc_private_key {
698                            d
699                        } else {
700                            return Err(DIDPeerError::KeyParsingError(
701                                "Missing private key".to_string(),
702                            ));
703                        };
704
705                        let x = if let Some(x) = &map.x_coordinate {
706                            x
707                        } else {
708                            return Err(DIDPeerError::KeyParsingError(
709                                "Missing public key (x)".to_string(),
710                            ));
711                        };
712                        let y = if let Some(y) = &map.y_coordinate {
713                            y
714                        } else {
715                            return Err(DIDPeerError::KeyParsingError(
716                                "Missing public key (y)".to_string(),
717                            ));
718                        };
719
720                        private_keys.push(DIDPeerCreatedKeys {
721                            key_multibase: did[8..].to_string(),
722                            curve: curve.into(),
723                            d: String::from(d),
724                            x: String::from(x),
725                            y: Some(String::from(y)),
726                        })
727                    }
728                    _ => return Err(DIDPeerError::UnsupportedKeyType),
729                }
730
731                did[8..].to_string()
732            };
733
734            // Place based on key types
735            match key.purpose {
736                DIDPeerKeys::Verification => {
737                    result.push_str(&format!(".V{}", public_key));
738                }
739                DIDPeerKeys::Encryption => {
740                    result.push_str(&format!(".E{}", public_key));
741                }
742            }
743        }
744
745        if let Some(services) = services {
746            for service in services {
747                let service = serde_json::to_string(&service).map_err(|e| {
748                    DIDPeerError::SyntaxErrorServiceDefinition(format!(
749                        "Error parsing service: {}",
750                        e
751                    ))
752                })?;
753                result.push_str(&format!(".S{}", BASE64_URL_SAFE_NO_PAD.encode(service)));
754            }
755        }
756
757        Ok((result, private_keys))
758    }
759
760    /// Expands an existing DID Document from the did:key Multikeys to full JWT keys
761    /// This is useful for when you want to resolve a did:peer DID Document to a full JWT included DID Document
762    /// Converts base58 multi-keys to full JWTs in verificationMethod
763    pub async fn expand_keys(doc: &Document) -> Result<Document, DIDPeerError> {
764        let mut new_doc = doc.clone();
765
766        let mut new_vms: Vec<DIDVerificationMethod> = vec![];
767        for v_method in &doc.verification_method {
768            new_vms.push(Self::_convert_vm(v_method).await?);
769        }
770
771        new_doc.verification_method = new_vms;
772        Ok(new_doc)
773    }
774
775    // Converts
776    async fn _convert_vm(
777        method: &DIDVerificationMethod,
778    ) -> Result<DIDVerificationMethod, DIDPeerError> {
779        let current_controller = method.controller.clone();
780        let current_id = method.id.clone();
781        let did_key = if let Some(key) = method.properties.get("publicKeyBase58") {
782            ["did:key:", key.as_str().unwrap()].concat()
783        } else if let Some(key) = method.properties.get("publicKeyMultibase") {
784            ["did:key:", key.as_str().unwrap()].concat()
785        } else {
786            return Err(DIDPeerError::KeyParsingError(
787                "Failed to convert verification_method. Reason: Missing publicKeyBase58"
788                    .to_string(),
789            ));
790        };
791
792        let key_method = DIDKey;
793
794        let output = match key_method
795            .dereference_with(
796                DIDURL::new::<String>(&did_key.clone()).unwrap(),
797                Options {
798                    accept: None,
799                    parameters: Parameters {
800                        public_key_format: Some("JsonWebKey2020".to_string()),
801                        ..Default::default()
802                    },
803                },
804            )
805            .await
806        {
807            Ok(output) => output.content,
808            Err(e) => {
809                return Err(DIDPeerError::KeyParsingError(format!(
810                    "Failed to resolve key ({}). Reason: {}",
811                    did_key, e
812                )));
813            }
814        };
815
816        if let Content::Resource(Resource::Document(doc)) = output {
817            if let Some(vm) = doc.into_any_verification_method() {
818                let mut new_vm = vm.clone();
819                new_vm.controller = current_controller;
820                new_vm.id = current_id;
821                return Ok(new_vm);
822            }
823        }
824
825        Err(DIDPeerError::KeyParsingError(
826            "Failed to convert verification_method. Reason: Missing verification_method"
827                .to_string(),
828        ))
829    }
830}
831
832#[cfg(test)]
833mod test {
834    use crate::{
835        DIDPeer, DIDPeerCreateKeys, DIDPeerKeyType, DIDPeerKeys, DIDPeerService,
836        PeerServiceEndPoint, PeerServiceEndPointLong, PeerServiceEndPointLongMap,
837    };
838
839    use ssi::{
840        JWK,
841        dids::{DID, DIDBuf, DIDResolver, document::DIDVerificationMethod},
842        verification_methods::ssi_core::OneOrMany,
843    };
844
845    const DID_PEER: &str = "did:peer:2.Vz6MkiToqovww7vYtxm1xNM15u9JzqzUFZ1k7s7MazYJUyAxv.EzQ3shQLqRUza6AMJFbPuMdvFRFWm1wKviQRnQSC1fScovJN4s.SeyJ0IjoiRElEQ29tbU1lc3NhZ2luZyIsInMiOnsidXJpIjoiaHR0cHM6Ly8xMjcuMC4wLjE6NzAzNyIsImEiOlsiZGlkY29tbS92MiJdLCJyIjpbXX19";
846
847    #[should_panic(
848        expected = "Failed to convert verification_method. Reason: Missing publicKeyBase58"
849    )]
850    #[tokio::test]
851    async fn expand_keys_throws_key_parsing_missing_pbk58_error() {
852        let peer = DIDPeer;
853        let output = peer
854            .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
855            .await
856            .unwrap();
857
858        let mut document = output.document.document().clone();
859        let mut new_vms: Vec<DIDVerificationMethod> = vec![];
860        for mut vm in document.verification_method {
861            vm.properties.remove("publicKeyMultibase");
862            new_vms.push(vm);
863        }
864
865        document.verification_method = new_vms;
866        let _expanded_doc = DIDPeer::expand_keys(&document).await.unwrap();
867    }
868
869    #[tokio::test]
870    async fn expand_keys_works() {
871        let peer = DIDPeer;
872        let document = peer
873            .resolve(DID::new::<String>(&DID_PEER.to_string()).unwrap())
874            .await
875            .expect("Couldn't resolve DID");
876
877        let vm_before_expansion = document.clone().document.verification_method.clone();
878        let expanded_doc = DIDPeer::expand_keys(&document.document).await.unwrap();
879        let vms_after_expansion = expanded_doc.verification_method;
880
881        for vm in vms_after_expansion.clone() {
882            assert!(vm.id.starts_with("did:peer"));
883        }
884        assert_eq!(vm_before_expansion.len(), vms_after_expansion.len())
885    }
886
887    #[tokio::test]
888    async fn create_peer_did_without_keys_and_services() {
889        let keys: Vec<DIDPeerCreateKeys> = vec![];
890        let services: Vec<DIDPeerService> = vec![];
891
892        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
893        let parts: Vec<&str> = did.split(":").collect();
894
895        assert_eq!(parts.len(), 3);
896        assert_eq!(parts[1], "peer");
897        assert!(parts[2].len() == 1);
898    }
899
900    #[tokio::test]
901    async fn create_peer_did_without_keys() {
902        let keys: Vec<DIDPeerCreateKeys> = vec![];
903        let services = vec![DIDPeerService {
904            _type: "dm".into(),
905            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
906                OneOrMany::One(PeerServiceEndPointLongMap {
907                    uri: "https://localhost:7037".into(),
908                    accept: vec!["didcomm/v2".into()],
909                    routing_keys: vec![],
910                }),
911            )),
912            id: None,
913        }];
914
915        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
916        let parts: Vec<&str> = did.split(":").collect();
917        let method_ids: Vec<&str> = parts[2].split(".").collect();
918
919        assert_eq!(parts.len(), 3);
920        assert_eq!(parts[1], "peer");
921        assert!(method_ids.len() > 1);
922        assert!(method_ids[1].len() > 1);
923    }
924
925    #[tokio::test]
926    async fn create_peer_did_without_services() {
927        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
928        let services: Vec<DIDPeerService> = vec![];
929
930        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
931        let parts: Vec<&str> = did.split(":").collect();
932        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
933        method_ids = method_ids[1..].to_vec();
934        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
935
936        method_ids.iter().take(2).for_each(|id| {
937            assert!(keys_multibase.contains(&id[1..].to_string()));
938        });
939        assert_eq!(parts.len(), 3);
940        assert_eq!(parts[1], "peer");
941    }
942
943    #[should_panic(expected = "UnsupportedKeyType")]
944    #[tokio::test]
945    async fn create_peer_did_should_throw_unsupported_key_error_p384() {
946        let (_, _, keys) = _get_keys(None, false);
947        // Create a service definition
948        let services = vec![DIDPeerService {
949            _type: "dm".into(),
950            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
951                OneOrMany::One(PeerServiceEndPointLongMap {
952                    uri: "https://localhost:7037".into(),
953                    accept: vec!["didcomm/v2".into()],
954                    routing_keys: vec![],
955                }),
956            )),
957            id: None,
958        }];
959
960        DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
961    }
962
963    #[tokio::test]
964    async fn create_peer_did_works_ed25519_without_passing_pub_key() {
965        let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), false);
966
967        // Create a service definition
968        let services = vec![DIDPeerService {
969            _type: "dm".into(),
970            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
971                OneOrMany::One(PeerServiceEndPointLongMap {
972                    uri: "https://localhost:7037".into(),
973                    accept: vec!["didcomm/v2".into()],
974                    routing_keys: vec![],
975                }),
976            )),
977            id: None,
978        }];
979
980        let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
981        let parts: Vec<&str> = did.split(":").collect();
982        let method_ids: Vec<&str> = parts[2].split(".").collect();
983
984        assert_eq!(keys.len(), 2);
985        assert_eq!(parts.len(), 3);
986        assert_eq!(parts[1], "peer");
987        assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
988        assert_eq!(method_ids.len(), 4);
989    }
990
991    #[tokio::test]
992    async fn create_peer_did_works_p256_without_passing_pub_key() {
993        let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::P256), false);
994
995        // Create a service definition
996        let services = vec![DIDPeerService {
997            _type: "dm".into(),
998            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
999                OneOrMany::One(PeerServiceEndPointLongMap {
1000                    uri: "https://localhost:7037".into(),
1001                    accept: vec!["didcomm/v2".into()],
1002                    routing_keys: vec![],
1003                }),
1004            )),
1005            id: None,
1006        }];
1007
1008        let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1009        let parts: Vec<&str> = did.split(":").collect();
1010        let method_ids: Vec<&str> = parts[2].split(".").collect();
1011
1012        assert_eq!(keys.len(), 2);
1013        assert_eq!(parts.len(), 3);
1014        assert_eq!(parts[1], "peer");
1015        assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1016        assert_eq!(method_ids.len(), 4);
1017    }
1018
1019    #[tokio::test]
1020    async fn create_peer_did_works_secp256k1_without_passing_pub_key() {
1021        let (_, _, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), false);
1022
1023        // Create a service definition
1024        let services = vec![DIDPeerService {
1025            _type: "dm".into(),
1026            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1027                OneOrMany::One(PeerServiceEndPointLongMap {
1028                    uri: "https://localhost:7037".into(),
1029                    accept: vec!["didcomm/v2".into()],
1030                    routing_keys: vec![],
1031                }),
1032            )),
1033            id: None,
1034        }];
1035
1036        let (did, keys) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1037
1038        let parts: Vec<&str> = did.split(":").collect();
1039        let method_ids: Vec<&str> = parts[2].split(".").collect();
1040
1041        assert_eq!(keys.len(), 2);
1042        assert_eq!(parts.len(), 3);
1043        assert_eq!(parts[1], "peer");
1044        assert_eq!(method_ids.first().unwrap().parse::<i32>().unwrap(), 2);
1045        assert_eq!(method_ids.len(), 4);
1046    }
1047
1048    #[tokio::test]
1049    async fn create_peer_did_works_ed25519() {
1050        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Ed25519), true);
1051
1052        // Create a service definition
1053        let services = vec![DIDPeerService {
1054            _type: "dm".into(),
1055            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1056                OneOrMany::One(PeerServiceEndPointLongMap {
1057                    uri: "https://localhost:7037".into(),
1058                    accept: vec!["didcomm/v2".into()],
1059                    routing_keys: vec![],
1060                }),
1061            )),
1062            id: None,
1063        }];
1064
1065        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1066        let parts: Vec<&str> = did.split(":").collect();
1067        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1068        method_ids = method_ids[1..].to_vec();
1069        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1070
1071        method_ids.iter().take(2).for_each(|id| {
1072            assert!(keys_multibase.contains(&id[1..].to_string()));
1073        });
1074
1075        assert_eq!(parts.len(), 3);
1076        assert_eq!(parts[1], "peer");
1077    }
1078
1079    #[tokio::test]
1080    async fn create_peer_did_works_p256() {
1081        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::P256), true);
1082        // Create a service definition
1083        let services = vec![DIDPeerService {
1084            _type: "dm".into(),
1085            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1086                OneOrMany::One(PeerServiceEndPointLongMap {
1087                    uri: "https://localhost:7037".into(),
1088                    accept: vec!["didcomm/v2".into()],
1089                    routing_keys: vec![],
1090                }),
1091            )),
1092            id: None,
1093        }];
1094
1095        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1096        let parts: Vec<&str> = did.split(":").collect();
1097        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1098        method_ids = method_ids[1..].to_vec();
1099        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1100
1101        method_ids.iter().take(2).for_each(|id| {
1102            assert!(keys_multibase.contains(&id[1..].to_string()));
1103        });
1104        assert_eq!(parts.len(), 3);
1105        assert_eq!(parts[1], "peer");
1106    }
1107
1108    #[tokio::test]
1109    async fn create_peer_did_works_secp256k1() {
1110        let (e_did_key, v_did_key, keys) = _get_keys(Some(DIDPeerKeyType::Secp256k1), true);
1111        // Create a service definition
1112        let services = vec![DIDPeerService {
1113            _type: "dm".into(),
1114            service_end_point: PeerServiceEndPoint::Long(PeerServiceEndPointLong::Map(
1115                OneOrMany::One(PeerServiceEndPointLongMap {
1116                    uri: "https://localhost:7037".into(),
1117                    accept: vec!["didcomm/v2".into()],
1118                    routing_keys: vec![],
1119                }),
1120            )),
1121            id: None,
1122        }];
1123
1124        let (did, _) = DIDPeer::create_peer_did(&keys, Some(&services)).unwrap();
1125        let parts: Vec<&str> = did.split(":").collect();
1126        let mut method_ids: Vec<&str> = parts[2].split(".").collect();
1127        method_ids = method_ids[1..].to_vec();
1128        let keys_multibase = [v_did_key[8..].to_string(), e_did_key[8..].to_string()];
1129
1130        method_ids.iter().take(2).for_each(|id| {
1131            assert!(keys_multibase.contains(&id[1..].to_string()));
1132        });
1133        assert_eq!(parts.len(), 3);
1134        assert_eq!(parts[1], "peer");
1135    }
1136
1137    fn _get_keys(
1138        key_type: Option<DIDPeerKeyType>,
1139        with_pub_key: bool,
1140    ) -> (DIDBuf, DIDBuf, Vec<DIDPeerCreateKeys>) {
1141        let encryption_key = match key_type {
1142            Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1143            Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1144            Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1145            None => JWK::generate_p384(),
1146        };
1147        let verification_key = match key_type {
1148            Some(DIDPeerKeyType::Ed25519) => JWK::generate_ed25519().unwrap(),
1149            Some(DIDPeerKeyType::P256) => JWK::generate_p256(),
1150            Some(DIDPeerKeyType::Secp256k1) => JWK::generate_secp256k1(),
1151            None => JWK::generate_p384(),
1152        };
1153        //  Create the did:key DID's for each key above
1154        let e_did_key = ssi::dids::DIDKey::generate(&encryption_key).unwrap();
1155        let v_did_key = ssi::dids::DIDKey::generate(&verification_key).unwrap();
1156
1157        // Put these keys in order and specify the type of each key (we strip the did:key: from the front)
1158        let keys = vec![
1159            DIDPeerCreateKeys {
1160                purpose: DIDPeerKeys::Verification,
1161                type_: key_type.clone(),
1162                public_key_multibase: if with_pub_key {
1163                    Some(v_did_key[8..].to_string())
1164                } else {
1165                    None
1166                },
1167            },
1168            DIDPeerCreateKeys {
1169                purpose: DIDPeerKeys::Encryption,
1170                type_: key_type.clone(),
1171                public_key_multibase: if with_pub_key {
1172                    Some(e_did_key[8..].to_string())
1173                } else {
1174                    None
1175                },
1176            },
1177        ];
1178
1179        (e_did_key, v_did_key, keys)
1180    }
1181}
1182
1183// **********************************************************************************************************************************
1184// WASM Specific structs and code
1185// **********************************************************************************************************************************
1186
1187/// DIDService structure, input into the DidPeerCreate structure
1188///
1189/// DIDService {
1190///         _type: `Option<String>` (Optional: If not specified, defaults to 'DIDCommMessaging')
1191///           uri: `String`         (Required: Service endpoint URI. E.g. https://localhost:7130/)
1192///        accept: `Vec<String>`    (Array of possible message types this service accepts)
1193///  routing_keys: `Vec<String>`    (Array of possible keys this Service endpoint can use)
1194///            id: `Option<String>` (Optional: ID of the service. If not specified, defaults to #service)
1195/// }
1196#[wasm_bindgen(getter_with_clone)]
1197#[derive(Clone, Serialize, Deserialize)]
1198pub struct DIDService {
1199    pub _type: Option<String>,
1200    pub uri: String,
1201    pub accept: Vec<String>,
1202    pub routing_keys: Vec<String>,
1203    pub id: Option<String>,
1204}
1205
1206#[wasm_bindgen]
1207impl DIDService {
1208    #[wasm_bindgen(constructor)]
1209    pub fn new(
1210        uri: String,
1211        accept: Vec<String>,
1212        routing_keys: Vec<String>,
1213        id: Option<String>,
1214    ) -> Self {
1215        DIDService {
1216            _type: None,
1217            uri,
1218            accept,
1219            routing_keys,
1220            id,
1221        }
1222    }
1223}
1224
1225impl From<DIDService> for DIDPeerService {
1226    fn from(service: DIDService) -> Self {
1227        DIDPeerService {
1228            _type: service._type.unwrap_or("DIDCommMessaging".into()),
1229            service_end_point: PeerServiceEndPoint::Short(PeerServiceEndPointShort::Map(
1230                OneOrMany::One(PeerServiceEndPointShortMap {
1231                    uri: service.uri,
1232                    a: service.accept,
1233                    r: service.routing_keys,
1234                }),
1235            )),
1236            id: service.id,
1237        }
1238    }
1239}
1240
1241impl From<&DIDService> for DIDPeerService {
1242    fn from(service: &DIDService) -> Self {
1243        service.clone().into()
1244    }
1245}
1246
1247/// DidPeerCreate structure,  input from JS into [create_did_peer] call
1248/// Contains the required keys and optional services to create a new did:peer DID
1249///
1250/// DIDPeerCreate {
1251///       keys: Vec<[DIDPeerCreateKeys]> (Required: Must contain at least one key for Encryption and another key for Verification)
1252///   services: Option<Vec<[DIDService]> (Optional: Array of DIDService structs to add to the DID Document)
1253/// }
1254#[derive(Clone)]
1255#[wasm_bindgen(getter_with_clone)]
1256pub struct DidPeerCreate {
1257    pub keys: Vec<DIDPeerCreateKeys>,
1258    pub services: Option<Vec<DIDService>>,
1259}
1260
1261#[wasm_bindgen]
1262impl DidPeerCreate {
1263    #[wasm_bindgen(constructor)]
1264    pub fn new(keys: Vec<DIDPeerCreateKeys>, services: Option<Vec<DIDService>>) -> Self {
1265        DidPeerCreate { keys, services }
1266    }
1267}
1268
1269#[derive(Serialize, Deserialize)]
1270#[wasm_bindgen(getter_with_clone)]
1271pub struct DIDPeerResult {
1272    pub did: String,
1273    pub keys: Vec<DIDPeerCreatedKeys>,
1274}
1275
1276#[wasm_bindgen]
1277/// create_did_peer() wasm wrapper for [DIDPeer::create_peer_did]
1278/// Input: reference to [DidPeerCreate] struct
1279/// Returns: Error or String of the newly created did:peer DID
1280///
1281/// Notes:
1282///   [DidPeerCreate] contains an array of keys and an optional array of Services
1283///   These arrays are processed in order (as in element 0 is processed first, then element 1, etc)
1284///   This means the key and service identifiers are auto-generated in the order they are provided
1285///   i.e. #service, #service-1, #service-2 and #key-1, #key-2, #key-3 ...
1286pub fn create_did_peer(input: &DidPeerCreate) -> Result<DIDPeerResult, DIDPeerError> {
1287    // Convert DIDService to DIDPeerService
1288    let mut new_services: Vec<DIDPeerService> = vec![];
1289    if let Some(services) = input.services.as_ref() {
1290        for service in services {
1291            new_services.push(service.into());
1292        }
1293    }
1294
1295    // Create the did:peer DID
1296    let response = DIDPeer::create_peer_did(&input.keys, Some(&new_services));
1297
1298    if let Ok((did, keys)) = response {
1299        Ok(DIDPeerResult { did, keys })
1300    } else {
1301        Err(response.unwrap_err())
1302    }
1303}
1304
1305#[wasm_bindgen]
1306/// resolve_did_peer() resolves a DID Peer method DID to a full DID Document represented by a JS object
1307/// Input: String of the DID Peer method DID (did:peer:2...)
1308/// Returns: Error or JSON String of the resolved DID Document
1309///
1310/// NOTE: This is an async call, so you must await the result
1311pub async fn resolve_did_peer(did: &str) -> Result<String, DIDPeerError> {
1312    let peer = DIDPeer;
1313
1314    match peer
1315        .resolve(DID::new::<String>(&did.to_string()).unwrap())
1316        .await
1317    {
1318        Ok(output) => match serde_json::to_string_pretty(&output.document) {
1319            Ok(json) => Ok(json),
1320            Err(e) => Err(DIDPeerError::JsonParsingError(format!(
1321                "Couldn't convert DID Document to JSON. Reason: {}",
1322                e
1323            ))),
1324        },
1325        Err(e) => Err(DIDPeerError::KeyParsingError(format!(
1326            "Failed to resolve key ({}). Reason: {}",
1327            did, e
1328        ))),
1329    }
1330}