Compare commits
25 Commits
b0c33a630d
...
cda6f6ec61
Author | SHA1 | Date |
---|---|---|
|
cda6f6ec61 | |
|
7dec812f99 | |
|
739f3c5263 | |
|
8830525250 | |
|
b224b0ecb8 | |
|
ce130e504a | |
|
0b45265a93 | |
|
e33f5cd38f | |
|
0595d438aa | |
|
f30a43bd37 | |
|
faba3f016d | |
|
e6de76f76b | |
|
aefad1876b | |
|
4984b057c2 | |
|
9be455bf57 | |
|
e50f37a527 | |
|
074b8eeb01 | |
|
1afb6da049 | |
|
d306f6b3f8 | |
|
82fffa0580 | |
|
477e3dfd4d | |
|
9afca6c4dc | |
|
4eed6e8368 | |
|
db3e3bddbe | |
|
6f3926c5b2 |
5
01.md
5
01.md
|
@ -85,7 +85,7 @@ As a convention, all single-letter (only english alphabet letters: a-z, A-Z) key
|
|||
|
||||
### 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, specifies the `kind:1` text note for social media applications.
|
||||
|
||||
This NIP defines one basic kind:
|
||||
|
||||
|
@ -170,8 +170,9 @@ 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, "restricted: not allowed to write."]`
|
||||
* `["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", "sub1", "unsupported: filter contains unknown elements"]`
|
||||
* `["CLOSED", "sub1", "error: could not connect to the database"]`
|
||||
* `["CLOSED", "sub1", "error: shutting down idle subscription"]`
|
||||
- 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.
|
||||
- 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.
|
||||
|
|
4
03.md
4
03.md
|
@ -12,8 +12,8 @@ This NIP defines an event with `kind:1040` that can contain an [OpenTimestamps](
|
|||
{
|
||||
"kind": 1040
|
||||
"tags": [
|
||||
["e", <event-id>, <relay-url>],
|
||||
["alt", "opentimestamps attestation"]
|
||||
["e", <target-event-id>, <relay-url>],
|
||||
["k", "<target-event-kind>"]
|
||||
],
|
||||
"content": <base64-encoded OTS file data>
|
||||
}
|
||||
|
|
3
18.md
3
18.md
|
@ -40,6 +40,5 @@ Since `kind 6` reposts are reserved for `kind 1` contents, we use `kind 16`
|
|||
as a "generic repost", that can include any kind of event inside other than
|
||||
`kind 1`.
|
||||
|
||||
`kind 16` reposts SHOULD contain a `k` tag with the stringified kind number
|
||||
`kind 16` reposts SHOULD contain a `"k"` tag with the stringified kind number
|
||||
of the reposted event as its value.
|
||||
|
||||
|
|
2
21.md
2
21.md
|
@ -32,7 +32,7 @@ The typed scheme is `nostr+<event type number>:` followed by a `note`, `nevent`
|
|||
|
||||
### 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:
|
||||
`<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>
|
||||
|
|
8
22.md
8
22.md
|
@ -143,13 +143,13 @@ A comment on a website's url looks like this:
|
|||
"tags": [
|
||||
// referencing the root url
|
||||
["I", "https://abc.com/articles/1"],
|
||||
// the root "kind": for an url, the kind is its domain
|
||||
["K", "https://abc.com"],
|
||||
// the root "kind": for an url
|
||||
["K", "web"],
|
||||
|
||||
// the parent reference (same as root for top-level comments)
|
||||
["i", "https://abc.com/articles/1"],
|
||||
// the parent "kind": for an url, the kind is its domain
|
||||
["k", "https://abc.com"]
|
||||
// the parent "kind": for an url
|
||||
["k", "web"]
|
||||
]
|
||||
// other fields
|
||||
}
|
||||
|
|
13
24.md
13
24.md
|
@ -8,8 +8,7 @@ Extra metadata fields and tags
|
|||
|
||||
This NIP keeps track of extra optional fields that can added to events which are not defined anywhere else but have become _de facto_ standards and other minor implementation possibilities that do not deserve their own NIP and do not have a place in other NIPs.
|
||||
|
||||
kind 0
|
||||
======
|
||||
### kind 0
|
||||
|
||||
These are extra fields not specified in NIP-01 that may be present in the stringified JSON of metadata events:
|
||||
|
||||
|
@ -19,24 +18,22 @@ These are extra fields not specified in NIP-01 that may be present in the string
|
|||
- `bot`: a boolean to clarify that the content is entirely or partially the result of automation, such as with chatbots or newsfeeds.
|
||||
- `birthday`: an object representing the author's birth date. The format is { "year": number, "month": number, "day": number }. Each field MAY be omitted.
|
||||
|
||||
### Deprecated fields
|
||||
#### Deprecated fields
|
||||
|
||||
These are fields that should be ignored or removed when found in the wild:
|
||||
|
||||
- `displayName`: use `display_name` instead.
|
||||
- `username`: use `name` instead.
|
||||
|
||||
kind 3
|
||||
======
|
||||
### kind 3
|
||||
|
||||
These are extra fields not specified in NIP-02 that may be present in the stringified JSON of follow events:
|
||||
|
||||
### Deprecated fields
|
||||
#### Deprecated fields
|
||||
|
||||
- `{<relay-url>: {"read": <true|false>, "write": <true|false>}, ...}`: an object of relays used by a user to read/write. [NIP-65](65.md) should be used instead.
|
||||
|
||||
tags
|
||||
====
|
||||
### tags
|
||||
|
||||
These tags may be present in multiple event kinds. Whenever a different meaning is not specified by some more specific NIP, they have the following meanings:
|
||||
|
||||
|
|
2
25.md
2
25.md
|
@ -26,8 +26,6 @@ There SHOULD be a `p` tag set to the `pubkey` of the event being reacted to. If
|
|||
|
||||
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 `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.
|
||||
|
|
12
34.md
12
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 in a patch set SHOULD include a NIP-10 `e` `reply` tag pointing to the previous patch.
|
||||
Patches in a patch set SHOULD include a [NIP-10](10.md) `e` `reply` tag pointing to the previous patch.
|
||||
|
||||
The first patch revision in a patch revision SHOULD include a NIP-10 `e` `reply` to the original root patch.
|
||||
The first patch revision in a patch revision SHOULD include a [NIP-10](10.md) `e` `reply` to the original root patch.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
@ -125,7 +125,7 @@ Issues may have a `subject` tag, which clients can utilize to display a header.
|
|||
|
||||
## 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
|
||||
|
||||
|
@ -150,7 +150,7 @@ Root Patches and Issues have a Status that defaults to 'Open' and can be set by
|
|||
["r", "<earliest-unique-commit-id-of-repo>"]
|
||||
|
||||
// optional for `1631` status
|
||||
["e", "<applied-or-merged-patch-event-id>", "", "mention"], // for each
|
||||
["q", "<applied-or-merged-patch-event-id>", "<relay-url>", "<pubkey>"], // for each
|
||||
// when merged
|
||||
["merge-commit", "<merge-commit-id>"]
|
||||
["r", "<merge-commit-id>"]
|
||||
|
@ -161,9 +161,9 @@ Root Patches and Issues have a Status that defaults to 'Open' and can be set by
|
|||
}
|
||||
```
|
||||
|
||||
The Status event with the largest created_at date is valid.
|
||||
The most recent Status event (by `created_at` date) from either the issue/patch author or a maintainer is considered valid.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
## Possible things to be added later
|
||||
|
|
153
47.md
153
47.md
|
@ -28,15 +28,16 @@ Fundamentally NWC is communication between a **client** and **wallet service** b
|
|||
|
||||
4. Once the payment is complete the **wallet service** will send an encrypted `response` (kind 23195) to the **user** over the relay(s) in the URI.
|
||||
|
||||
5. The **wallet service** may send encrypted notifications (kind 23196) of wallet events (such as a received payment) to the **client**.
|
||||
5. The **wallet service** may send encrypted notifications (kind 23197 or 23196) of wallet events (such as a received payment) to the **client**.
|
||||
|
||||
## Events
|
||||
|
||||
There are four event kinds:
|
||||
|
||||
- `NIP-47 info event`: 13194
|
||||
- `NIP-47 request`: 23194
|
||||
- `NIP-47 response`: 23195
|
||||
- `NIP-47 notification event`: 23196
|
||||
- `NIP-47 notification event`: 23197 (23196 for backwards compatibility with NIP-04)
|
||||
|
||||
### Info Event
|
||||
|
||||
|
@ -46,34 +47,71 @@ The content should be a plaintext string with the supported capabilities space-s
|
|||
|
||||
If the **wallet service** supports notifications, the info event SHOULD contain a `notifications` tag with the supported notification types space-separated, eg. `payment_received payment_sent`.
|
||||
|
||||
It should also contain supported encryption modes as described in the [Encryption](#encryption) section. For example:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 13194,
|
||||
"tags": [
|
||||
["encryption", "nip44_v2 nip04"], // List of supported encryption schemes as described in the Encryption section.
|
||||
["notifications", "payment_received payment_sent"]
|
||||
// ...
|
||||
],
|
||||
"content": "pay_invoice get_balance make_invoice lookup_invoice list_transactions get_info notifications",
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Request and Response Events
|
||||
|
||||
Both the request and response events SHOULD contain one `p` tag, containing the public key of the **wallet service** if this is a request, and the public key of the **client** if this is a response. The response event SHOULD contain an `e` tag with the id of the request event it is responding to.
|
||||
Optionally, a request can have an `expiration` tag that has a unix timestamp in seconds. If the request is received after this timestamp, it should be ignored.
|
||||
|
||||
The content of requests and responses is encrypted with [NIP04](04.md), and is a JSON-RPCish object with a semi-fixed structure:
|
||||
The content of requests and responses is encrypted with [NIP44](44.md), and is a JSON-RPCish object with a semi-fixed structure.
|
||||
|
||||
Request:
|
||||
```jsonc
|
||||
**Important note for backwards-compatibility:** The initial version of the protocol used [NIP04](04.md). If a **wallet service** or client app does not include the `encryption` tag in the
|
||||
`info` or request events, it should be assumed that the connection is using NIP04 for encryption. See the [Encryption](#encryption) section for more information.
|
||||
|
||||
Example request:
|
||||
|
||||
```js
|
||||
{
|
||||
"method": "pay_invoice", // method, string
|
||||
"params": { // params, object
|
||||
"invoice": "lnbc50n1..." // command-related data
|
||||
}
|
||||
"kind" 23194,
|
||||
"tags": [
|
||||
["encryption", "nip44_v2"],
|
||||
["p", "03..." ] // public key of the wallet service.
|
||||
// ...
|
||||
],
|
||||
"content": nip44_encrypt({ // Encryption type corresponds to the `encryption` tag.
|
||||
"method": "pay_invoice", // method, string
|
||||
"params": { // params, object
|
||||
"invoice": "lnbc50n1..." // command-related data
|
||||
}
|
||||
}),
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
```jsonc
|
||||
Example response:
|
||||
|
||||
```js
|
||||
{
|
||||
"result_type": "pay_invoice", //indicates the structure of the result field
|
||||
"error": { //object, non-null in case of error
|
||||
"code": "UNAUTHORIZED", //string error code, see below
|
||||
"message": "human readable error message"
|
||||
},
|
||||
"result": { // result, object. null in case of error.
|
||||
"preimage": "0123456789abcdef..." // command-related data
|
||||
}
|
||||
"kind" 23195,
|
||||
"tags": [
|
||||
["p", "03..." ] // public key of the requesting client app
|
||||
["e", "1234"] // id of the request event this is responding to
|
||||
// ...
|
||||
],
|
||||
"content": nip44_encrypt({ // Encrypted using the scheme requested by the client.
|
||||
"result_type": "pay_invoice", //indicates the structure of the result field
|
||||
"error": { //object, non-null in case of error
|
||||
"code": "UNAUTHORIZED", //string error code, see below
|
||||
"message": "human readable error message"
|
||||
},
|
||||
"result": { // result, object. null in case of error.
|
||||
"preimage": "0123456789abcdef..." // command-related data
|
||||
}
|
||||
})
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -83,9 +121,9 @@ If the command was successful, the `error` field must be null.
|
|||
|
||||
### Notification Events
|
||||
|
||||
The notification event SHOULD contain one `p` tag, the public key of the **client**.
|
||||
The notification event is a kind 23197 event SHOULD contain one `p` tag, the public key of the **client**.
|
||||
|
||||
The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPCish object with a semi-fixed structure:
|
||||
The content of notifications is encrypted with [NIP44](44.md) (or NIP-04 for legacy client apps), and is a JSON-RPCish object with a semi-fixed structure:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
@ -96,6 +134,7 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC
|
|||
}
|
||||
```
|
||||
|
||||
_Note on backwards-compatibility:_ If a **wallet service** supports both nip44 and nip04 for legacy client apps, it should publish both notification events for each notification - kind 23196 encrypted with NIP-04, and kind 23197 encrypted with NIP-44. It is up to the **client** to decide which event to listen to based on its supported encryption and declared supported encryption schemes of the **wallet service** in the `info` event.
|
||||
|
||||
### Error codes
|
||||
- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds.
|
||||
|
@ -105,6 +144,7 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC
|
|||
- `RESTRICTED`: This public key is not allowed to do this operation.
|
||||
- `UNAUTHORIZED`: This public key has no wallet connected.
|
||||
- `INTERNAL`: An internal error.
|
||||
- `UNSUPPORTED_ENCRYPTION`: The encryption type of the request is not supported by the wallet service.
|
||||
- `OTHER`: Other error.
|
||||
|
||||
## Nostr Wallet Connect URI
|
||||
|
@ -295,6 +335,7 @@ Response:
|
|||
"result_type": "make_invoice",
|
||||
"result": {
|
||||
"type": "incoming", // "incoming" for invoices, "outgoing" for payments
|
||||
"state": "pending",
|
||||
"invoice": "string", // encoded invoice, optional
|
||||
"description": "string", // invoice's description, optional
|
||||
"description_hash": "string", // invoice's description hash, optional
|
||||
|
@ -328,6 +369,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)
|
||||
"invoice": "string", // encoded invoice, optional
|
||||
"description": "string", // invoice's description, optional
|
||||
"description_hash": "string", // invoice's description hash, optional
|
||||
|
@ -376,6 +418,7 @@ Response:
|
|||
"transactions": [
|
||||
{
|
||||
"type": "incoming", // "incoming" for invoices, "outgoing" for payments
|
||||
"state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments)
|
||||
"invoice": "string", // encoded invoice, optional
|
||||
"description": "string", // invoice's description, optional
|
||||
"description_hash": "string", // invoice's description hash, optional
|
||||
|
@ -452,6 +495,7 @@ Notification:
|
|||
"notification_type": "payment_received",
|
||||
"notification": {
|
||||
"type": "incoming",
|
||||
"state": "settled",
|
||||
"invoice": "string", // encoded invoice
|
||||
"description": "string", // invoice's description, optional
|
||||
"description_hash": "string", // invoice's description hash, optional
|
||||
|
@ -477,6 +521,7 @@ Notification:
|
|||
"notification_type": "payment_sent",
|
||||
"notification": {
|
||||
"type": "outgoing",
|
||||
"state": "settled",
|
||||
"invoice": "string", // encoded invoice
|
||||
"description": "string", // invoice's description, optional
|
||||
"description_hash": "string", // invoice's description hash, optional
|
||||
|
@ -499,6 +544,71 @@ Notification:
|
|||
2. **wallet service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment.
|
||||
3. **wallet service** responds to the event by sending an event with kind `23195` and content being a response either containing an error message or a preimage.
|
||||
|
||||
## Encryption
|
||||
|
||||
The initial version of NWC used [NIP-04](04.md) for encryption which has been deprecated and replaced by [NIP-44](44.md). NIP-44 should always be preferred for encryption, but there may be legacy cases
|
||||
where the **wallet service** or **client** has not yet migrated to NIP-44. The **wallet service** and **client** should negotiate the encryption method to use based on the `encryption` tag in the `info` event.
|
||||
|
||||
The encryption tag can contain either `nip44_v2` or `nip04`. The absence of this tag implies that the wallet only supports `nip04`.
|
||||
|
||||
| Encryption code | Use | Notes |
|
||||
|-----------------|----------------------|---------------------------------------------------------|
|
||||
| `nip44_v2` | NIP-44 | Required |
|
||||
| `nip04` | NIP-04 | Deprecated and only here for backward compatibility |
|
||||
| `<not present>` | NIP-04 | Deprecated and only here for backward compatibility |
|
||||
|
||||
The negotiation works as follows.
|
||||
|
||||
1. The **wallet service** includes an `encryption` tag in the `info` event. This tag contains a space-separated list of encryption schemes that the **wallet service** supports (eg. `nip44_v2 nip04`)
|
||||
2. The **client application** includes an `encryption` tag in each request event. This tag contains the encryption scheme which should be used for the request. The **client application** should always prefer nip44 if supported by the **wallet service**.
|
||||
|
||||
### Info event
|
||||
|
||||
First, the **wallet service** adds an `encryption` tag to its `info` event containing a space-separated list of encryption schemes it supports. For example,
|
||||
if a wallet service supports nip44, but also allows backwards-compatibility to nip04 client applications, its `encryption` tag in the `info` event might look something like:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 13194,
|
||||
"tags": [
|
||||
["encryption", "nip44_v2 nip04"],
|
||||
// ...
|
||||
],
|
||||
"content": "pay_invoice get_balance make_invoice lookup_invoice list_transactions get_info",
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
When a **client application** establishes a connection, it should read the info event and look for the `encryption` tag.
|
||||
|
||||
**Absence of this tag implies that the wallet only supports nip04.**
|
||||
|
||||
If the `encryption` tag is present, the **client application** will choose optimal encryption supported by both itself, and the **wallet service**, which should always be nip44 if possible.
|
||||
|
||||
### Request events
|
||||
|
||||
When a **client application** sends a request event, it should include a `encryption` tag with the encryption scheme it is using. The scheme MUST be supported by the **wallet service** as indicated by the info event.
|
||||
For example, if the client application supports nip44, the request event might look like:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 23194,
|
||||
"tags": [
|
||||
["encryption", "nip44_v2"],
|
||||
// ...
|
||||
],
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
If the **wallet service** does not support the specified encryption scheme, it will return an `UNSUPPORTED_ENCRYPTION` error. Absence of the `encryption` tag indicates use of nip04 for encryption.
|
||||
|
||||
### Notification events
|
||||
|
||||
As described above in the [Notifications](#notifications) section, if a **wallet service** supports both nip04 and nip44, it should publish two notification events for each notification - kind 23196 encrypted with NIP-04, and kind 23197 encrypted with NIP-44. If the **wallet service** only supports nip44, it should only publish kind 23197 events.
|
||||
|
||||
The **client** should check the `encryption` tag in the `info` event to determine which encryption schemes the **wallet service** supports, and listen to the appropriate notification event.
|
||||
|
||||
## 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.
|
||||
|
||||
|
@ -513,6 +623,7 @@ This NIP does not specify any requirements on the type of relays used. However,
|
|||
"created_at": 1713883677,
|
||||
"kind": 13194,
|
||||
"tags": [
|
||||
[ "encryption", "nip44_v2 nip04" ],
|
||||
[
|
||||
"notifications",
|
||||
"payment_received payment_sent"
|
||||
|
|
2
51.md
2
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) |
|
||||
| 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 |
|
||||
| Favorite relays | 10012 | user favorite relays and pointers to relay sets | `"relay"` (relay URLs) and `"a"` (kind:30002 relay set) |
|
||||
| Relay feeds | 10012 | user favorite browsable relays (and 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) |
|
||||
| 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) |
|
||||
|
|
9
52.md
9
52.md
|
@ -25,6 +25,7 @@ These tags are common to both types of calendar events:
|
|||
* `p` (optional, repeated) 32-bytes hex pubkey of a participant, optional recommended relay URL, and participant's role in the meeting
|
||||
* `t` (optional, repeated) hashtag to categorize calendar event
|
||||
* `r` (optional, repeated) references / links to web pages, documents, video calls, recorded videos, etc.
|
||||
* `a` (repeated) reference tag to kind `31924` calendar event requesting to be included in Calendar
|
||||
|
||||
The following tags are deprecated:
|
||||
|
||||
|
@ -32,6 +33,12 @@ The following tags are deprecated:
|
|||
|
||||
Calendar events are _not_ required to be part of a [calendar](#calendar).
|
||||
|
||||
## Collaborative Calendar Event Requests
|
||||
|
||||
Calendar events can include an `a` tag referencing a calendar (kind 31924) to request addition to that calendar. When a calendar event includes such a reference, clients should interpret this as a request to add the event to the referenced calendar by referencing it with an `a` tag.
|
||||
|
||||
This enables collaborative calendar management where multiple users can contribute events to calendars they do not own, subject to the calendar owner's approval.
|
||||
|
||||
### 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.
|
||||
|
@ -125,6 +132,8 @@ Aside from the common tags, this also takes the following tags:
|
|||
|
||||
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.
|
||||
|
||||
Calendars can accept event requests from other users. When calendar events reference a calendar via an `a` tag, this represents a request for inclusion.
|
||||
|
||||
The `.content` of these events should be a detailed description of the calendar. It is required but can be an empty string.
|
||||
|
||||
* `d` (required) universally unique identifier. Generated by the client creating the calendar.
|
||||
|
|
5
57.md
5
57.md
|
@ -37,6 +37,7 @@ In addition, the event MAY include the following tags:
|
|||
|
||||
- `e` is an optional hex-encoded event id. Clients MUST include this if zapping an event rather than a person.
|
||||
- `a` is an optional event coordinate that allows tipping addressable events such as NIP-23 long-form notes.
|
||||
- `k` is the stringified kind of the target event.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -49,7 +50,8 @@ Example:
|
|||
["amount", "21000"],
|
||||
["lnurl", "lnurl1dp68gurn8ghj7um5v93kketj9ehx2amn9uh8wetvdskkkmn0wahz7mrww4excup0dajx2mrv92x9xp"],
|
||||
["p", "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9"],
|
||||
["e", "9ae37aa68f48645127299e9453eb5d908a0cbb6058ff340d528ed4d37c8994fb"]
|
||||
["e", "9ae37aa68f48645127299e9453eb5d908a0cbb6058ff340d528ed4d37c8994fb"],
|
||||
["k", "1"]
|
||||
],
|
||||
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
|
||||
"created_at": 1679673265,
|
||||
|
@ -151,6 +153,7 @@ Example `zap receipt`:
|
|||
["p", "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"],
|
||||
["P", "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322"],
|
||||
["e", "3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8"],
|
||||
["k", "1"],
|
||||
["bolt11", "lnbc10u1p3unwfusp5t9r3yymhpfqculx78u027lxspgxcr2n2987mx2j55nnfs95nxnzqpp5jmrh92pfld78spqs78v9euf2385t83uvpwk9ldrlvf6ch7tpascqhp5zvkrmemgth3tufcvflmzjzfvjt023nazlhljz2n9hattj4f8jq8qxqyjw5qcqpjrzjqtc4fc44feggv7065fqe5m4ytjarg3repr5j9el35xhmtfexc42yczarjuqqfzqqqqqqqqlgqqqqqqgq9q9qxpqysgq079nkq507a5tw7xgttmj4u990j7wfggtrasah5gd4ywfr2pjcn29383tphp4t48gquelz9z78p4cq7ml3nrrphw5w6eckhjwmhezhnqpy6gyf0"],
|
||||
["description", "{\"pubkey\":\"97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322\",\"content\":\"\",\"id\":\"d9cc14d50fcb8c27539aacf776882942c1a11ea4472f8cdec1dea82fab66279d\",\"created_at\":1674164539,\"sig\":\"77127f636577e9029276be060332ea565deaf89ff215a494ccff16ae3f757065e2bc59b2e8c113dd407917a010b3abd36c8d7ad84c0e3ab7dab3a0b0caa9835d\",\"kind\":9734,\"tags\":[[\"e\",\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\"],[\"p\",\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\"],[\"relays\",\"wss://relay.damus.io\",\"wss://nostr-relay.wlvs.space\",\"wss://nostr.fmt.wiz.biz\",\"wss://relay.nostr.bg\",\"wss://nostr.oxtr.dev\",\"wss://nostr.v0l.io\",\"wss://brb.io\",\"wss://nostr.bitcoiner.social\",\"ws://monad.jb55.com:8080\",\"wss://relay.snort.social\"]]}"],
|
||||
["preimage", "5d006d2cf1e73c7148e7519a4c68adc81642ce0e25a432b2434c99f97344c15f"]
|
||||
|
|
1
61.md
1
61.md
|
@ -53,6 +53,7 @@ Clients MUST prefix the public key they P2PK-lock with `"02"` (for nostr<>cashu
|
|||
[ "proof", "{\"amount\":1,\"C\":\"02277c66191736eb72fce9d975d08e3191f8f96afb73ab1eec37e4465683066d3f\",\"id\":\"000a93d6f8a1d2c4\",\"secret\":\"[\\\"P2PK\\\",{\\\"nonce\\\":\\\"b00bdd0467b0090a25bdf2d2f0d45ac4e355c482c1418350f273a04fedaaee83\\\",\\\"data\\\":\\\"02eaee8939e3565e48cc62967e2fde9d8e2a4b3ec0081f29eceff5c64ef10ac1ed\\\"}]\"}" ],
|
||||
[ "u", "https://stablenut.umint.cash" ],
|
||||
[ "e", "<nutzapped-event-id>", "<relay-hint>" ],
|
||||
[ "k", "<nutzapped-kind>"],
|
||||
[ "p", "e9fbced3a42dcf551486650cc752ab354347dd413b307484e4fd1818ab53f991" ], // recipient of nutzap
|
||||
]
|
||||
}
|
||||
|
|
225
66.md
225
66.md
|
@ -6,137 +6,46 @@ Relay Discovery and Liveness Monitoring
|
|||
|
||||
`draft` `optional`
|
||||
|
||||
You want to find relays. You may want to discover relays based on criteria that's up to date. You may even want to ensure that you have a complete dataset. You probably want to filter relays based on their reported liveness.
|
||||
This NIP defines events for relay discovery and the announcement of relay monitors.
|
||||
|
||||
In its purest form:
|
||||
## Relay Discovery Events
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": 30166,
|
||||
"created_at": 1722173222,
|
||||
"content": "{}",
|
||||
"tags": [
|
||||
[ "d", "wss://somerelay.abc/" ]
|
||||
],
|
||||
"pubkey": "<pubkey>",
|
||||
"sig": "<signature>",
|
||||
"id": "<eventid>"
|
||||
}
|
||||
```
|
||||
`30166` relay discovery events document relay characteristics inferred either from a relay's [NIP 11](https://github.com/nostr-protocol/nips/blob/master/11.md) document, or via probing.
|
||||
|
||||
This event signals that the relay at `wss://somerelay.abc/` was reported "online" by `<pubkey>` at timestamp `1722173222`. This event **MAY** be extended upon to include more information.
|
||||
Information corresponding to field in a relay's NIP 11 document MAY contradict actual values if monitors find that a different policy is implemented than is advertised.
|
||||
|
||||
## Kinds
|
||||
`NIP-66` defines two (2) event kinds, `30166` and `10166`
|
||||
`content` MAY include the stringified JSON of the relay's NIP-11 informational document.
|
||||
|
||||
| kind | name | description |
|
||||
|-------|----------------------------|-----------------------------------------------------------------------------------------|
|
||||
| [30166](#k30166) | Relay Discovery | An addressable event that is published by a monitor when a relay is online |
|
||||
| [10166](#k10166) | Relay Monitor Announcement | An RE that stores data that signals the intent of a pubkey to monitor relays and publish `30166` events at a regular _frequency_ |
|
||||
The only required tag is the `d` tag, which MUST be set to the relay's [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) URL. For relays not accessible via URL, a hex-encoded pubkey MAY be used instead.
|
||||
|
||||
## Ontology
|
||||
- `Relay Operator`: someone who operates a relay
|
||||
- `Monitor`: A pubkey that monitors relays and publishes `30166` events at the frequency specified in their `10166` event.
|
||||
- `Ad-hoc Monitor`: A pubkey that monitors relays and publishes `30166` events at an irregular frequency.
|
||||
- `Monitor Service`: A group or individual that monitors relays using one or more `Monitors`.
|
||||
- `Check`: a specific data point that is tested or aggregated by a monitor.
|
||||
Other tags include:
|
||||
|
||||
## `30166`: "Relay Discovery" <a id="k30166"></a>
|
||||
- `rtt-open` - The relay's open round-trip time in milliseconds.
|
||||
- `rtt-read` - The relay's read round-trip time in milliseconds.
|
||||
- `rtt-write` - The relay's write round-trip time in milliseconds.
|
||||
- `n` - The relay's network type. SHOULD be one of `clearnet`, `tor`, `i2p`, `loki`
|
||||
- `T` - The relay type. Enumerated [relay type](https://github.com/nostr-protocol/nips/issues/1282) formatted as `PascalCase`, e.g. `PrivateInbox`
|
||||
- `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
|
||||
- `g` - A [NIP-52](https://github.com/nostr-protocol/nips/blob/master/52.md) geohash
|
||||
- `l` - A language tag
|
||||
|
||||
### Summary
|
||||
`30166` is a `NIP-33` addressable event, referred to as a "Relay Discovery" event. These events are optimized with a small footprint for protocol-level relay Discovery.
|
||||
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"]]`.
|
||||
|
||||
### Purpose
|
||||
Discovery of relays over nostr.
|
||||
Example:
|
||||
|
||||
### Schema
|
||||
|
||||
#### Content
|
||||
`30166` content fields **SHOULD** include the stringified JSON of the relay's NIP-11 informational document. This data **MAY** be provided for informational purposes only.
|
||||
|
||||
#### `created_at`
|
||||
The `created_at` field in a NIP-66 event should reflect the time when the relay liveness (and potentially other data points) was checked.
|
||||
|
||||
#### `tags`
|
||||
|
||||
##### Meta Tags (unindexed)
|
||||
- `rtt-open` The relay's open **round-trip time** in milliseconds.
|
||||
- `rtt-read` The relay's read **round-trip time** in milliseconds.
|
||||
- `rtt-write` The relay's write **round-trip time** in milliseconds.
|
||||
|
||||
_Other `rtt` values **MAY** be present. This NIP should be updated if there is value found in more `rtt` values._
|
||||
|
||||
##### Single Letter Tags (indexed)
|
||||
- `d` The relay URL/URI. The `#d` tag **must** be included in the `event.tags[]` array. Index position `1` **must** be the relay websocket URL/URI. If a URL it **SHOULD** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6). For relays not accessible via conventional means but rather by an npub/pubkey, an npub/pubkey **MAY** be used in place of a URL.
|
||||
```json
|
||||
[ "d", "wss://somerelay.abc/"]
|
||||
```
|
||||
|
||||
- `n`: Network
|
||||
```json
|
||||
[ "n", "clearnet" ]
|
||||
```
|
||||
|
||||
- `T`: Relay Type. Enumerated [relay type](https://github.com/nostr-protocol/nips/issues/1282) formatted as `PascalCase`
|
||||
```json
|
||||
["T", "PrivateInbox" ]
|
||||
```
|
||||
|
||||
- `N`: Supported Nips _From NIP-11 "Informational Document" `nip11.supported_nips[]`_
|
||||
```json
|
||||
[ "N", "42" ]
|
||||
```
|
||||
|
||||
- `R`: Requirements _NIP-11 "Informational Document" `nip11.limitations.payment_required`, `nip11.limitations.auth_required` and/or any other boolean value within `nip11.limitations[]` that is added in the future_
|
||||
```json
|
||||
[ "R", "payment" ],
|
||||
[ "R", "auth" ],
|
||||
```
|
||||
Since the nostr protocol does not currently support filtering on whether an indexed tag **is** or **is not** set, to make "public" and "no auth" relays discoverable requires a `!` flag
|
||||
|
||||
```json
|
||||
[ "R", "!payment" ], //no payment required, is public
|
||||
[ "R", "!auth" ], //no authentication required
|
||||
```
|
||||
|
||||
- `t`: "Topics" _From NIP-11 "Informational Document" `nip11.tags[]`_
|
||||
```json
|
||||
[ "t", "nsfw" ]
|
||||
```
|
||||
|
||||
- `k`: Accepted/Blocked Kinds [`NIP-22`]
|
||||
```json
|
||||
[ "k", "0" ],
|
||||
[ "k", "3" ],
|
||||
[ "k", "10002" ]
|
||||
```
|
||||
|
||||
or for blocked kinds
|
||||
|
||||
```json
|
||||
[ "k", "!0" ]
|
||||
[ "k", "!3" ],
|
||||
[ "k", "!10002" ]
|
||||
```
|
||||
|
||||
- `g`: `NIP-52` `g` tags (geohash)
|
||||
```json
|
||||
[ "g", "9r1652whz" ]
|
||||
```
|
||||
|
||||
- `30166` **MAY** be extended with global tags defined by other NIPs that do no collide with locally defined indices, including but not limited to: `p`, `t`, `e`, `a`, `i` and `l/L`.
|
||||
|
||||
#### Robust Example of a `30166` Event
|
||||
_Relay was online, and you can filter on a number of different tags_
|
||||
```json
|
||||
{
|
||||
"id": "<eventid>",
|
||||
"pubkey": "<monitor's pubkey>",
|
||||
"created_at": "<created_at [some recent date ...]>",
|
||||
"signature": "<signature>",
|
||||
"content": "{}",
|
||||
"content": "<optional nip 11 document>",
|
||||
"kind": 30166,
|
||||
"tags": [
|
||||
"tags": [
|
||||
["d","wss://some.relay/"],
|
||||
["n", "clearnet"],
|
||||
["N", "40"],
|
||||
|
@ -144,64 +53,28 @@ _Relay was online, and you can filter on a number of different tags_
|
|||
["R", "!payment"],
|
||||
["R", "auth"],
|
||||
["g", "ww8p1r4t8"],
|
||||
["p", "somehexkey..."],
|
||||
["l", "en", "ISO-639-1"],
|
||||
["t", "nsfw" ],
|
||||
["rtt-open", 234 ]
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `10166`: "Relay Monitor Announcement" Events <a id="k10166"></a>
|
||||
## Relay Monitor Announcements
|
||||
|
||||
### Summary
|
||||
`10166` is a replacable event herein referred to as "Relay Monitor Announcement" events. These events contain information about a publisher's intent to monitor and publish data as `30166` events. This event is optional and is intended for monitors who intend to provide monitoring services at a regular and predictable frequency.
|
||||
Kind `10166` relay monitor announcements advertise the author's intent to publish `30166` events. This event is optional and is intended for monitors who intend to provide monitoring services at a regular and predictable frequency.
|
||||
|
||||
### Purpose
|
||||
To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. Absence of this event implies the monitor is ad-hoc and does not publish events at a predictable frequency, and relies on mechanisms to infer data integrity, such as web-of-trust.
|
||||
Tags include:
|
||||
|
||||
### Schema
|
||||
- `frequency` - The frequency in seconds at which the monitor publishes events.
|
||||
- `timeout` (optional) - The timeout values for various checks conducted by a monitor. Index `1` is the monitor's timeout in milliseconds. Index `2` describes what test the timeout is used for. If no index `2` is provided, it is inferred that the timeout provided applies to all tests.
|
||||
- `c` - a lowercase string describing the checks conducted by a monitor. Examples include `open`, `read`, `write`, `auth`, `nip11`, `dns`, and `geo`.
|
||||
- `g` - [NIP-52](https://github.com/nostr-protocol/nips/blob/master/11.md) geohash tag
|
||||
|
||||
#### Standard Tags
|
||||
Monitors SHOULD also publish a `kind 0` profile and a `kind 10002` relay selections event.
|
||||
|
||||
- `frequency` The frequency **in seconds** at which the monitor publishes events. A string-integer at index `1` represents the expected frequency the monitor will publish `30166` events. There should only be `1` frequency per monitor.
|
||||
Example:
|
||||
|
||||
```json
|
||||
[ "frequency", "3600" ]
|
||||
```
|
||||
|
||||
- `timeout` (optional) The timeout values for various checks conducted by a monitor. Index `1` is the monitor's timeout in milliseconds. Index `2` describes what test the timeout is used for. If no index `2` is provided, it is inferred that the timeout provided applies to all tests. These values can assist relay operators in understanding data signaled by the monitor in _Relay Discovery Events_.
|
||||
```json
|
||||
[ "timeout", "2000", "open" ],
|
||||
[ "timeout", "2000", "read" ],
|
||||
[ "timeout", "3000", "write" ],
|
||||
[ "timeout", "2000", "nip11" ],
|
||||
[ "timeout", "4000", "ssl" ]
|
||||
```
|
||||
|
||||
#### Indexed Tags
|
||||
- `c` "Checks" **SHOULD** be a lowercase string describing the check(s) conducted by a monitor. Due to the rapidly evolving nature of relays, enumeration is organic and not strictly defined. But examples of some checks could be websocket `open/read/write/auth`, `nip11` checks, `dns` and `geo` checks, and and any other checks the monitor may deem useful.. Other checks **MAY** be included. New types of checks **SHOULD** be added to this NIP as they are needed.
|
||||
```json
|
||||
[ "c", "ws" ],
|
||||
[ "c", "nip11" ],
|
||||
[ "c", "dns" ],
|
||||
[ "c", "geo" ],
|
||||
[ "c", "ssl" ],
|
||||
```
|
||||
|
||||
- `g`: `NIP-52` `g` tags (geohash)
|
||||
```json
|
||||
[ "g", "9r1652whz" ]
|
||||
```
|
||||
|
||||
- Any other globally defined indexable tags **MAY** be included as found necessary.
|
||||
|
||||
### Other Requirements
|
||||
Monitors **SHOULD** have the following
|
||||
- A published `0` (NIP-1) event
|
||||
- A published `10002` (NIP-65) event that defines the relays the monitor publishes to.
|
||||
|
||||
### Robust Example of a `10166` Event
|
||||
```json
|
||||
{
|
||||
"id": "<eventid>",
|
||||
|
@ -209,46 +82,18 @@ Monitors **SHOULD** have the following
|
|||
"created_at": "<created_at [some recent date ...]>",
|
||||
"signature": "<signature>",
|
||||
"content": "",
|
||||
"tags": [
|
||||
|
||||
"tags": [
|
||||
[ "timeout", "open", "5000" ],
|
||||
[ "timeout", "read", "3000" ],
|
||||
[ "timeout", "write", "3000" ],
|
||||
[ "timeout", "nip11", "3000" ],
|
||||
|
||||
[ "frequency", "3600" ],
|
||||
|
||||
[ "c", "ws" ],
|
||||
[ "c", "nip11" ],
|
||||
[ "c", "ssl" ],
|
||||
[ "c", "dns" ],
|
||||
[ "c", "geo" ]
|
||||
|
||||
[ "g", "ww8p1r4t8" ]
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Methodology
|
||||
|
||||
### Monitors
|
||||
1. A _Relay Monitor_ checks the liveness and potentially other attributes of a relay.
|
||||
|
||||
2. _Relay Monitor_ publishes a kind `30166` note when a relay it is monitoring is online. If the monitor has a `10166` event, events should be published at the frequency defined in their `10166` note.
|
||||
|
||||
_Any pubkey that publishes `30166` events **SHOULD** at a minimum be checking that the relay is available by websocket and behaves like a relay_
|
||||
|
||||
### Clients
|
||||
1. In most cases, a client **SHOULD** filter on `30166` events using either a statically or dynamically defined monitor's `pubkey` and a `created_at` value respective of the monitor's published `frequency`. If the monitor has no stated frequency, other mechanisms should be employed to determine data integrity.
|
||||
|
||||
2. _Relay Liveness_ is subjectively determined by the client, starting with the `frequency` value of a monitor.
|
||||
|
||||
3. The liveness of a _Relay Monitor_ can be subjectively determined by detecting whether the _Relay Monitor_ has published events with respect to `frequency` value of any particular monitor.
|
||||
|
||||
4. The reliability and trustworthiness of a _Relay Monitor_ could be established via web-of-trust, reviews or similar mechanisms.
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
- When a client implements `NIP-66` events, the client should have a fallback if `NIP-66` events cannot be located.
|
||||
|
||||
- A `Monitor` or `Ad-hoc Monitor` may publish erroneous `30166` events, intentionally or otherwise. Therefor, it's important to program defensively to limit the impact of such events. This can be achieved with web-of-trust, reviews, fallbacks and/or data-aggregation for example.
|
||||
|
|
1
69.md
1
69.md
|
@ -80,6 +80,7 @@ Currently implemented on the following platforms:
|
|||
- [Mostro](https://github.com/MostroP2P/mostro)
|
||||
- [@lnp2pBot](https://github.com/lnp2pBot/bot)
|
||||
- [Robosats](https://github.com/RoboSats/robosats/pull/1362)
|
||||
- [Peach Bitcoin](https://github.com/Peach2Peach/peach-nostr-announcer-bot)
|
||||
|
||||
## References
|
||||
|
||||
|
|
44
72.md
44
72.md
|
@ -41,19 +41,55 @@ The goal of this NIP is to enable public communities. It defines the replaceable
|
|||
|
||||
# Posting to a community
|
||||
|
||||
Any Nostr event can be posted to a community. Clients MUST add one or more community `a` tags, each with a recommended relay.
|
||||
[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
|
||||
|
||||
For top-level posts, the uppercase and lowercase NIP-22 tags should both refer to the community definition itself.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 1,
|
||||
"kind": 1111,
|
||||
"tags": [
|
||||
["a", "34550:<community event author pubkey>:<community-d-identifier>", "<optional-relay-url>"],
|
||||
["A", "34550:<community-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": "hello world",
|
||||
"content": "Hi everyone. It's great to be here!",
|
||||
// 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
|
||||
|
||||
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.
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
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.
|
||||
|
||||
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 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 structure of these events is very similar to [NIP-23](23.md) long-form content events.
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
NIP-A0
|
||||
======
|
||||
|
||||
Voice Messages
|
||||
-----------
|
||||
|
||||
**Status:** Draft
|
||||
|
||||
This NIP defines new events `kind: 1222` for root messages and `kind: 1244` for reply messages to be used for short voice messages, typically up to 60 seconds in length.
|
||||
|
||||
## Specification
|
||||
|
||||
### Event Kind `1222` and Kind `1244`
|
||||
|
||||
The `kind: 1222` event is defined as follows:
|
||||
|
||||
- `content`: MUST be a URL pointing directly to an audio file.
|
||||
- The audio file SHOULD be in `audio/mp4` (.m4a) format using AAC or Opus encoding. Clients MAY support other common audio formats like `audio/ogg`, `audio/webm`, or `audio/mpeg` (mp3), but `audio/mp4` is recommended for broad compatibility and efficiency.
|
||||
- The audio duration SHOULD be no longer than 60 seconds. Clients publishing `kind: 1222` events SHOULD enforce this limit or provide a clear warning to the user if exceeded.
|
||||
- `tags`:
|
||||
- Tags MAY be included as per other NIPs (e.g., `t` for hashtags, `g` for geohash, etc.).
|
||||
|
||||
The `kind: 1244` event is defined as follows:
|
||||
|
||||
- To be used for replies, `kind: 1244` events MUST follow the structure of `NIP-22`.
|
||||
- `content`: MUST be a URL pointing directly to an audio file.
|
||||
- The audio file SHOULD be in `audio/mp4` (.m4a) format using AAC or Opus encoding. Clients MAY support other common audio formats like `audio/ogg`, `audio/webm`, or `audio/mpeg` (mp3), but `audio/mp4` is recommended for broad compatibility and efficiency.
|
||||
- The audio duration SHOULD be no longer than 60 seconds. Clients publishing `kind: 1222` events SHOULD enforce this limit or provide a clear warning to the user if exceeded.
|
||||
- `tags`:
|
||||
- Tags MAY be included as per other NIPs (e.g., `t` for hashtags, `g` for geohash, etc.).
|
||||
|
||||
|
||||
## Visual representation with `imeta` (NIP-92) tag (optional)
|
||||
|
||||
The following imeta (NIP-92) tags MAY be included so clients can render a visual preview without having to download the audio file first:
|
||||
|
||||
- `waveform`: amplitude values over time, space separated full integers, less than 100 values should be enough to render a nice visual
|
||||
- `duration`: audio length in seconds
|
||||
|
||||
## Examples
|
||||
|
||||
### Root Voice Message Example
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "https://blossom.primal.net/5fe7df0e46ee6b14b5a8b8b92939e84e3ca5e3950eb630299742325d5ed9891b.mp4",
|
||||
"created_at": 1752501052,
|
||||
"id": "...",
|
||||
"kind": 1222,
|
||||
"pubkey": "...",
|
||||
"sig": "...",
|
||||
"tags": [
|
||||
[
|
||||
"imeta",
|
||||
"url https://blossom.primal.net/5fe7df0e46ee6b14b5a8b8b92939e84e3ca5e3950eb630299742325d5ed9891b.mp4",
|
||||
"waveform 0 7 35 8 100 100 49 8 4 16 8 10 7 2 20 10 100 100 100 100 100 100 15 100 100 100 25 60 5 4 3 1 0 100 100 15 100 29 88 0 33 11 39 100 100 19 4 100 42 35 5 0 1 5 0 0 11 38 100 94 17 11 44 58 5 100 100 100 55 14 72 100 100 57 6 1 14 2 16 100 100 40 16 100 100 6 32 14 13 41 36 16 14 6 3 0 1 2 1 6 0",
|
||||
"duration 8"
|
||||
]
|
||||
]
|
||||
}
|
18
README.md
18
README.md
|
@ -93,6 +93,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
- [NIP-7D: Threads](7D.md)
|
||||
- [NIP-84: Highlights](84.md)
|
||||
- [NIP-86: Relay Management API](86.md)
|
||||
- [NIP-87: Ecash Mint Discoverability](87.md)
|
||||
- [NIP-88: Polls](88.md)
|
||||
- [NIP-89: Recommended Application Handlers](89.md)
|
||||
- [NIP-90: Data Vending Machines](90.md)
|
||||
|
@ -101,13 +102,13 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
- [NIP-96: HTTP File Storage Integration](96.md)
|
||||
- [NIP-98: HTTP Auth](98.md)
|
||||
- [NIP-99: Classified Listings](99.md)
|
||||
- [NIP-A0: Voice Messages](A0.md)
|
||||
- [NIP-B0: Web Bookmarks](B0.md)
|
||||
- [NIP-B7: Blossom](B7.md)
|
||||
- [NIP-C0: Code Snippets](C0.md)
|
||||
- [NIP-C7: Chats](C7.md)
|
||||
|
||||
## Event Kinds
|
||||
|
||||
| kind | description | NIP |
|
||||
| ------------- | ------------------------------- | -------------------------------------- |
|
||||
| `0` | User Metadata | [01](01.md) |
|
||||
|
@ -151,6 +152,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
| `1063` | File Metadata | [94](94.md) |
|
||||
| `1068` | Poll | [88](88.md) |
|
||||
| `1111` | Comment | [22](22.md) |
|
||||
| `1222` | Voice Message | [A0](A0.md) |
|
||||
| `1244` | Voice Message Comment | [A0](A0.md) |
|
||||
| `1311` | Live Chat Message | [53](53.md) |
|
||||
| `1337` | Code Snippet | [C0](C0.md) |
|
||||
| `1617` | Patches | [34](34.md) |
|
||||
|
@ -172,6 +175,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
| `7374` | Reserved Cashu Wallet Tokens | [60](60.md) |
|
||||
| `7375` | Cashu Wallet Tokens | [60](60.md) |
|
||||
| `7376` | Cashu Wallet History | [60](60.md) |
|
||||
| `7516` | Geocache log | [geocaching](geocaching) |
|
||||
| `7517` | Geocache proof of find | [geocaching](geocaching) |
|
||||
| `9000`-`9030` | Group Control Events | [29](29.md) |
|
||||
| `9041` | Zap Goal | [75](75.md) |
|
||||
| `9321` | Nutzap | [61](61.md) |
|
||||
|
@ -198,6 +203,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
| `10063` | User server list | [Blossom][blossom] |
|
||||
| `10096` | File storage server list | [96](96.md) |
|
||||
| `10166` | Relay Monitor Announcement | [66](66.md) |
|
||||
| `10312` | Room Presence | [53](53.md) |
|
||||
| `13194` | Wallet Info | [47](47.md) |
|
||||
| `17375` | Cashu Wallet Event | [60](60.md) |
|
||||
| `21000` | Lightning Pub RPC | [Lightning.Pub][lnpub] |
|
||||
|
@ -231,6 +237,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
| `30166` | Relay Discovery | [66](66.md) |
|
||||
| `30267` | App curation sets | [51](51.md) |
|
||||
| `30311` | Live Event | [53](53.md) |
|
||||
| `30312` | Interactive Room | [53](53.md) |
|
||||
| `30313` | Conference Event | [53](53.md) |
|
||||
| `30315` | User Statuses | [38](38.md) |
|
||||
| `30388` | Slide Set | [Corny Chat][cornychat-slideset] |
|
||||
| `30402` | Classified Listing | [99](99.md) |
|
||||
|
@ -247,9 +255,12 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
| `31924` | Calendar | [52](52.md) |
|
||||
| `31925` | Calendar Event RSVP | [52](52.md) |
|
||||
| `31989` | Handler recommendation | [89](89.md) |
|
||||
| `31990` | Handler information | [89](89.md) | |
|
||||
| `32267` | Software Application | | |
|
||||
| `31990` | Handler information | [89](89.md) |
|
||||
| `32267` | Software Application | |
|
||||
| `34550` | Community Definition | [72](72.md) |
|
||||
| `38172` | Cashu Mint Announcement | [87](87.md) |
|
||||
| `38173` | Fedimint Announcement | [87](87.md) |
|
||||
| `37516` | Geocache listing | [geocaching](geocaching) |
|
||||
| `38383` | Peer-to-peer Order events | [69](69.md) |
|
||||
| `39000-9` | Group metadata events | [29](29.md) |
|
||||
| `39089` | Starter packs | [51](51.md) |
|
||||
|
@ -267,6 +278,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
|||
[NKBIP-03]: https://wikistr.com/nkbip-03*fd208ee8c8f283780a9552896e4823cc9dc6bfd442063889577106940fd927c1
|
||||
[blossom]: https://github.com/hzrd149/blossom
|
||||
[Tidal-nostr]: https://wikistr.com/tidal-nostr
|
||||
[geocaching]: https://nostrhub.io/naddr1qvzqqqrcvypzppscgyy746fhmrt0nq955z6xmf80pkvrat0yq0hpknqtd00z8z68qqgkwet0vdskx6rfdenj6etkv4h8guc6gs5y5
|
||||
|
||||
## Message types
|
||||
|
||||
|
|
Loading…
Reference in New Issue