upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/01.md
diff options
context:
space:
mode:
Diffstat (limited to '01.md')
-rw-r--r--01.md49
1 files changed, 30 insertions, 19 deletions
diff --git a/01.md b/01.md
index 99c991a..1da6e83 100644
--- a/01.md
+++ b/01.md
@@ -14,7 +14,7 @@ Each user has a keypair. Signatures, public key, and encodings are done accordin
14 14
15The only object type that exists is the `event`, which has the following format on the wire: 15The only object type that exists is the `event`, which has the following format on the wire:
16 16
17```json 17```jsonc
18{ 18{
19 "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>, 19 "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>,
20 "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, 20 "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
@@ -22,14 +22,14 @@ The only object type that exists is the `event`, which has the following format
22 "kind": <integer between 0 and 65535>, 22 "kind": <integer between 0 and 65535>,
23 "tags": [ 23 "tags": [
24 [<arbitrary string>...], 24 [<arbitrary string>...],
25 ... 25 // ...
26 ], 26 ],
27 "content": <arbitrary string>, 27 "content": <arbitrary string>,
28 "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> 28 "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>
29} 29}
30``` 30```
31 31
32To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no white space or line breaks between the fields) of the following structure: 32To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (which is described below) of the following structure:
33 33
34``` 34```
35[ 35[
@@ -42,21 +42,32 @@ To obtain the `event.id`, we `sha256` the serialized event. The serialization is
42] 42]
43``` 43```
44 44
45To prevent implementation differences from creating a different event ID for the same event, the following rules MUST be followed while serializing:
46- UTF-8 should be used for encoding.
47- Whitespace, line breaks or other unnecessary formatting should not be included in the output JSON.
48- The following characters in the content field must be escaped as shown, and all other characters must be included verbatim:
49 - A line break (`0x0A`), use `\n`
50 - A double quote (`0x22`), use `\"`
51 - A backslash (`0x5C`), use `\\`
52 - A carriage return (`0x0D`), use `\r`
53 - A tab character (`0x09`), use `\t`
54 - A backspace, (`0x08`), use `\b`
55 - A form feed, (`0x0C`), use `\f`
56
45### Tags 57### Tags
46 58
47Each tag is an array of strings of arbitrary size, with some conventions around them. Take a look at the example below: 59Each tag is an array of one or more strings, with some conventions around them. Take a look at the example below:
48 60
49```json 61```jsonc
50{ 62{
51 ...,
52 "tags": [ 63 "tags": [
53 ["e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com"], 64 ["e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com"],
54 ["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca"], 65 ["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca"],
55 ["a", "30023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd", "wss://nostr.example.com"], 66 ["a", "30023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd", "wss://nostr.example.com"],
56 ["alt", "reply"], 67 ["alt", "reply"],
57 ... 68 // ...
58 ], 69 ],
59 ... 70 // ...
60} 71}
61``` 72```
62 73
@@ -70,18 +81,18 @@ This NIP defines 3 standard tags that can be used across all event kinds with th
70 - for a parameterized replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:<d tag value>, <recommended relay URL, optional>]` 81 - for a parameterized replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:<d tag value>, <recommended relay URL, optional>]`
71 - for a non-parameterized replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:, <recommended relay URL, optional>]` 82 - for a non-parameterized replaceable event: `["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:, <recommended relay URL, optional>]`
72 83
73As a convention, all single-letter (only english alphabet letters: a-z, A-Z) key tags are expected 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. 84As a convention, all single-letter (only english alphabet letters: a-z, A-Z) key tags are expected 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.
74 85
75### Kinds 86### Kinds
76 87
77Kinds specify how clients should interpret the meaning of each event and the other fields of each event (e.g. an `"r"` tag may have a meaning in an event of kind 1 and an entirely different meaning in an event of kind 10002). Each NIP may define the meaning of a set of kinds that weren't defined elsewhere. This NIP defines two basic kinds: 88Kinds specify how clients should interpret the meaning of each event and the other fields of each event (e.g. an `"r"` tag may have a meaning in an event of kind 1 and an entirely different meaning in an event of kind 10002). Each NIP may define the meaning of a set of kinds that weren't defined elsewhere. This NIP defines two basic kinds:
78 89
79- `0`: **metadata**: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete older events once it gets a new one for the same pubkey. 90- `0`: **user metadata**: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. [Extra metadata fields](24.md#kind-0) may be set. A relay may delete older events once it gets a new one for the same pubkey.
80- `1`: **text note**: the `content` is set to the **plaintext** content of a note (anything the user wants to say). Content that must be parsed, such as Markdown and HTML, should not be used. Clients should also not parse content as those. 91- `1`: **text note**: the `content` is set to the **plaintext** content of a note (anything the user wants to say). Content that must be parsed, such as Markdown and HTML, should not be used. Clients should also not parse content as those.
81 92
82And also a convention for kind ranges that allow for easier experimentation and flexibility of relay implementation: 93And also a convention for kind ranges that allow for easier experimentation and flexibility of relay implementation:
83 94
84- for kind `n` such that `1000 <= n < 10000`, events are **regular**, which means they're all expected to be stored by relays. 95- for kind `n` such that `1000 <= n < 10000 || 4 <= n < 45 || n == 1 || n == 2`, events are **regular**, which means they're all expected to be stored by relays.
85- for kind `n` such that `10000 <= n < 20000 || n == 0 || n == 3`, events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event MUST be stored by relays, older versions MAY be discarded. 96- for kind `n` such that `10000 <= n < 20000 || n == 0 || n == 3`, events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event MUST be stored by relays, older versions MAY be discarded.
86- for kind `n` such that `20000 <= n < 30000`, events are **ephemeral**, which means they are not expected to be stored by relays. 97- for kind `n` such that `20000 <= n < 30000`, events are **ephemeral**, which means they are not expected to be stored by relays.
87- for kind `n` such that `30000 <= n < 40000`, events are **parameterized replaceable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag's first value, only the latest event MUST be stored by relays, older versions MAY be discarded. 98- for kind `n` such that `30000 <= n < 40000`, events are **parameterized replaceable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag's first value, only the latest event MUST be stored by relays, older versions MAY be discarded.
@@ -101,21 +112,21 @@ Relays expose a websocket endpoint to which clients can connect. Clients SHOULD
101Clients can send 3 types of messages, which must be JSON arrays, according to the following patterns: 112Clients can send 3 types of messages, which must be JSON arrays, according to the following patterns:
102 113
103 * `["EVENT", <event JSON as defined above>]`, used to publish events. 114 * `["EVENT", <event JSON as defined above>]`, used to publish events.
104 * `["REQ", <subscription_id>, <filters JSON>...]`, used to request events and subscribe to new updates. 115 * `["REQ", <subscription_id>, <filters1>, <filters2>, ...]`, used to request events and subscribe to new updates.
105 * `["CLOSE", <subscription_id>]`, used to stop previous subscriptions. 116 * `["CLOSE", <subscription_id>]`, used to stop previous subscriptions.
106 117
107`<subscription_id>` is an arbitrary, non-empty string of max length 64 chars, that should be used to represent a subscription. Relays should manage `<subscription_id>`s independently for each WebSocket connection; even if `<subscription_id>`s are the same string, they should be treated as different subscriptions for different connections. 118`<subscription_id>` is an arbitrary, non-empty string of max length 64 chars. It represents a subscription per connection. Relays MUST manage `<subscription_id>`s independently for each WebSocket connection. `<subscription_id>`s are not guaranteed to be globally unique.
108 119
109`<filters>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes: 120`<filtersX>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes:
110 121
111```json 122```json
112{ 123{
113 "ids": <a list of event ids>, 124 "ids": <a list of event ids>,
114 "authors": <a list of lowercase pubkeys, the pubkey of an event must be one of these>, 125 "authors": <a list of lowercase pubkeys, the pubkey of an event must be one of these>,
115 "kinds": <a list of a kind numbers>, 126 "kinds": <a list of a kind numbers>,
116 "#<single-letter (a-zA-Z)>": <a list of tag values, for #e — a list of event ids, for #p — a list of event pubkeys etc>, 127 "#<single-letter (a-zA-Z)>": <a list of tag values, for #e — a list of event ids, for #p — a list of pubkeys, etc.>,
117 "since": <an integer unix timestamp in seconds, events must be newer than this to pass>, 128 "since": <an integer unix timestamp in seconds. Events must have a created_at >= to this to pass>,
118 "until": <an integer unix timestamp in seconds, events must be older than this to pass>, 129 "until": <an integer unix timestamp in seconds. Events must have a created_at <= to this to pass>,
119 "limit": <maximum number of events relays SHOULD return in the initial query> 130 "limit": <maximum number of events relays SHOULD return in the initial query>
120} 131}
121``` 132```
@@ -132,11 +143,11 @@ All conditions of a filter that are specified must match for an event for it to
132 143
133A `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. 144A `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.
134 145
135The `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. It is safe to return less events than `limit` specifies, but it is expected that relays do not return (much) more events than requested so clients don't get unnecessarily overwhelmed by data. 146The `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. Newer events should appear first, and in the case of ties the event with the lowest id (first in lexical order) should be first. It is safe to return less events than `limit` specifies, but it is expected that relays do not return (much) more events than requested so clients don't get unnecessarily overwhelmed by data.
136 147
137### From relay to client: sending events and notices 148### From relay to client: sending events and notices
138 149
139Relays can send 4 types of messages, which must also be JSON arrays, according to the following patterns: 150Relays can send 5 types of messages, which must also be JSON arrays, according to the following patterns:
140 151
141 * `["EVENT", <subscription_id>, <event JSON as defined above>]`, used to send events requested by clients. 152 * `["EVENT", <subscription_id>, <event JSON as defined above>]`, used to send events requested by clients.
142 * `["OK", <event_id>, <true|false>, <message>]`, used to indicate acceptance or denial of an `EVENT` message. 153 * `["OK", <event_id>, <true|false>, <message>]`, used to indicate acceptance or denial of an `EVENT` message.