mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-22 08:25:53 -05:00
migrate nips from main nostr repo.
This commit is contained in:
commit
f25c7e672c
107
01.md
Normal file
107
01.md
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
NIP-01
|
||||||
|
======
|
||||||
|
|
||||||
|
Basic protocol flow description
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
`draft` `mandatory` `author:fiatjaf` `author:distbit` `author:scsibug` `author:kukks`
|
||||||
|
|
||||||
|
This NIP defines the basic protocol that should be implemented by everybody. New NIPs may add new optional (or mandatory) fields and messages and features to the structures and flows described here.
|
||||||
|
|
||||||
|
## Events and signatures
|
||||||
|
|
||||||
|
Each user has a keypair. Signatures, public key and encodings are done according to the [Schnorr signatures standard for the curve `secp256k1`](https://bips.xyz/340).
|
||||||
|
|
||||||
|
The only object type that exists is the `event`, which has the following format on the wire:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"id": <32-bytes sha256 of the the serialized event data>
|
||||||
|
"pubkey": <32-bytes hex-encoded public key of the event creator>,
|
||||||
|
"created_at": <unix timestamp in seconds>,
|
||||||
|
"kind": <integer>,
|
||||||
|
"tags": [
|
||||||
|
["e", <32-bytes hex of the id of another event>, <recommended relay URL>],
|
||||||
|
["p", <32-bytes hex of the key>, <recommended relay URL>],
|
||||||
|
... // other kinds of tags may be included later
|
||||||
|
]
|
||||||
|
"content": <arbitrary string>,
|
||||||
|
"sig": <64-bytes signature of the sha256 hash of the serialized event data, which is the same as the "id" field>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no indentation or extra spaces) of the following structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
<pubkey, as a (lowercase) hex string>,
|
||||||
|
<created_at, as a number>,
|
||||||
|
<kind, as a number>,
|
||||||
|
<tags, as an array of arrays of strings>,
|
||||||
|
<content, as a string>
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Communication between clients and relays
|
||||||
|
|
||||||
|
Relays expose a websocket endpoint to which clients can connect.
|
||||||
|
|
||||||
|
### From client to relay: sending events and creating subscriptions
|
||||||
|
|
||||||
|
Clients can send 3 types of messages, which must be JSON arrays, according to the following patterns:
|
||||||
|
|
||||||
|
* `["EVENT", <event JSON as defined above>`], used to publish events.
|
||||||
|
* `["REQ", <subscription_id>, <filters JSON>...`], used to request events and subscribe to new updates.
|
||||||
|
* `["CLOSE", <subscription_id>]`, used to stop previous subscriptions.
|
||||||
|
|
||||||
|
`<subscription_id>` is a random string that should be used to represent a subscription.
|
||||||
|
|
||||||
|
`<filters>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"ids": <a list of event ids or prefixes>,
|
||||||
|
"kinds": <a list of a kind numbers>,
|
||||||
|
"#e": <a list of event ids that are referenced in an "e" tag>,
|
||||||
|
"#p": <a list of pubkeys that are referenced in a "p" tag>,
|
||||||
|
"since": <a timestamp, events must be newer than this to pass>,
|
||||||
|
"until": <a timestamp, events must be older than this to pass>,
|
||||||
|
"authors": <a list of pubkeys or prefixes, the pubkey of an event must be one of these>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Upon receiving a `REQ` message, the relay MUST query its internal database and return events that match the filter, then store that filter and send again all future events it receives to that same websocket until the websocket is closed. The `CLOSE` event is received with the same `<subscription_id>` or a new `REQ` is sent using the same `<subscription_id>`, in which case it should overwrite the previous subscription.
|
||||||
|
|
||||||
|
Filter attributes containing lists (such as `ids`, `kinds`, or `#e`) are JSON arrays with one or more values. At least one of the array's values must match the relevant field in an event for the condition itself to be considered a match. For scalar event attributes such as `kind`, the attribute from the event must be contained in the filter list. For tag attributes such as `#e`, where an event may have multiple values, the event and filter condition values must have at least one item in common.
|
||||||
|
|
||||||
|
The `ids` and `authors` lists contain lowercase hexadecimal strings, which may either be an exact 64-character match, or a prefix of the event value. A prefix match is when the filter string is an exact string prefix of the event value. The use of prefixes allows for more compact filters where a large number of values are queried, and can provide some privacy for clients that may not want to disclose the exact authors or events they are searching for.
|
||||||
|
|
||||||
|
All conditions of a filter that are specified must match for an event for it to pass the filter, i.e., multiple conditions are interpreted as `&&` conditions.
|
||||||
|
|
||||||
|
A `REQ` message may contain multiple filters. In this case events that match any of the filters are to be returned, i.e., multiple filters are to be interpreted as `||` conditions.
|
||||||
|
|
||||||
|
### From relay to client: sending events and notices
|
||||||
|
|
||||||
|
Relays can send 2 types of messages, which must also be JSON arrays, according to the following patterns:
|
||||||
|
|
||||||
|
* `["EVENT", <subscription_id>, <event JSON as defined above>]`, used to send events requested by clients.
|
||||||
|
* `["NOTICE", <message>]`, used to send human-readable error messages or other things to clients.
|
||||||
|
|
||||||
|
This NIP defines no rules for how `NOTICE` messages should be sent or treated.
|
||||||
|
|
||||||
|
`EVENT` messages MUST be sent only with a subscription ID related to a subscription previously initiated by the client (using the `REQ` message above).
|
||||||
|
|
||||||
|
## Basic Event Kinds
|
||||||
|
|
||||||
|
- `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: <string>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey.
|
||||||
|
- `1`: `text_note`: the `content` is set to the text content of a note (anything the user wants to say).
|
||||||
|
- `2`: `recommend_server`: the `content` is set to the URL (e.g., `https://somerelay.com`) of a relay the event creator wants to recommend to its followers.
|
||||||
|
|
||||||
|
A relay may choose to treat different message kinds differently, and it may or may not choose to have a default way to handle kinds it doesn't know about.
|
||||||
|
|
||||||
|
## Other Notes:
|
||||||
|
|
||||||
|
- Clients should not open more than one websocket to each relay. It also is advised that clients do not open more than 3 subscriptions to the same relay. 3 is enough for most use cases and relays should impose limits to prevent over usage by clients.
|
||||||
|
- The `tags` array can store a tag identifier as the first element of each subarray, plus arbitrary information afterwards (always as strings). This NIP defines `"p"` — meaning "pubkey", which points to a pubkey of someone that is referred to in the event —, and `"e"` — meaning "event", which points to the id of an event this event is quoting, replying to or referring to somehow.
|
||||||
|
- The `<recommended relay URL>` item present on the `"e"` and `"p"` tags is an optional (could be set to `""`) URL of a relay the client could attempt to connect to fetch the tagged event or other events from a tagged profile. It MAY be ignored, but it exists to increase censorship resistance and make the spread of relay addresses more seamless across clients.
|
73
02.md
Normal file
73
02.md
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
NIP-02
|
||||||
|
======
|
||||||
|
|
||||||
|
Contact List and Petnames
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:fiatjaf` `author:arcbtc`
|
||||||
|
|
||||||
|
A special event with kind `3`, meaning "contact list" is defined as having a list of `p` tags, one for each of the followed/known profiles one is following.
|
||||||
|
|
||||||
|
Each tag entry should contain the key for the profile, a relay URL where events from that key can be found (can be set to `null` or a invalid string if not needed), and a local name (or "petname") for that profile (can also be set to `null`), i.e., `["p", <32-bytes hex key>, <main relay URL>, <petname>]`. The `content` can be anything and should be ignored.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": 3,
|
||||||
|
"tags": [
|
||||||
|
["p", "91cf9..4e5ca", "wss://alicerelay.com/", "alice"],
|
||||||
|
["p", "14aeb..8dad4", "wss://bobrelay.com/nostr", "bob"],
|
||||||
|
["p", "612ae..e610f", "ws://carolrelay.com/ws", "carol"]
|
||||||
|
],
|
||||||
|
"content": "",
|
||||||
|
...other fields
|
||||||
|
```
|
||||||
|
|
||||||
|
Every new contact list that gets published overwrites the past ones, so it should contain all entries. Relays and clients SHOULD delete past contact lists as soon as they receive a new one.
|
||||||
|
|
||||||
|
## Uses
|
||||||
|
|
||||||
|
### Contact list backup
|
||||||
|
|
||||||
|
If one believes a relay will store their events for sufficient time, they can use this kind-3 event to backup their following list and recover on a different device.
|
||||||
|
|
||||||
|
### Profile discovery and context augmentation
|
||||||
|
|
||||||
|
A client may rely on the kind-3 event to display a list of followed people by profiles one is browsing; make lists of suggestions on who to follow based on the contact lists of other people one might be following or browsing; or show the data in other contexts.
|
||||||
|
|
||||||
|
### Relay sharing
|
||||||
|
|
||||||
|
A client may publish a full list of contacts with good relays for each of their contacts so other clients may use these to update their internal relay lists if needed, increasing censorship-resistant.
|
||||||
|
|
||||||
|
### Petname scheme
|
||||||
|
|
||||||
|
The data from these contact lists can be used by clients to construct local ["petname"](http://www.skyhunter.com/marcs/petnames/IntroPetNames.html) tables derived from other people's contact lists. This alleviates the need for global human-readable names. For example:
|
||||||
|
|
||||||
|
A user has an internal contact list that says
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
["p", "21df6d143fb96c2ec9d63726bf9edc71", null, "erin"]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
And receives two contact lists, one from `21df6d143fb96c2ec9d63726bf9edc71` that says
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
["p", "a8bb3d884d5d90b413d9891fe4c4e46d", null, "david"]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
and another from `a8bb3d884d5d90b413d9891fe4c4e46d` that says
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
["p", "f57f54057d2a7af0efecc8b0b66f5708", null, "frank"]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
When the user sees `21df6d143fb96c2ec9d63726bf9edc71` the client can show _erin_ instead;
|
||||||
|
When the user sees `a8bb3d884d5d90b413d9891fe4c4e46d` the client can show _david.erin_ instead;
|
||||||
|
When the user sees `f57f54057d2a7af0efecc8b0b66f5708` the client can show _frank.david.erin_ instead.
|
23
03.md
Normal file
23
03.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
NIP-03
|
||||||
|
======
|
||||||
|
|
||||||
|
OpenTimestamps Attestations for Events
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:fiatjaf`
|
||||||
|
|
||||||
|
When there is an OTS available it MAY be included in the existing event body under the `ots` key:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
id: ...,
|
||||||
|
kind: ...,
|
||||||
|
...,
|
||||||
|
...,
|
||||||
|
ots: <base64-encoded OTS file data>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The _event id_ MUST be used as the raw hash to be included in the OpenTimestamps merkle tree.
|
||||||
|
|
||||||
|
The attestation can be either provided by relays automatically (and the OTS binary contents just appended to the events it receives) or by clients themselves when they first upload the event to relays — and used by clients to show that an event is really "at least as old as [OTS date]".
|
43
04.md
Normal file
43
04.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
NIP-04
|
||||||
|
======
|
||||||
|
|
||||||
|
Encrypted Direct Message
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:arcbtc`
|
||||||
|
|
||||||
|
A special event with kind `4`, meaning "encrypted direct message". It is supposed to have the following attributes:
|
||||||
|
|
||||||
|
**`content`** MUST be equal to the base64-encoded, aes-256-cbc encrypted string of anything a user wants to write, encrypted using a shared cipher generated by combining the recipient's public-key with the sender's private-key; this appended by the base64-encoded initialization vector as if it was a querystring parameter named "iv". The format is the following: `"content": "<encrypted_text>?iv=<initialization_vector>"`.
|
||||||
|
|
||||||
|
**`tags`** MUST contain an entry identifying the receiver of the message (such that relays may naturally forward this event to them), in the form `["p", "<pubkey, as a hex string>"]`.
|
||||||
|
|
||||||
|
**`tags`** MAY contain an entry identifying the previous message in a conversation or a message we are explicitly replying to (such that contextual, more organized conversations may happen), in the form `["e", "<event_id>"]`.
|
||||||
|
|
||||||
|
Code sample for generating such an event in JavaScript:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import crypto from 'crypto'
|
||||||
|
import * as secp from 'noble-secp256k1'
|
||||||
|
|
||||||
|
let sharedPoint = secp.getSharedSecret(ourPrivateKey, '02' + theirPublicKey)
|
||||||
|
let sharedX = sharedPoint.substr(2, 64)
|
||||||
|
|
||||||
|
let iv = crypto.randomFillSync(new Uint8Array(16))
|
||||||
|
var cipher = crypto.createCipheriv(
|
||||||
|
'aes-256-cbc',
|
||||||
|
Buffer.from(sharedX, 'hex'),
|
||||||
|
iv
|
||||||
|
)
|
||||||
|
let encryptedMessage = cipher.update(text, 'utf8', 'base64')
|
||||||
|
encryptedMessage += cipher.final('base64')
|
||||||
|
let ivBase64 = Buffer.from(iv.buffer).toString('base64')
|
||||||
|
|
||||||
|
let event = {
|
||||||
|
pubkey: ourPubKey,
|
||||||
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
|
kind: 4,
|
||||||
|
tags: [['p', theirPublicKey]],
|
||||||
|
content: encryptedMessage + '?iv=' + ivBase64
|
||||||
|
}
|
||||||
|
```
|
52
05.md
Normal file
52
05.md
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
NIP-05
|
||||||
|
======
|
||||||
|
|
||||||
|
Mapping Nostr keys to DNS-based internet identifiers
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:fiatjaf`
|
||||||
|
|
||||||
|
On events of type `0` (`set_metadata`) one can specify the key `"nip05"` with an [internet identifier](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) (an email-like address) as the value. Although there is a link to a very liberal "internet identifier" specification above, NIP-05 assumes the `<local-part>` part will be restricted to the characters `a-z0-9-_.`, case insensitive.
|
||||||
|
|
||||||
|
Upon seeing that, the client splits the identifier into `<local-part>` and `<domain>` and use these values to make a GET request to `https://<domain>/.well-known/nostr.json?name=<local-part>`.
|
||||||
|
|
||||||
|
The result should be a JSON document object with a key `"names"` that should then be a mapping of names to public keys. If the public key for the given `<name>` matches the `pubkey` from the `set_metadata` event, the client then concludes that the given pubkey can indeed be referenced by its identifier.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
If a client sees an event like this:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pubkey": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9",
|
||||||
|
"kind": 0,
|
||||||
|
"content": "{\"name\": \"bob\", \"nip05\": \"bob@example.com\"}"
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It will make a GET request to `https://example.com/.well-known/nostr.json?name=bob` and get back a response that will look like
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"names": {
|
||||||
|
"bob": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That will mean everything is alright.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
### User Discovery implementation suggestion
|
||||||
|
|
||||||
|
A client can also use this to allow users to search other profiles. If a client has a search box or something like that, a user may be able to type "bob@example.com" there and the client would recognize that and do the proper queries to obtain a pubkey and suggest that to the user.
|
||||||
|
|
||||||
|
### Showing just the domain as an identifier
|
||||||
|
|
||||||
|
Clients may treat the identifier `_@domain` as the "root" identifier, and choose to display it as just the `<domain>`. For example, if Bob owns `bob.com`, he may not want an identifier like `bob@bob.com` as that is redundant. Instead Bob can use the identifier `_@bob.com` and expect Nostr clients to show and treat that as just `bob.com` for all purposes.
|
||||||
|
|
||||||
|
### Reasoning for the `/.well-known/nostr.json?name=<local-part>` format
|
||||||
|
|
||||||
|
By adding the `<local-part>` as a query string instead of as part of the path the protocol can support both dynamic servers that can generate JSON on-demand and static servers with a JSON file in it that may contain multiple names.
|
15
06.md
Normal file
15
06.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
NIP-06
|
||||||
|
======
|
||||||
|
|
||||||
|
Basic key derivation from mnemonic seed phrase
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:fiatjaf`
|
||||||
|
|
||||||
|
[BIP39](https://bips.xyz/39) is used to generate mnemonic seed words and derive a binary seed from them.
|
||||||
|
|
||||||
|
[BIP32](https://bips.xyz/32) is used to derive the path `m/44'/1237'/0'/0/0` (according to the Nostr entry on [SLIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)).
|
||||||
|
|
||||||
|
This is the default for a basic, normal, single-key client.
|
||||||
|
|
||||||
|
Other types of clients can still get fancy and use other derivation paths for their own other purposes.
|
17
08.md
Normal file
17
08.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
NIP-08
|
||||||
|
======
|
||||||
|
|
||||||
|
Handling Mentions
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:fiatjaf` `author:scsibug`
|
||||||
|
|
||||||
|
This document standardizes the treatment given by clients of inline mentions of other events and pubkeys inside the content of `text_note`s.
|
||||||
|
|
||||||
|
Clients that want to allow tagged mentions they MUST show an autocomplete component or something analogous to that whenever the user starts typing a special key (for example, "@") or presses some button to include a mention etc -- or these clients can come up with other ways to unambiguously differentiate between mentions and normal text.
|
||||||
|
|
||||||
|
Once a mention is identified, for example, the pubkey `27866e9d854c78ae625b867eefdfa9580434bc3e675be08d2acb526610d96fbe`, the client MUST add that pubkey to the `.tags` with the tag `p`, then replace its textual reference (inside `.content`) with the notation `#[index]` in which "index" is equal to the 0-based index of the related tag in the tags array.
|
||||||
|
|
||||||
|
The same process applies for mentioning event IDs.
|
||||||
|
|
||||||
|
A client that receives a `text_note` event with such `#[index]` mentions in its `.content` CAN do a search-and-replace using the actual contents from the `.tags` array with the actual pubkey or event ID that is mentioned, doing any desired context augmentation (for example, linking to the pubkey or showing a preview of the mentioned event contents) it wants in the process.
|
46
09.md
Normal file
46
09.md
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
NIP-09
|
||||||
|
======
|
||||||
|
|
||||||
|
Event Deletion
|
||||||
|
--------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:scsibug`
|
||||||
|
|
||||||
|
A special event with kind `5`, meaning "deletion" is defined as having a list of one or more `e` tags, each referencing an event the author is requesting to be deleted.
|
||||||
|
|
||||||
|
Each tag entry must contain an "e" event id intended for deletion.
|
||||||
|
|
||||||
|
The event's `content` field MAY contain a text note describing the reason for the deletion.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"kind": 5,
|
||||||
|
"pubkey": <32-bytes hex-encoded public key of the event creator>,
|
||||||
|
"tags": [
|
||||||
|
["e", "dcd59..464a2"],
|
||||||
|
["e", "968c5..ad7a4"],
|
||||||
|
],
|
||||||
|
"content": "these posts were published by accident",
|
||||||
|
...other fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Relays MAY delete or stop publishing any referenced events that have an identical `pubkey` as the deletion request. Clients may hide or otherwise indicate a deletion status for referenced events.
|
||||||
|
|
||||||
|
## Client Usage
|
||||||
|
|
||||||
|
Clients MAY choose to fully hide any events that are referenced by valid deletion events. This includes text notes, direct messages, or other yet-to-be defined event kinds. Alternatively, they MAY show the event along with an icon or other indication that the author has "disowned" the event. The `content` field MAY also be used to replace the deleted events own content, although a user interface should clearly indicate that this is a deletion reason, not the original content.
|
||||||
|
|
||||||
|
A client MUST validate that each event `pubkey` referenced in the `e` tag of the deletion request is identical to the deletion request `pubkey`, before hiding or deleting any event. Relays can not, in general, perform this validation and should not be treated as authoritative.
|
||||||
|
|
||||||
|
Clients display the deletion event itself in any way they choose, e.g., not at all, or with a prominent notice.
|
||||||
|
|
||||||
|
## Relay Usage
|
||||||
|
|
||||||
|
Relays MAY validate that a deletion event only references events that have the same `pubkey` as the deletion itself, however this is not required since relays may not have knowledge of all referenced events.
|
||||||
|
|
||||||
|
## Deleting a Deletion
|
||||||
|
|
||||||
|
Publishing a deletion event against a deletion has no effect. Clients and relays are not obliged to support "undelete" functionality.
|
58
11.md
Normal file
58
11.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
NIP-11
|
||||||
|
======
|
||||||
|
|
||||||
|
Relay Information Document
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:scsibug`
|
||||||
|
|
||||||
|
Relays may provide server metadata to clients to inform them of capabilities, administrative contacts, and various server attributes. This is made available as a JSON document over HTTP, on the same URI as the relay's websocket.
|
||||||
|
|
||||||
|
When a relay receives an HTTP(s) request with an `Accept` header of `application/nostr+json` to a URI supporting WebSocket upgrades, they SHOULD return a document with the following structure.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
name: <string identifying relay>,
|
||||||
|
description: <string with detailed information>,
|
||||||
|
pubkey: <administrative contact pubkey>,
|
||||||
|
contact: <administrative alternate contact>,
|
||||||
|
supported_nips: <a list of NIP numbers supported by the relay>,
|
||||||
|
software: <string identifying relay software URL>,
|
||||||
|
version: <string version identifier>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Any field may be omitted, and clients MUST ignore any additional fields they do not understand.
|
||||||
|
|
||||||
|
Field Descriptions
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
### Name ###
|
||||||
|
|
||||||
|
A relay may select a `name` for use in client software. This is a string, and SHOULD be less than 30 characters to avoid client truncation.
|
||||||
|
|
||||||
|
### Description ###
|
||||||
|
|
||||||
|
Detailed plain-text information about the relay may be contained in the `description` string. It is recommended that this contain no markup, formatting or line breaks for word wrapping, and simply use double newline characters to separate paragraphs. There are no limitations on length.
|
||||||
|
|
||||||
|
### Pubkey ###
|
||||||
|
|
||||||
|
An administrative contact may be listed with a `pubkey`, in the same format as Nostr events (32-byte hex for a `secp256k1` public key). If a contact is listed, this provides clients with a recommended address to send encrypted direct messages (See `NIP-04`) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance.
|
||||||
|
|
||||||
|
Relay operators have no obligation to respond to direct messages.
|
||||||
|
|
||||||
|
### Contact ###
|
||||||
|
|
||||||
|
An alternative contact may be listed under the `contact` field as well, with the same purpose as `pubkey`. Use of a Nostr public key and direct message SHOULD be preferred over this. Contents of this field SHOULD be a URI, using schemes such as `mailto` or `https` to provide users with a means of contact.
|
||||||
|
|
||||||
|
### Supported NIPs ###
|
||||||
|
|
||||||
|
As the Nostr protocol evolves, some functionality may only be available by relays that implement a specific `NIP`. This field is an array of the integer identifiers of `NIP`s that are implemented in the relay. Examples would include `1`, for `"NIP-01"` and `9`, for `"NIP-09"`. Client-side `NIPs` SHOULD not be advertised, and can be ignored by clients.
|
||||||
|
|
||||||
|
### Software ###
|
||||||
|
|
||||||
|
The relay server implementation MAY be provided in the `software` attribute. If present, this MUST be a URL to the project's homepage.
|
||||||
|
|
||||||
|
### Version ###
|
||||||
|
|
||||||
|
The relay MAY choose to publish its software version as a string attribute. The string format is defined by the relay implementation. It is recommended this be a version number or commit identifier.
|
38
12.md
Normal file
38
12.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
NIP-12
|
||||||
|
======
|
||||||
|
|
||||||
|
Generic Tag Queries
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:scsibug`
|
||||||
|
|
||||||
|
Relays may support subscriptions over arbitrary tags. `NIP-01` requires relays to respond to queries for `e` and `p` tags. This NIP allows any tag present in an event to be queried.
|
||||||
|
|
||||||
|
The `<filters>` object described in `NIP-01` is expanded to contain arbitrary keys with a `#` prefix. Any key in a filter beginning with `#` is a tag query, and MUST have a value of an array of strings. The filter condition matches if the event has a tag with the same name, and there is at least one tag value in common with the filter and event. The tag name is the first element of a tag array with the initial `#` removed, and the tag value is the second element. Subsequent elements are ignored for the purposes of tag queries.
|
||||||
|
|
||||||
|
|
||||||
|
Example Subscription Filter
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The following provides an example of a filter that matches events of kind `1` with a `foo` tag set to either `bar` or `baz`.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"kinds": [1],
|
||||||
|
"#foo": ["bar", "baz"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Client Behavior
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Clients SHOULD use the `supported_nips` field to learn if a relay supports generic tag queries. Clients MAY send generic tag queries to any relay, if they are prepared to filter out extraneous responses from relays that do not support this NIP.
|
||||||
|
|
||||||
|
Suggested Use Cases
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Motivating examples for generic tag queries are provided below. This NIP does not promote or standardize the use of any specific tag for any purpose.
|
||||||
|
|
||||||
|
* Decentralized Commenting System: clients can comment on arbitrary web pages, and easily search for other comments, by using a `url` tag and value.
|
||||||
|
* Location-specific Posts: clients can use a `geohash` tag to associate a post with a physical location. Clients can search for a set of geohashes of varying precisions near them to find local content.
|
||||||
|
* Hashtags: clients can use simple `hashtag` tags to associate an event with an easily searchable topic name. Since Nostr events themselves are not searchable through the protocol, this provides a mechanism for user-driven search.
|
26
README.md
Normal file
26
README.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# NIPs
|
||||||
|
|
||||||
|
NIPs stand for **Nostr Implementation Possibilities**. They exist to document what MUST, what SHOULD and what MAY be implemented by [Nostr](https://github.com/fiatjaf/nostr)-compatible _relay_ and _client_ software.
|
||||||
|
|
||||||
|
- [NIP-01: Basic protocol flow description](https://github.com/fiatjaf/nostr/blob/master/nips/01.md)
|
||||||
|
- [NIP-02: Contact List and Petnames](https://github.com/fiatjaf/nostr/blob/master/nips/02.md)
|
||||||
|
- [NIP-03: OpenTimestamps Attestations for Events](https://github.com/fiatjaf/nostr/blob/master/nips/03.md)
|
||||||
|
- [NIP-04: Encrypted Direct Message](https://github.com/fiatjaf/nostr/blob/master/nips/04.md)
|
||||||
|
- [NIP-05: Mapping Nostr keys to DNS-based internet identifiers](https://github.com/fiatjaf/nostr/blob/master/nips/05.md)
|
||||||
|
- [NIP-06: Basic key derivation from mnemonic seed phrase](https://github.com/fiatjaf/nostr/blob/master/nips/06.md)
|
||||||
|
- [NIP-08: Handling Mentions](https://github.com/fiatjaf/nostr/blob/master/nips/08.md)
|
||||||
|
- [NIP-09: Event Deletion](https://github.com/fiatjaf/nostr/blob/master/nips/09.md)
|
||||||
|
- [NIP-11: Relay Information Document](https://github.com/fiatjaf/nostr/blob/master/nips/11.md)
|
||||||
|
- [NIP-12: Generic Tag Queries](https://github.com/fiatjaf/nostr/blob/master/nips/12.md)
|
||||||
|
|
||||||
|
## Event Kinds
|
||||||
|
|
||||||
|
| kind | description | NIP |
|
||||||
|
|------|---------------------------|-----|
|
||||||
|
| 0 | Metadata | 5 |
|
||||||
|
| 1 | Text | 1 |
|
||||||
|
| 3 | Contacts | 2 |
|
||||||
|
| 4 | Encrypted Direct Messages | 4 |
|
||||||
|
| 5 | Event Deletion | 9 |
|
||||||
|
|
||||||
|
Please update this list when proposing NIPs introducing new event kinds.
|
Loading…
Reference in New Issue
Block a user