mirror of
https://github.com/nostr-protocol/nips.git
synced 2025-12-13 18:38:52 +00:00
Compare commits
2 Commits
052fffd45b
...
nip-60-rel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
baa382ca7d | ||
|
|
58cfc3189c |
39
37.md
39
37.md
@@ -1,57 +1,50 @@
|
|||||||
NIP-37
|
NIP-37
|
||||||
======
|
======
|
||||||
|
|
||||||
Draft Wraps
|
Draft Events
|
||||||
-----------
|
------------
|
||||||
|
|
||||||
`draft` `optional`
|
`draft` `optional`
|
||||||
|
|
||||||
This NIP defines kind `31234` as an encrypted storage for unsigned draft events of any other kind.
|
This NIP defines kind `31234` as a private wrap for drafts of any other event kind.
|
||||||
|
|
||||||
The draft is JSON-stringified, [NIP44-encrypted](44.md) to the signer's public key and placed inside the `.content`.
|
The draft event is JSON-stringified, [NIP44-encrypted](44.md) to the signer's public key and placed inside the `.content` of the event.
|
||||||
|
|
||||||
`k` tags identify the kind of the draft.
|
An additional `k` tag identifies the kind of the draft event.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
"kind": 31234,
|
"kind": 31234,
|
||||||
"tags": [
|
"tags": [
|
||||||
["d", "<identifier>"],
|
["d", "<identifier>"],
|
||||||
["k", "<kind of the draft event>"], // required
|
["k", "<kind of the draft event>"],
|
||||||
["expiration", "now + 90 days"] // recommended
|
["e", "<anchor event event id>", "<relay-url>"],
|
||||||
|
["a", "<anchor event address>", "<relay-url>"],
|
||||||
],
|
],
|
||||||
"content": nip44Encrypt(JSON.stringify(draft_event)),
|
"content": nip44Encrypt(JSON.stringify(draft_event)),
|
||||||
// other fields
|
// other fields
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A blanked `.content` field signals that the draft has been deleted.
|
A blanked `.content` means this draft has been deleted by a client but relays still have the event.
|
||||||
|
|
||||||
[NIP-40](40.md) `expiration` tags are recommended.
|
Tags `e` and `a` identify one or more anchor events, such as parent events on replies.
|
||||||
|
|
||||||
Clients SHOULD publish kind `31234` events to relays listed on kind `10013` below.
|
|
||||||
|
|
||||||
## Relay List for Private Content
|
## Relay List for Private Content
|
||||||
|
|
||||||
Kind `10013` indicates the user's preferred relays to store private events like Draft Wraps.
|
Kind `10013` indicates the user's preferred relays to store private events like Drafts. The event MUST include a list of `relay` URLs in private tags. Private tags are JSON Stringified, NIP-44-encrypted to the signer's keys and placed inside the .content of the event.
|
||||||
|
|
||||||
The event MUST include a list of `relay` URLs in private tags. Private tags are JSON Stringified, [NIP44-encrypted](44.md) to the signer's keys and placed inside the .content of the event.
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
"kind": 10013,
|
"kind": 10013,
|
||||||
"tags": [],
|
"tags": [],
|
||||||
"content": nip44Encrypt(
|
"content": nip44Encrypt(JSON.stringify([
|
||||||
JSON.stringify(
|
["relay", "wss://myrelay.mydomain.com"]
|
||||||
[
|
]))
|
||||||
["relay", "wss://myrelay.mydomain.com"]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
//...other fields
|
//...other fields
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It's recommended that Private Storage relays SHOULD be [NIP-42](42.md)-authed and only allow downloads of events signed by the authed user.
|
Relays listed in this event SHOULD be authed and only allow downloads to events signed by the authed user.
|
||||||
|
|
||||||
Clients MUST publish kind `10013` events to the author's [NIP-65](65.md) `write` relays.
|
Clients SHOULD publish kind `10013` events to the author's [NIP-65](65.md) `write` relays.
|
||||||
|
|||||||
22
45.md
22
45.md
@@ -14,17 +14,17 @@ Some queries a client may want to execute against connected relays are prohibiti
|
|||||||
|
|
||||||
## Filters and return values
|
## Filters and return values
|
||||||
|
|
||||||
This NIP defines the verb `COUNT`, which accepts a query id and filters as specified in [NIP 01](01.md) for the verb `REQ`. Multiple filters are OR'd together and aggregated into a single count result.
|
This NIP defines the verb `COUNT`, which accepts a subscription id and filters as specified in [NIP 01](01.md) for the verb `REQ`. Multiple filters are OR'd together and aggregated into a single count result.
|
||||||
|
|
||||||
```
|
```
|
||||||
["COUNT", <query_id>, <filters JSON>...]
|
["COUNT", <subscription_id>, <filters JSON>...]
|
||||||
```
|
```
|
||||||
|
|
||||||
Counts are returned using a `COUNT` response in the form `{"count": <integer>}`. Relays may use probabilistic counts to reduce compute requirements.
|
Counts are returned using a `COUNT` response in the form `{"count": <integer>}`. Relays may use probabilistic counts to reduce compute requirements.
|
||||||
In case a relay uses probabilistic counts, it MAY indicate it in the response with `approximate` key i.e. `{"count": <integer>, "approximate": <true|false>}`.
|
In case a relay uses probabilistic counts, it MAY indicate it in the response with `approximate` key i.e. `{"count": <integer>, "approximate": <true|false>}`.
|
||||||
|
|
||||||
```
|
```
|
||||||
["COUNT", <query_id>, {"count": <integer>}]
|
["COUNT", <subscription_id>, {"count": <integer>}]
|
||||||
```
|
```
|
||||||
|
|
||||||
Whenever the relay decides to refuse to fulfill the `COUNT` request, it MUST return a `CLOSED` message.
|
Whenever the relay decides to refuse to fulfill the `COUNT` request, it MUST return a `CLOSED` message.
|
||||||
@@ -34,27 +34,27 @@ Whenever the relay decides to refuse to fulfill the `COUNT` request, it MUST ret
|
|||||||
### Followers count
|
### Followers count
|
||||||
|
|
||||||
```
|
```
|
||||||
["COUNT", <query_id>, {"kinds": [3], "#p": [<pubkey>]}]
|
["COUNT", <subscription_id>, {"kinds": [3], "#p": [<pubkey>]}]
|
||||||
["COUNT", <query_id>, {"count": 238}]
|
["COUNT", <subscription_id>, {"count": 238}]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Count posts and reactions
|
### Count posts and reactions
|
||||||
|
|
||||||
```
|
```
|
||||||
["COUNT", <query_id>, {"kinds": [1, 7], "authors": [<pubkey>]}]
|
["COUNT", <subscription_id>, {"kinds": [1, 7], "authors": [<pubkey>]}]
|
||||||
["COUNT", <query_id>, {"count": 5}]
|
["COUNT", <subscription_id>, {"count": 5}]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Count posts approximately
|
### Count posts approximately
|
||||||
|
|
||||||
```
|
```
|
||||||
["COUNT", <query_id>, {"kinds": [1]}]
|
["COUNT", <subscription_id>, {"kinds": [1]}]
|
||||||
["COUNT", <query_id>, {"count": 93412452, "approximate": true}]
|
["COUNT", <subscription_id>, {"count": 93412452, "approximate": true}]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Relay refuses to count
|
### Relay refuses to count
|
||||||
|
|
||||||
```
|
```
|
||||||
["COUNT", <query_id>, {"kinds": [1059], "#p": [<pubkey>]}]
|
["COUNT", <subscription_id>, {"kinds": [4], "authors": [<pubkey>], "#p": [<pubkey>]}]
|
||||||
["CLOSED", <query_id>, "auth-required: cannot count other people's DMs"]
|
["CLOSED", <subscription_id>, "auth-required: cannot count other people's DMs"]
|
||||||
```
|
```
|
||||||
|
|||||||
18
47.md
18
47.md
@@ -667,21 +667,3 @@ Here are some properties that are recognized by some NWC clients:
|
|||||||
"sig": "31f57b369459b5306a5353aa9e03be7fbde169bc881c3233625605dd12f53548179def16b9fe1137e6465d7e4d5bb27ce81fd6e75908c46b06269f4233c845d8"
|
"sig": "31f57b369459b5306a5353aa9e03be7fbde169bc881c3233625605dd12f53548179def16b9fe1137e6465d7e4d5bb27ce81fd6e75908c46b06269f4233c845d8"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Deep-links
|
|
||||||
|
|
||||||
Wallet applications can register deeplinks in mobile systems to make it possible to create a linking UX that doesn't require the user scanning a QR code or pasting some code.
|
|
||||||
|
|
||||||
`nostrnwc://connect` and `nostrnwc+{app_name}://connect` can be registered by wallet apps and queried by apps that want to receive an NWC pairing code.
|
|
||||||
|
|
||||||
All URI parameters, MUST be URI-encoded.
|
|
||||||
|
|
||||||
URI parameters:
|
|
||||||
* `appicon` -- URL to an icon of the client that wants to create a connection.
|
|
||||||
* `appname` -- Name of the client that wants to create a connection.
|
|
||||||
* `callback` -- URI schema the wallet should open with the connection string
|
|
||||||
|
|
||||||
Once a connection has been created by the wallet, it should be returned to the client by opening the callback with the following parameters
|
|
||||||
* `value` -- NWC pairing code (e.g. `nostr+walletconnect://...`)
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
55.md
4
55.md
@@ -295,8 +295,6 @@ For the other types Signer Application returns the column "result"
|
|||||||
|
|
||||||
If the user chose to always reject the event, signer application will return the column "rejected" and you should not open signer application
|
If the user chose to always reject the event, signer application will return the column "rejected" and you should not open signer application
|
||||||
|
|
||||||
Clients SHOULD save the user pubkey locally and avoid calling the `get_public_key` after the user is logged in to the Client
|
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
|
|
||||||
- **get_public_key**
|
- **get_public_key**
|
||||||
@@ -305,7 +303,7 @@ Clients SHOULD save the user pubkey locally and avoid calling the `get_public_ke
|
|||||||
```kotlin
|
```kotlin
|
||||||
val result = context.contentResolver.query(
|
val result = context.contentResolver.query(
|
||||||
Uri.parse("content://com.example.signer.GET_PUBLIC_KEY"),
|
Uri.parse("content://com.example.signer.GET_PUBLIC_KEY"),
|
||||||
listOf(hex_pub_key),
|
listOf("login"),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
|
|||||||
15
60.md
15
60.md
@@ -28,7 +28,9 @@ This NIP doesn't deal with users' *receiving* money from someone else, it's just
|
|||||||
"content": nip44_encrypt([
|
"content": nip44_encrypt([
|
||||||
[ "privkey", "hexkey" ],
|
[ "privkey", "hexkey" ],
|
||||||
[ "mint", "https://mint1" ],
|
[ "mint", "https://mint1" ],
|
||||||
[ "mint", "https://mint2" ]
|
[ "mint", "https://mint2" ],
|
||||||
|
[ "relay", "wss://relay1.example.com" ],
|
||||||
|
[ "relay", "wss://relay2.example.com" ]
|
||||||
]),
|
]),
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
@@ -36,9 +38,10 @@ This NIP doesn't deal with users' *receiving* money from someone else, it's just
|
|||||||
|
|
||||||
The wallet event is an replaceable event `kind:17375`.
|
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.
|
* `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.
|
* `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.
|
Token events are used to record unspent proofs.
|
||||||
@@ -104,10 +107,14 @@ 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.
|
Multiple `e` tags can be added, and should be encrypted, except for tags with the `redeemed` marker.
|
||||||
|
|
||||||
## Flow
|
## 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.
|
A client that wants to check for user's wallet information:
|
||||||
|
|
||||||
|
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
|
### Fetch wallet and token list
|
||||||
From those relays, the client should fetch wallet and token events.
|
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>"]`
|
`"kinds": [17375, 7375], "authors": ["<my-pubkey>"]`
|
||||||
|
|
||||||
|
|||||||
2
66.md
2
66.md
@@ -53,7 +53,7 @@ Example:
|
|||||||
["g", "ww8p1r4t8"],
|
["g", "ww8p1r4t8"],
|
||||||
["l", "en", "ISO-639-1"],
|
["l", "en", "ISO-639-1"],
|
||||||
["t", "nsfw" ],
|
["t", "nsfw" ],
|
||||||
["rtt-open", "234" ]
|
["rtt-open", 234 ]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
12
71.md
12
71.md
@@ -26,11 +26,6 @@ The primary source of video information is the `imeta` tags which is defined in
|
|||||||
|
|
||||||
Each `imeta` tag can be used to specify a variant of the video by the `dim` & `m` properties.
|
Each `imeta` tag can be used to specify a variant of the video by the `dim` & `m` properties.
|
||||||
|
|
||||||
This NIP defines the following additional `imeta` properties aside form those listen in [NIP-92](92.md) & [NIP-94](94.md):
|
|
||||||
|
|
||||||
* `duration` (recommended) the duration of the video/audio in seconds (floating point number)
|
|
||||||
* `bitrate` (recommended) the average bitrate of the video/audio in bits/sec
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
@@ -44,8 +39,6 @@ Example:
|
|||||||
"fallback https://myotherserver.com/1080/12345.mp4",
|
"fallback https://myotherserver.com/1080/12345.mp4",
|
||||||
"fallback https://andanotherserver.com/1080/12345.mp4",
|
"fallback https://andanotherserver.com/1080/12345.mp4",
|
||||||
"service nip96",
|
"service nip96",
|
||||||
"bitrate 3000000",
|
|
||||||
"duration 29.223"
|
|
||||||
],
|
],
|
||||||
["imeta",
|
["imeta",
|
||||||
"dim 1280x720",
|
"dim 1280x720",
|
||||||
@@ -57,8 +50,6 @@ Example:
|
|||||||
"fallback https://myotherserver.com/720/12345.mp4",
|
"fallback https://myotherserver.com/720/12345.mp4",
|
||||||
"fallback https://andanotherserver.com/720/12345.mp4",
|
"fallback https://andanotherserver.com/720/12345.mp4",
|
||||||
"service nip96",
|
"service nip96",
|
||||||
"bitrate 2000000",
|
|
||||||
"duration 29.24"
|
|
||||||
],
|
],
|
||||||
["imeta",
|
["imeta",
|
||||||
"dim 1280x720",
|
"dim 1280x720",
|
||||||
@@ -70,7 +61,6 @@ Example:
|
|||||||
"fallback https://myotherserver.com/720/12345.m3u8",
|
"fallback https://myotherserver.com/720/12345.m3u8",
|
||||||
"fallback https://andanotherserver.com/720/12345.m3u8",
|
"fallback https://andanotherserver.com/720/12345.m3u8",
|
||||||
"service nip96",
|
"service nip96",
|
||||||
"duration 29.21"
|
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@@ -84,6 +74,7 @@ Additionally `service nip96` may be included to allow clients to search the auth
|
|||||||
### Other tags:
|
### Other tags:
|
||||||
* `title` (required) title of the video
|
* `title` (required) title of the video
|
||||||
* `published_at`, for the timestamp in unix seconds (stringified) of the first time the video was published
|
* `published_at`, for the timestamp in unix seconds (stringified) of the first time the video was published
|
||||||
|
* `duration` (optional) video duration in seconds
|
||||||
* `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code
|
* `text-track` (optional, repeated) link to WebVTT file for video, type of supplementary information (captions/subtitles/chapters/metadata), optional language code
|
||||||
* `content-warning` (optional) warning about content of NSFW video
|
* `content-warning` (optional) warning about content of NSFW video
|
||||||
* `alt` (optional) description for accessibility
|
* `alt` (optional) description for accessibility
|
||||||
@@ -117,6 +108,7 @@ Additionally `service nip96` may be included to allow clients to search the auth
|
|||||||
"service nip96",
|
"service nip96",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
["duration", "<duration of video in seconds>"],
|
||||||
["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"],
|
["text-track", "<encoded `kind 6000` event>", "<recommended relay urls>"],
|
||||||
["content-warning", "<reason>"],
|
["content-warning", "<reason>"],
|
||||||
["segment", <start>, <end>, "<title>", "<thumbnail URL>"],
|
["segment", <start>, <end>, "<title>", "<thumbnail URL>"],
|
||||||
|
|||||||
Reference in New Issue
Block a user