Compare commits

...

30 Commits

Author SHA1 Message Date
pablof7z
baa382ca7d move relay tags into encrypted section and remove from nip51 2025-10-08 15:37:10 +03:00
pablof7z
58cfc3189c relay tags in nip-60 on 17375 instead of 10019 2025-10-08 14:29:40 +03:00
Sandwich
b516adbf42 Fix fundamentally incorrect assertions in NIP-66 (#2067) 2025-09-20 07:39:40 -03:00
Yoji Shidara
90fcf4a44e NIP-11: add comma and remove empty lines (#2066) 2025-09-19 07:55:42 -04:00
hodlbod
abe6fb959c Remove lud06 field (#2065)
Co-authored-by: Jon Staab <shtaab@gmail.com>
2025-09-18 17:09:53 -07:00
AsaiToshiya
4b19bf2e40 delete BREAKING.md (#2058) 2025-09-18 12:30:58 +09:00
Roland
7dfb3b35d8 docs: clarify NIP-47 zap request metadata (#2064) 2025-09-17 08:07:11 -04:00
Roland
400d975da3 feat: add metadata to NIP-47 make_invoice and payment commands (#2063) 2025-09-15 09:42:07 -07:00
Rosano
e35a1bebbc Quote values (#2057)
Co-authored-by: Vitor Pamplona <vitor@vitorpamplona.com>
2025-09-10 15:48:05 -04:00
RΞDKAZ⚡
8b541fe8cd Curation sets (kind-30005) should be regular event e tag and not a. (#2059) 2025-09-10 07:32:39 -03:00
Vitor Pamplona
c3f92ca577 Deprecates NIP-96 (#2047) 2025-09-09 19:24:13 -03:00
AsaiToshiya
020609ed9f standard -> common 2025-09-09 19:01:01 +09:00
Vitor Pamplona
5d81c9100e Removing the idea of "Standard" Tags (#2055) 2025-09-08 15:25:05 -03:00
Yoji Shidara
3a126a51a6 Typos (#2054) 2025-09-07 06:04:01 -07:00
Vitor Pamplona
4c5d5fff99 Allow multi-user AUTH (#1881)
Co-authored-by: Leo Wandersleb <leo@leowandersleb.de>
2025-09-06 09:52:22 -03:00
SubatomicPlanets
d6fe55a6ad Fix weird list in NIP-99 (#2053) 2025-09-06 09:38:46 -03:00
Riccardo Balbo
7c4a2cb829 NIP-47: mark "state" field as optional in make_invoice response for backward compatibility (#2046) 2025-09-04 11:12:45 -04:00
Vitor Pamplona
3760a6e308 NIP-53 Text Refinements and formatting fixes (#2052) 2025-09-04 11:50:33 -03:00
Alex Gleason
8c45ff5d96 NIP-11: fix default_limit (#2049) 2025-09-02 22:39:19 -03:00
AsaiToshiya
fd9c627b36 add NIP-EE kinds (#2044) 2025-08-28 23:15:52 +09:00
Jeff Gardner
fe114c6473 Fix link to nostr_data_extension and clarify how to use exporter_secret with NIP-44 (#2043)
Co-authored-by: hodlbod <jstaab@protonmail.com>
2025-08-27 13:24:50 -07:00
Jeff Gardner
581452e845 Add NIP-EE: E2EE messaging using MLS (#1427) 2025-08-27 09:03:06 -07:00
Vitor Pamplona
1f4d6d1c46 NIP-51: Updates lists to NIP-44, deprecates NIP-04 (#2034) 2025-08-25 09:09:44 -07:00
AsaiToshiya
3f4c696f24 clean up B0. (#2039) 2025-08-22 16:20:13 -07:00
Oscar Merry
84e0b44f93 NIP-25: Add External Content Reactions (#2020) 2025-08-22 09:44:53 -07:00
Yoji Shidara
0d7c5ef0f8 NIP-61: Fix heading levels (#2030) 2025-08-19 09:12:04 -07:00
Yoji Shidara
d5bfb6e848 NIP-72: Fix heading levels (#2031) 2025-08-19 09:11:55 -07:00
Yoji Shidara
38bc891e67 NIP-89: Fix heading levels (#2032) 2025-08-19 09:11:47 -07:00
Yoji Shidara
c222f71102 NIP-60: Fix heading levels (#2029) 2025-08-19 09:11:40 -07:00
Yoji Shidara
68e5d0ada4 NIP-90: Fix heading levels (#2033) 2025-08-19 09:11:14 -07:00
20 changed files with 455 additions and 193 deletions

6
11.md
View File

@@ -20,11 +20,9 @@ When a relay receives an HTTP(s) request with an `Accept` header of `application
"contact": <administrative alternate contact>,
"supported_nips": <a list of NIP numbers supported by the relay>,
"software": <string identifying relay software URL>,
"version": <string version identifier>
"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>,
}
```
@@ -162,7 +160,7 @@ a specific niche kind or content. Normal anti-spam heuristics, for example, do n
- `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

28
25.md
View File

@@ -45,25 +45,39 @@ func make_like_event(pubkey: String, privkey: String, liked: NostrEvent, hint: S
}
```
Reactions to a website
External Content Reactions
---------------------
If the target of the reaction is a website, the reaction MUST be a `kind 17` event and MUST include an `r` tag with the website's URL.
If the target of a reaction is not a native nostr event, the reaction MUST be a `kind 17` event and MUST include [NIP-73](73.md) external content `k` + `i` tags to properly reference the content.
_Reacting to a website:_
```jsonc
{
"kind": 17,
"content": "⭐",
"tags": [
["r", "https://example.com/"]
["k", "web"],
["i", "https://example.com"]
],
// other fields...
}
```
URLs SHOULD be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6), so that reactions to the same website are not omitted from queries.
A fragment MAY be attached to the URL, to react to a section of the page.
It should be noted that a URL with a fragment is not considered to be the same URL as the original.
_Reacting to a podcast episode:_
```jsonc
{
"kind": 17,
"content": "+",
"tags": [
["k", "podcast:guid"],
["i", "podcast:guid:917393e3-1b1e-5cef-ace4-edaa54e1f810", "https://fountain.fm/show/QRT0l2EfrKXNGDlRrmjL"],
["k", "podcast:item:guid"],
["i", "podcast:item:guid:PC20-229", "https://fountain.fm/episode/DQqBg5sD3qFGMCZoSuLF"]
],
}
```
Custom Emoji Reaction
---------------------

4
42.md
View File

@@ -32,6 +32,8 @@ And, when sent by clients, the following form:
["AUTH", <signed-event-json>]
```
Clients MAY provide signed events from multiple pubkeys in a sequence of `AUTH` messages. Relays MUST treat all pubkeys as authenticated accordingly.
`AUTH` messages sent by clients MUST be answered with an `OK` message, like any `EVENT` message.
### Canonical authentication event
@@ -69,7 +71,9 @@ relay: ["AUTH", "<challenge>"]
client: ["REQ", "sub_1", {"kinds": [4]}]
relay: ["CLOSED", "sub_1", "auth-required: we can't serve DMs to unauthenticated users"]
client: ["AUTH", {"id": "abcdef...", ...}]
client: ["AUTH", {"id": "abcde2...", ...}]
relay: ["OK", "abcdef...", true, ""]
relay: ["OK", "abcde2...", true, ""]
client: ["REQ", "sub_1", {"kinds": [4]}]
relay: ["EVENT", "sub_1", {...}]
relay: ["EVENT", "sub_1", {...}]

48
47.md
View File

@@ -188,6 +188,7 @@ Request:
"params": {
"invoice": "lnbc50n1...", // bolt11 invoice
"amount": 123, // invoice amount in msats, optional
"metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc, optional
}
}
```
@@ -217,7 +218,7 @@ Request:
"params": {
"invoices": [
{"id":"4da52c32a1", "invoice": "lnbc1...", "amount": 123}, // bolt11 invoice and amount in msats, amount is optional
{"id":"3da52c32a1", "invoice": "lnbc50n1..."},
{"id":"3da52c32a1", "invoice": "lnbc50n1...", "metadata": {} }, // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc, optional
],
}
}
@@ -324,7 +325,8 @@ Request:
"amount": 123, // value in msats
"description": "string", // invoice's description, optional
"description_hash": "string", // invoice's description hash, optional
"expiry": 213 // expiry in seconds from time invoice is created, optional
"expiry": 213, // expiry in seconds from time invoice is created, optional
"metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc, optional
}
}
```
@@ -335,7 +337,7 @@ Response:
"result_type": "make_invoice",
"result": {
"type": "incoming", // "incoming" for invoices, "outgoing" for payments
"state": "pending",
"state": "pending", // optional
"invoice": "string", // encoded invoice, optional
"description": "string", // invoice's description, optional
"description_hash": "string", // invoice's description hash, optional
@@ -369,7 +371,7 @@ Response:
"result_type": "lookup_invoice",
"result": {
"type": "incoming", // "incoming" for invoices, "outgoing" for payments
"state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments)
"state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments), optional
"invoice": "string", // encoded invoice, optional
"description": "string", // invoice's description, optional
"description_hash": "string", // invoice's description hash, optional
@@ -418,7 +420,7 @@ Response:
"transactions": [
{
"type": "incoming", // "incoming" for invoices, "outgoing" for payments
"state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments)
"state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments), optional
"invoice": "string", // encoded invoice, optional
"description": "string", // invoice's description, optional
"description_hash": "string", // invoice's description hash, optional
@@ -495,7 +497,7 @@ Notification:
"notification_type": "payment_received",
"notification": {
"type": "incoming",
"state": "settled",
"state": "settled", // optional
"invoice": "string", // encoded invoice
"description": "string", // invoice's description, optional
"description_hash": "string", // invoice's description hash, optional
@@ -521,7 +523,7 @@ Notification:
"notification_type": "payment_sent",
"notification": {
"type": "outgoing",
"state": "settled",
"state": "settled", // optional
"invoice": "string", // encoded invoice
"description": "string", // invoice's description, optional
"description_hash": "string", // invoice's description hash, optional
@@ -612,6 +614,38 @@ The **client** should check the `encryption` tag in the `info` event to determin
## Using a dedicated relay
This NIP does not specify any requirements on the type of relays used. However, if the user is using a custodial service it might make sense to use a relay that is hosted by the custodial service. The relay may then enforce authentication to prevent metadata leaks. Not depending on a 3rd party relay would also improve reliability in this case.
## Metadata
Metadata MAY be stored by the **wallet service** alongside invoices and payments. The metadata MUST be no more than 4096 characters, otherwise MUST be dropped. This is to ensure transactions do not get too large to be relayed.
NWC relays SHOULD allow at least a payload size of 64KB and **clients** SHOULD fetch small page sizes (maximum of 20 transactions per page) otherwise there is risk of `list_transactions` responses being rejected.
Here are some properties that are recognized by some NWC clients:
```jsonc
{
"comment": "string", // LUD-12 comment
"payer_data": {
"email": "string",
"name": "string",
"pubkey": "string",
}, // LUD-18 payer data
"recipient_data": {
"identifier": "string"
}, // similar to LUD-18 payer data, but to record recipient data e.g. the lightning address of the recipient
"nostr": {
"pubkey": "string",
"tags": [],
// ... rest of zap request event
}, // NIP-57 Zap Request event (kind 9734)
"tlv_records": [
{
"type": 5482373484, // tlv type
"value": "0123456789abcdef" // hex encoded tlv value
}
] // keysend TLV records (e.g. for podcasting 2.0 boostagrams)
} & Record<string, unknown>;
```
## Appendix
### Example NIP-47 info event

6
51.md
View File

@@ -8,7 +8,7 @@ Lists
This NIP defines lists of things that users can create. Lists can contain references to anything, and these references can be **public** or **private**.
Public items in a list are specified in the event `tags` array, while private items are specified in a JSON array that mimics the structure of the event `tags` array, but stringified and encrypted using the same scheme from [NIP-04](04.md) (the shared key is computed using the author's public and private key) and stored in the `.content`.
Public items in a list are specified in the event `tags` array, while private items are specified in a JSON array that mimics the structure of the event `tags` array, but stringified and encrypted using the same scheme from [NIP-44](44.md) (the shared key is computed using the author's public and private key) and stored in the `.content`. An earlier version of this specification used [NIP-04](04.md) for encryptions. Those are now deprecated. For backward compatibility, Clients can automatically discover if the encryption is NIP-04 or NIP-44 by searching for "iv" in the ciphertext and decrypting accordingly.
When new items are added to an existing list, clients SHOULD append them to the end of the list, so they are stored in chronological order.
@@ -54,7 +54,7 @@ Aside from their main identifier, the `"d"` tag, sets can optionally have a `"ti
| Relay sets | 30002 | user-defined relay groups the user can easily pick and choose from during various operations | `"relay"` (relay URLs) |
| Bookmark sets | 30003 | user-defined bookmarks categories , for when bookmarks must be in labeled separate groups | `"e"` (kind:1 notes), `"a"` (kind:30023 articles), `"t"` (hashtags), `"r"` (URLs) |
| Curation sets | 30004 | groups of articles picked by users as interesting and/or belonging to the same category | `"a"` (kind:30023 articles), `"e"` (kind:1 notes) |
| Curation sets | 30005 | groups of videos picked by users as interesting and/or belonging to the same category | `"a"` (kind:21 videos) |
| Curation sets | 30005 | groups of videos picked by users as interesting and/or belonging to the same category | `"e"` (kind:21 videos) |
| Kind mute sets | 30007 | mute pubkeys by kinds<br>`"d"` tag MUST be the kind string | `"p"` (pubkeys) |
| Interest sets | 30015 | interest topics represented by a bunch of "hashtags" | `"t"` (hashtags) |
| Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) |
@@ -165,6 +165,6 @@ val private_items = [
["p", "07caba282f76441955b695551c3c5c742e5b9202a3784780f8086fdcdc1da3a9"],
["a", "a55c15f5e41d5aebd236eca5e0142789c5385703f1a7485aa4b38d94fd18dcc4"],
]
val base64blob = nip04.encrypt(json.encode_to_string(private_items))
val base64blob = nip44.encrypt(json.encode_to_string(private_items))
event.content = base64blob
```

55
53.md
View File

@@ -6,13 +6,13 @@ Live Activities
`draft` `optional`
Service providers want to offer live activities 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 the involvement of pubkeys in such live activities.
This NIP introduces event kinds to advertise live spaces and the participation of pubkeys in them.
## Concepts
## Live Streaming
### Live Event
A special event with `kind:30311` "Live Streaming Event" is defined as an _addressable event_ whose tags advertise the content and participants of a live stream.
A special event with `kind:30311` "Live Event" is defined as an _addressable event_ of public `p` tags. Each `p` tag SHOULD have a **displayable** marker name for the current role (e.g. `Host`, `Speaker`, `Participant`) of the user in the event and the relay information MAY be empty. This event will be constantly updated as participants join and leave the activity.
Each `p` tag SHOULD have a **displayable** marker name for the current role (e.g. `Host`, `Speaker`, `Participant`) of the user in the event and the relay information MAY be empty. This event will be constantly updated as participants join and leave the activity.
For example:
@@ -63,13 +63,13 @@ This feature is important to avoid malicious event owners adding large account h
### Live Chat Message
Event `kind:1311` is live chat's channel message. Clients MUST include the `a` tag of the activity. An `e` tag denotes the direct parent message this post is replying to.
Event `kind:1311` is live chat's channel message. Clients MUST include the `a` tag of the activity. An `e` tag denotes the direct parent message this post is replying to.
```jsonc
{
"kind": 1311,
"tags": [
["a", "30311:<Community event author pubkey>:<d-identifier of the community>", "<Optional relay url>", "root"],
["a", "30311:<Community event author pubkey>:<d-identifier of the community>", "<Optional relay url>"],
],
"content": "Zaps to live streams is beautiful.",
// other fields...
@@ -84,13 +84,9 @@ Event `kind:1311` is live chat's channel message. Clients MUST include the `a` t
Hosts may choose to pin one or more live chat messages by updating the `pinned` tags in the live event kind `30311`.
## Use Cases
### Examples
Common use cases include meeting rooms/workshops, watch-together activities, or event spaces, such as [zap.stream](https://zap.stream).
## Example
### Live Streaming
#### Live Streaming
```json
{
@@ -114,7 +110,7 @@ Common use cases include meeting rooms/workshops, watch-together activities, or
}
```
### Live Streaming chat message
#### Live Streaming chat message
```json
{
@@ -130,18 +126,13 @@ Common use cases include meeting rooms/workshops, watch-together activities, or
}
```
## Interactive Rooms and Meetings
-----
## Meeting Spaces
`draft` `optional`
Meeting spaces contain one or more video/audio rooms where users can join and participate in the streaming.
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.
### Meeting Space Event (kind:30312)
## 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.
A special event with `kind:30312` "Space Host" defines the configuration and properties of a virtual interactive space. Each space has a unique identifier and can host multiple events/meetings.
```jsonc
{
@@ -162,19 +153,20 @@ A special event with `kind:30312` "Interactive Room" defines the configuration a
}
```
Room properties:
Space 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)
### Meeting Room Events (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.
@@ -183,7 +175,7 @@ A special event with kind:30313 represents a scheduled or ongoing meeting within
"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
["a", "30312:<pubkey>:<room-id>", "wss://nostr.example.com"], // Required: Reference to parent space, 'd' from 30312
["title", "<meeting-title>"], // Required: Meeting title
["summary", "<description>"], // Optional: Meeting description
["image", "<preview image url>"], // Optional: Meeting image
@@ -204,14 +196,15 @@ Event properties:
* 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
### Examples
Interactive Room (kind:30312)
#### Meeting Space (kind:30312)
```jsonc
{
@@ -233,7 +226,7 @@ Interactive Room (kind:30312)
}
```
Conference Event (kind:30313)
#### Meeting room (kind:30313)
```jsonc
{
@@ -254,11 +247,11 @@ Conference Event (kind:30313)
"content": ""
}
```
## Room Presence
### Room Presence
New `kind: 10312` provides an event which signals presence of a listener.
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
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.**

2
57.md
View File

@@ -12,7 +12,7 @@ Having lightning receipts on nostr allows clients to display lightning payments
## Protocol flow
1. Client calculates a recipient's lnurl pay request url from the `zap` tag on the event being zapped (see Appendix G), or by decoding their lud06 or lud16 field on their profile according to the [lnurl specifications](https://github.com/lnurl/luds). The client MUST send a GET request to this url and parse the response. If `allowsNostr` exists and it is `true`, and if `nostrPubkey` exists and is a valid BIP 340 public key in hex, the client should associate this information with the user, along with the response's `callback`, `minSendable`, and `maxSendable` values.
1. Client calculates a recipient's lnurl pay request url from the `zap` tag on the event being zapped (see Appendix G), or by decoding their lud16 field on their profile according to the [lnurl specifications](https://github.com/lnurl/luds). The client MUST send a GET request to this url and parse the response. If `allowsNostr` exists and it is `true`, and if `nostrPubkey` exists and is a valid BIP 340 public key in hex, the client should associate this information with the user, along with the response's `callback`, `minSendable`, and `maxSendable` values.
2. Clients may choose to display a lightning zap button on each post or on a user's profile. If the user's lnurl pay request endpoint supports nostr, the client SHOULD use this NIP to request a `zap receipt` rather than a normal lnurl invoice.
3. When a user (the "sender") indicates they want to send a zap to another user (the "recipient"), the client should create a `zap request` event as described in Appendix A of this NIP and sign it.
4. Instead of publishing the `zap request`, the `9734` event should instead be sent to the `callback` url received from the lnurl pay endpoint for the recipient using a GET request. See Appendix B for details and an example.

33
60.md
View File

@@ -16,19 +16,21 @@ The purpose of this NIP is:
This NIP doesn't deal with users' *receiving* money from someone else, it's just to keep state of the user's wallet.
# High-level flow
## High-level flow
1. A user has a `kind:17375` event that represents a wallet.
2. A user has `kind:7375` events that represent the unspent proofs of the wallet. -- The proofs are encrypted with the user's private key.
3. A user has `kind:7376` events that represent the spending history of the wallet -- This history is for informational purposes only and is completely optional.
## Wallet Event
### Wallet Event
```jsonc
{
"kind": 17375,
"content": nip44_encrypt([
[ "privkey", "hexkey" ],
[ "mint", "https://mint1" ],
[ "mint", "https://mint2" ]
[ "mint", "https://mint2" ],
[ "relay", "wss://relay1.example.com" ],
[ "relay", "wss://relay2.example.com" ]
]),
"tags": []
}
@@ -36,11 +38,12 @@ This NIP doesn't deal with users' *receiving* money from someone else, it's just
The wallet event is an replaceable event `kind:17375`.
Tags:
Encrypted Tags:
* `mint` - Mint(s) this wallet uses -- there MUST be one or more mint tags.
* `privkey` - Private key used to unlock P2PK ecash. MUST be stored encrypted in the `.content` field. **This is a different private key exclusively used for the wallet, not associated in any way to the user's Nostr private key** -- This is only used for receiving [NIP-61](61.md) nutzaps.
* `relay` - Relay(s) where the wallet's events (`kind:7374`, `kind:7375`, `kind:7376`) are published to and queried from. Clients MUST use these relays for all wallet operations. If no `relay` tags are present, clients SHOULD fall back to the user's [NIP-65](65.md) relay list.
## Token Event
### Token Event
Token events are used to record unspent proofs.
There can be multiple `kind:7375` events for the same mint, and multiple proofs inside each `kind:7375` event.
@@ -75,7 +78,7 @@ When one or more proofs of a token are spent, the token event should be [NIP-09]
The `kind:5` _delete event_ created in the [NIP-09](09.md) process MUST have a tag `["k", "7375"]` to allow easy filtering by clients interested in state transitions.
## Spending History Event
### Spending History Event
Clients SHOULD publish `kind:7376` events to create a transaction history when their balance changes.
```jsonc
@@ -103,17 +106,21 @@ All tags can be [NIP-44](44.md) encrypted. Clients SHOULD leave `e` tags with a
Multiple `e` tags can be added, and should be encrypted, except for tags with the `redeemed` marker.
# Flow
A client that wants to check for user's wallets information starts by fetching `kind:10019` events from the user's relays, if no event is found, it should fall back to using the user's [NIP-65](65.md) relays.
## Flow
A client that wants to check for user's wallet information:
## Fetch wallet and token list
From those relays, the client should fetch wallet and token events.
1. Fetches the user's `kind:17375` wallet event from the user's [NIP-65](65.md) relays (or any known relays)
2. Reads the `relay` tags from the wallet event to determine which relays to use for wallet operations
3. If no `relay` tags are present, falls back to using the user's [NIP-65](65.md) relay list
### Fetch wallet and token list
Using the relays from the wallet event's `relay` tags (or NIP-65 relays if not specified), the client should fetch wallet and token events:
`"kinds": [17375, 7375], "authors": ["<my-pubkey>"]`
## Fetch proofs
### Fetch proofs
## Spending token
### Spending token
If Alice spends 4 sats from this token event
```jsonc
{
@@ -166,7 +173,7 @@ Her client:
}
```
## Redeeming a quote (optional)
### Redeeming a quote (optional)
When creating a quote at a mint, an event can be used to keep the state of the quote ID, which will be used to check when the quote has been paid. These events should be created with an expiration tag [NIP-40](40.md) of 2 weeks (which is around the maximum amount of time a Lightning payment may be in-flight).
However, application developers SHOULD use local state when possible and only publish this event when it makes sense in the context of their application.

20
61.md
View File

@@ -8,19 +8,19 @@ Nutzaps
A Nutzap is a P2PK Cashu token in which the payment itself is the receipt.
# High-level flow
## High-level flow
Alice wants to nutzap 1 sat to Bob because of an event `event-id-1` she liked.
## Alice nutzaps Bob
### Alice nutzaps Bob
1. Alice fetches event `kind:10019` from Bob to see the mints Bob trusts.
2. She mints a token at that mint (or swaps some tokens she already had in that mint) P2PK-locked to the pubkey Bob has listed in his `kind:10019`.
3. She publishes a `kind:9321` event to the relays Bob indicated with the proofs she minted.
## Bob receives the nutzap
### Bob receives the nutzap
1. At some point, Bob's client fetches `kind:9321` events p-tagging him from his relays.
2. Bob's client swaps the token into his wallet.
# Nutzap informational event
## Nutzap informational event
```jsonc
{
"kind": 10019,
@@ -39,7 +39,7 @@ Alice wants to nutzap 1 sat to Bob because of an event `event-id-1` she liked.
* `mint`: mints the user is explicitly agreeing to use to receive funds on. Clients SHOULD not send money on mints not listed here or risk burning their money. Additional markers can be used to list the supported base units of the mint.
* `pubkey`: Public key that MUST be used to P2PK-lock receiving nutzaps -- implementations MUST NOT use the target user's main Nostr public key. This public key corresponds to the `privkey` field encrypted in a user's [nip-60](60.md) _wallet event_.
## Nutzap event
### Nutzap event
Event `kind:9321` is a nutzap event published by the sender, p-tagging the recipient. The outputs are P2PK-locked to the public key the recipient indicated in their `kind:10019` event.
Clients MUST prefix the public key they P2PK-lock with `"02"` (for nostr<>cashu compatibility).
@@ -66,13 +66,13 @@ Clients MUST prefix the public key they P2PK-lock with `"02"` (for nostr<>cashu
* `p` is the Nostr identity public key of nutzap recipient.
* `e` is the event that is being nutzapped, if any.
# Sending a nutzap
## Sending a nutzap
* The sender fetches the recipient's `kind:10019`.
* The sender mints/swaps ecash on one of the recipient's listed mints.
* The sender P2PK-locks to the recipient's specified public key in their `kind:10019`
# Receiving nutzaps
## Receiving nutzaps
Clients should REQ for nutzaps:
* Filtering with `#u` for mints they expect to receive ecash from.
@@ -84,7 +84,7 @@ Clients should REQ for nutzaps:
Upon receiving a new nutzap, the client should swap the tokens into a wallet the user controls, either a [NIP-60](60.md) wallet, their own LN wallet or anything else.
## Updating nutzap-redemption history
### Updating nutzap-redemption history
When claiming a token the client SHOULD create a `kind:7376` event and `e` tag the original nutzap event. This is to record that this token has already been claimed (and shouldn't be attempted again) and as signaling to the recipient that the ecash has been redeemed.
Multiple `kind:9321` events can be tagged in the same `kind:7376` event.
@@ -106,7 +106,7 @@ Multiple `kind:9321` events can be tagged in the same `kind:7376` event.
Events that redeem a nutzap SHOULD be published to the sender's [NIP-65](65.md) "read" relays.
## Verifying a Cashu Zap
### Verifying a Cashu Zap
When listing or counting zaps received by any given event, observer clients SHOULD:
* check that the receiving user has issued a `kind:10019` tagging the mint where the cashu has been minted.
@@ -116,7 +116,7 @@ When listing or counting zaps received by any given event, observer clients SHOU
All these checks can be done offline (as long as the observer has the receiver mints' keyset and their `kind:10019` event), so the process should be reasonably fast.
## Final Considerations
### Final Considerations
1. Clients SHOULD guide their users to use NUT-11 (P2PK) and NUT-12 (DLEQ proofs) compatible-mints in their `kind:10019` event to avoid receiving nutzaps anyone can spend.
2. Clients SHOULD normalize and deduplicate mint URLs as described in NIP-65.
3. A nutzap event MUST include proofs in one of the mints the recipient has listed in their `kind:10019` and published to the NIP-65 relays of the recipient, failure to do so may result in the recipient donating the tokens to the mint since the recipient might never see the event.

4
66.md
View File

@@ -28,10 +28,8 @@ Other tags include:
- `N` - NIPs supported by the relay
- `R` - Keys corresponding to requirements per [NIP 11](https://github.com/nostr-protocol/nips/blob/master/11.md)'s `limitations` array, including `auth`, `writes`, `pow`, and `payment`. False values should be specified using a `!` prefix, for example `!auth`.
- `t` - A topic associated with this relay
- `k` - An event kind accepted by the relay
- `!k` - An event kind not accepted by the relay
- `k` - Accepted and unaccepted kinds (false values prepended by `!`)
- `g` - A [NIP-52](https://github.com/nostr-protocol/nips/blob/master/52.md) geohash
- `l` - A language tag
Tags with more than one value should be repeated, rather than putting all values in a single tag, for example `[["t", "cats"], ["t", "dogs"]]`, rather than `[["t", "cats", "dogs"]]`.

8
71.md
View File

@@ -85,15 +85,15 @@ Additionally `service nip96` may be included to allow clients to search the auth
```jsonc
{
"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>,
"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>",
"created_at": <Unix timestamp in seconds>,
"kind": 21 | 22,
"content": "<summary / description of video>",
"tags": [
["title", "<title of video>"],
["published_at", "<unix timestamp>"],
["alt", <description>],
["alt", "<description>"],
// video Data
["imeta",
@@ -108,7 +108,7 @@ Additionally `service nip96` may be included to allow clients to search the auth
"service nip96",
],
["duration", <duration of video in seconds>],
["duration", "<duration of video in seconds>"],
["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"],
["content-warning", "<reason>"],
["segment", <start>, <end>, "<title>", "<thumbnail URL>"],

14
72.md
View File

@@ -8,7 +8,7 @@ Moderated Communities (Reddit Style)
The goal of this NIP is to enable public communities. It defines the replaceable event `kind:34550` to define the community and the current list of moderators/administrators. Users that want to post into the community, simply tag any Nostr event with the community's `a` tag. Moderators may issue an approval event `kind:4550`.
# Community Definition
## Community Definition
`Kind:34550` SHOULD include any field that helps define the community and the set of moderators. `relay` tags MAY be used to describe the preferred relay to download requests and approvals. A community definition event's `d` tag MAY double as its name, but if a `name` tag is provided, it SHOULD be displayed instead of the `d` tag.
@@ -39,11 +39,11 @@ 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.
## Top-level posts
### Top-level posts
For top-level posts, the uppercase and lowercase NIP-22 tags should both refer to the community definition itself.
@@ -63,7 +63,7 @@ For top-level posts, the uppercase and lowercase NIP-22 tags should both refer t
}
```
## Nested replies
### 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.
@@ -86,11 +86,11 @@ For nested replies, the uppercase tags should still refer to the community defin
}
```
## Backwards compatibility note
### 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.
@@ -127,6 +127,6 @@ Since relays are instructed to delete old versions of a replaceable event, the `
Clients SHOULD evaluate any non-`34550:*` `a` tag as posts to be approved for all `34550:*` `a` tags.
# Cross-posting
## Cross-posting
Clients MAY support cross-posting between communities by posting a NIP 18 `kind 6` or `kind 16` repost to one or more communities using `a` tags as described above. The `content` of the repost MUST be the original event, not the approval event.

4
89.md
View File

@@ -47,7 +47,7 @@ Multiple `a` tags can appear on the same `kind:31989`.
The second value of the tag SHOULD be a relay hint.
The third value of the tag SHOULD be the platform where this recommendation might apply.
## Handler information
### Handler information
```jsonc
{
"kind": 31990,
@@ -76,7 +76,7 @@ Multiple tags might be registered by the app, following NIP-19 nomenclature as t
A tag without a second value in the array SHOULD be considered a generic handler for any NIP-19 entity that is not handled by a different tag.
# Client tag
## Client tag
When publishing events, clients MAY include a `client` tag. Identifying the client that published the note. This tag is a tuple of `name`, `address` identifying a handler event and, a relay `hint` for finding the handler event. This has privacy implications for users, so clients SHOULD allow users to opt-out of using this tag.
```jsonc

14
90.md
View File

@@ -68,7 +68,7 @@ All tags are optional.
* `relays`: List of relays where Service Providers SHOULD publish responses to
* `p`: Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job
## Encrypted Params
### Encrypted Params
If the user wants to keep the input parameters a secret, they can encrypt the `i` and `param` tags with the service provider's 'p' tag and add it to the content field. Add a tag `encrypted` as tags. Encryption for private tags will use [NIP-04 - Encrypted Direct Message encryption](04.md), using the user's private and service provider's public key for the shared secret
@@ -122,7 +122,7 @@ Service providers publish job results, providing the output of the job result. T
* `amount`: millisats that the Service Provider is requesting to be paid. An optional third value can be a bolt11 invoice.
* `i`: The original input(s) specified in the request.
## Encrypted Output
### Encrypted Output
If the request has encrypted params, then output should be encrypted and placed in `content` field. If the output is encrypted, then avoid including `i` tag with input-data as clear text.
Add a tag encrypted to mark the output content as `encrypted`
@@ -180,7 +180,7 @@ Service providers can give feedback about a job back to the customer.
Any job feedback event MIGHT include results in the `.content` field, as described in the [Job Result](#job-result-kind6000-6999) section. This is useful for service providers to provide a sample of the results that have been processed so far.
# Protocol Flow
## Protocol Flow
* Customer publishes a job request (e.g. `kind:5000` speech-to-text).
* Service Providers MAY submit `kind:7000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.).
@@ -191,24 +191,24 @@ Job feedback (`kind:7000`) and Job Results (`kind:6000-6999`) events MAY include
Customers can always either pay the included `bolt11` invoice or zap the event requesting the payment and service providers should monitor for both if they choose to include a bolt11 invoice.
## Notes about the protocol flow
### Notes about the protocol flow
The flow is deliberately ambiguous, allowing vast flexibility for the interaction between customers and service providers so that service providers can model their behavior based on their own decisions/perceptions of risk.
Some service providers might choose to submit a `payment-required` as the first reaction before sending a `processing` or before delivering results, some might choose to serve partial results for the job (e.g. a sample), send a `payment-required` to deliver the rest of the results, and some service providers might choose to assess likelihood of payment based on an npub's past behavior and thus serve the job results before requesting payment for the best possible UX.
It's not up to this NIP to define how individual vending machines should choose to run their business.
# Cancellation
## Cancellation
A job request might be canceled by publishing a `kind:5` delete request event tagging the job request event.
# Appendix 1: Job chaining
## Appendix 1: Job chaining
A Customer MAY request multiple jobs to be processed as a chain, where the output of a job is the input of another job. (e.g. podcast transcription -> summarization of the transcription). This is done by specifying as input an event id of a different job with the `job` type.
Service Providers MAY begin processing a subsequent job the moment they see the prior job's result, but they will likely wait for a zap to be published first. This introduces a risk that Service Provider of job #1 might delay publishing the zap event in order to have an advantage. This risk is up to Service Providers to mitigate or to decide whether the service provider of job #1 tends to have good-enough results so as to not wait for an explicit zap to assume the job was accepted.
This gives a higher level of flexibility to service providers (which sophisticated service providers would take anyway).
# Appendix 2: Service provider discoverability
## Appendix 2: Service provider discoverability
Service Providers MAY use NIP-89 announcements to advertise their support for job kinds:
```jsonc

2
96.md
View File

@@ -1,3 +1,5 @@
> __Warning__ `unrecommended`: deprecated in favor of [NIP-B7](B7.md)
NIP-96
======

4
99.md
View File

@@ -40,7 +40,7 @@ The following tags, used for structured metadata, are standardized and SHOULD be
- `"<number>"` is the amount in numeric format (but included in the tag as a string)
- `"<currency>"` is the currency unit in 3-character ISO 4217 format or ISO 4217-like currency code (e.g. `"btc"`, `"eth"`).
- `"<frequency>"` is optional and can be used to describe recurring payments. SHOULD be in noun format (hour, day, week, month, year, etc.)
- - `"status"` (optional), the status of the listing. SHOULD be either "active" or "sold".
- `"status"` (optional), the status of the listing. SHOULD be either "active" or "sold".
#### `price` examples
@@ -48,7 +48,7 @@ The following tags, used for structured metadata, are standardized and SHOULD be
- €15 per month `["price", "15", "EUR", "month"]`
- £50,000 per year `["price", "50000", "GBP", "year"]`
Other standard tags that might be useful.
Other common tags that might be useful.
- `"g"`, a geohash for more precise location

22
B0.md
View File

@@ -6,31 +6,23 @@ Web Bookmarking
`draft` `optional`
This NIP defines `kind:39701` (an _addressable event_) for a URI as a web bookmark which uses the HTTP (Hypertext transfer protocol) scheme.
These web bookmark events are _addressable_ and deletable per [NIP-09](09.md).
### Editability
Web bookmarks are meant to be editable, so they should include a `d` tag with an identifier for the bookmark. Clients should take care to only publish and read these events from relays that implement that. If they don't do that they should also take care to hide old versions of the same bookmark they may receive.
This NIP defines `kind:39701` for a URI as editable web bookmark which uses the HTTP scheme.
### Format
The format uses an _addressable event_ of `kind:39701`.
The format uses `kind:39701`.
The `.content` of these events should be a detailed description of the web bookmark. It is required but can be an empty string.
The `.content` should be a detailed description of the web bookmark. It can be an empty string.
The `d` tag is required.
The `d` tag is just their URL without the scheme, which is always and everywhere assumed to be `https://` or `http://`.
In this way web bookmarks events can be queried by the `d` tag by clients, which is just their URL without the scheme, which is always and everywhere assumed to be `https://` or `http://`.
The querystring and the hash must be removed entirely, unless their requirement is explicitly stated either by the user or by some hardcoded list of URLs that rely on querystrings for basic routing provided by the client.
In this way web bookmarks events can be queried by the `d` tag by clients.
### Metadata
For the date of the last update the `.created_at` field should be used. For "tags"/"hashtags" (i.e. topics about which the event might be of relevance) the `t` tag should be used.
Other metadata fields can be added as tags to the event as necessary.
Metadata fields can be added as tags to the event as necessary.
* `"t"`, for "tags"/"hashtags" (i.e. topics about which the event might be of relevance)
* `"published_at"`, for the timestamp in unix seconds (stringified) of the first time the bookmark was published
* `"title"`, title about bookmark and can be used as a attribute for the HTML link element

View File

@@ -1,68 +0,0 @@
# Breaking Changes
This is a history of NIP changes that potentially break pre-existing implementations, in
reverse chronological order.
| Date | Commit | NIP | Change |
| ----------- | --------- | -------- | ------ |
| 2025-02-14 | [81908b6e](https://github.com/nostr-protocol/nips/commit/81908b6e) | [07](07.md), [46](46.md), [55](55.md) | `getRelays` and `get_relays` were removed |
| 2025-02-07 | [0023ca81](https://github.com/nostr-protocol/nips/commit/0023ca81) | [10](10.md) | `"mention"` marker was removed |
| 2025-01-31 | [6a4b125a](https://github.com/nostr-protocol/nips/commit/6a4b125a) | [71](71.md) | video events were changed to regular |
| 2024-12-05 | [6d16019e](https://github.com/nostr-protocol/nips/commit/6d16019e) | [46](46.md) | message encryption was changed to NIP-44 |
| 2024-11-12 | [2838e3bd](https://github.com/nostr-protocol/nips/commit/2838e3bd) | [29](29.md) | `kind: 12` and `kind: 10` were removed (use `kind: 1111` instead) |
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | NIP-05 login was removed |
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | `create_account` method was removed |
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | `connect` params and result were changed |
| 2024-10-29 | [f1e8d2c4](https://github.com/nostr-protocol/nips/commit/f1e8d2c4) | [46](46.md) | bunker URL should use `remote-signer-key` |
| 2024-10-15 | [1cda2dcc](https://github.com/nostr-protocol/nips/commit/1cda2dcc) | [71](71.md) | some tags were replaced with `imeta` tag |
| 2024-10-15 | [1cda2dcc](https://github.com/nostr-protocol/nips/commit/1cda2dcc) | [71](71.md) | `kind: 34237` was dropped |
| 2024-10-07 | [7bb8997b](https://github.com/nostr-protocol/nips/commit/7bb8997b) | [55](55.md) | some fields and passing data were changed |
| 2024-08-18 | [3aff37bd](https://github.com/nostr-protocol/nips/commit/3aff37bd) | [54](54.md) | content should be Asciidoc |
| 2024-07-31 | [3ea2f1a4](https://github.com/nostr-protocol/nips/commit/3ea2f1a4) | [45](45.md) | [444ad28d](https://github.com/nostr-protocol/nips/commit/444ad28d) was reverted |
| 2024-07-30 | [444ad28d](https://github.com/nostr-protocol/nips/commit/444ad28d) | [45](45.md) | NIP-45 was deprecated |
| 2024-07-26 | [ecee40df](https://github.com/nostr-protocol/nips/commit/ecee40df) | [19](19.md) | `nrelay` was deprecated |
| 2024-07-23 | [0227a2cd](https://github.com/nostr-protocol/nips/commit/0227a2cd) | [01](01.md) | events should be sorted by id after created_at |
| 2024-06-06 | [58e94b20](https://github.com/nostr-protocol/nips/commit/58e94b20) | [25](25.md) | [8073c848](https://github.com/nostr-protocol/nips/commit/8073c848) was reverted |
| 2024-06-06 | [a6dfc7b5](https://github.com/nostr-protocol/nips/commit/a6dfc7b5) | [55](55.md) | NIP number was changed |
| 2024-05-25 | [5d1d1c17](https://github.com/nostr-protocol/nips/commit/5d1d1c17) | [71](71.md) | `aes-256-gcm` tag was removed |
| 2024-05-07 | [8073c848](https://github.com/nostr-protocol/nips/commit/8073c848) | [25](25.md) | e-tags were changed to not include entire thread |
| 2024-04-30 | [bad88262](https://github.com/nostr-protocol/nips/commit/bad88262) | [34](34.md) | `earliest-unique-commit` tag was removed (use `r` tag instead) |
| 2024-02-25 | [4a171cb0](https://github.com/nostr-protocol/nips/commit/4a171cb0) | [18](18.md) | quote repost should use `q` tag |
| 2024-02-21 | [c6cd655c](https://github.com/nostr-protocol/nips/commit/c6cd655c) | [46](46.md) | Params were stringified |
| 2024-02-16 | [cbec02ab](https://github.com/nostr-protocol/nips/commit/cbec02ab) | [49](49.md) | Password first normalized to NFKC |
| 2024-02-15 | [afbb8dd0](https://github.com/nostr-protocol/nips/commit/afbb8dd0) | [39](39.md) | PGP identity was removed |
| 2024-02-07 | [d3dad114](https://github.com/nostr-protocol/nips/commit/d3dad114) | [46](46.md) | Connection token format was changed |
| 2024-01-30 | [1a2b21b6](https://github.com/nostr-protocol/nips/commit/1a2b21b6) | [59](59.md) | `p` tag became optional |
| 2023-01-27 | [c2f34817](https://github.com/nostr-protocol/nips/commit/c2f34817) | [47](47.md) | optional expiration tag should be honored |
| 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [02](02.md), [51](51.md) | list entries should be chronological |
| 2023-12-30 | [29869821](https://github.com/nostr-protocol/nips/commit/29869821) | [52](52.md) | `name` tag was removed (use `title` tag instead) |
| 2023-12-27 | [17c67ef5](https://github.com/nostr-protocol/nips/commit/17c67ef5) | [94](94.md) | `aes-256-gcm` tag was removed |
| 2023-12-03 | [0ba45895](https://github.com/nostr-protocol/nips/commit/0ba45895) | [01](01.md) | WebSocket status code `4000` was replaced by `CLOSED` message |
| 2023-11-28 | [6de35f9e](https://github.com/nostr-protocol/nips/commit/6de35f9e) | [89](89.md) | `client` tag value was changed |
| 2023-11-20 | [7822a8b1](https://github.com/nostr-protocol/nips/commit/7822a8b1) | [51](51.md) | `kind: 30001` was deprecated |
| 2023-11-20 | [7822a8b1](https://github.com/nostr-protocol/nips/commit/7822a8b1) | [51](51.md) | the meaning of `kind: 30000` was changed |
| 2023-11-11 | [cbdca1e9](https://github.com/nostr-protocol/nips/commit/cbdca1e9) | [84](84.md) | `range` tag was removed |
| 2023-11-10 | [c945d8bd](https://github.com/nostr-protocol/nips/commit/c945d8bd) | [32](32.md) | `l` tag annotations was removed |
| 2023-11-07 | [108b7f16](https://github.com/nostr-protocol/nips/commit/108b7f16) | [01](01.md) | `OK` message must have 4 items |
| 2023-10-17 | [cf672b76](https://github.com/nostr-protocol/nips/commit/cf672b76) | [03](03.md) | `block` tag was removed |
| 2023-09-29 | [7dc6385f](https://github.com/nostr-protocol/nips/commit/7dc6385f) | [57](57.md) | optional `a` tag was included in `zap receipt` |
| 2023-08-21 | [89915e02](https://github.com/nostr-protocol/nips/commit/89915e02) | [11](11.md) | `min_prefix` was removed |
| 2023-08-20 | [37c4375e](https://github.com/nostr-protocol/nips/commit/37c4375e) | [01](01.md) | replaceable events with same timestamp should be retained event with lowest id |
| 2023-08-15 | [88ee873c](https://github.com/nostr-protocol/nips/commit/88ee873c) | [15](15.md) | `countries` tag was renamed to `regions` |
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [12](12.md), [16](16.md), [20](20.md), [33](33.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
| 2023-08-11 | [d87f8617](https://github.com/nostr-protocol/nips/commit/d87f8617) | [25](25.md) | empty `content` should be considered as "+" |
| 2023-08-01 | [5d63b157](https://github.com/nostr-protocol/nips/commit/5d63b157) | [57](57.md) | `zap` tag was changed |
| 2023-07-15 | [d1814405](https://github.com/nostr-protocol/nips/commit/d1814405) | [01](01.md) | `since` and `until` filters should be `since <= created_at <= until` |
| 2023-07-12 | [a1cd2bd8](https://github.com/nostr-protocol/nips/commit/a1cd2bd8) | [25](25.md) | custom emoji was supported |
| 2023-06-18 | [83cbd3e1](https://github.com/nostr-protocol/nips/commit/83cbd3e1) | [11](11.md) | `image` was renamed to `icon` |
| 2023-04-13 | [bf0a0da6](https://github.com/nostr-protocol/nips/commit/bf0a0da6) | [15](15.md) | different NIP was re-added as NIP-15 |
| 2023-04-09 | [fb5b7c73](https://github.com/nostr-protocol/nips/commit/fb5b7c73) | [15](15.md) | NIP-15 was merged into NIP-01 |
| 2023-03-29 | [599e1313](https://github.com/nostr-protocol/nips/commit/599e1313) | [18](18.md) | NIP-18 was bring back |
| 2023-03-15 | [e1004d3d](https://github.com/nostr-protocol/nips/commit/e1004d3d) | [19](19.md) | `1: relay` was changed to optionally |
Breaking changes prior to 2023-03-01 are not yet documented.
## NOTES
- If it isn't clear that a change is breaking or not, we list it.
- The date is the date it was merged, not necessarily the date of the commit.

288
EE.md Normal file
View File

@@ -0,0 +1,288 @@
# NIP-EE
## E2EE Messaging using the Messaging Layer Security (MLS) Protocol
`draft` `optional`
This NIP standardizes how to use the [MLS Protocol](https://www.rfc-editor.org/rfc/rfc9420.html) with Nostr for efficient and E2EE (end-to-end encrypted) direct and group messaging.
## Context
Originally, one-to-one direct messages (DMs) in Nostr happened via the scheme defined in [NIP-04](04.md). This NIP is not recommended because, while it encrypts the content of the message (provides decent confidentiality), it leaks significant amounts of metadata about the parties involved in the conversation (completely lacks privacy).
With the addition of [NIP-44](44.md), we have an updated encryption scheme that improves confidentiality guarantees but stops short of defining a new scheme for doing direct messages using this encryption scheme. Hence, makes little to no difference to privacy.
Most recently, [NIP-17](17.md) combines [NIP-44](44.md) encryption with [NIP-59](59.md) gift-wrapping to hide the encrypted direct message inside another set of events to ensure that it's impossible to see who is talking to who and when messages passed between the users. This largely solves the metadata leakage problem; while it's still possible to see that a user is receiving gift-wrapped events, you can't tell from whom and what kind of events are within the gift-wrap outer event. This gives some degree of deniability/repudiation but doesn't solve forward secrecy or post compromise security. That is to say, if a user's private key (or the calculated conversation key shared between two users used to encrypt messages) is compromised, the attacker will have full access to all past and future DMs sent between those users.
In addition, neither [NIP-04](04.md) or [NIP-17](17.md) attempt to solve the problem of group messages.
### Why is this important?
Without proper E2EE, Nostr cannot be used as the protocol for secure messaging clients. While clients like Signal do a fantastic job with E2EE, they still rely on centralized servers and as a result can be shut down by a powerful (i.e. state-level) actor. The goal of Nostr is not only to protect against centralized entities censoring you and your communications, but also protect against the ability of a state-level actor to stop these sorts of services from existing in the first place. By replacing centralized servers with decentralized relays, we make it nearly impossible for a centralized actor to completely stop communications between individual users.
### Goals of this NIP
1. Private _and_ Confidential DMs and Group messages
1. **Private** means that an observer cannot tell that Alice and Bob are talking to one another, or that Alice is part of a specific group. This necessarily requires protecting metadata.
2. **Confidential** means that the contents of conversations can only be viewed by the intended recipients.
2. Forward secrecy and Post-compromise security
1. **Forward secrecy** means that encrypted content in the past remains encrypted even if a key material is leaked.
2. **Post compromise security** means that leaking key material doesn't allow an attacker to continue to read messages indefinitely into the future.
3. Scales efficiently for large groups
4. Allows for the use of multiple device/clients in a single conversation/group.
### Why MLS?
This scheme adapts the Message Layer Security (MLS) protocol for use with Nostr. You can think of MLS as an evolution of the Signal Protocol. However, it significantly improves the scalability of encryption operations for large group messaging significantly (linear -> log), is built to accommodate federated environments, and also allows for graceful updating of ciphersuites and versions over time. In addition, it's very flexible and agnostic about the message content that is sent.
It's beyond the scope of this NIP to explain the MLS protocol but you can read more about it in it's [Architectural Overview](https://www.ietf.org/archive/id/draft-ietf-mls-architecture-13.html) or the [RFC](https://www.rfc-editor.org/rfc/rfc9420). MLS is on track to become an internet standard under the IETF so the protocol itself is extremely well vetted and researched. This also means there is the potential for cross network messaging interoperability in the future as MLS gains more adoption.
## Core MLS Concepts
From the [MLS Architectural Overview](https://www.ietf.org/archive/id/draft-ietf-mls-architecture-13.html):
> MLS provides a way for clients to form groups within which they can communicate securely. For example, a set of users might use clients on their phones or laptops to join a group and communicate with each other. A group may be as small as two clients (e.g., for simple person to person messaging) or as large as hundreds of thousands. A client that is part of a group is a member of that group. As groups change membership and group or member properties, they advance from one epoch to another and the cryptographic state of the group evolves.
>
> The group is represented as a tree, which represents the members as the leaves of a tree. It is used to efficiently encrypt to subsets of the members. Each member has a state called a LeafNode object holding the client's identity, credentials, and capabilities.
The MLS protocol's job is to manage and evolve the cryptographic state of a group. This includes managing the membership of a group, the cryptographic state of a group (ratchet tree, keys, and encryption/decryption/authentication of messages), and managing the evolution of the group over time.
### Groups
Groups are created by their first member, who then invites one or more other members. Groups evolve over time in blocks called `Epochs`. New epochs are proposed via one ore more `Proposal` messages and then committed to via a `Commit` message.
### Clients
The device/client pair (e.g. Primal on iOS or Coracle on web) with which a user joins the group is represented as a `LeafNode` in the tree. The terms `Client` and `Member` are interchangeable in this regard. It is not possible to share group state across multiple `Clients`. If a user joins a group from 2 separate devices, their state is separate and they will be tracked as 2 separate members of the group.
### Messages
There are several different types of messages sent within a group. Some of these are control messages that are used to update the group state over time. These include `Welcome`, `Proposal`, and `Commit` messages. Others are the actual messages that are sent between members in a group. These include `Application` messages.
Messages in MLS are "framed". Meaning that they are wrapped in a data structure that includes information about the sender, the epoch, the message index within the epoch and the message content. This framing makes it possible to authenticate and decrypt messages correctly, even if they arrive out of order.
MLS is agnostic to the "content" of the messages that are sent. This is a key feature of MLS that allows for the use of MLS for a wide variety of applications.
MLS is also agnostic to the transport protocol that is used to send messages. Obviously for us, we'll be using websockets, Nostr events and relays.
## The focus of this NIP
This NIP focuses on how to use Nostr to perform the Authentication Service and Delivery Service functions required by the MLS protocol. Most clients will choose to use an MLS implementation to handle keys, ratcheting, group state management, and other aspects of the MLS protocol itself. [OpenMLS](https://github.com/openmls/openmls) is the most actively developed library that implements MLS.
This NIP specifies the following:
1. A standardized way that Nostr clients should [create MLS groups](#creating-groups).
2. The required format of the MLS [`Credential`](#mls-credentials) that Nostr clients should use to represent a Nostr user in a group.
3. The structure of [KeyPackage Events](#keypackage-event-and-signing-keys) published to relays that allow Nostr users to be added to a group asynchronously.
4. The structure of [Group Events](#group-events) published to relays that represent the evolution of a group's state and the contents of the messages sent in the group.
## Security Considerations
This is a concise overview of the security trade-offs and considerations of this NIP in various scenarios. The NIP strives to fully maintain MLS security guarantees.
### Forward Secrecy and Post-compromise Security
- As per the MLS spec, keys are deleted as soon as they are used to encrypt or decrypt a message. This is usually handled by the MLS implementation library itself but attention needs to be paid by clients to ensure they're not storing secrets (especially the [exporter secret](#group-events)) for longer than absolutely necessary.
- This NIP maintains MLS forward secrecy and post-compromise security guarantees. You can read more about those in the MLS Architectural Overview section on [Forward Secrecy and Post-compromise Security](https://www.ietf.org/archive/id/draft-ietf-mls-architecture-15.html#name-forward-and-post-compromise).
### Leakage of various keys
- This NIP does not depend on a user's Nostr identity key for any aspect of the MLS messaging protocol. Compromise of a user's Nostr identity key does not give access to past or future messages in any MLS-based group.
- For a complete discussion of MLS key leakage, please see the Endpoint Compromise section of the [MLS Architectural Overview](https://www.ietf.org/archive/id/draft-ietf-mls-architecture-15.html#name-endpoint-compromise).
### Metadata
- The only group specific metadata published to relays is the Nostr group ID value. This value is used to identify the group in the `h` tag of the Group Message Event (`kind: 445`). These events are published ephemerally and this Nostr group ID value can be updated over the lifetime of the group by group admins. This is a tradeoff to ensure that group participants and group size are obfuscated but still makes it possible to efficiently fan out group messages to all participants. The content field of this event is a value encrypted in two separate ways (using NIP-44 and MLS) with MLS group state/keys. Only group members with up-to-date group state can decrypt and read these messages.
- A user's key package events can be used one or more times to be added to groups. There is a tradeoff inherent here: Reusing key packages (initial signing keys) carries some degree of risk but this risk is mitigated as long as a user rotates their signing key immediately upon joining a group. This step also improves the forward secrecy of the entire group.
### Device Compromise
Clients implementing this NIP should take every precaution to ensure that data is stored in a secure way on the device and is protected against unwanted access in the case that a device is compromised (e.g. encryption at rest, biometric authentication, etc.). That said, full device compromise should be viewed as a catastrophic event and any group the compromised device was a part of should be considered compromised until they can remove that member and update their group's state. Some suggestions:
- Clients should support and encourage self-destructing messages (ensuring that full transcript history isn't available on a device forever).
- Clients should regularly suggest to group admins that inactive users be removed.
- Clients should regularly suggest (or automatically) rotate a user's signing key in each of their groups.
- Clients should encrypt group state and keys on the device using a secret value that isn't part of the group state or the user's Nostr identity key.
- Clients should use secure enclave storage where possible.
For a full discussion of the security considerations of MLS, please see the Security Considerations section of the [MLS RFC](https://www.rfc-editor.org/rfc/rfc9420.html#name-security-considerations).
## Creating groups
MLS Groups are created with a random 32-byte ID value that is effectively permanent. This ID should be treated as private to the group and MUST not be published to relays in any form.
Clients must also ensure that the ciphersuite, capabilities, and extensions they use when creating the group are compatible with those advertised by the users they'd like to invite to the group. They can check this info via the user's published KeyPackage Events.
When creating a new group, the following MLS extensions MUST be used.
- [`required_capabilities`](https://docs.rs/openmls/latest/openmls/extensions/struct.RequiredCapabilitiesExtension.html)
- [`ratchet_tree`](https://docs.rs/openmls/latest/openmls/extensions/struct.RatchetTreeExtension.html)
- [`nostr_group_data`](https://github.com/rust-nostr/nostr/blob/master/mls/nostr-mls/src/extension.rs)
And the following MLS extension is highly recommended (more [here](#keypackage-event-and-signing-keys)):
- [`last_resort`](https://docs.rs/openmls/latest/openmls/extensions/struct.LastResortExtension.html)
Changes to an MLS group are affected by first creating one or more `Proposal` events and then committing to a set of proposals in a `Commit` event. These are MLS events, not Nostr events. However, for the group state to properly evolve the Commit events (which represent a specific set of proposals - like adding a new user to the group) must be published to relays for the other group members to see. See [Group Messages](#group-events) for more information.
## MLS Credentials
A `Credential` in MLS is an assertion of who the user is coupled with a signing key. When constructing `Credentials` for MLS, clients MUST use the `BasicCredential` type and set the `identity` value as the 32-byte hex-encoded public key of the user's Nostr identity key. Clients MUST not allow users to change the identity field and MUST validate that all `Proposal` messages do not attempt to change the identity field on any credential in the group.
A `Credential` also has an associated signing key. The initial signing key for a user is included in the KeyPackage event. The signing key MUST be different from the user's Nostr identity key. This signing key SHOULD be rotated over time to provide improved post-compromise security.
## Nostr Group Data Extension
As mentioned above, the `nostr_group_data` extension is a required MLS extension used to associate Nostr-specific data with an MLS group in a cryptographically secure and proveable way. This extension MUST be included as a required capability when creating a new group.
The extension stores the following data about the group:
- `nostr_group_id`: A 32-byte ID for the group. This is a different value from the group ID used by MLS and CAN be changed over time. This value is the group ID value used in the `h` tags when sending group message events.
- `name`: The name of the group.
- `description`: A short description of the group.
- `admin_pubkeys`: An array of the hex-encoded public keys of the group admins. The MLS protocol itself does not have a concept of group admins. Clients MUST check the list of `admin_pubkeys` before making any change to the group data (anything in this extension), or before changing group membership (add/remove members), or updating any other aspect of the group itself (e.g. ciphersuite, etc.). Note, all members of the group can send `Proposal` and `Commits` messages for changes to their own credentials (e.g. updating their signing key).
- `relays`: An array of the Nostr relay URLs that the group uses to publish and receive messages.
All of these values can be updated over time using MLS `Proposal` and `Commit` events (by group admins).
## KeyPackage Event and Signing Keys
Each user that wishes to be reachable via MLS-based messaging MUST first publish at least one KeyPackage event. The KeyPackage Event is used to authenticate users and create the necessary `Credential` to add members to groups in an asynchronous way. Users can publish multiple KeyPackage Events with different parameters (supporting different ciphersuites or MLS extensions, for example). KeyPackages include a signing key that is used for signing MLS messages within a group. This signing key MUST not be the same as the user's Nostr identity key.
KeyPackage reuse SHOULD be minimized. However, in normal MLS use, KeyPackages are consumed when joining a group. In order to reduce race conditions between invites for multiple groups using the same Key Package, Nostr clients SHOULD use "Last resort" KeyPackages. This requires the inclusion of the `last_resort` extension on the KeyPackage's capabilities (same as with the Group).
It's important that clients immediately rotate a user's signing key after joining a group via a last resort key package to improve post-compromise security. The signing key (the public key included in the KeyPackage Event) is used for signing within the group. Therefore, clients implementing this NIP MUST ensure that they retain access to the private key material of the signing key for each group they are a member of.
In most cases, it's assumed that clients implementing this NIP will manage the creation and rotation of KeyPackage Events.
### Example KeyPackage Event
```json
{
"id": <id>,
"kind": 443,
"created_at": <unix timestamp in seconds>,
"pubkey": <main identity pubkey>,
"content": "",
"tags": [
["mls_protocol_version", "1.0"],
["ciphersuite", <MLS CipherSuite ID value e.g. "0x0001">],
["extensions", <An array of MLS Extension ID values e.g. "0x0001, 0x0002">],
["client", <client name>, <handler event id>, <optional relay url>],
["relays", <array of relay urls>],
["-"]
],
"sig": <signed with main identity key>
}
```
- The `content` hex encoded serialized `KeyPackageBundle` from MLS.
- The `mls_protocol_version` tag is required and MUST be the version number of the MLS protocol version being used. For now, this is `1.0`.
- The `ciphersuite` tag is the value of the MLS ciphersuite that this KeyPackage Event supports. [Read more about ciphersuites in MLS](https://www.rfc-editor.org/rfc/rfc9420.html#name-mls-cipher-suites).
- The `extensions` tag is an array of MLS extension IDs that this KeyPackage Event supports. [Read more about MLS extensions](https://www.rfc-editor.org/rfc/rfc9420.html#name-extensions).
- (optional) The `client` tag helps other clients manage the user experience when they receive group invites but don't have access to the signing key.
- The `relays` tag identifies each of the relays that the client will attempt to publish this KeyPackage event. This allows for deletion of KeyPackage Events at a later date.
- (optional) The `-` tag can be used to ensure that KeyPackage Events are only published by their authenticated author. Read more in [NIP-70](70.md)
### Deleting KeyPackage Events
Clients SHOULD delete the KeyPackage Event on all the listed relays any time they successfully process a group request event for a given KeyPackage Event. Clients MAY also create a new KeyPackage Event at the same time.
If clients cannot process a Welcome message (e.g. because the signing key was generated on another client), clients MUST not delete the KeyPackage Event and SHOULD show a human-understandable error to the user.
### Rotating Signing Keys
Clients MUST regularly rotate the user's signing key in each group that they are a part of. The more often the signing key is rotated the stronger the post-compromise security. This rotation is done via `Proposal` and `Commit` events and broadcast to the group via a Group Event. [Read more about forward secrecy and post-compromise security inherent in MLS](https://www.rfc-editor.org/rfc/rfc9420.html#name-forward-secrecy-and-post-co).
### KeyPackage Relays List Event
A `kind: 10051` event indicates the relays that a user will publish their KeyPackage Events to. The event MUST include a list of relay tags with relay URIs. These relays SHOULD be readable by anyone the user wants to be able to contact them.
```json
{
"kind": 10051,
"tags": [
["relay", "wss://inbox.nostr.wine"],
["relay", "wss://myrelay.nostr1.com"],
],
"content": "",
//...other fields
}
```
### Welcome Event
When a new user is added to a group via an MLS `Commit` message. The member who sends the `Commit` message to the group is responsible for sending the user being added to the group a Welcome Event. This Welcome Event is sent to the user as a [NIP-59](59.md) gift-wrapped event. The Welcome Event gives the new member the context they need to join the group and start sending messages.
Clients creating the Welcome Event SHOULD wait until they have received acknowledgement from relays that their Group Event with the `Commit` has been received before publishing the Welcome Event.
```json
{
"id": <id>,
"kind": 444,
"created_at": <unix timestamp in seconds>,
"pubkey": <nostr identity pubkey of sender>,
"content": <serialized Welcome object>,
"tags": [
["e", <ID of the KeyPackage Event used to add the user to the group>],
["relays", <array of relay urls>],
],
"sig": <NOT SIGNED>
}
```
- The `content` field is required and is a serialized MLSMessage object containing the MLS `Welcome` object.
- The `e` tag is required and is the ID of the KeyPackage Event used to add the user to the group.
- The `relays` tag is required and is a list of relays clients should query for Group Events.
Welcome Events are then sealed and gift-wrapped as detailed in [NIP-59](59.md) before being published. Like all events that are sealed and gift-wrapped, `kind: 444` events MUST never be signed. This ensures that if they were ever leaked they would not be publishable to relays.
#### Large Groups
For groups above ~150 participants, welcome messages will become larger than the maximum event size allowed by Nostr. There is currently work underway on the MLS protocol to support "light" client welcomes that don't require the full Ratchet Tree state to be sent to the new member. This section will be updated with recommendations for how to handle large groups.
## Group Events
Group Events are all the messages that are sent within a group. This includes all "control" events that update the shared group state over time (`Proposal`, `Commit`) and messages sent between members of the group (`Application` messages).
Group Events are published using an ephemeral Nostr keypair to obfuscate the number and identity of group participants. Clients MUST use a new Nostr keypair for each Group Event they publish.
```json
{
"id": <id>,
"kind": 445,
"created_at": <unix timestamp in seconds>,
"pubkey": <ephemeral sender pubkey>,
"content": <NIP-44 encrypted serialized MLSMessage object>,
"tags": [
["h", <group id>]
],
"sig": <signed with ephemeral sender key>
}
```
- The `content` field is a [tls-style](https://www.rfc-editor.org/rfc/rfc9420.html#name-the-message-mls-media-type) serialized [`MLSMessage`](https://www.rfc-editor.org/rfc/rfc9420.html#section-6-4) object which is then encrypted according to [NIP-44](44.md). However, instead of using the sender and receivers keys to derive a `conversation_key`, the NIP-44 encryption is done using a Nostr keypair generated from the MLS [`exporter_secret`](https://www.rfc-editor.org/rfc/rfc9420.html#section-8.5) to calculate the `conversation_key` value. Essentially, you use the hex-encoded `exporter_secret` value as the private key (used as the sender key), calculate the public key for that private key (used as the receiver key), and then proceed with the standard NIP-44 scheme to encrypt and decrypt messages.
- The `exporter_secret` value should be generated with a 32-byte length and labeled `nostr`. This `exporter_secret` value is rotated on each new epoch in the group. Clients should generate a new 32-byte value each time they process a valid `Commit` message.
- The `pubkey` is the hex-encoded public key of the ephemeral sender.
- The `h` tag is the nostr group ID value (from the Nostr Group Data Extension).
### Application Messages
Application messages are the messages that are sent within the group by members. These are contained within the `MLSMessage` object. The format of these messages should be unsigned Nostr events of the appropriate kind. For normal DM or group messages, clents SHOULD use `kind: 9` chat message events. If the user reacts to a message, it would be a `kind: 7` event, and so on.
This means that once the application message has been decrypted and deserialized, clients can store those events and treat them as any other Nostr event, effectively creating a private Nostr feed of the group's activity and taking advantage of all the features of Nostr.
These inner unsigned Nostr events MUST use the member's Nostr identity key for the `pubkey` field and clients MUST check that the identity of them member who sent the message matches the pubkey of the inner Nostr event.
These Nostr events MUST remain **unsigned** to ensure that if they were to leak to relays they would not be published publicly. These Nostr events MUST not include any "h" tags or other tags that would identify the group that they belong to.
### `Commit` Message race conditions
The MLS protocol is resilient to almost all messages arriving out of order. However, the order of `Commit` messages is important for the group state to move forward from one epoch to the next correctly. Given Nostr's nature as a decentralized network, it is possible for a client to receive 2 or more `Commit` messages all attempting to update to a new epoch at the same time.
Clients sending commit messages MUST wait until they receive acknowledgement from at least one relay that their Group Message Event with the `Commit` has been received before applying the commit to their own group state.
If a client receives 2 or more `Commit` messages attempting to change same epoch, they MUST apply only one of the `Commit` messages they receive, determined by the following:
1. Using the `created_at` timestamp on the kind `445` event. The `Commit` with the lowest value for `created_at` is the message to be applied. The other `Commit` message is discarded.
2. If the `created_at` timestamp is the same for two or more `Commit` messages, the `Commit` message with the lowest value for `id` field is the message to be applied.
Clients SHOULD retain previous group state for a short period of time in order to recover from forked group state.

View File

@@ -11,11 +11,10 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [Message Types](#message-types)
- [Client to Relay](#client-to-relay)
- [Relay to Client](#relay-to-client)
- [Standardized Tags](#standardized-tags)
- [Common Tags](#common-tags)
- [Criteria for acceptance of NIPs](#criteria-for-acceptance-of-nips)
- [Is this repository a centralizing factor?](#is-this-repository-a-centralizing-factor)
- [How this repository works](#how-this-repository-works)
- [Breaking Changes](#breaking-changes)
- [License](#license)
---
@@ -99,7 +98,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-90: Data Vending Machines](90.md)
- [NIP-92: Media Attachments](92.md)
- [NIP-94: File Metadata](94.md)
- [NIP-96: HTTP File Storage Integration](96.md)
- [NIP-96: HTTP File Storage Integration](96.md) --- **unrecommended**: replaced by blossom APIs
- [NIP-98: HTTP Auth](98.md)
- [NIP-99: Classified Listings](99.md)
- [NIP-A0: Voice Messages](A0.md)
@@ -107,6 +106,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-B7: Blossom](B7.md)
- [NIP-C0: Code Snippets](C0.md)
- [NIP-C7: Chats](C7.md)
- [NIP-EE: E2EE Messaging using MLS Protocol](EE.md)
## Event Kinds
| kind | description | NIP |
@@ -143,6 +143,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `44` | Channel Mute User | [28](28.md) |
| `62` | Request to Vanish | [62](62.md) |
| `64` | Chess (PGN) | [64](64.md) |
| `443` | KeyPackage | [EE](EE.md) |
| `444` | Welcome Message | [EE](EE.md) |
| `445` | Group Event | [EE](EE.md) |
| `818` | Merge Requests | [54](54.md) |
| `1018` | Poll Response | [88](88.md) |
| `1021` | Bid | [15](15.md) |
@@ -200,8 +203,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `10020` | Media follows | [51](51.md) |
| `10030` | User emoji list | [51](51.md) |
| `10050` | Relay list to receive DMs | [51](51.md), [17](17.md) |
| `10051` | KeyPackage Relays List | [EE](EE.md) |
| `10063` | User server list | [Blossom][blossom] |
| `10096` | File storage server list | [96](96.md) |
| `10096` | File storage server list | [96](96.md) (deprecated) |
| `10166` | Relay Monitor Announcement | [66](66.md) |
| `10312` | Room Presence | [53](53.md) |
| `10377` | Proxy Announcement | [Nostr Epoxy][nostr-epoxy] |
@@ -307,7 +311,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `AUTH` | used to send authentication challenges | [42](42.md) |
| `COUNT` | used to send requested event counts to clients | [45](45.md) |
## Standardized Tags
## Common Tags
| name | value | other parameters | NIP |
| ----------------- | ------------------------------------ | ------------------------------- | -------------------------------------------------- |
@@ -403,10 +407,6 @@ Standards may emerge in two ways: the first way is that someone starts doing som
These two ways of standardizing things are supported by this repository. Although the second is preferred, an effort will be made to codify standards emerged outside this repository into NIPs that can be later referenced and easily understood and implemented by others -- but obviously as in any human system discretion may be applied when standards are considered harmful.
## Breaking Changes
[Breaking Changes](BREAKING.md)
## License
All NIPs are public domain.