did_utils/methods/peer/
resolver.rs

1use async_trait::async_trait;
2
3use super::method::DidPeer;
4use crate::{
5    ldmodel::Context,
6    methods::{
7        errors::DIDResolutionError,
8        resolution::{DIDResolutionMetadata, DIDResolutionOptions, MediaType, ResolutionOutput},
9        traits::DIDResolver,
10    },
11};
12
13#[async_trait]
14impl DIDResolver for DidPeer {
15    /// Resolves a DID address into its corresponding DID document.
16    async fn resolve(&self, did: &str, _options: &DIDResolutionOptions) -> ResolutionOutput {
17        let context = Context::SingleString(String::from("https://w3id.org/did-resolution/v1"));
18
19        match self.expand(did) {
20            Ok(diddoc) => ResolutionOutput {
21                context,
22                did_document: Some(diddoc),
23                did_resolution_metadata: Some(DIDResolutionMetadata {
24                    error: None,
25                    content_type: Some(MediaType::DidLdJson.to_string()),
26                    additional_properties: None,
27                }),
28                did_document_metadata: None,
29                additional_properties: None,
30            },
31            Err(err) => ResolutionOutput {
32                context,
33                did_document: None,
34                did_resolution_metadata: Some(DIDResolutionMetadata {
35                    error: Some(if !did.starts_with("did:peer:") {
36                        DIDResolutionError::MethodNotSupported
37                    } else {
38                        err.into()
39                    }),
40                    content_type: None,
41                    additional_properties: None,
42                }),
43                did_document_metadata: None,
44                additional_properties: None,
45            },
46        }
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53    use serde_json::Value;
54
55    #[async_std::test]
56    async fn test_did_peer_resolution() {
57        let did_method = DidPeer::new();
58
59        let did = "did:peer:0z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
60        let expected: Value = serde_json::from_str(
61            r##"{
62                "@context": "https://w3id.org/did-resolution/v1",
63                "didDocument": {
64                    "@context": [
65                        "https://www.w3.org/ns/did/v1",
66                        "https://w3id.org/security/multikey/v1"
67                    ],
68                    "id": "did:peer:0z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
69                    "verificationMethod": [
70                        {
71                            "id": "#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
72                            "type": "Multikey",
73                            "controller": "did:peer:0z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
74                            "publicKeyMultibase": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
75                        },
76                        {
77                            "id": "#z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p",
78                            "type": "Multikey",
79                            "controller": "did:peer:0z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
80                            "publicKeyMultibase": "z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p"
81                        }
82                    ],
83                    "authentication": ["#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"],
84                    "assertionMethod": ["#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"],
85                    "capabilityDelegation": ["#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"],
86                    "capabilityInvocation": ["#z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"],
87                    "keyAgreement": ["#z6LSj72tK8brWgZja8NLRwPigth2T9QRiG1uH9oKZuKjdh9p"]
88                },
89                "didResolutionMetadata": {
90                    "contentType": "application/did+ld+json"
91                },
92                "didDocumentMetadata": null
93            }"##,
94        )
95        .unwrap();
96
97        let output = did_method.resolve(did, &DIDResolutionOptions::default()).await;
98        assert_eq!(
99            json_canon::to_string(&output).unwrap(),   //
100            json_canon::to_string(&expected).unwrap(), //
101        );
102    }
103
104    #[async_std::test]
105    async fn test_did_peer_resolution_fails_on_invalid_did() {
106        let did_method = DidPeer::new();
107        let did = concat!(
108            "did:peer:2",
109            ".Vz6Mkj3PUd1WjvaDhNZhhhXQdz5UnZXmS7ehtx8bsPpD47kKc",
110            // {"s":"http://example.com/xyz","t":"dm" (missing closing brace)
111            ".SeyJzIjoiaHR0cDovL2V4YW1wbGUuY29tL3h5eiIsInQiOiJkbSI",
112        );
113
114        let expected: Value = serde_json::from_str(
115            r#"{
116                "@context": "https://w3id.org/did-resolution/v1",
117                "didDocument": null,
118                "didResolutionMetadata": {
119                    "error": "invalidDid"
120                },
121                "didDocumentMetadata": null
122            }"#,
123        )
124        .unwrap();
125
126        let output = did_method.resolve(did, &DIDResolutionOptions::default()).await;
127        assert_eq!(
128            json_canon::to_string(&output).unwrap(),   //
129            json_canon::to_string(&expected).unwrap(), //
130        );
131    }
132
133    #[async_std::test]
134    async fn test_did_peer_resolution_fails_on_unsupported_peer_did_submethod() {
135        let did_method = DidPeer::new();
136        let did = "did:peer:1zQmbEB1EqP7PnNVaHiSpXhkatAA6kNyQK9mWkvrMx2eckgq";
137
138        let expected: Value = serde_json::from_str(
139            r#"{
140                "@context": "https://w3id.org/did-resolution/v1",
141                "didDocument": null,
142                "didResolutionMetadata": {
143                    "error": "methodNotSupported"
144                },
145                "didDocumentMetadata": null
146            }"#,
147        )
148        .unwrap();
149
150        let output = did_method.resolve(did, &DIDResolutionOptions::default()).await;
151        assert_eq!(
152            json_canon::to_string(&output).unwrap(),   //
153            json_canon::to_string(&expected).unwrap(), //
154        );
155    }
156}