mirror of
https://github.com/nostr-protocol/nips.git
synced 2025-12-09 08:38:50 +00:00
Compare commits
1 Commits
scrobbling
...
nip11clean
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc38176820 |
7
01.md
7
01.md
@@ -85,7 +85,7 @@ As a convention, all single-letter (only english alphabet letters: a-z, A-Z) key
|
|||||||
|
|
||||||
### Kinds
|
### Kinds
|
||||||
|
|
||||||
Kinds 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. [NIP-10](10.md), for instance, specifies the `kind:1` text note for social media applications.
|
Kinds 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. [NIP-10](10.md), for instance, especifies the `kind:1` text note for social media applications.
|
||||||
|
|
||||||
This NIP defines one basic kind:
|
This NIP defines one basic kind:
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ All conditions of a filter that are specified must match for an event for it to
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
The `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. Relays SHOULD use the `limit` value to guide how many events are returned in the initial response. Returning fewer events is acceptable, but returning (much) more should be avoided to prevent overwhelming clients.
|
The `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.
|
||||||
|
|
||||||
### From relay to client: sending events and notices
|
### From relay to client: sending events and notices
|
||||||
|
|
||||||
@@ -170,9 +170,8 @@ This NIP defines no rules for how `NOTICE` messages should be sent or treated.
|
|||||||
* `["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]`
|
* `["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "restricted: not allowed to write."]`
|
* `["OK", "b1a649ebe8...", false, "restricted: not allowed to write."]`
|
||||||
* `["OK", "b1a649ebe8...", false, "error: could not connect to the database"]`
|
* `["OK", "b1a649ebe8...", false, "error: could not connect to the database"]`
|
||||||
* `["OK", "b1a649ebe8...", false, "mute: no one was listening to your ephemeral event and it wasn't handled in any way, it was ignored"]`
|
|
||||||
- `CLOSED` messages MUST be sent in response to a `REQ` when the relay refuses to fulfill it. It can also be sent when a relay decides to kill a subscription on its side before a client has disconnected or sent a `CLOSE`. This message uses the same pattern of `OK` messages with the machine-readable prefix and human-readable message. Some examples:
|
- `CLOSED` messages MUST be sent in response to a `REQ` when the relay refuses to fulfill it. It can also be sent when a relay decides to kill a subscription on its side before a client has disconnected or sent a `CLOSE`. This message uses the same pattern of `OK` messages with the machine-readable prefix and human-readable message. Some examples:
|
||||||
* `["CLOSED", "sub1", "unsupported: filter contains unknown elements"]`
|
* `["CLOSED", "sub1", "unsupported: filter contains unknown elements"]`
|
||||||
* `["CLOSED", "sub1", "error: could not connect to the database"]`
|
* `["CLOSED", "sub1", "error: could not connect to the database"]`
|
||||||
* `["CLOSED", "sub1", "error: shutting down idle subscription"]`
|
* `["CLOSED", "sub1", "error: shutting down idle subscription"]`
|
||||||
- The standardized machine-readable prefixes for `OK` and `CLOSED` are: `duplicate`, `pow`, `blocked`, `rate-limited`, `invalid`, `restricted`, `mute` and `error` for when none of that fits.
|
- The standardized machine-readable prefixes for `OK` and `CLOSED` are: `duplicate`, `pow`, `blocked`, `rate-limited`, `invalid`, `restricted`, and `error` for when none of that fits.
|
||||||
|
|||||||
254
11.md
254
11.md
@@ -6,7 +6,7 @@ Relay Information Document
|
|||||||
|
|
||||||
`draft` `optional`
|
`draft` `optional`
|
||||||
|
|
||||||
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.
|
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.
|
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.
|
||||||
|
|
||||||
@@ -20,11 +20,9 @@ When a relay receives an HTTP(s) request with an `Accept` header of `application
|
|||||||
"contact": <administrative alternate contact>,
|
"contact": <administrative alternate contact>,
|
||||||
"supported_nips": <a list of NIP numbers supported by the relay>,
|
"supported_nips": <a list of NIP numbers supported by the relay>,
|
||||||
"software": <string identifying relay software URL>,
|
"software": <string identifying relay software URL>,
|
||||||
"version": <string version identifier>
|
"version": <string version identifier>,
|
||||||
"privacy_policy": <a link to a text file describing the relay's privacy policy>,
|
|
||||||
"terms_of_service": <a link to a text file describing the relay's term of service>,
|
"terms_of_service": <a link to a text file describing the relay's term of service>,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -35,11 +33,11 @@ Field Descriptions
|
|||||||
|
|
||||||
### Name
|
### 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.
|
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
|
### 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.
|
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.
|
||||||
|
|
||||||
### Banner
|
### Banner
|
||||||
|
|
||||||
@@ -58,35 +56,29 @@ Icon is a compact visual representation of the relay for use in UI with limited
|
|||||||
|
|
||||||
### Pubkey
|
### 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-17](17.md)) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance.
|
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-17](17.md)) 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.
|
Relay operators have no obligation to respond to direct messages.
|
||||||
|
|
||||||
### Contact
|
### 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.
|
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
|
### 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.
|
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
|
### Software
|
||||||
|
|
||||||
The relay server implementation MAY be provided in the `software` attribute. If present, this MUST be a URL to the project's homepage.
|
The relay server implementation MAY be provided in the `software` attribute. If present, this MUST be a URL to the project's homepage.
|
||||||
|
|
||||||
### Version
|
### 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.
|
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.
|
||||||
|
|
||||||
### Privacy Policy
|
|
||||||
|
|
||||||
The relay owner/admin MAY choose to link to a privacy policy document, which describes how the relay utilizes user data. Data collection, data usage, data retention, monetization of data, and third party data sharing SHOULD be included.
|
|
||||||
|
|
||||||
### Terms of Service
|
### Terms of Service
|
||||||
|
|
||||||
The relay owner/admin MAY choose to link to a terms of service document.
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Extra Fields
|
Extra Fields
|
||||||
------------
|
------------
|
||||||
@@ -162,113 +154,7 @@ a specific niche kind or content. Normal anti-spam heuristics, for example, do n
|
|||||||
|
|
||||||
- `created_at_upper_limit`: 'created_at' upper limit
|
- `created_at_upper_limit`: 'created_at' upper limit
|
||||||
|
|
||||||
- `default_limit`: The maximum returned events if you send a filter with the limit set to 0.
|
- `default_limit`: The maximum returned events if you send a filter without a limit.
|
||||||
|
|
||||||
### Event Retention
|
|
||||||
|
|
||||||
There may be a cost associated with storing data forever, so relays
|
|
||||||
may wish to state retention times. The values stated here are defaults
|
|
||||||
for unauthenticated users and visitors. Paid users would likely have
|
|
||||||
other policies.
|
|
||||||
|
|
||||||
Retention times are given in seconds, with `null` indicating infinity.
|
|
||||||
If zero is provided, this means the event will not be stored at
|
|
||||||
all, and preferably an error will be provided when those are received.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"retention": [
|
|
||||||
{"kinds": [0, 1, [5, 7], [40, 49]], "time": 3600},
|
|
||||||
{"kinds": [[40000, 49999]], "time": 100},
|
|
||||||
{"kinds": [[30000, 39999]], "count": 1000},
|
|
||||||
{"time": 3600, "count": 10000}
|
|
||||||
],
|
|
||||||
// other fields...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`retention` is a list of specifications: each will apply to either all kinds, or
|
|
||||||
a subset of kinds. Ranges may be specified for the kind field as a tuple of inclusive
|
|
||||||
start and end values. Events of indicated kind (or all) are then limited to a `count`
|
|
||||||
and/or time period.
|
|
||||||
|
|
||||||
It is possible to effectively blacklist Nostr-based protocols that rely on
|
|
||||||
a specific `kind` number, by giving a retention time of zero for those `kind` values.
|
|
||||||
While that is unfortunate, it does allow clients to discover servers that will
|
|
||||||
support their protocol quickly via a single HTTP fetch.
|
|
||||||
|
|
||||||
There is no need to specify retention times for _ephemeral events_ since they are not retained.
|
|
||||||
|
|
||||||
### Content Limitations
|
|
||||||
|
|
||||||
Some relays may be governed by the arbitrary laws of a nation state. This
|
|
||||||
may limit what content can be stored in clear-text on those relays. All
|
|
||||||
clients are encouraged to use encryption to work around this limitation.
|
|
||||||
|
|
||||||
It is not possible to describe the limitations of each country's laws
|
|
||||||
and policies which themselves are typically vague and constantly shifting.
|
|
||||||
|
|
||||||
Therefore, this field allows the relay operator to indicate which
|
|
||||||
countries' laws might end up being enforced on them, and then
|
|
||||||
indirectly on their users' content.
|
|
||||||
|
|
||||||
Users should be able to avoid relays in countries they don't like,
|
|
||||||
and/or select relays in more favorable zones. Exposing this
|
|
||||||
flexibility is up to the client software.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"relay_countries": [ "CA", "US" ],
|
|
||||||
// other fields...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `relay_countries`: a list of two-level ISO country codes (ISO 3166-1 alpha-2) whose
|
|
||||||
laws and policies may affect this relay. `EU` may be used for European Union countries. A `*` can be used for global relays.
|
|
||||||
|
|
||||||
Remember that a relay may be hosted in a country which is not the
|
|
||||||
country of the legal entities who own the relay, so it's very
|
|
||||||
likely a number of countries are involved.
|
|
||||||
|
|
||||||
|
|
||||||
### Community Preferences
|
|
||||||
|
|
||||||
For public text notes at least, a relay may try to foster a
|
|
||||||
local community. This would encourage users to follow the global
|
|
||||||
feed on that relay, in addition to their usual individual follows.
|
|
||||||
To support this goal, relays MAY specify some of the following values.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"language_tags": ["en", "en-419"],
|
|
||||||
"tags": ["sfw-only", "bitcoin-only", "anime"],
|
|
||||||
"posting_policy": "https://example.com/posting-policy.html",
|
|
||||||
// other fields...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `language_tags` is an ordered list
|
|
||||||
of [IETF language tags](https://en.wikipedia.org/wiki/IETF_language_tag) indicating
|
|
||||||
the major languages spoken on the relay. A `*` can be used for global relays.
|
|
||||||
|
|
||||||
- `tags` is a list of limitations on the topics to be discussed.
|
|
||||||
For example `sfw-only` indicates that only "Safe For Work" content
|
|
||||||
is encouraged on this relay. This relies on assumptions of what the
|
|
||||||
"work" "community" feels "safe" talking about. In time, a common
|
|
||||||
set of tags may emerge that allow users to find relays that suit
|
|
||||||
their needs, and client software will be able to parse these tags easily.
|
|
||||||
The `bitcoin-only` tag indicates that any *altcoin*, *"crypto"* or *blockchain*
|
|
||||||
comments will be ridiculed without mercy.
|
|
||||||
|
|
||||||
- `posting_policy` is a link to a human-readable page which specifies the
|
|
||||||
community policies for the relay. In cases where `sfw-only` is True, it's
|
|
||||||
important to link to a page which gets into the specifics of your posting policy.
|
|
||||||
|
|
||||||
The `description` field should be used to describe your community
|
|
||||||
goals and values, in brief. The `posting_policy` is for additional
|
|
||||||
detail and legal terms. Use the `tags` field to signify limitations
|
|
||||||
on content, or topics to be discussed, which could be machine
|
|
||||||
processed by appropriate client software.
|
|
||||||
|
|
||||||
### Pay-to-Relay
|
### Pay-to-Relay
|
||||||
|
|
||||||
@@ -288,82 +174,68 @@ Relays that require payments may want to expose their fee schedules.
|
|||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
As of 25 March 2025 the following command provided these results:
|
```yaml
|
||||||
|
~> curl -H "Accept: application/nostr+json" https://nostr.wine | jq
|
||||||
```bash
|
|
||||||
curl -H "Accept: application/nostr+json" https://jellyfish.land | jq
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
{
|
||||||
"name": "JellyFish",
|
"contact": "wino@nostr.wine",
|
||||||
"description": "Stay Immortal!",
|
"description": "A paid nostr relay for wine enthusiasts and everyone else.",
|
||||||
"banner": "https://image.nostr.build/7fdefea2dec1f1ec25b8ce69362566c13b2b7f13f1726c2e4584f05f64f62496.jpg",
|
|
||||||
"pubkey": "bf2bee5281149c7c350f5d12ae32f514c7864ff10805182f4178538c2c421007",
|
|
||||||
"contact": "hi@dezh.tech",
|
|
||||||
"software": "https://github.com/dezh-tech/immortal",
|
|
||||||
"supported_nips": [
|
|
||||||
1,
|
|
||||||
9,
|
|
||||||
11,
|
|
||||||
13,
|
|
||||||
17,
|
|
||||||
40,
|
|
||||||
42,
|
|
||||||
59,
|
|
||||||
62,
|
|
||||||
70
|
|
||||||
],
|
|
||||||
"version": "immortal - 0.0.9",
|
|
||||||
"relay_countries": [
|
|
||||||
"*"
|
|
||||||
],
|
|
||||||
"language_tags": [
|
|
||||||
"*"
|
|
||||||
],
|
|
||||||
"tags": [],
|
|
||||||
"posting_policy": "https://jellyfish.land/tos.txt",
|
|
||||||
"payments_url": "https://jellyfish.land/relay",
|
|
||||||
"icon": "https://image.nostr.build/2547e9ec4b23589e09bc7071e0806c3d4293f76284c58ff331a64bce978aaee8.jpg",
|
|
||||||
"retention": [],
|
|
||||||
"fees": {
|
"fees": {
|
||||||
"subscription": [
|
"admission": [
|
||||||
{
|
{
|
||||||
"amount": 3000,
|
"amount": 18888000,
|
||||||
"period": 2628003,
|
"unit": "msats"
|
||||||
"unit": "sats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"amount": 8000,
|
|
||||||
"period": 7884009,
|
|
||||||
"unit": "sats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"amount": 15000,
|
|
||||||
"period": 15768018,
|
|
||||||
"unit": "sats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"amount": 28000,
|
|
||||||
"period": 31536036,
|
|
||||||
"unit": "sats"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"icon": "https://image.nostr.build/30acdce4a81926f386622a07343228ae99fa68d012d54c538c0b2129dffe400c.png",
|
||||||
"limitation": {
|
"limitation": {
|
||||||
"auth_required": false,
|
"auth_required": false,
|
||||||
"max_message_length": 70000,
|
"created_at_lower_limit": 94608000,
|
||||||
"max_subid_length": 256,
|
"created_at_upper_limit": 300,
|
||||||
"max_subscriptions": 350,
|
"max_event_tags": 4000,
|
||||||
|
"max_limit": 1000,
|
||||||
|
"max_message_length": 524288,
|
||||||
|
"max_subid_length": 71,
|
||||||
|
"max_subscriptions": 50,
|
||||||
"min_pow_difficulty": 0,
|
"min_pow_difficulty": 0,
|
||||||
"payment_required": true,
|
"payment_required": true,
|
||||||
"restricted_writes": true,
|
"restricted_writes": true
|
||||||
|
},
|
||||||
|
"name": "nostr.wine",
|
||||||
|
"payments_url": "https://nostr.wine/invoices",
|
||||||
|
"pubkey": "4918eb332a41b71ba9a74b1dc64276cfff592e55107b93baae38af3520e55975",
|
||||||
|
"software": "https://nostr.wine",
|
||||||
|
"supported_nips": [ 1, 2, 4, 9, 11, 40, 42, 50, 70, 77 ],
|
||||||
|
"terms_of_service": "https://nostr.wine/terms",
|
||||||
|
"version": "0.3.3"
|
||||||
|
}
|
||||||
|
|
||||||
|
~> curl -H "Accept: application/nostr+json" https://nostr.land | jq
|
||||||
|
{
|
||||||
|
"description": "[✨ NFDB] nostr.land family of relays (fi-01 [tiger])",
|
||||||
|
"name": "[✨ NFDB] nostr.land",
|
||||||
|
"pubkey": "52b4a076bcbbbdc3a1aefa3735816cf74993b1b8db202b01c883c58be7fad8bd",
|
||||||
|
"software": "NFDB",
|
||||||
|
"icon": "https://i.nostr.build/b3thno790aodH8lE.jpg",
|
||||||
|
"supported_nips": [ 1, 2, 4, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 27, 28, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 42, 44, 46, 47, 48, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 65, 68, 69, 71, 72, 73, 75, 78, 84, 88, 89, 90, 92, 99 ],
|
||||||
|
"version": "1.0.0",
|
||||||
|
"limitation": {
|
||||||
|
"payment_required": true,
|
||||||
|
"max_message_length": 65535,
|
||||||
"max_event_tags": 2000,
|
"max_event_tags": 2000,
|
||||||
"max_content_length": 70000,
|
"max_subscriptions": 200,
|
||||||
"created_at_lower_limit": 0,
|
"auth_required": false
|
||||||
"created_at_upper_limit": 2147483647,
|
},
|
||||||
"default_limit": 500,
|
"payments_url": "https://nostr.land",
|
||||||
"max_limit": 5000
|
"fees": {
|
||||||
}
|
"subscription": [
|
||||||
|
{
|
||||||
|
"amount": 4000000,
|
||||||
|
"unit": "msats",
|
||||||
|
"period": 2592000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"terms_of_service": "https://nostr.land/terms"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
2
19.md
2
19.md
@@ -34,7 +34,7 @@ These are the possible bech32 prefixes with `TLV`:
|
|||||||
|
|
||||||
- `nprofile`: a nostr profile
|
- `nprofile`: a nostr profile
|
||||||
- `nevent`: a nostr event
|
- `nevent`: a nostr event
|
||||||
- `naddr`: a nostr _addressable event_ coordinate
|
- `naddr`: a nostr _replaceable event_ coordinate
|
||||||
- `nrelay`: a nostr relay (deprecated)
|
- `nrelay`: a nostr relay (deprecated)
|
||||||
|
|
||||||
These possible standardized `TLV` types are indicated here:
|
These possible standardized `TLV` types are indicated here:
|
||||||
|
|||||||
20
21.md
20
21.md
@@ -12,27 +12,9 @@ The scheme is `nostr:`.
|
|||||||
|
|
||||||
The identifiers that come after are expected to be the same as those defined in [NIP-19](19.md) (except `nsec`).
|
The identifiers that come after are expected to be the same as those defined in [NIP-19](19.md) (except `nsec`).
|
||||||
|
|
||||||
#### Examples
|
## Examples
|
||||||
|
|
||||||
- `nostr:npub1sn0wdenkukak0d9dfczzeacvhkrgz92ak56egt7vdgzn8pv2wfqqhrjdv9`
|
- `nostr:npub1sn0wdenkukak0d9dfczzeacvhkrgz92ak56egt7vdgzn8pv2wfqqhrjdv9`
|
||||||
- `nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p`
|
- `nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p`
|
||||||
- `nostr:note1fntxtkcy9pjwucqwa9mddn7v03wwwsu9j330jj350nvhpky2tuaspk6nqc`
|
- `nostr:note1fntxtkcy9pjwucqwa9mddn7v03wwwsu9j330jj350nvhpky2tuaspk6nqc`
|
||||||
- `nostr:nevent1qqstna2yrezu5wghjvswqqculvvwxsrcvu7uc0f78gan4xqhvz49d9spr3mhxue69uhkummnw3ez6un9d3shjtn4de6x2argwghx6egpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5nxnepm`
|
- `nostr:nevent1qqstna2yrezu5wghjvswqqculvvwxsrcvu7uc0f78gan4xqhvz49d9spr3mhxue69uhkummnw3ez6un9d3shjtn4de6x2argwghx6egpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5nxnepm`
|
||||||
|
|
||||||
### Linking HTML pages to Nostr entities
|
|
||||||
|
|
||||||
`<link>` tags with `rel="alternate"` can be used to associate webpages to Nostr events, in cases where the same content is served via the two mediums (for example, a web server that exposes Markdown articles both as HTML pages and as `kind:30023' events served under itself as a relay or through some other relay). For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
<head>
|
|
||||||
<link rel="alternate" href="nostr:naddr1qqyrzwrxvc6ngvfkqyghwumn8ghj7enfv96x5ctx9e3k7mgzyqalp33lewf5vdq847t6te0wvnags0gs0mu72kz8938tn24wlfze6qcyqqq823cph95ag" />
|
|
||||||
</head>
|
|
||||||
```
|
|
||||||
|
|
||||||
Likewise, `<link>` tags with `rel="me"` or `rel="author"` can be used to assign authorship of webpages to Nostr profiles. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
<head>
|
|
||||||
<link rel="me" href="nostr:nprofile1qyxhwumn8ghj7mn0wvhxcmmvqyd8wumn8ghj7un9d3shjtnhv4ehgetjde38gcewvdhk6qpq80cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwswpnfsn" />
|
|
||||||
</head>
|
|
||||||
```
|
|
||||||
|
|||||||
32
25.md
32
25.md
@@ -7,38 +7,38 @@ Reactions
|
|||||||
|
|
||||||
`draft` `optional`
|
`draft` `optional`
|
||||||
|
|
||||||
A reaction is a `kind 7` event that is used to indicate user reactions to other events. A
|
A reaction is a `kind 7` event that is used to react to other events.
|
||||||
reaction's `content` field MUST include user-generated-content indicating the value of the
|
|
||||||
reaction (conventionally `+`, `-`, or an emoji).
|
|
||||||
|
|
||||||
A reaction with `content` set to `+` or an empty string MUST be interpreted as a "like" or "upvote".
|
The generic reaction, represented by the `content` set to a `+` string, SHOULD
|
||||||
A reaction with `content` set to `-` MUST be interpreted as a "dislike" or "downvote".
|
be interpreted as a "like" or "upvote".
|
||||||
|
|
||||||
A reaction with `content` set to an emoji or [NIP-30](30.md) custom emoji SHOULD NOT be interpreted
|
A reaction with `content` set to `-` SHOULD be interpreted as a "dislike" or
|
||||||
as a "like" or "dislike". Clients MAY instead display this emoji reaction on the post.
|
"downvote". It SHOULD NOT be counted as a "like", and MAY be displayed as a
|
||||||
|
downvote or dislike on a post. A client MAY also choose to tally likes against
|
||||||
|
dislikes in a reddit-like system of upvotes and downvotes, or display them as
|
||||||
|
separate tallies.
|
||||||
|
|
||||||
|
The `content` MAY be an emoji, or [NIP-30](30.md) custom emoji in this case it MAY be interpreted as a "like" or "dislike",
|
||||||
|
or the client MAY display this emoji reaction on the post. If the `content` is an empty string then the client should
|
||||||
|
consider it a "+".
|
||||||
|
|
||||||
Tags
|
Tags
|
||||||
----
|
----
|
||||||
|
|
||||||
There MUST be always an `e` tag set to the `id` of the event that is being reacted to. The `e` tag SHOULD include a relay hint pointing to a relay where the event being reacted to can be found. If a client decides to include other `e`, which not recommended, the target event `id` should be last of the `e` tags.
|
There MUST be always an `e` tag set to the `id` of the event that is being reacted to. The `e` tag SHOULD include a relay hint pointing to a relay where the event being reacted to can be found. If a client decides to include other `e`, which not recommended, the target event `id` should be last of the `e` tags.
|
||||||
|
|
||||||
There SHOULD be a `p` tag set to the `pubkey` of the event being reacted to. If a client decides to include other `p` tags, which not recommended, the target event `pubkey` should be last the `p` tags.
|
The SHOULD be a `p` tag set to the `pubkey` of the event being reacted to. If a client decides to include other `p` tags, which not recommended, the target event `pubkey` should be last the `p` tags.
|
||||||
|
|
||||||
If the event being reacted to is an addressable event, an `a` SHOULD be included together with the `e` tag, it must be set to the coordinates (`kind:pubkey:d-tag`) of the event being reacted to.
|
If the event being reacted to is an addressable event, an `a` SHOULD be included together with the `e` tag, it must be set to the coordinates (`kind:pubkey:d-tag`) of the event being reacted to.
|
||||||
|
|
||||||
The reaction SHOULD include a `k` tag with the stringified kind number of the reacted event as its value.
|
The reaction SHOULD include a `k` tag with the stringified kind number of the reacted event as its value.
|
||||||
|
|
||||||
The `e` and `a` tags SHOULD include relay and pubkey hints. The `p` tags SHOULD include relay hints.
|
|
||||||
|
|
||||||
The reaction event MAY include a `k` tag with the stringified kind number of the reacted event as its value.
|
|
||||||
|
|
||||||
**Example code**
|
**Example code**
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
func make_like_event(pubkey: String, privkey: String, liked: NostrEvent, hint: String) -> NostrEvent {
|
func make_like_event(pubkey: String, privkey: String, liked: NostrEvent) -> NostrEvent {
|
||||||
var tags: [[String]] = []
|
tags.append(["e", liked.id, liked.source_relays.first ?? ""])
|
||||||
tags.append(["e", liked.id, hint, liked.pubkey])
|
tags.append(["p", liked.pubkey])
|
||||||
tags.append(["p", liked.pubkey, hint])
|
|
||||||
tags.append(["k", String(liked.kind)])
|
tags.append(["k", String(liked.kind)])
|
||||||
let ev = NostrEvent(content: "+", pubkey: pubkey, kind: 7, tags: tags)
|
let ev = NostrEvent(content: "+", pubkey: pubkey, kind: 7, tags: tags)
|
||||||
ev.calculate_id()
|
ev.calculate_id()
|
||||||
|
|||||||
10
34.md
10
34.md
@@ -70,9 +70,9 @@ The `refs` tag can be optionally extended to enable clients to identify how many
|
|||||||
|
|
||||||
Patches can be sent by anyone to any repository. Patches to a specific repository SHOULD be sent to the relays specified in that repository's announcement event's `"relays"` tag. Patch events SHOULD include an `a` tag pointing to that repository's announcement address.
|
Patches can be sent by anyone to any repository. Patches to a specific repository SHOULD be sent to the relays specified in that repository's announcement event's `"relays"` tag. Patch events SHOULD include an `a` tag pointing to that repository's announcement address.
|
||||||
|
|
||||||
Patches in a patch set SHOULD include a [NIP-10](10.md) `e` `reply` tag pointing to the previous patch.
|
Patches in a patch set SHOULD include a NIP-10 `e` `reply` tag pointing to the previous patch.
|
||||||
|
|
||||||
The first patch revision in a patch revision SHOULD include a [NIP-10](10.md) `e` `reply` to the original root patch.
|
The first patch revision in a patch revision SHOULD include a NIP-10 `e` `reply` to the original root patch.
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
@@ -125,7 +125,7 @@ Issues may have a `subject` tag, which clients can utilize to display a header.
|
|||||||
|
|
||||||
## Replies
|
## Replies
|
||||||
|
|
||||||
Replies to either a `kind:1621` (_issue_) or a `kind:1617` (_patch_) event should follow [NIP-22 comment](22.md).
|
Replies to either a `kind:1621` _issue_ or a `kind:1617` _patch_ event should follow [NIP-22 comment](22.md).
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
@@ -161,9 +161,9 @@ Root Patches and Issues have a Status that defaults to 'Open' and can be set by
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The most recent Status event (by `created_at` date) from either the issue/patch author or a maintainer is considered valid.
|
The Status event with the largest created_at date is valid.
|
||||||
|
|
||||||
The Status of a patch-revision is to either that of the root-patch, or `1632` (_Closed_) if the root-patch's Status is `1631` (_Applied/Merged_) and the patch-revision isn't tagged in the `1631` (_Applied/Merged_) event.
|
The Status of a patch-revision defaults to either that of the root-patch, or `1632` (Closed) if the root-patch's Status is `1631` and the patch-revision isn't tagged in the `1631` event.
|
||||||
|
|
||||||
|
|
||||||
## Possible things to be added later
|
## Possible things to be added later
|
||||||
|
|||||||
9
51.md
9
51.md
@@ -32,7 +32,7 @@ For example, _mute list_ can contain the public keys of spammers and bad actors
|
|||||||
| Blocked relays | 10006 | relays clients should never connect to | `"relay"` (relay URLs) |
|
| Blocked relays | 10006 | relays clients should never connect to | `"relay"` (relay URLs) |
|
||||||
| Search relays | 10007 | relays clients should use when performing search queries | `"relay"` (relay URLs) |
|
| Search relays | 10007 | relays clients should use when performing search queries | `"relay"` (relay URLs) |
|
||||||
| Simple groups | 10009 | [NIP-29](29.md) groups the user is in | `"group"` ([NIP-29](29.md) group id + relay URL + optional group name), `"r"` for each relay in use |
|
| Simple groups | 10009 | [NIP-29](29.md) groups the user is in | `"group"` ([NIP-29](29.md) group id + relay URL + optional group name), `"r"` for each relay in use |
|
||||||
| Relay feeds | 10012 | user favorite browsable relays (and relay sets) | `"relay"` (relay URLs) and `"a"` (kind:30002 relay set) |
|
| Favorite relays | 10012 | user favorite relays and pointers to relay sets | `"relay"` (relay URLs) and `"a"` (kind:30002 relay set) |
|
||||||
| Interests | 10015 | topics a user may be interested in and pointers | `"t"` (hashtags) and `"a"` (kind:30015 interest set) |
|
| Interests | 10015 | topics a user may be interested in and pointers | `"t"` (hashtags) and `"a"` (kind:30015 interest set) |
|
||||||
| Media follows | 10020 | multimedia (photos, short video) follow list | `"p"` (pubkeys -- with optional relay hint and petname) |
|
| Media follows | 10020 | multimedia (photos, short video) follow list | `"p"` (pubkeys -- with optional relay hint and petname) |
|
||||||
| Emojis | 10030 | user preferred emojis and pointers to emoji sets | `"emoji"` (see [NIP-30](30.md)) and `"a"` (kind:30030 emoji set) |
|
| Emojis | 10030 | user preferred emojis and pointers to emoji sets | `"emoji"` (see [NIP-30](30.md)) and `"a"` (kind:30030 emoji set) |
|
||||||
@@ -60,7 +60,6 @@ Aside from their main identifier, the `"d"` tag, sets can optionally have a `"ti
|
|||||||
| Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) |
|
| Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) |
|
||||||
| Release artifact sets | 30063 | group of artifacts of a software release | `"e"` (kind:1063 [file metadata](94.md) events), `"a"` (software application event) |
|
| Release artifact sets | 30063 | group of artifacts of a software release | `"e"` (kind:1063 [file metadata](94.md) events), `"a"` (software application event) |
|
||||||
| App curation sets | 30267 | references to multiple software applications | `"a"` (software application event) |
|
| App curation sets | 30267 | references to multiple software applications | `"a"` (software application event) |
|
||||||
| Calendar | 31924 | a set of events categorized in any way | `"a"` (calendar event event) |
|
|
||||||
| Starter packs | 39089 | a named set of profiles to be shared around with the goal of being followed together | `"p"` (pubkeys) |
|
| Starter packs | 39089 | a named set of profiles to be shared around with the goal of being followed together | `"p"` (pubkeys) |
|
||||||
| Media starter packs | 39092 | same as above, but specific to multimedia (photos, short video) clients | `"p"` (pubkeys) |
|
| Media starter packs | 39092 | same as above, but specific to multimedia (photos, short video) clients | `"p"` (pubkeys) |
|
||||||
|
|
||||||
@@ -104,9 +103,9 @@ Some clients have used these lists in the past, but they should work on transiti
|
|||||||
"kind": 30004,
|
"kind": 30004,
|
||||||
"tags": [
|
"tags": [
|
||||||
["d", "jvdy9i4"],
|
["d", "jvdy9i4"],
|
||||||
["title", "Yaks"],
|
["name", "Yaks"],
|
||||||
["image", "https://cdn.britannica.com/40/188540-050-9AC748DE/Yak-Himalayas-Nepal.jpg"],
|
["picture", "https://cdn.britannica.com/40/188540-050-9AC748DE/Yak-Himalayas-Nepal.jpg"],
|
||||||
["description", "The domestic yak, also known as the Tartary ox, grunting ox, or hairy cattle, is a species of long-haired domesticated cattle found throughout the Himalayan region of the Indian subcontinent, the Tibetan Plateau, Gilgit-Baltistan, Tajikistan and as far north as Mongolia and Siberia."],
|
["about", "The domestic yak, also known as the Tartary ox, grunting ox, or hairy cattle, is a species of long-haired domesticated cattle found throughout the Himalayan region of the Indian subcontinent, the Tibetan Plateau, Gilgit-Baltistan, Tajikistan and as far north as Mongolia and Siberia."],
|
||||||
["a", "30023:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:95ODQzw3ajNoZ8SyMDOzQ"],
|
["a", "30023:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:95ODQzw3ajNoZ8SyMDOzQ"],
|
||||||
["a", "30023:54af95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:1-MYP8dAhramH9J5gJWKx"],
|
["a", "30023:54af95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:1-MYP8dAhramH9J5gJWKx"],
|
||||||
["a", "30023:f8fe95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:D2Tbd38bGrFvU0bIbvSMt"],
|
["a", "30023:f8fe95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:D2Tbd38bGrFvU0bIbvSMt"],
|
||||||
|
|||||||
119
52.md
119
52.md
@@ -12,14 +12,23 @@ Unlike the term `calendar event` specific to this NIP, the term `event` is used
|
|||||||
|
|
||||||
## Calendar Events
|
## Calendar Events
|
||||||
|
|
||||||
There are two types of calendar events represented by different kinds: _date-based_ and _time-based_ calendar events.
|
There are two types of calendar events represented by different kinds: date-based and time-based calendar events. Calendar events are not required to be part of a [calendar](#calendar).
|
||||||
|
|
||||||
These tags are common to both types of calendar events:
|
### Date-Based Calendar Event
|
||||||
|
|
||||||
|
This kind of calendar event starts on a date and ends before a different date in the future. Its use is appropriate for all-day or multi-day events where time and time zone hold no significance. e.g., anniversary, public holidays, vacation days.
|
||||||
|
|
||||||
|
#### Format
|
||||||
|
|
||||||
|
The format uses an _addressable event_ of `kind:31922`.
|
||||||
|
|
||||||
|
The `.content` of these events should be a detailed description of the calendar event. It is required but can be an empty string.
|
||||||
|
|
||||||
|
The list of tags are as follows:
|
||||||
* `d` (required) a short unique string identifier. Generated by the client creating the calendar event.
|
* `d` (required) a short unique string identifier. Generated by the client creating the calendar event.
|
||||||
* `title` (required) title of the calendar event
|
* `title` (required) title of the calendar event
|
||||||
* `summary` (optional) brief description of the calendar event
|
* `start` (required) inclusive start date in ISO 8601 format (YYYY-MM-DD). Must be less than `end`, if it exists.
|
||||||
* `image` (optional) url of an image to use for the event
|
* `end` (optional) exclusive end date in ISO 8601 format (YYYY-MM-DD). If omitted, the calendar event ends on the same date as `start`.
|
||||||
* `location` (optional, repeated) location of the calendar event. e.g. address, GPS coordinates, meeting room name, link to video call
|
* `location` (optional, repeated) location of the calendar event. e.g. address, GPS coordinates, meeting room name, link to video call
|
||||||
* `g` (optional) [geohash](https://en.wikipedia.org/wiki/Geohash) to associate calendar event with a searchable physical location
|
* `g` (optional) [geohash](https://en.wikipedia.org/wiki/Geohash) to associate calendar event with a searchable physical location
|
||||||
* `p` (optional, repeated) 32-bytes hex pubkey of a participant, optional recommended relay URL, and participant's role in the meeting
|
* `p` (optional, repeated) 32-bytes hex pubkey of a participant, optional recommended relay URL, and participant's role in the meeting
|
||||||
@@ -27,31 +36,13 @@ These tags are common to both types of calendar events:
|
|||||||
* `r` (optional, repeated) references / links to web pages, documents, video calls, recorded videos, etc.
|
* `r` (optional, repeated) references / links to web pages, documents, video calls, recorded videos, etc.
|
||||||
|
|
||||||
The following tags are deprecated:
|
The following tags are deprecated:
|
||||||
|
|
||||||
* `name` name of the calendar event. Use only if `title` is not available.
|
* `name` name of the calendar event. Use only if `title` is not available.
|
||||||
|
|
||||||
Calendar events are _not_ required to be part of a [calendar](#calendar).
|
```jsonc
|
||||||
|
|
||||||
### Date-Based Calendar Event
|
|
||||||
|
|
||||||
This kind of calendar event starts on a date and ends before a different date in the future. Its use is appropriate for all-day or multi-day events where time and time zone hold no significance. e.g., anniversary, public holidays, vacation days.
|
|
||||||
|
|
||||||
It's an _addressable event_ of `kind:31922`.
|
|
||||||
|
|
||||||
The `.content` of these events SHOULD be a description of the calendar event.
|
|
||||||
|
|
||||||
Aside from the common tags, this also takes the following tags:
|
|
||||||
|
|
||||||
* `start` (required) inclusive start date in ISO 8601 format (YYYY-MM-DD). Must be less than `end`, if it exists.
|
|
||||||
* `end` (optional) exclusive end date in ISO 8601 format (YYYY-MM-DD). If omitted, the calendar event ends on the same date as `start`.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
{
|
{
|
||||||
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
||||||
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
||||||
"created_at": <unix timestamp in seconds>,
|
"created_at": <Unix timestamp in seconds>,
|
||||||
"kind": 31922,
|
"kind": 31922,
|
||||||
"content": "<description of calendar event>",
|
"content": "<description of calendar event>",
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -59,17 +50,25 @@ Example:
|
|||||||
|
|
||||||
["title", "<title of calendar event>"],
|
["title", "<title of calendar event>"],
|
||||||
|
|
||||||
// dates
|
// Dates
|
||||||
["start", "<YYYY-MM-DD>"],
|
["start", "<YYYY-MM-DD>"],
|
||||||
["end", "<YYYY-MM-DD>"],
|
["end", "<YYYY-MM-DD>"],
|
||||||
|
|
||||||
// location
|
// Location
|
||||||
["location", "<location>"],
|
["location", "<location>"],
|
||||||
["g", "<geohash>"],
|
["g", "<geohash>"],
|
||||||
|
|
||||||
// participants
|
// Participants
|
||||||
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
||||||
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
||||||
|
|
||||||
|
// Hashtags
|
||||||
|
["t", "<tag>"],
|
||||||
|
["t", "<tag>"],
|
||||||
|
|
||||||
|
// Reference links
|
||||||
|
["r", "<url>"],
|
||||||
|
["r", "<url>"]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -78,22 +77,36 @@ Example:
|
|||||||
|
|
||||||
This kind of calendar event spans between a start time and end time.
|
This kind of calendar event spans between a start time and end time.
|
||||||
|
|
||||||
It's an _addressable event_ of `kind:31923`.
|
#### Format
|
||||||
|
|
||||||
The `.content` of these events should be a description of the calendar event. It is required but can be an empty string.
|
The format uses an _addressable event_ kind `31923`.
|
||||||
|
|
||||||
Aside from the common tags, this also takes the following tags:
|
The `.content` of these events should be a detailed description of the calendar event. It is required but can be an empty string.
|
||||||
|
|
||||||
|
The list of tags are as follows:
|
||||||
|
* `d` (required) a short unique string identifier. Generated by the client creating the calendar event.
|
||||||
|
* `title` (required) title of the calendar event
|
||||||
* `start` (required) inclusive start Unix timestamp in seconds. Must be less than `end`, if it exists.
|
* `start` (required) inclusive start Unix timestamp in seconds. Must be less than `end`, if it exists.
|
||||||
* `end` (optional) exclusive end Unix timestamp in seconds. If omitted, the calendar event ends instantaneously.
|
* `end` (optional) exclusive end Unix timestamp in seconds. If omitted, the calendar event ends instantaneously.
|
||||||
* `start_tzid` (optional) time zone of the start timestamp, as defined by the IANA Time Zone Database. e.g., `America/Costa_Rica`
|
* `start_tzid` (optional) time zone of the start timestamp, as defined by the IANA Time Zone Database. e.g., `America/Costa_Rica`
|
||||||
* `end_tzid` (optional) time zone of the end timestamp, as defined by the IANA Time Zone Database. e.g., `America/Costa_Rica`. If omitted and `start_tzid` is provided, the time zone of the end timestamp is the same as the start timestamp.
|
* `end_tzid` (optional) time zone of the end timestamp, as defined by the IANA Time Zone Database. e.g., `America/Costa_Rica`. If omitted and `start_tzid` is provided, the time zone of the end timestamp is the same as the start timestamp.
|
||||||
|
* `summary` (optional) brief description of the calendar event
|
||||||
|
* `image` (optional) url of an image to use for the event
|
||||||
|
* `location` (optional, repeated) location of the calendar event. e.g. address, GPS coordinates, meeting room name, link to video call
|
||||||
|
* `g` (optional) [geohash](https://en.wikipedia.org/wiki/Geohash) to associate calendar event with a searchable physical location
|
||||||
|
* `p` (optional, repeated) 32-bytes hex pubkey of a participant, optional recommended relay URL, and participant's role in the meeting
|
||||||
|
* `l` (optional, repeated) label to categorize calendar event. e.g. `audiospace` to denote a scheduled event from a live audio space implementation such as cornychat.com
|
||||||
|
* `t` (optional, repeated) hashtag to categorize calendar event
|
||||||
|
* `r` (optional, repeated) references / links to web pages, documents, video calls, recorded videos, etc.
|
||||||
|
|
||||||
```yaml
|
The following tags are deprecated:
|
||||||
|
* `name` name of the calendar event. Use only if `title` is not available.
|
||||||
|
|
||||||
|
```jsonc
|
||||||
{
|
{
|
||||||
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
||||||
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
||||||
"created_at": <unix timestamp in seconds>,
|
"created_at": <Unix timestamp in seconds>,
|
||||||
"kind": 31923,
|
"kind": 31923,
|
||||||
"content": "<description of calendar event>",
|
"content": "<description of calendar event>",
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -103,39 +116,54 @@ Aside from the common tags, this also takes the following tags:
|
|||||||
["summary", "<brief description of the calendar event>"],
|
["summary", "<brief description of the calendar event>"],
|
||||||
["image", "<string with image URI>"],
|
["image", "<string with image URI>"],
|
||||||
|
|
||||||
// timestamps
|
// Timestamps
|
||||||
["start", "<unix timestamp in seconds>"],
|
["start", "<Unix timestamp in seconds>"],
|
||||||
["end", "<unix timestamp in seconds>"],
|
["end", "<Unix timestamp in seconds>"],
|
||||||
|
|
||||||
["start_tzid", "<IANA Time Zone Database identifier>"],
|
["start_tzid", "<IANA Time Zone Database identifier>"],
|
||||||
["end_tzid", "<IANA Time Zone Database identifier>"],
|
["end_tzid", "<IANA Time Zone Database identifier>"],
|
||||||
|
|
||||||
// location
|
// Location
|
||||||
["location", "<location>"],
|
["location", "<location>"],
|
||||||
["g", "<geohash>"],
|
["g", "<geohash>"],
|
||||||
|
|
||||||
// participants
|
// Participants
|
||||||
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
||||||
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
["p", "<32-bytes hex of a pubkey>", "<optional recommended relay URL>", "<role>"],
|
||||||
|
|
||||||
|
// Labels (example using com.cornychat namespace denoting the event as an audiospace)
|
||||||
|
["L", "com.cornychat"],
|
||||||
|
["l", "audiospace", "com.cornychat"],
|
||||||
|
|
||||||
|
// Hashtags
|
||||||
|
["t", "<tag>"],
|
||||||
|
["t", "<tag>"],
|
||||||
|
|
||||||
|
// Reference links
|
||||||
|
["r", "<url>"],
|
||||||
|
["r", "<url>"]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Calendar
|
## Calendar
|
||||||
|
|
||||||
A calendar is a collection of calendar events, represented as a custom _addressable list_ event using kind `31924`. A user can have multiple calendars. One may create a calendar to segment calendar events for specific purposes. e.g., personal, work, travel, meetups, and conferences.
|
A calendar is a collection of calendar events, represented as a custom replaceable list event using kind `31924`. A user can have multiple calendars. One may create a calendar to segment calendar events for specific purposes. e.g., personal, work, travel, meetups, and conferences.
|
||||||
|
|
||||||
|
### Format
|
||||||
|
|
||||||
The `.content` of these events should be a detailed description of the calendar. It is required but can be an empty string.
|
The `.content` of these events should be a detailed description of the calendar. It is required but can be an empty string.
|
||||||
|
|
||||||
|
The format uses a custom replaceable list of kind `31924` with a list of tags as described below:
|
||||||
* `d` (required) universally unique identifier. Generated by the client creating the calendar.
|
* `d` (required) universally unique identifier. Generated by the client creating the calendar.
|
||||||
* `title` (required) calendar title
|
* `title` (required) calendar title
|
||||||
* `a` (repeated) reference tag to kind `31922` or `31923` calendar event being responded to
|
* `a` (repeated) reference tag to kind `31922` or `31923` calendar event being responded to
|
||||||
|
|
||||||
```yaml
|
```json
|
||||||
{
|
{
|
||||||
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
||||||
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
||||||
"created_at": <unix timestamp in seconds>,
|
"created_at": <Unix timestamp in seconds>,
|
||||||
"kind": 31924,
|
"kind": 31924,
|
||||||
"content": "<description of calendar>",
|
"content": "<description of calendar>",
|
||||||
"tags": [
|
"tags": [
|
||||||
@@ -163,12 +191,13 @@ The RSVP MUST have an `a` tag of the event coordinates to the calendar event, an
|
|||||||
|
|
||||||
The RSVP MAY tag the author of the calendar event it is in response to using a `p` tag so that clients can easily query all RSVPs that pertain to the author.
|
The RSVP MAY tag the author of the calendar event it is in response to using a `p` tag so that clients can easily query all RSVPs that pertain to the author.
|
||||||
|
|
||||||
The RSVP is an _addressable event_ of `kind:31925`.
|
### Format
|
||||||
|
|
||||||
|
The format uses an _addressable event_ kind `31925`.
|
||||||
|
|
||||||
The `.content` of these events is optional and should be a free-form note that adds more context to this calendar event response.
|
The `.content` of these events is optional and should be a free-form note that adds more context to this calendar event response.
|
||||||
|
|
||||||
The list of tags is as follows:
|
The list of tags are as follows:
|
||||||
|
|
||||||
* `a` (required) coordinates to a kind `31922` or `31923` calendar event being responded to.
|
* `a` (required) coordinates to a kind `31922` or `31923` calendar event being responded to.
|
||||||
* `e` (optional) event id of a kind `31922` or `31923` calendar event being responded to.
|
* `e` (optional) event id of a kind `31922` or `31923` calendar event being responded to.
|
||||||
* `d` (required) universally unique identifier. Generated by the client creating the calendar event RSVP.
|
* `d` (required) universally unique identifier. Generated by the client creating the calendar event RSVP.
|
||||||
@@ -176,11 +205,11 @@ The list of tags is as follows:
|
|||||||
* `fb` (optional) `free` or `busy`. Determines if the user would be free or busy for the duration of the calendar event. This tag must be omitted or ignored if the `status` label is set to `declined`.
|
* `fb` (optional) `free` or `busy`. Determines if the user would be free or busy for the duration of the calendar event. This tag must be omitted or ignored if the `status` label is set to `declined`.
|
||||||
* `p` (optional) pubkey of the author of the calendar event being responded to.
|
* `p` (optional) pubkey of the author of the calendar event being responded to.
|
||||||
|
|
||||||
```yaml
|
```json
|
||||||
{
|
{
|
||||||
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
|
||||||
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
||||||
"created_at": <unix timestamp in seconds>,
|
"created_at": <Unix timestamp in seconds>,
|
||||||
"kind": 31925,
|
"kind": 31925,
|
||||||
"content": "<note>",
|
"content": "<note>",
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
143
53.md
143
53.md
@@ -129,146 +129,3 @@ Common use cases include meeting rooms/workshops, watch-together activities, or
|
|||||||
"sig": "997f62ddfc0827c121043074d50cfce7a528e978c575722748629a4137c45b75bdbc84170bedc723ef0a5a4c3daebf1fef2e93f5e2ddb98e5d685d022c30b622"
|
"sig": "997f62ddfc0827c121043074d50cfce7a528e978c575722748629a4137c45b75bdbc84170bedc723ef0a5a4c3daebf1fef2e93f5e2ddb98e5d685d022c30b622"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Interactive Rooms and Meetings
|
|
||||||
-----
|
|
||||||
|
|
||||||
`draft` `optional`
|
|
||||||
|
|
||||||
Service providers want to offer Interactive Rooms to the Nostr network in such a way that participants can easily log and query by clients. This NIP describes a general framework to advertise rooms and their associated events.
|
|
||||||
|
|
||||||
## Concepts
|
|
||||||
|
|
||||||
### Interactive Room (kind:30312)
|
|
||||||
|
|
||||||
A special event with `kind:30312` "Interactive Room" defines the configuration and properties of a virtual interactive space. Each room has a unique identifier and can host multiple events/meetings.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"kind": 30312,
|
|
||||||
"tags": [
|
|
||||||
["d", "<unique identifier>"], // Required: Room identifier
|
|
||||||
["room", "<name of the room>"], // Required: Display name
|
|
||||||
["summary", "<description>"], // Optional: Room description
|
|
||||||
["image", "<preview image url>"], // Optional: Room image
|
|
||||||
["status", "<open, private, closed>"], // Required: Room accessibility
|
|
||||||
["service", "<url>"], // Required: URL to access the room
|
|
||||||
["endpoint", "<url>"], // Optional: API endpoint for status/info
|
|
||||||
["t", "<hashtag>"], // Optional: Multiple hashtags allowed
|
|
||||||
["p", "<pubkey>", "<url>", "<role>", "<proof>"], // Required: At least one provider
|
|
||||||
["relays", "<url>", "<url>", /*...*/] // Optional: Preferred relays
|
|
||||||
],
|
|
||||||
"content": "" // Usually empty, may contain additional metadata
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Room properties:
|
|
||||||
* MUST be either open, private or closed. Closed means the room is not in operation.
|
|
||||||
* MAY specify access control policy for private rooms (e.g. invite-only, payment required)
|
|
||||||
* MAY persist when not in use
|
|
||||||
* MUST have at least one provider with "Host" role
|
|
||||||
* MAY have multiple providers with different roles
|
|
||||||
Provider roles (p tags):
|
|
||||||
* Host: Full room management capabilities
|
|
||||||
* Moderator: Room moderation capabilities
|
|
||||||
* Speaker: Allowed to present/speak
|
|
||||||
* Optional proof field for role verification
|
|
||||||
|
|
||||||
### Room Meeting (kind:30313)
|
|
||||||
|
|
||||||
A special event with kind:30313 represents a scheduled or ongoing meeting within a room. It MUST reference its parent room using the d tag.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"kind": 30313,
|
|
||||||
"tags": [
|
|
||||||
["d", "<event-unique-identifier>"], // Required: Event identifier
|
|
||||||
["a", "30312:<pubkey>:<room-id>", "wss://nostr.example.com"], // Required: Reference to parent room, 'd' from 30312
|
|
||||||
["title", "<meeting-title>"], // Required: Meeting title
|
|
||||||
["summary", "<description>"], // Optional: Meeting description
|
|
||||||
["image", "<preview image url>"], // Optional: Meeting image
|
|
||||||
["starts", "<unix timestamp>"], // Required: Start time
|
|
||||||
["ends", "<unix timestamp>"], // Optional: End time
|
|
||||||
["status", "<planned, live, ended>"], // Required: Meeting status
|
|
||||||
["total_participants", "<number>"], // Optional: Total registered
|
|
||||||
["current_participants", "<number>"], // Optional: Currently active
|
|
||||||
["p", "<pubkey>", "<url>", "<role>"], // Optional: Participant with role
|
|
||||||
],
|
|
||||||
"content": "" // Usually empty, may contain additional metadata
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Event properties:
|
|
||||||
* MUST reference parent room via d tag
|
|
||||||
* MUST have a status (planned/live/ended)
|
|
||||||
* MUST have a start time
|
|
||||||
* MAY track participant counts
|
|
||||||
* MAY include participant roles specific to the event
|
|
||||||
Event management:
|
|
||||||
* Clients SHOULD update event status regularly when live
|
|
||||||
* Events without updates for 1 hour MAY be considered ended
|
|
||||||
* starts and ends timestamps SHOULD be updated when status changes
|
|
||||||
|
|
||||||
Examples
|
|
||||||
|
|
||||||
Interactive Room (kind:30312)
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"kind": 30312,
|
|
||||||
"tags": [
|
|
||||||
["d", "main-conference-room"],
|
|
||||||
["room", "Main Conference Hall"],
|
|
||||||
["summary", "Our primary conference space"],
|
|
||||||
["image", "https://example.com/room.jpg"],
|
|
||||||
["status", "open"],
|
|
||||||
["service", "https://meet.example.com/room"],
|
|
||||||
["endpoint", "https://api.example.com/room"],
|
|
||||||
["t", "conference"],
|
|
||||||
["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca", "wss://nostr.example.com/", "Owner"],
|
|
||||||
["p", "14aeb..8dad4", "wss://provider2.com/", "Moderator"],
|
|
||||||
["relays", "wss://relay1.com", "wss://relay2.com"]
|
|
||||||
],
|
|
||||||
"content": ""
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Conference Event (kind:30313)
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"kind": 30313,
|
|
||||||
"tags": [
|
|
||||||
["d", "annual-meeting-2025"],
|
|
||||||
["a", "30312:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:main-conference-room", "wss://nostr.example.com"]
|
|
||||||
["title", "Annual Company Meeting 2025"],
|
|
||||||
["summary", "Yearly company-wide meeting"],
|
|
||||||
["image", "https://example.com/meeting.jpg"],
|
|
||||||
["starts", "1676262123"],
|
|
||||||
["ends", "1676269323"],
|
|
||||||
["status", "live"],
|
|
||||||
["total_participants", "180"],
|
|
||||||
["current_participants", "175"],
|
|
||||||
["p", "91cf9..4e5ca", "wss://provider1.com/", "Speaker"],
|
|
||||||
],
|
|
||||||
"content": ""
|
|
||||||
}
|
|
||||||
```
|
|
||||||
## Room Presence
|
|
||||||
|
|
||||||
New `kind: 10312` provides an event which signals presence of a listener.
|
|
||||||
|
|
||||||
The presence event SHOULD be updated at regular intervals and clients SHOULD filter presence events older than
|
|
||||||
a given time window.
|
|
||||||
|
|
||||||
**This kind `10312` is a regular replaceable event, as such presence can only be indicated in one room at a time.**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"kind": 10312,
|
|
||||||
"tags": [
|
|
||||||
["a" , "<room-a-tag>", "<relay-hint>", "root"],
|
|
||||||
["hand", "1"] // hand raised flag
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
1
69.md
1
69.md
@@ -80,7 +80,6 @@ Currently implemented on the following platforms:
|
|||||||
- [Mostro](https://github.com/MostroP2P/mostro)
|
- [Mostro](https://github.com/MostroP2P/mostro)
|
||||||
- [@lnp2pBot](https://github.com/lnp2pBot/bot)
|
- [@lnp2pBot](https://github.com/lnp2pBot/bot)
|
||||||
- [Robosats](https://github.com/RoboSats/robosats/pull/1362)
|
- [Robosats](https://github.com/RoboSats/robosats/pull/1362)
|
||||||
- [Peach Bitcoin](https://github.com/Peach2Peach/peach-nostr-announcer-bot)
|
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
|
|||||||
44
72.md
44
72.md
@@ -41,55 +41,19 @@ The goal of this NIP is to enable public communities. It defines the replaceable
|
|||||||
|
|
||||||
# Posting to a community
|
# Posting to a community
|
||||||
|
|
||||||
[NIP-22](NIP-22) kind 1111 events SHOULD be used for text notes posted to a community, with the `A` tag always scoped to the community definition.
|
Any Nostr event can be posted to a community. Clients MUST add one or more community `a` tags, each with a recommended relay.
|
||||||
|
|
||||||
## Top-level posts
|
|
||||||
|
|
||||||
For top-level posts, the uppercase and lowercase NIP-22 tags should both refer to the community definition itself.
|
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
"kind": 1111,
|
"kind": 1,
|
||||||
"tags": [
|
"tags": [
|
||||||
["A", "34550:<community-author-pubkey>:<community-d-identifier>", "<optional-relay-url>"],
|
["a", "34550:<community event author pubkey>:<community-d-identifier>", "<optional-relay-url>"],
|
||||||
["a", "34550:<community-author-pubkey>:<community-d-identifier>", "<optional-relay-url>"],
|
|
||||||
["P", "<community-author-pubkey>", "<optional-relay-url>"],
|
|
||||||
["p", "<community-author-pubkey>", "<optional-relay-url>"],
|
|
||||||
["K", "34550"],
|
|
||||||
["k", "34550"],
|
|
||||||
],
|
],
|
||||||
"content": "Hi everyone. It's great to be here!",
|
"content": "hello world",
|
||||||
// other fields...
|
// other fields...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Nested replies
|
|
||||||
|
|
||||||
For nested replies, the uppercase tags should still refer to the community definition, while the lowercase tags should refer to the parent post or reply.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"kind": 1111,
|
|
||||||
"tags": [
|
|
||||||
// community definition itself
|
|
||||||
["A", "34550:<community-author-pubkey>:<community-d-identifier>", "<optional-relay-url>"],
|
|
||||||
["P", "<community-author-pubkey>", "<optional-relay-url>"],
|
|
||||||
["K", "34550"],
|
|
||||||
|
|
||||||
// parent post or reply
|
|
||||||
["e", "<parent-event-id>", "<optional-relay-url>"],
|
|
||||||
["p", "<parent-event-author-pubkey>", "<optional-relay-url>"],
|
|
||||||
["k", "<parent-event-kind>"] // most likely "1111"
|
|
||||||
],
|
|
||||||
"content": "Agreed! Welcome everyone!",
|
|
||||||
// other fields...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Backwards compatibility note
|
|
||||||
|
|
||||||
Previously kind 1 events were used for posts in communities, with an "a" tag pointing to the community. For backwards compatibility, clients MAY still query for kind 1 events, but SHOULD NOT use them for new posts. Instead, clients SHOULD use kind 1111 events with the `A` and `a` tags as described above.
|
|
||||||
|
|
||||||
# Moderation
|
# Moderation
|
||||||
|
|
||||||
Anyone may issue an approval event to express their opinion that a post is appropriate for a community. Clients MAY choose which approval events to honor, but SHOULD at least use ones published by the group's defined moderators.
|
Anyone may issue an approval event to express their opinion that a post is appropriate for a community. Clients MAY choose which approval events to honor, but SHOULD at least use ones published by the group's defined moderators.
|
||||||
|
|||||||
1
73.md
1
73.md
@@ -20,7 +20,6 @@ There are certain established global content identifiers such as [Book ISBNs](ht
|
|||||||
| Geohashes | "geo:`<geohash, lowercase>`" | "geo" |
|
| Geohashes | "geo:`<geohash, lowercase>`" | "geo" |
|
||||||
| Movies | "isan:`<id, without version part>`" | "isan" |
|
| Movies | "isan:`<id, without version part>`" | "isan" |
|
||||||
| Papers | "doi:`<id, lowercase>`" | "doi" |
|
| Papers | "doi:`<id, lowercase>`" | "doi" |
|
||||||
| Music pieces | "isrc:`<id, uppercase>`" | "isrc" |
|
|
||||||
| Hashtags | "#`<topic, lowercase>`" | "#" |
|
| Hashtags | "#`<topic, lowercase>`" | "#" |
|
||||||
| Podcast Feeds | "podcast:guid:`<guid>`" | "podcast:guid" |
|
| Podcast Feeds | "podcast:guid:`<guid>`" | "podcast:guid" |
|
||||||
| Podcast Episodes | "podcast:item:guid:`<guid>`" | "podcast:item:guid" |
|
| Podcast Episodes | "podcast:item:guid:`<guid>`" | "podcast:item:guid" |
|
||||||
|
|||||||
175
77.md
175
77.md
@@ -1,175 +0,0 @@
|
|||||||
NIP-77
|
|
||||||
======
|
|
||||||
|
|
||||||
Negentropy Syncing
|
|
||||||
------------------
|
|
||||||
|
|
||||||
`draft` `optional`
|
|
||||||
|
|
||||||
This document describes a protocol extension for syncing events. It works for both client-relay and relay-relay scenarios. If both sides of the sync have events in common, then this protocol will use less bandwidth than transferring the full set of events (or even just their IDs).
|
|
||||||
|
|
||||||
It is a Nostr-friendly wrapper around the [Negentropy](https://github.com/hoytech/negentropy) protocol, which uses a technique called [Range-Based Set Reconciliation](https://logperiodic.com/rbsr.html).
|
|
||||||
|
|
||||||
Since Negentropy is a binary protocol, this wrapper hex-encodes its messages. The specification for Negentropy Protocol V1 is attached as an appendix to this NIP below.
|
|
||||||
|
|
||||||
## High-Level Protocol Description
|
|
||||||
|
|
||||||
We're going to call the two sides engaged in the sync the client and the relay (even though the initiator could be another relay instead of a client).
|
|
||||||
|
|
||||||
* (1) Client (initiator) chooses a filter, and retrieves the set of events that it has locally that match this filter (or uses a cache), and constructs an initial message.
|
|
||||||
* (2) Client sends a `NEG-OPEN` message to the relay, which includes the filter and the initial message.
|
|
||||||
* (3) Relay selects the set of events that it has locally that match the filter (or uses a cache).
|
|
||||||
* (4) Relay constructs a response and returns it to the client in a `NEG-MSG` message.
|
|
||||||
* (5) Client parses the message to learn about IDs it has (and relay needs) and IDs it needs (and relay has).
|
|
||||||
* If client wishes to continue, then it constructs a new message and sends it to the relay in a `NEG-MSG` message. Goto step 4.
|
|
||||||
* If client wishes to stop, then it sends a `NEG-CLOSE` message or disconnects the websocket.
|
|
||||||
|
|
||||||
The above protocol only results in the client learning about IDs it has/needs, and does not actually transfer events. Given these IDs, the client can upload events it has with `EVENT`, and/or download events it needs with `REQ`. This can be performed over the same websocket connection in parallel with subsequent `NEG-MSG` messages. If a client is only interested in determining the number of unique events (ie, reaction counts), it may choose to not download/upload at all.
|
|
||||||
|
|
||||||
## Nostr Messages
|
|
||||||
|
|
||||||
### Initial message (client to relay):
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
[
|
|
||||||
"NEG-OPEN",
|
|
||||||
<subscription ID string>,
|
|
||||||
<filter>,
|
|
||||||
<initialMessage, hex-encoded>
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
* The subscription ID is used by each side to identify which query a message refers to. It only needs to be long enough to distinguish it from any other concurrent subscriptions on this websocket connection (an integer that increments once per `NEG-OPEN` is fine). Subscription IDs are in a separate namespace from `REQ` subscription IDs. If a `NEG-OPEN` is issued for a currently open subscription ID, the existing subscription is first closed.
|
|
||||||
* The filter is as described in [NIP-01](01.md).
|
|
||||||
* `initialMessage` is the initial Negentropy binary message, hex-encoded. See appendix.
|
|
||||||
|
|
||||||
### Error message (relay to client):
|
|
||||||
|
|
||||||
If a request cannot be serviced by the relay, an error is returned to the client:
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
[
|
|
||||||
"NEG-ERR",
|
|
||||||
<subscription ID string>,
|
|
||||||
<reason code string>
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Error reasons are the same format as in NIP-01. They should begin with a machine-readable single-word prefix, followed by a `:` and then a human-readable message with more information.
|
|
||||||
|
|
||||||
The current suggested error reasons are
|
|
||||||
|
|
||||||
* `blocked`
|
|
||||||
* Relays can optionally reject queries that would require them to process too many records, or records that are too old
|
|
||||||
* The maximum number of records that can be processed can optionally be returned as the 4th element in the response
|
|
||||||
* Example: `blocked: this query is too big`
|
|
||||||
* `closed`
|
|
||||||
* Because the `NEG-OPEN` queries may be stateful, relays may choose to time-out inactive queries to recover memory resources
|
|
||||||
* Example: `closed: you took too long to respond!`
|
|
||||||
|
|
||||||
After a `NEG-ERR` is issued, the subscription is considered to be closed.
|
|
||||||
|
|
||||||
### Subsequent messages (bidirectional):
|
|
||||||
|
|
||||||
Relay and client alternate sending each other `NEG-MSG`s:
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
[
|
|
||||||
"NEG-MSG",
|
|
||||||
<subscription ID string>,
|
|
||||||
<message, hex-encoded>
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
* `message` is a Negentropy binary message, hex-encoded. Both message directions use the same format. See appendix.
|
|
||||||
|
|
||||||
### Close message (client to relay):
|
|
||||||
|
|
||||||
When finished, the client should tell the relay it can release its resources with a `NEG-CLOSE`:
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
[
|
|
||||||
"NEG-CLOSE",
|
|
||||||
<subscription ID string>
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Appendix: Negentropy Protocol V1
|
|
||||||
|
|
||||||
### Preparation
|
|
||||||
|
|
||||||
There are two protocol participants: Client and server. The client creates an initial message and transmits it to the server, which replies with its own message in response. The client continues querying the server until it is satisifed, and then terminates the protocol. Messages in either direction have the same format.
|
|
||||||
|
|
||||||
Each participant has a collection of records. A records consists of a 64-bit numeric timestamp and a 256-bit ID. Each participant starts by sorting their items according to timestamp, ascending. If two timestamps are equal then items are sorted lexically by ID, ascending by first differing byte. Items may not use the max uint64 value (`2**64 - 1`) as a timestamp since this is reserved as a special "infinity" value.
|
|
||||||
|
|
||||||
The goal of the protocol is for the client to learn the set of IDs that it has and the server does not, and the set of items that the server has and it does not.
|
|
||||||
|
|
||||||
### `Varint`
|
|
||||||
|
|
||||||
Varints (variable-sized unsigned integers) are represented as base-128 digits, most significant digit first, with as few digits as possible. Bit eight (the high bit) is set on each byte except the last.
|
|
||||||
|
|
||||||
Varint := <Digit+128>* <Digit>
|
|
||||||
|
|
||||||
### `Id`
|
|
||||||
|
|
||||||
IDs are represented as byte-strings of length `32`:
|
|
||||||
|
|
||||||
Id := Byte{32}
|
|
||||||
|
|
||||||
### `Message`
|
|
||||||
|
|
||||||
A reconciliation message is a protocol version byte followed by an ordered list of ranges:
|
|
||||||
|
|
||||||
Message := <protocolVersion (Byte)> <Range>*
|
|
||||||
|
|
||||||
The current protocol version is 1, represented by the byte `0x61`. Protocol version 2 will be `0x62`, and so forth. If a server receives a message with a protocol version that it cannot handle, it should reply with a single byte containing the highest protocol version it supports, allowing the client to downgrade and retry its message.
|
|
||||||
|
|
||||||
Each Range corresponds to a contiguous section of the timestamp/ID space. The first Range starts at timestamp 0 and an ID of 0 bytes. Ranges are always adjacent (no gaps). If the last Range doesn't end at the special infinity value, an implicit `Skip` to infinity Range is appended. This means that the list of Ranges always covers the full timestamp/ID space.
|
|
||||||
|
|
||||||
### `Range`
|
|
||||||
|
|
||||||
A Range consists of an upper bound, a mode, and a payload:
|
|
||||||
|
|
||||||
Range := <upperBound (Bound)> <mode (Varint)> <payload (Skip | Fingerprint | IdList)>
|
|
||||||
|
|
||||||
The contents of the payload is determined by mode:
|
|
||||||
|
|
||||||
* If `mode = 0`, then payload is `Skip`, meaning the sender does not wish to process this Range further. This payload is empty:
|
|
||||||
|
|
||||||
Skip :=
|
|
||||||
|
|
||||||
* If `mode = 1`, then payload is a `Fingerprint`, which is a [digest](#fingerprint-algorithm) of all the IDs the sender has within the Range:
|
|
||||||
|
|
||||||
Fingerprint := Byte{16}
|
|
||||||
|
|
||||||
* If `mode = 2`, the payload is `IdList`, a variable-length list of all IDs the sender has within the Range:
|
|
||||||
|
|
||||||
IdList := <length (Varint)> <ids (Id)>*
|
|
||||||
|
|
||||||
|
|
||||||
### `Bound`
|
|
||||||
|
|
||||||
Each Range is specified by an *inclusive* lower bound and an *exclusive* upper bound. As defined above, each Range only includes an upper bound: the lower bound of a Range is the upper bound of the previous Range, or 0 timestamp/0 ID for the first Range.
|
|
||||||
|
|
||||||
A Bound consists of an encoded timestamp and a variable-length disambiguating prefix of an ID (in case multiple items have the same timestamp):
|
|
||||||
|
|
||||||
Bound := <encodedTimestamp (Varint)> <length (Varint)> <idPrefix (Byte)>*
|
|
||||||
|
|
||||||
* The timestamp is encoded specially. The infinity timestamp is encoded as `0`. All other values are encoded as `1 + offset`, where offset is the difference between this timestamp and the previously encoded timestamp. The initial offset starts at `0` and resets at the beginning of each message.
|
|
||||||
|
|
||||||
Offsets are always non-negative since the upper bound's timestamp is greater than or equal to the lower bound's timestamp, ranges in a message are always encoded in ascending order, and ranges never overlap.
|
|
||||||
|
|
||||||
* The size of `idPrefix` is encoded in `length`, and can be between `0` and `32` bytes, inclusive. This allows implementations to use the shortest possible prefix to separate the first record of this Range from the last record of the previous Range. If these records' timestamps differ, then the length should be 0, otherwise it should be the byte-length of their common ID-prefix plus 1.
|
|
||||||
|
|
||||||
If the `idPrefix` length is less than `32` then the omitted trailing bytes are implicitly 0 bytes.
|
|
||||||
|
|
||||||
|
|
||||||
### Fingerprint Algorithm
|
|
||||||
|
|
||||||
The fingerprint of a Range is computed with the following algorithm:
|
|
||||||
|
|
||||||
* Compute the addition mod 2<sup>256</sup> of the element IDs (interpreted as 32-byte little-endian unsigned integers)
|
|
||||||
* Concatenate with the number of elements in the Range, encoded as a [Varint](#varint)
|
|
||||||
* Hash with SHA-256
|
|
||||||
* Take the first 16 bytes
|
|
||||||
2
84.md
2
84.md
@@ -23,7 +23,7 @@ or obvious non-useful information from the query string.
|
|||||||
### Attribution
|
### Attribution
|
||||||
Clients MAY include one or more `p` tags, tagging the original authors of the material being highlighted; this is particularly
|
Clients MAY include one or more `p` tags, tagging the original authors of the material being highlighted; this is particularly
|
||||||
useful when highlighting non-nostr content for which the client might be able to get a nostr pubkey somehow
|
useful when highlighting non-nostr content for which the client might be able to get a nostr pubkey somehow
|
||||||
(e.g. prompting the user or reading a `<link rel="me" href="nostr:nprofile1..." />` tag on the document). A role MAY be included as the
|
(e.g. prompting the user or reading a `<meta name="nostr:nprofile1..." />` tag on the document). A role MAY be included as the
|
||||||
last value of the tag.
|
last value of the tag.
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
|
|||||||
142
87.md
142
87.md
@@ -1,142 +0,0 @@
|
|||||||
NIP-87
|
|
||||||
======
|
|
||||||
|
|
||||||
Ecash Mint Discoverability
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
`draft` `optional`
|
|
||||||
|
|
||||||
This NIP describes `kind:38173`, `kind:38172` and `kind:38000`: a way to discover ecash mints, their capabilities, and people who recommend them.
|
|
||||||
|
|
||||||
## Rationale
|
|
||||||
|
|
||||||
Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics.
|
|
||||||
This NIP provides a simple way for users to discover ecash mints recommended by other users and to interact with them.
|
|
||||||
|
|
||||||
### Parties involved
|
|
||||||
|
|
||||||
There are three actors to this workflow:
|
|
||||||
|
|
||||||
* An ecash mint operator, announces their mint and its capabilities.
|
|
||||||
* Publishes `kind:38173` or `kind:38172`, detailing how to connect to it and its capabilities.
|
|
||||||
* user A, who recommends an ecash mint
|
|
||||||
* Publishes `kind:38000`
|
|
||||||
* user B, who seeks a recommendation for an ecash mint
|
|
||||||
* Queries for `kind:38000` and, based on results, queries for `kind:38173`/`kind:38172`
|
|
||||||
|
|
||||||
## Events
|
|
||||||
|
|
||||||
### Recommendation event
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"kind": 38000,
|
|
||||||
"pubkey": <recommender-user-pubkey>,
|
|
||||||
"tags": [
|
|
||||||
["k", "38173"],
|
|
||||||
["d", "<d-identifier>"],
|
|
||||||
["u", <recommended-fedimint-invite-code>],
|
|
||||||
["a", "38173:fedimint-pubkey:<d-identifier>", "wss://relay1"]
|
|
||||||
],
|
|
||||||
"content": "I trust this mint with my life"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The recommendation event is a parameterized-replacable event so that a user can change edit their recommendation without creating a new event.
|
|
||||||
|
|
||||||
The `d` tag in `kind:38000` is the `kind:38173`/`kind:38172` event identifier this event is recommending, if no event exists, the `d` tag can still be calculated from the mint's pubkey/id.
|
|
||||||
The `k` tag is the kind number that corresponds to the event kind that the user is recommending, in this case `kind:38173` for fedimints and `kind:38172` for cashu mints.
|
|
||||||
|
|
||||||
Optional `u` tags can be added to give a recommend way to connect to the mint.
|
|
||||||
The value of the tag is the URL or invite code of the ecash mint.
|
|
||||||
Multiple `u` tags can appear on the same `kind:38000`.
|
|
||||||
|
|
||||||
`a` tags are used to point to the `kind:38173`/`kind:38172` event of the ecash mint.
|
|
||||||
The first value of the tag is the `kind:38173`/`kind:38172` event identifier, the second value of the tag is a relay hint.
|
|
||||||
This is used to correctly point to the mint's `kind:38173`/`kind:38172` event in case there are duplicates claiming to be the same mint.
|
|
||||||
|
|
||||||
The content can be used to give a review.
|
|
||||||
|
|
||||||
## Ecash Mint Information
|
|
||||||
|
|
||||||
Cashu mints SHOULD publish `kind:38172` events to announce their capabilities and how to connect to them.
|
|
||||||
|
|
||||||
For cashu mints, the `u` tag SHOULD be the URL to the cashu mint and it should list the nuts that the cashu mint supports.
|
|
||||||
|
|
||||||
The `d` tag SHOULD be the mint's pubkey (found when querying `/v1/info`), this way users can query by pubkey and find the mint announcement.
|
|
||||||
|
|
||||||
An `n` tag SHOULD be added to signify the network the cashu mint is on (either `mainnet`, `testnet`, `signet`, or `regtest`)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"kind": 38172,
|
|
||||||
"pubkey": "<application-pubkey>",
|
|
||||||
"content": "<optional-kind:0-style-metadata>",
|
|
||||||
"tags": [
|
|
||||||
["d", <cashu mint pubkey>],
|
|
||||||
["u", "https://cashu.example.com"],
|
|
||||||
["nuts", "1,2,3,4,5,6,7"],
|
|
||||||
["n", "mainnet"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Fedimints SHOULD publish `kind:38173` events to announce their capabilities and how to connect to them.
|
|
||||||
|
|
||||||
For fedimints, it should list all known fedimint invite codes in `u` tags and it should list the modules it supports.
|
|
||||||
|
|
||||||
The `d` tag SHOULD be the federation id, this way users can query by federation id and find the fedimint announcement.
|
|
||||||
|
|
||||||
An `n` tag SHOULD be added to signify the network the fedimint is on (either `mainnet`, `testnet`, `signet`, or `regtest`)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"kind": 38173,
|
|
||||||
"pubkey": "<application-pubkey>",
|
|
||||||
"content": "<optional-kind:0-style-metadata>",
|
|
||||||
"tags": [
|
|
||||||
["d", <federation-id>],
|
|
||||||
["u", "fed11abc.."],
|
|
||||||
["u", "fed11xyz.."],
|
|
||||||
["modules", "lightning,wallet,mint"],
|
|
||||||
["n", "signet"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* `content` is an optional `metadata`-like stringified JSON object, as described in NIP-01. This content is useful when the pubkey creating the `kind:38173` is not a normal user. If `content` is empty, the `kind:0` of the pubkey should be used to display mint information (e.g. name, picture, web, LUD16, etc.)
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
### User A recommends some mints
|
|
||||||
User A might be a user of a cashu mint. Using a client, user A publishes an event recommending the cashu mint they use.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"kind": 38000,
|
|
||||||
"tags": [
|
|
||||||
["u", "fed11abc..", "fedimint"],
|
|
||||||
["u", "https://cashu.example.com", "cashu"],
|
|
||||||
["a", "38173:fedimint-pubkey:<d-identifier>", "wss://relay1", "fedimint"],
|
|
||||||
["a", "38172:cashu-mint-pubkey:<d-identifier>", "wss://relay2", "cashu"]
|
|
||||||
],
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### User B finds a mint
|
|
||||||
User B wants to use an ecash wallet, they need to find a mint.
|
|
||||||
|
|
||||||
User B's wallet client queries for `kind:38000` events, looking for recommendations for ecash mints.
|
|
||||||
|
|
||||||
```json
|
|
||||||
["REQ", <id>, [{ "kinds": [38000], "authors": [<user>, <users-contact-list>], "#k": ["38173"] }]]
|
|
||||||
```
|
|
||||||
|
|
||||||
User B, who follows User A, sees that `kind:38000` event and tries to connect to the corresponding mints.
|
|
||||||
|
|
||||||
### Alternative query bypassing `kind:38000`
|
|
||||||
Alternatively, users might choose to query directly for `kind:38173` for an event kind. Clients SHOULD be careful doing this and use spam-prevention mechanisms or querying high-quality restricted relays to avoid directing users to malicious handlers.
|
|
||||||
|
|
||||||
```json
|
|
||||||
["REQ", <id>, [{ "kinds": [38173], "authors": [...] }]]
|
|
||||||
```
|
|
||||||
2
99.md
2
99.md
@@ -8,7 +8,7 @@ Classified Listings
|
|||||||
|
|
||||||
This NIP defines `kind:30402`: an addressable event to describe classified listings that list any arbitrary product, service, or other thing for sale or offer and includes enough structured metadata to make them useful.
|
This NIP defines `kind:30402`: an addressable event to describe classified listings that list any arbitrary product, service, or other thing for sale or offer and includes enough structured metadata to make them useful.
|
||||||
|
|
||||||
The specification supports a broad range of use cases physical goods, services, work opportunities, rentals, free giveaways, personals, etc. To promote interoperability between clients implementing NIP-99 for e-commerce, you can find the extension proposal [here](https://github.com/GammaMarkets/market-spec/blob/main/spec.md) which standardizes the e-commerce use case while maintaining the specification's lightweight and flexible nature. While [NIP-15](15.md) provides a strictly structured marketplace specification, NIP-99 has emerged as a simpler and more flexible alternative.
|
The category of classifieds includes a very broad range of physical goods, services, work opportunities, rentals, free giveaways, personals, etc. and is distinct from the more strictly structured marketplaces defined in [NIP-15](15.md) that often sell many units of specific products through very specific channels.
|
||||||
|
|
||||||
The structure of these events is very similar to [NIP-23](23.md) long-form content events.
|
The structure of these events is very similar to [NIP-23](23.md) long-form content events.
|
||||||
|
|
||||||
|
|||||||
48
F3.md
48
F3.md
@@ -1,48 +0,0 @@
|
|||||||
NIP-F3
|
|
||||||
======
|
|
||||||
|
|
||||||
Scrobbling
|
|
||||||
----------
|
|
||||||
|
|
||||||
`draft` `optional`
|
|
||||||
|
|
||||||
This NIP defines `kind:1073` as a _scrobble_ event. It has the following format:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
{
|
|
||||||
"kind": 1073,
|
|
||||||
"tags": [
|
|
||||||
["i", "isrc:<code>"],
|
|
||||||
["title", "<song title>"],
|
|
||||||
["album", "<song album>", "<optional variant>"],
|
|
||||||
["artist", "<musician or band>", "<optional variant>"]
|
|
||||||
]
|
|
||||||
// other fields...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Metadata
|
|
||||||
|
|
||||||
`"title"`, `"album"` and `"artist"` should always be included, but in case the ISRC code is also included (as it should unless it's too impossible) ISRC can be seen as the authoritative source for all metadata related to the given song, the other tags being just hints.
|
|
||||||
|
|
||||||
### Relays
|
|
||||||
|
|
||||||
Scrobbles should be published to the author's "write" relays (as per [NIP-65](65.md)).
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
Given that Nostr is open it makes no sense to speak of a _global_ "most listened" tracks, for example, as _last.fm_ does.
|
|
||||||
|
|
||||||
It does make sense, however, for clients to display the "most listened" and other stats in the context of individual relays or groups of relays, as long as such relays are gated to a certain community or trusted to not have sybils or spam.
|
|
||||||
|
|
||||||
It also makes sense to display data such as "most listened by your friends", "most listened by friends of friends" and other arbitrary selections.
|
|
||||||
|
|
||||||
The same is true for things like a feed of "recently listened" tracks.
|
|
||||||
|
|
||||||
#### Commenting on tracks
|
|
||||||
|
|
||||||
It makes sense to comment on a track by using a [NIP-22](22.md) with a `"i"` tag containing its ISRC code, as specified in [NIP-73](73.md). That way it's possible to display comments in context with scrobbles on a track page, for example, and whatever else.
|
|
||||||
|
|
||||||
#### Correcting History
|
|
||||||
|
|
||||||
It shouldn't be hard to "edit" an old scrobble by simply deleting it and creating a new scrobble.
|
|
||||||
10
README.md
10
README.md
@@ -88,12 +88,10 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||||||
- [NIP-72: Moderated Communities](72.md)
|
- [NIP-72: Moderated Communities](72.md)
|
||||||
- [NIP-73: External Content IDs](73.md)
|
- [NIP-73: External Content IDs](73.md)
|
||||||
- [NIP-75: Zap Goals](75.md)
|
- [NIP-75: Zap Goals](75.md)
|
||||||
- [NIP-77: Negentropy Syncing](77.md)
|
|
||||||
- [NIP-78: Application-specific data](78.md)
|
- [NIP-78: Application-specific data](78.md)
|
||||||
- [NIP-7D: Threads](7D.md)
|
- [NIP-7D: Threads](7D.md)
|
||||||
- [NIP-84: Highlights](84.md)
|
- [NIP-84: Highlights](84.md)
|
||||||
- [NIP-86: Relay Management API](86.md)
|
- [NIP-86: Relay Management API](86.md)
|
||||||
- [NIP-87: Ecash Mint Discoverability](87.md)
|
|
||||||
- [NIP-88: Polls](88.md)
|
- [NIP-88: Polls](88.md)
|
||||||
- [NIP-89: Recommended Application Handlers](89.md)
|
- [NIP-89: Recommended Application Handlers](89.md)
|
||||||
- [NIP-90: Data Vending Machines](90.md)
|
- [NIP-90: Data Vending Machines](90.md)
|
||||||
@@ -108,6 +106,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||||||
- [NIP-C7: Chats](C7.md)
|
- [NIP-C7: Chats](C7.md)
|
||||||
|
|
||||||
## Event Kinds
|
## Event Kinds
|
||||||
|
|
||||||
| kind | description | NIP |
|
| kind | description | NIP |
|
||||||
| ------------- | ------------------------------- | -------------------------------------- |
|
| ------------- | ------------------------------- | -------------------------------------- |
|
||||||
| `0` | User Metadata | [01](01.md) |
|
| `0` | User Metadata | [01](01.md) |
|
||||||
@@ -200,7 +199,6 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||||||
| `10166` | Relay Monitor Announcement | [66](66.md) |
|
| `10166` | Relay Monitor Announcement | [66](66.md) |
|
||||||
| `13194` | Wallet Info | [47](47.md) |
|
| `13194` | Wallet Info | [47](47.md) |
|
||||||
| `17375` | Cashu Wallet Event | [60](60.md) |
|
| `17375` | Cashu Wallet Event | [60](60.md) |
|
||||||
| `17375` | Ecash Mint Recommendation | [87](87.md) |
|
|
||||||
| `21000` | Lightning Pub RPC | [Lightning.Pub][lnpub] |
|
| `21000` | Lightning Pub RPC | [Lightning.Pub][lnpub] |
|
||||||
| `22242` | Client Authentication | [42](42.md) |
|
| `22242` | Client Authentication | [42](42.md) |
|
||||||
| `23194` | Wallet Request | [47](47.md) |
|
| `23194` | Wallet Request | [47](47.md) |
|
||||||
@@ -248,11 +246,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||||||
| `31924` | Calendar | [52](52.md) |
|
| `31924` | Calendar | [52](52.md) |
|
||||||
| `31925` | Calendar Event RSVP | [52](52.md) |
|
| `31925` | Calendar Event RSVP | [52](52.md) |
|
||||||
| `31989` | Handler recommendation | [89](89.md) |
|
| `31989` | Handler recommendation | [89](89.md) |
|
||||||
| `31990` | Handler information | [89](89.md) |
|
| `31990` | Handler information | [89](89.md) | |
|
||||||
| `32267` | Software Application | |
|
| `32267` | Software Application | | |
|
||||||
| `34550` | Community Definition | [72](72.md) |
|
| `34550` | Community Definition | [72](72.md) |
|
||||||
| `38172` | Cashu Mint Announcement | [87](87.md) |
|
|
||||||
| `38173` | Fedimint Announcement | [87](87.md) |
|
|
||||||
| `38383` | Peer-to-peer Order events | [69](69.md) |
|
| `38383` | Peer-to-peer Order events | [69](69.md) |
|
||||||
| `39000-9` | Group metadata events | [29](29.md) |
|
| `39000-9` | Group metadata events | [29](29.md) |
|
||||||
| `39089` | Starter packs | [51](51.md) |
|
| `39089` | Starter packs | [51](51.md) |
|
||||||
|
|||||||
Reference in New Issue
Block a user