From aae4c2436c453faddf94f376cfdc8566c2d939e3 Mon Sep 17 00:00:00 2001 From: w3irdrobot Date: Sat, 16 Sep 2023 14:02:26 -0400 Subject: [PATCH] add extra nip11 fields --- crates/nostr/src/nips/nip11.rs | 142 +++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/crates/nostr/src/nips/nip11.rs b/crates/nostr/src/nips/nip11.rs index 982817c5a..11ac985f5 100644 --- a/crates/nostr/src/nips/nip11.rs +++ b/crates/nostr/src/nips/nip11.rs @@ -16,6 +16,8 @@ use std::net::SocketAddr; use reqwest::Proxy; use url_fork::Url; +use crate::types::time::Timestamp; + /// `NIP11` error #[derive(Debug)] pub enum Error { @@ -69,6 +71,113 @@ pub struct RelayInformationDocument { pub software: Option, /// Software version pub version: Option, + /// Limitations imposed by the relay on clients + pub limitation: Option, + /// The relay's retention policies + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub retention: Vec, + /// Country codes whose laws and policies may affect this relay + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub relay_countries: Vec, + /// Ordered list of IETF language tags indicating the major languages spoken on the relay + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub language_tags: Vec, + /// List of limitations on the topics to be discussed + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub tags: Vec, + /// Link to a human-readable page which specifies the community policies + pub posting_policy: Option, + /// Link to relay's fee schedules + pub payments_url: Option, + /// Relay fee schedules + pub fees: Option, + /// URL pointing to an image to be used as an icon for the relay + pub icon: Option, +} + +/// These are limitations imposed by the relay on clients. Your client should +/// expect that requests which exceed these practical limitations are rejected or fail immediately. +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub struct Limitation { + /// Maximum number of bytes for incoming JSON that the relay will attempt to decode and act upon + pub max_message_length: Option, + /// Total number of subscriptions that may be active on a single websocket connection + pub max_subscriptions: Option, + /// Maximum number of filter values in each subscription + pub max_filters: Option, + /// Relay will clamp each filter's limit value to this number + pub max_limit: Option, + /// Maximum length of subscription id as a string + pub max_subid_length: Option, + /// Maximum number of elements in the tags list + pub max_event_tags: Option, + /// Maximum number of characters in the content field of any event + pub max_content_length: Option, + /// New events will require at least this difficulty of PoW, + pub min_pow_difficulty: Option, + /// Relay requires NIP-42 authentication to happen before a new connection may perform any other action + pub auth_required: Option, + /// Relay requires payment before a new connection may perform any action + pub payment_required: Option, + /// 'created_at' lower limit + pub created_at_lower_limit: Option, + /// 'created_at' upper limit + pub created_at_upper_limit: Option, +} + +/// A retention shedule for the relay +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub struct Retention { + /// The event kinds this retention pertains to + pub kinds: Option>, + /// The amount of time these events are kept + pub time: Option, + /// The max number of events kept before removing older events + pub count: Option, +} + +/// A single kind or range of kinds the retention pertains to +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[serde(untagged)] +pub enum RetentionKind { + /// A single kind + Single(u64), + /// A kind range + Range(u64, u64), +} + +/// Available fee schedules +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub struct FeeSchedules { + /// Fees for admission to use the relay + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub admission: Vec, + /// Fees for subscription to use the relay + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub subscription: Vec, + /// Fees to publish to the relay + #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default)] + pub publication: Vec, +} + +/// The specific information about a fee schedule +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +pub struct FeeSchedule { + /// The fee amount + pub amount: i32, + /// The denomination of the feed + pub unit: String, + /// The duration for which the fee is valid + pub period: Option, + /// The event kinds the fee allows the client to publish to the relay + pub kinds: Option>, } impl RelayInformationDocument { @@ -157,3 +266,36 @@ impl RelayInformationDocument { Ok(url) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn correctly_serializes_retention_kind() { + let kinds = vec![ + RetentionKind::Single(0), + RetentionKind::Single(1), + RetentionKind::Range(5, 7), + RetentionKind::Range(40, 49), + ]; + let got = serde_json::to_string(&kinds).unwrap(); + let expected = "[0,1,[5,7],[40,49]]".to_string(); + + assert!(got == expected, "got: {}, expected: {}", got, expected); + } + + #[test] + fn correctly_deserializes_retention_kind() { + let kinds = "[0, 1, [5, 7], [40, 49]]"; + let got = serde_json::from_str::>(kinds).unwrap(); + let expected = vec![ + RetentionKind::Single(0), + RetentionKind::Single(1), + RetentionKind::Range(5, 7), + RetentionKind::Range(40, 49), + ]; + + assert!(got == expected, "got: {:?}, expected: {:?}", got, expected); + } +}