nostr_types/versioned/
nip05.rs

1use crate::types::{PublicKeyHex, UncheckedUrl};
2use serde::{Deserialize, Serialize};
3#[cfg(feature = "speedy")]
4use speedy::{Readable, Writable};
5use std::collections::HashMap;
6
7/// The content of a webserver's /.well-known/nostr.json file used in NIP-05 and NIP-35
8/// This allows lookup and verification of a nostr user via a `user@domain` style identifier.
9#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
10#[cfg_attr(feature = "speedy", derive(Readable, Writable))]
11pub struct Nip05V1 {
12    /// DNS names mapped to public keys
13    pub names: HashMap<String, PublicKeyHex>,
14
15    /// Public keys mapped to arrays of relays where they post
16    #[serde(skip_serializing_if = "HashMap::is_empty")]
17    #[serde(default)]
18    pub relays: HashMap<PublicKeyHex, Vec<UncheckedUrl>>,
19}
20
21impl Nip05V1 {
22    // Mock data for testing
23    #[allow(dead_code)]
24    pub(crate) fn mock() -> Nip05V1 {
25        let pubkey = PublicKeyHex::try_from_str(
26            "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9",
27        )
28        .unwrap();
29
30        let mut names: HashMap<String, PublicKeyHex> = HashMap::new();
31        let _ = names.insert("bob".to_string(), pubkey.clone());
32
33        let mut relays: HashMap<PublicKeyHex, Vec<UncheckedUrl>> = HashMap::new();
34        let _ = relays.insert(
35            pubkey,
36            vec![
37                UncheckedUrl::from_str("wss://relay.example.com"),
38                UncheckedUrl::from_str("wss://relay2.example.com"),
39            ],
40        );
41
42        Nip05V1 { names, relays }
43    }
44}
45
46#[cfg(test)]
47mod test {
48    use super::*;
49
50    test_serde! {Nip05V1, test_nip05_serde}
51
52    #[test]
53    fn test_nip05_example() {
54        let body = r#"{
55  "names": {
56    "bob": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
57  },
58  "relays": {
59    "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": [ "wss://relay.example.com", "wss://relay2.example.com" ]
60  }
61}"#;
62
63        let nip05: Nip05V1 = serde_json::from_str(body).unwrap();
64
65        let bobs_pk: PublicKeyHex = nip05.names.get("bob").unwrap().clone();
66        assert_eq!(
67            bobs_pk.as_str(),
68            "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
69        );
70
71        let bobs_relays: Vec<UncheckedUrl> = nip05.relays.get(&bobs_pk).unwrap().to_owned();
72
73        assert_eq!(
74            bobs_relays,
75            vec![
76                UncheckedUrl::from_str("wss://relay.example.com"),
77                UncheckedUrl::from_str("wss://relay2.example.com")
78            ]
79        );
80    }
81}