nips/59.md

5.7 KiB

NIP-59: Relay Status

draft optional author:dskvr

This NIP defines 30303, a parameterized replaceable event [NIP-33], referred to as Relay Statuses. Relay Statuses use tags extensively and may have .content populated with Stringified JSON.

Purpose

To store relay meta-data and the result of subjective checks as queryable [NIP-12] events on nostr.

Personas

  • Publishers generate and push 30303 events. Events should be published at a regular interval. Events may be stale.
  • Consumers aggregate 30303 for insight on relays. Some example consumers are a social client or relay status client.

schema

event.created_at

created_at should be interpreted by consumers as updated_at

event.tags

Relay status events have one (1) required tags and nine (9) optional tags.

The tags should be used to represent the Relay's abilities and meta at a point in time. Below the tags schema is expressed using pseudo-types for reasons of communication and brevity, for example tagDescriptor[].

  1. "d" == tagId[0] The relay URL. The #d tag must be included in the event.tags[] array. tagId[1] must be the relay websocket URL. The URL should be normalized.
["d", "wss://history.nostr.watch/"] //tagId[]
  1. "t" == tagTopic[0] Topics relevant to the relay. tagTopic[] may be included in the event.tags[] array. tagTopic[1] should be string. There should be no more than twenty (20) tagTopic[] arrays.
["t", "bitcoin"]  //tagTopic[]
  1. "g" == tagGeo[0] Relay Geo Data. tagGeo[] may be included in the event.tags[] array. tagGeo[1] must be string and should be a geohash. There may be strings defined in the key range 2+ (tagGeo[2...]) and they must be strings if set. tagGeo[] items should be descending by precision. There should be no more than one (1) tagGeo[] per event.
["g", "ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth", "Sol", "Milky Way"] //tagGeo[]
  1. "online" == tagOnline[0] Is the relay online. tagOnline[] may be included in the event.tags[] array. tagOnline[1] must be type string as exactly true or false
["online", "true"]     //tagOnline[]
  1. "read" == tagRead[0] Was able to read from the relay. tagRead[] may be included in the event.tags[] array. tagRead[1] must be type string as exactly true or false
["read", "true"]     //tagRead[]
  1. "write" == tagWrite[0] Was able to write to the relay. tagWrite[] may be included in the event.tags[] array. tagWrite[1] must be type string as exactly true or false
["write", "false"]    //tagWrite[]
  1. "ssl" == tagSsl[0] Is the relay's SSL valid. tagSsl[] may be included in the event.tags[] array. tagSsl[1] must be type string as exactly true or false
["ssl", "true"]     //tagSsl[]
  1. "ip" == tagIp[0] Relay IP. tagIp[] may be included in the event.tags[] array. tagIp[1] must be string. There may be more than one (1) tagIp[]
["ip", "1.1.1.1"],  //tagIp[]
["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[]
  1. "events" == tagEvents[0] Number of events on relay. tagEvents[] may be included in the event.tags[] array. tagEvents[1] must be string. There should only be one (1) tagEvents[]
["events", "502341"],  //tagIp[]
  1. "users" == tagUsers[0] Relay IP. tagUsers[] may be included in the event.tags[] array. tagUsers[1] must be string. There should be no more than one (1) tagUsers[]
["users","37482"]

Example with Minimum Requirements:

{
  "id": "<eventid>",
  "pubkey": "<pubkey>",
  "created_at": "<created_at>",
  "signature": "<signature>",
  "content": "",
  "tags": [  
    ["d","wss://relay.snort.social/"]
  ]
}

Example with all Tags:

{
  "id": "<eventid>",
  "pubkey": "<pubkey>",
  "created_at": "<created_at>",
  "signature": "<signature>",
  "content": "{}",
  "tags": [  
    ["d","wss://some.relay/"],
    ["t","nostrica"],
    ["t","bitcoin"],
    ["g","ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth"],
    ["ip", "1.1.1.1"],
    ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"]
    ["open","true"],
    ["read","true"],
    ["write","false"],
    ["ssl","true"]
  ]
}

event.content optional

The .content of these events may be empty. .content may contain stringified JSON. The parsed JSON has a flexible schema, all members are optional. The parsed .content JSON should be extended by NIPs.

Testing Criteria

The testing criteria to determine conditions defined in event's tags may be subjective and may vary between publishers.

Consumption

The data in 30303 may be erroneous, intentionally or otherwise. When accuracy is required, the data in 30303 events should be subscribed to by populating the authors filter array with the pubkeys of trusted publishers

Use Cases

  • Aggregate relays quickly.
  • A lite social client identifies relays that were recently reported to be online without client-side tests
  • A social client may find relays where a particular topic is popular.
  • A social client may find relays based on their geographic proximity
  • A status client shows relay statuses
  • Identify macro-patterns amongst relays.
  • Relays self-report statuses and/or metadata in .content signed by their NIP-11 pubkey.
  • Could be used to store user checks for a relay to express personalized policies. For example, a user's pubkey was blacklisted on a relay, so they were unable to write: ..., tags: { [ ["d","wss://relay.damus.io"], ["o","true"], ["w","false"] ] }, ....