# 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 computationally expensive relay meta-data from active relays as events on nostr. ## Personas - **Publishers** generate and push `30303` events. Events **should** be published at a regular interval. Events **must** implement `NIP-40`. - **Consumers** aggregate `30303` for insight on relays. Some example consumers are a social client or relay status client. ## schema ### `event.tags` Relay status events have **two** (2) required tags and **eight** (8) optional tags. Relay status events introduce **one** (1) new indexable tag (NIP-12) 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. ```json ["d", "wss://history.nostr.watch/"] //tagId[] ``` 2. `"expiration" == tagExpiration[0]` [NIP-40]. The `tagExpiration[]` tag **must** be included in the `event.tags[]` array. `tagExpiration[1]` **should** be set to a future timestamp (seconds) that correlates with the publisher's intended update frequency. ```json ["expiration", "1600000000"] //tagExpiration[] ``` 3. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be a string. There **should** be no more than **fifty (50)** `tagTopic[]` arrays. ```json ["t", "bitcoin"] //tagTopic[] ``` 4. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string. `tagGeo[2]` **must** be a string and **should** be a label that describes `tagGeo[1]`. There **may** be more than **one (1)** `tagGeo[]` per event. ```json ["g","ww8p1r4t8","geohash"], ["g","NL","countryCode"], ["g","EU","continent"], ["g","Earth","planet"] ``` 5. `"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` ```json ["read", "true"] //tagRead[] ``` 6. `"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` ```json ["write", "false"] //tagWrite[] ``` 7. `"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` ```json ["ssl", "true"] //tagSsl[] ``` 8. `"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[]`. ```json ["ip", "1.1.1.1"], //tagIp[] ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] ``` 9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** be no more than **one (1)** `tagEvents[]` ```json ["events", "502341"], //tagEvents[] ``` 10. `"users" == tagUsers[0]` Number of users on relay. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` ```json ["users","37482"] //tagUsers[] ``` Example with Minimum Requirements, "Relay is online" ```json { "id": "", "pubkey": "", "created_at": "", "signature": "", "content": "", "tags": [ ["d","wss://relay.snort.social/"], ["expiration", "1600000000"] ] } ``` Example with all Tags, "Relay is online and here's some data" ```json { "id": "", "pubkey": "", "created_at": "", "signature": "", "content": "{}", "tags": [ ["d","wss://some.relay/"], ["expiration", "1600000000"], ["t","nostrica"], ["t","bitcoin"], ["g","ww8p1r4t8","geohash"], ["g","NL","countryCode"], ["g","EU","continent"], ["g","Earth","planet"], ["ip","1.1.1.1"], ["ip","2001:db8:3333:4444:5555:6666:7777:8888"], ["read","true"], ["write","false"], ["ssl","true"], ["events", "502341"], ["users","37482"] ] } ``` ### `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. Where accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers**. **IP** data is for informational purposes only. ## Use Cases - Aggregate relays quickly using an implementation pattern native to nostr. - 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 - Relays self-report statuses and/or metadata in `.content` signed by their NIP-11 `pubkey`.