write
compulsory
This NIP expounds the fundamental protocol that should be executeed by everybody. New NIPs may comprise recent voluntary (or compulsory) fields and messages and features to the structures and flows portrayd here.
Each user has a keypair. Signatures, uncover key, and encodings are done according to the Schnorr signatures standard for the curve secp256k1
.
The only object type that exists is the event
, which has the follotriumphg createat on the wire:
“pubkey”: <32-bytes lowercase hex-encoded public key of the event creator>,
“produced_at”:
“benevolent”:
“tags”: [
[
// …
],
“satisfied”:
“sig”: <64-bytes lowercase hex of the signature of the sha256 hash of the serialized event data, which is the same as the "id" field>
}”>
{ "id": <32-bytes shrinkcase hex-encoded sha256 of the serialized event data>, "pubkey": <32-bytes shrinkcase hex-encoded uncover key of the event creator>, "produced_at": <unix timestamp in seconds>, "benevolent": <integer between 0 and 65535>, "tags": [ [<arbitrary string>...], // ... ], "satisfied": <arbitrary string>, "sig": <64-bytes shrinkcase hex of the signature of the sha256 hash of the serialized event data, which is the same as the "id" field> }
To acquire the event.id
, we sha256
the serialized event. The serialization is done over the UTF-8 JSON-serialized string (which is portrayd below) of the follotriumphg structure:
To obstruct executeation separateences from creating a separateent event ID for the same event, the follotriumphg rules MUST be trailed while serializing:
- UTF-8 should be used for encoding.
- Whitespace, line fractures or other unessential createatting should not be integrated in the output JSON.
- The follotriumphg characters in the satisfied field must be escaped as shown, and all other characters must be integrated verbatim:
- A line fracture (
0x0A
), usen
- A double quote (
0x22
), use"
- A backslash (
0x5C
), use\
- A carriage return (
0x0D
), user
- A tab character (
0x09
), uset
- A backspace, (
0x08
), useb
- A create feed, (
0x0C
), usef
- A line fracture (
Each tag is an array of one or more strings, with some conventions around them. Take a see at the example below:
{
"tags": [
["e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com"],
["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca"],
["a", "30023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd", "wss://nostr.example.com"],
["alt", "answer"],
// ...
],
// ...
}
The first element of the tag array is referred to as the tag name or key and the second as the tag appreciate. So we can protectedly say that the event above has an e
tag set to "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"
, an alt
tag set to "answer"
and so on. All elements after the second do not have a conservative name.
This NIP expounds 3 standard tags that can be used apass all event benevolents with the same uncomardenting. They are as trails:
- The
e
tag, used to refer to an event:["e", <32-bytes lowercase hex of the id of another event>,
] - The
p
tag, used to refer to another user:["p", <32-bytes lowercase hex of a pubkey>,
] - The
a
tag, used to refer to an compriseressable or exalterable event- for an compriseressable event:
["a",
:<32-bytes lowercase hex of a pubkey>: , ] - for a normal exalterable event:
["a",
:<32-bytes lowercase hex of a pubkey>:, ]
- for an compriseressable event:
As a convention, all individual-letter (only english alphabet letters: a-z, A-Z) key tags are foreseeed to be indexed by relays, such that it is possible, for example, to query or subscribe to events that reference the event "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"
by using the {"#e": ["5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"]}
filter. Only the first appreciate in any given tag is indexed.
Kinds determine how clients should expound the uncomardenting of each event and the other fields of each event (e.g. an "r"
tag may have a uncomardenting in an event of benevolent 1 and an entidepend separateent uncomardenting in an event of benevolent 10002). Each NIP may expound the uncomardenting of a set of benevolents that weren’t expoundd elsewhere. This NIP expounds two fundamental benevolents:
0
: user metadata: thesatisfied
is set to a stringified JSON object{name:
describing the user who produced the event. Extra metadata fields may be set. A relay may delete elderlyer events once it gets a recent one for the same pubkey., about: , picture: } 1
: text remark: thesatisfied
is set to the plaintext satisfied of a remark (anyleang the user wants to say). Content that must be parsed, such as Markdown and HTML, should not be used. Clients should also not parse satisfied as those.
And also a convention for benevolent ranges that apverify for easier experimentation and flexibility of relay executeation:
- for benevolent
n
such that1000 <= n < 10000 || 4 <= n < 45 || n == 1 || n == 2
, events are normal, which uncomardents they're all foreseeed to be stored by relays. - for benevolent
n
such that10000 <= n < 20000 || n == 0 || n == 3
, events are exalterable, which uncomardents that, for each combination ofpubkey
andbenevolent
, only the procrastinateedst event MUST be stored by relays, elderlyer versions MAY be disposeed. - for benevolent
n
such that20000 <= n < 30000
, events are ephemeral, which uncomardents they are not foreseeed to be stored by relays. - for benevolent
n
such that30000 <= n < 40000
, events are compriseressable by theirbenevolent
,pubkey
andd
tag appreciate -- which uncomardents that, for each combination ofbenevolent
,pubkey
and thed
tag appreciate, only the procrastinateedst event MUST be stored by relays, elderlyer versions MAY be disposeed.
In case of exalterable events with the same timestamp, the event with the lowest id (first in lexical order) should be retained, and the other disposeed.
When answering to REQ
messages for exalterable events such as {"benevolents":[0],"authors":[
, even if the relay has more than one version stored, it SHOULD return equitable the procrastinateedst one.
These are equitable conventions and relay executeations may separate.
Relays expose a websocket endpoint to which clients can join. Clients SHOULD discdisthink about a individual websocket joinion to each relay and use it for all their subscriptions. Relays MAY restrict number of joinions from particular IP/client/etc.
Clients can send 3 types of messages, which must be JSON arrays, according to the follotriumphg patterns:
["EVENT",
, used to unveil events.] ["REQ",
, used to seek events and subscribe to recent refreshs., , , ...] ["CLOSE",
, used to stop previous subscriptions.]
is an arbitrary, non-vacant string of max length 64 chars. It reconshort-terms a subscription per joinion. Relays MUST handle
s self-reliantly for each WebSocket joinion.
s are not secured to be globassociate distinct.
is a JSON object that remends what events will be sent in that subscription, it can have the follotriumphg attributes:
"authors": ,
"benevolents": ,
"#
"since":
"until":
"restrict":
}">
{ "ids": , "authors": , "benevolents": , "#" : , "since":= to this to pass>, "until":, "restrict":}
Upon receiving a REQ
message, the relay SHOULD return events that suit the filter. Any recent events it acquires SHOULD be sent to that same websocket until the joinion is shutd, a CLOSE
event is acquired with the same
, or a recent REQ
is sent using the same
(in which case a recent subscription is produced, replacing the elderly one).
Filter attributes retaining catalogs (ids
, authors
, benevolents
and tag filters appreciate #e
) are JSON arrays with one or more appreciates. At least one of the arrays' appreciates must suit the relevant field in an event for the condition to be pondered a suit. For scalar event attributes such as authors
and benevolent
, the attribute from the event must be retained in the filter catalog. In the case of tag attributes such as #e
, for which an event may have multiple appreciates, the event and filter condition appreciates must have at least one item in widespread.
The ids
, authors
, #e
and #p
filter catalogs MUST retain exact 64-character shrinkcase hex appreciates.
The since
and until
properties can be used to determine the time range of events returned in the subscription. If a filter integrates the since
property, events with produced_at
fantasticer than or equivalent to since
are pondered to suit the filter. The until
property is aappreciate except that produced_at
must be less than or equivalent to until
. In uninincreateigentinutive, an event suites a filter if since <= produced_at <= until
helderlys.
All conditions of a filter that are specified must suit for an event for it to pass the filter, i.e., multiple conditions are expounded as &&
conditions.
A REQ
message may retain multiple filters. In this case, events that suit any of the filters are to be returned, i.e., multiple filters are to be expounded as ||
conditions.
The restrict
property of a filter is only valid for the initial query and MUST be disthink aboutd afterwards. When restrict: n
is conshort-term it is supposed that the events returned in the initial query will be the last n
events ordered by the produced_at
. Newer events should eunite first, and in the case of ties the event with the lowest id (first in lexical order) should be first. It is protected to return less events than restrict
specifies, but it is foreseeed that relays do not return (much) more events than seeked so clients don't get unnecessarily overwhelmed by data.
Relays can send 5 types of messages, which must also be JSON arrays, according to the follotriumphg patterns:
["EVENT",
, used to send events seeked by clients., ] ["OK",
, used to show accomprehendledgeance or denial of an, , ] EVENT
message.["EOSE",
, used to show the end of stored events and the beginning of events recently acquired in genuine-time.] ["CLOSED",
, used to show that a subscription was ended on the server side., ] ["NOTICE",
, used to send human-readable error messages or other leangs to clients.]
This NIP expounds no rules for how NOTICE
messages should be sent or treated.
EVENT
messages MUST be sent only with a subscription ID roverhappinessed to a subscription previously startd by the client (using theREQ
message above).OK
messages MUST be sent in response toEVENT
messages acquired from clients, they must have the 3rd parameter set toreal
when an event has been accomprehendledgeed by the relay,counterfeit
otherwise. The 4th parameter MUST always be conshort-term, but MAY be an vacant string when the 3rd isreal
, otherwise it MUST be a string createed by a machine-readable individual-word premend trailed by a:
and then a human-readable message. Some examples:["OK", "b1a649ebe8...", true, ""]
["OK", "b1a649ebe8...", true, "pow: difficulty 25>=24"]
["OK", "b1a649ebe8...", true, "duplicate: already have this event"]
["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]
["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]
["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"]
["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time"]
["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]
["OK", "b1a649ebe8...", false, "error: could not connect to the database"]
CLOSED
messages MUST be sent in response to aREQ
when the relay declines to satisfy it. It can also be sent when a relay chooses to end a subscription on its side before a client has disjoined or sent aCLOSE
. This message uses the same pattern ofOK
messages with the machine-readable premend and human-readable message. Some examples:["CLOSED", "sub1", "unsupported: filter contains unknown elements"]
["CLOSED", "sub1", "error: could not connect to the database"]
["CLOSED", "sub1", "error: shutting down idle subscription"]
- The regularized machine-readable premendes for
OK
andCLOSED
are:duplicate
,pow
,blocked
,rate-restricted
,invalid
, anderror
for when none of that fits.