mirror of
https://github.com/nostr-protocol/nips.git
synced 2025-12-09 00:28:51 +00:00
Compare commits
2 Commits
nip11clean
...
dvm-cleanu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87ba38e73b | ||
|
|
8b9f440233 |
4
01.md
4
01.md
@@ -14,7 +14,7 @@ Each user has a keypair. Signatures, public key, and encodings are done accordin
|
||||
|
||||
The only object type that exists is the `event`, which has the following format on the wire:
|
||||
|
||||
```yaml
|
||||
```jsonc
|
||||
{
|
||||
"id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>,
|
||||
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
|
||||
@@ -120,7 +120,7 @@ Clients can send 3 types of messages, which must be JSON arrays, according to th
|
||||
|
||||
`<filtersX>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes:
|
||||
|
||||
```yaml
|
||||
```json
|
||||
{
|
||||
"ids": <a list of event ids>,
|
||||
"authors": <a list of lowercase pubkeys, the pubkey of an event must be one of these>,
|
||||
|
||||
260
11.md
260
11.md
@@ -6,7 +6,7 @@ Relay Information Document
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
Relays may provide server metadata to clients to inform them of capabilities, administrative contacts, and various server attributes. This is made available as a JSON document over HTTP, on the same URI as the relay's websocket.
|
||||
Relays may provide server metadata to clients to inform them of capabilities, administrative contacts, and various server attributes. This is made available as a JSON document over HTTP, on the same URI as the relay's websocket.
|
||||
|
||||
When a relay receives an HTTP(s) request with an `Accept` header of `application/nostr+json` to a URI supporting WebSocket upgrades, they SHOULD return a document with the following structure.
|
||||
|
||||
@@ -20,9 +20,11 @@ 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>,
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@@ -33,11 +35,11 @@ Field Descriptions
|
||||
|
||||
### Name
|
||||
|
||||
A relay may select a `name` for use in client software. This is a string, and SHOULD be less than 30 characters to avoid client truncation.
|
||||
A relay may select a `name` for use in client software. This is a string, and SHOULD be less than 30 characters to avoid client truncation.
|
||||
|
||||
### Description
|
||||
|
||||
Detailed plain-text information about the relay may be contained in the `description` string. It is recommended that this contain no markup, formatting or line breaks for word wrapping, and simply use double newline characters to separate paragraphs. There are no limitations on length.
|
||||
Detailed plain-text information about the relay may be contained in the `description` string. It is recommended that this contain no markup, formatting or line breaks for word wrapping, and simply use double newline characters to separate paragraphs. There are no limitations on length.
|
||||
|
||||
### Banner
|
||||
|
||||
@@ -56,29 +58,35 @@ Icon is a compact visual representation of the relay for use in UI with limited
|
||||
|
||||
### Pubkey
|
||||
|
||||
An administrative contact may be listed with a `pubkey`, in the same format as Nostr events (32-byte hex for a `secp256k1` public key). If a contact is listed, this provides clients with a recommended address to send encrypted direct messages (See [NIP-17](17.md)) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance.
|
||||
An administrative contact may be listed with a `pubkey`, in the same format as Nostr events (32-byte hex for a `secp256k1` public key). If a contact is listed, this provides clients with a recommended address to send encrypted direct messages (See [NIP-17](17.md)) to a system administrator. Expected uses of this address are to report abuse or illegal content, file bug reports, or request other technical assistance.
|
||||
|
||||
Relay operators have no obligation to respond to direct messages.
|
||||
|
||||
### Contact
|
||||
|
||||
An alternative contact may be listed under the `contact` field as well, with the same purpose as `pubkey`. Use of a Nostr public key and direct message SHOULD be preferred over this. Contents of this field SHOULD be a URI, using schemes such as `mailto` or `https` to provide users with a means of contact.
|
||||
An alternative contact may be listed under the `contact` field as well, with the same purpose as `pubkey`. Use of a Nostr public key and direct message SHOULD be preferred over this. Contents of this field SHOULD be a URI, using schemes such as `mailto` or `https` to provide users with a means of contact.
|
||||
|
||||
### Supported NIPs
|
||||
|
||||
As the Nostr protocol evolves, some functionality may only be available by relays that implement a specific `NIP`. This field is an array of the integer identifiers of `NIP`s that are implemented in the relay. Examples would include `1`, for `"NIP-01"` and `9`, for `"NIP-09"`. Client-side `NIPs` SHOULD NOT be advertised, and can be ignored by clients.
|
||||
As the Nostr protocol evolves, some functionality may only be available by relays that implement a specific `NIP`. This field is an array of the integer identifiers of `NIP`s that are implemented in the relay. Examples would include `1`, for `"NIP-01"` and `9`, for `"NIP-09"`. Client-side `NIPs` SHOULD NOT be advertised, and can be ignored by clients.
|
||||
|
||||
### Software
|
||||
|
||||
The relay server implementation MAY be provided in the `software` attribute. If present, this MUST be a URL to the project's homepage.
|
||||
The relay server implementation MAY be provided in the `software` attribute. If present, this MUST be a URL to the project's homepage.
|
||||
|
||||
### Version
|
||||
|
||||
The relay MAY choose to publish its software version as a string attribute. The string format is defined by the relay implementation. It is recommended this be a version number or commit identifier.
|
||||
The relay MAY choose to publish its software version as a string attribute. The string format is defined by the relay implementation. It is recommended this be a version number or commit identifier.
|
||||
|
||||
### Privacy Policy
|
||||
|
||||
The relay owner/admin MAY choose to link to a privacy policy document, which describes how the relay utilizes user data. Data collection, data usage, data retention, monetization of data, and third party data sharing SHOULD be included.
|
||||
|
||||
### Terms of Service
|
||||
|
||||
The relay MAY choose to publish its software version as a string attribute. The string format is defined by the relay implementation. It is recommended this be a version number or commit identifier.
|
||||
The relay owner/admin MAY choose to link to a terms of service document.
|
||||
|
||||
|
||||
|
||||
Extra Fields
|
||||
------------
|
||||
@@ -154,7 +162,113 @@ 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 without a limit.
|
||||
- `default_limit`: The maximum returned events if you send a filter with the limit set to 0.
|
||||
|
||||
### Event Retention
|
||||
|
||||
There may be a cost associated with storing data forever, so relays
|
||||
may wish to state retention times. The values stated here are defaults
|
||||
for unauthenticated users and visitors. Paid users would likely have
|
||||
other policies.
|
||||
|
||||
Retention times are given in seconds, with `null` indicating infinity.
|
||||
If zero is provided, this means the event will not be stored at
|
||||
all, and preferably an error will be provided when those are received.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"retention": [
|
||||
{"kinds": [0, 1, [5, 7], [40, 49]], "time": 3600},
|
||||
{"kinds": [[40000, 49999]], "time": 100},
|
||||
{"kinds": [[30000, 39999]], "count": 1000},
|
||||
{"time": 3600, "count": 10000}
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
`retention` is a list of specifications: each will apply to either all kinds, or
|
||||
a subset of kinds. Ranges may be specified for the kind field as a tuple of inclusive
|
||||
start and end values. Events of indicated kind (or all) are then limited to a `count`
|
||||
and/or time period.
|
||||
|
||||
It is possible to effectively blacklist Nostr-based protocols that rely on
|
||||
a specific `kind` number, by giving a retention time of zero for those `kind` values.
|
||||
While that is unfortunate, it does allow clients to discover servers that will
|
||||
support their protocol quickly via a single HTTP fetch.
|
||||
|
||||
There is no need to specify retention times for _ephemeral events_ since they are not retained.
|
||||
|
||||
### Content Limitations
|
||||
|
||||
Some relays may be governed by the arbitrary laws of a nation state. This
|
||||
may limit what content can be stored in clear-text on those relays. All
|
||||
clients are encouraged to use encryption to work around this limitation.
|
||||
|
||||
It is not possible to describe the limitations of each country's laws
|
||||
and policies which themselves are typically vague and constantly shifting.
|
||||
|
||||
Therefore, this field allows the relay operator to indicate which
|
||||
countries' laws might end up being enforced on them, and then
|
||||
indirectly on their users' content.
|
||||
|
||||
Users should be able to avoid relays in countries they don't like,
|
||||
and/or select relays in more favorable zones. Exposing this
|
||||
flexibility is up to the client software.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"relay_countries": [ "CA", "US" ],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
- `relay_countries`: a list of two-level ISO country codes (ISO 3166-1 alpha-2) whose
|
||||
laws and policies may affect this relay. `EU` may be used for European Union countries. A `*` can be used for global relays.
|
||||
|
||||
Remember that a relay may be hosted in a country which is not the
|
||||
country of the legal entities who own the relay, so it's very
|
||||
likely a number of countries are involved.
|
||||
|
||||
|
||||
### Community Preferences
|
||||
|
||||
For public text notes at least, a relay may try to foster a
|
||||
local community. This would encourage users to follow the global
|
||||
feed on that relay, in addition to their usual individual follows.
|
||||
To support this goal, relays MAY specify some of the following values.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"language_tags": ["en", "en-419"],
|
||||
"tags": ["sfw-only", "bitcoin-only", "anime"],
|
||||
"posting_policy": "https://example.com/posting-policy.html",
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
- `language_tags` is an ordered list
|
||||
of [IETF language tags](https://en.wikipedia.org/wiki/IETF_language_tag) indicating
|
||||
the major languages spoken on the relay. A `*` can be used for global relays.
|
||||
|
||||
- `tags` is a list of limitations on the topics to be discussed.
|
||||
For example `sfw-only` indicates that only "Safe For Work" content
|
||||
is encouraged on this relay. This relies on assumptions of what the
|
||||
"work" "community" feels "safe" talking about. In time, a common
|
||||
set of tags may emerge that allow users to find relays that suit
|
||||
their needs, and client software will be able to parse these tags easily.
|
||||
The `bitcoin-only` tag indicates that any *altcoin*, *"crypto"* or *blockchain*
|
||||
comments will be ridiculed without mercy.
|
||||
|
||||
- `posting_policy` is a link to a human-readable page which specifies the
|
||||
community policies for the relay. In cases where `sfw-only` is True, it's
|
||||
important to link to a page which gets into the specifics of your posting policy.
|
||||
|
||||
The `description` field should be used to describe your community
|
||||
goals and values, in brief. The `posting_policy` is for additional
|
||||
detail and legal terms. Use the `tags` field to signify limitations
|
||||
on content, or topics to be discussed, which could be machine
|
||||
processed by appropriate client software.
|
||||
|
||||
### Pay-to-Relay
|
||||
|
||||
@@ -174,68 +288,82 @@ Relays that require payments may want to expose their fee schedules.
|
||||
|
||||
### Examples
|
||||
|
||||
```yaml
|
||||
~> curl -H "Accept: application/nostr+json" https://nostr.wine | jq
|
||||
{
|
||||
"contact": "wino@nostr.wine",
|
||||
"description": "A paid nostr relay for wine enthusiasts and everyone else.",
|
||||
"fees": {
|
||||
"admission": [
|
||||
{
|
||||
"amount": 18888000,
|
||||
"unit": "msats"
|
||||
}
|
||||
]
|
||||
},
|
||||
"icon": "https://image.nostr.build/30acdce4a81926f386622a07343228ae99fa68d012d54c538c0b2129dffe400c.png",
|
||||
"limitation": {
|
||||
"auth_required": false,
|
||||
"created_at_lower_limit": 94608000,
|
||||
"created_at_upper_limit": 300,
|
||||
"max_event_tags": 4000,
|
||||
"max_limit": 1000,
|
||||
"max_message_length": 524288,
|
||||
"max_subid_length": 71,
|
||||
"max_subscriptions": 50,
|
||||
"min_pow_difficulty": 0,
|
||||
"payment_required": true,
|
||||
"restricted_writes": true
|
||||
},
|
||||
"name": "nostr.wine",
|
||||
"payments_url": "https://nostr.wine/invoices",
|
||||
"pubkey": "4918eb332a41b71ba9a74b1dc64276cfff592e55107b93baae38af3520e55975",
|
||||
"software": "https://nostr.wine",
|
||||
"supported_nips": [ 1, 2, 4, 9, 11, 40, 42, 50, 70, 77 ],
|
||||
"terms_of_service": "https://nostr.wine/terms",
|
||||
"version": "0.3.3"
|
||||
}
|
||||
As of 25 March 2025 the following command provided these results:
|
||||
|
||||
~> curl -H "Accept: application/nostr+json" https://nostr.land | jq
|
||||
```bash
|
||||
curl -H "Accept: application/nostr+json" https://jellyfish.land | jq
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"description": "[✨ NFDB] nostr.land family of relays (fi-01 [tiger])",
|
||||
"name": "[✨ NFDB] nostr.land",
|
||||
"pubkey": "52b4a076bcbbbdc3a1aefa3735816cf74993b1b8db202b01c883c58be7fad8bd",
|
||||
"software": "NFDB",
|
||||
"icon": "https://i.nostr.build/b3thno790aodH8lE.jpg",
|
||||
"supported_nips": [ 1, 2, 4, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 27, 28, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 42, 44, 46, 47, 48, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 65, 68, 69, 71, 72, 73, 75, 78, 84, 88, 89, 90, 92, 99 ],
|
||||
"version": "1.0.0",
|
||||
"limitation": {
|
||||
"payment_required": true,
|
||||
"max_message_length": 65535,
|
||||
"max_event_tags": 2000,
|
||||
"max_subscriptions": 200,
|
||||
"auth_required": false
|
||||
},
|
||||
"payments_url": "https://nostr.land",
|
||||
"name": "JellyFish",
|
||||
"description": "Stay Immortal!",
|
||||
"banner": "https://image.nostr.build/7fdefea2dec1f1ec25b8ce69362566c13b2b7f13f1726c2e4584f05f64f62496.jpg",
|
||||
"pubkey": "bf2bee5281149c7c350f5d12ae32f514c7864ff10805182f4178538c2c421007",
|
||||
"contact": "hi@dezh.tech",
|
||||
"software": "https://github.com/dezh-tech/immortal",
|
||||
"supported_nips": [
|
||||
1,
|
||||
9,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
40,
|
||||
42,
|
||||
59,
|
||||
62,
|
||||
70
|
||||
],
|
||||
"version": "immortal - 0.0.9",
|
||||
"relay_countries": [
|
||||
"*"
|
||||
],
|
||||
"language_tags": [
|
||||
"*"
|
||||
],
|
||||
"tags": [],
|
||||
"posting_policy": "https://jellyfish.land/tos.txt",
|
||||
"payments_url": "https://jellyfish.land/relay",
|
||||
"icon": "https://image.nostr.build/2547e9ec4b23589e09bc7071e0806c3d4293f76284c58ff331a64bce978aaee8.jpg",
|
||||
"retention": [],
|
||||
"fees": {
|
||||
"subscription": [
|
||||
{
|
||||
"amount": 4000000,
|
||||
"unit": "msats",
|
||||
"period": 2592000
|
||||
"amount": 3000,
|
||||
"period": 2628003,
|
||||
"unit": "sats"
|
||||
},
|
||||
{
|
||||
"amount": 8000,
|
||||
"period": 7884009,
|
||||
"unit": "sats"
|
||||
},
|
||||
{
|
||||
"amount": 15000,
|
||||
"period": 15768018,
|
||||
"unit": "sats"
|
||||
},
|
||||
{
|
||||
"amount": 28000,
|
||||
"period": 31536036,
|
||||
"unit": "sats"
|
||||
}
|
||||
]
|
||||
},
|
||||
"terms_of_service": "https://nostr.land/terms"
|
||||
"limitation": {
|
||||
"auth_required": false,
|
||||
"max_message_length": 70000,
|
||||
"max_subid_length": 256,
|
||||
"max_subscriptions": 350,
|
||||
"min_pow_difficulty": 0,
|
||||
"payment_required": true,
|
||||
"restricted_writes": true,
|
||||
"max_event_tags": 2000,
|
||||
"max_content_length": 70000,
|
||||
"created_at_lower_limit": 0,
|
||||
"created_at_upper_limit": 2147483647,
|
||||
"default_limit": 500,
|
||||
"max_limit": 5000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
79
17.md
79
17.md
@@ -15,17 +15,17 @@ Kind `14` is a chat message. `p` tags identify one or more receivers of the mess
|
||||
```jsonc
|
||||
{
|
||||
"id": "<usual hash>",
|
||||
"pubkey": "<sender-pubkey>",
|
||||
"pubkey": "<sender-pubkey>",
|
||||
"created_at": "<current-time>",
|
||||
"kind": 14,
|
||||
"tags": [
|
||||
["p", "<receiver-1-pubkey>", "<relay-url>"],
|
||||
["p", "<receiver-2-pubkey>", "<relay-url>"],
|
||||
["e", "<kind-14-id>", "<relay-url>"] // if this is a reply
|
||||
"kind": 14,
|
||||
"tags": [
|
||||
["p", "<receiver-1-pubkey>", "<relay-url>"],
|
||||
["p", "<receiver-2-pubkey>", "<relay-url>"],
|
||||
["e", "<kind-14-id>", "<relay-url>"] // if this is a reply
|
||||
["subject", "<conversation-title>"],
|
||||
// rest of tags...
|
||||
],
|
||||
"content": "<message-in-plain-text>",
|
||||
// rest of tags...
|
||||
],
|
||||
"content": "<message-in-plain-text>",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -65,22 +65,21 @@ Kind `14`s MUST never be signed. If it is signed, the message might leak to rela
|
||||
}
|
||||
```
|
||||
|
||||
Kind `15` is used for sending encrypted file event messages:
|
||||
Kind 15 is used for sending encrypted file event messages:
|
||||
|
||||
- `file-type`: Specifies the MIME type of the attached file (e.g., `image/jpeg`, `audio/mpeg`, etc.) before encryption.
|
||||
- `encryption-algorithm`: Indicates the encryption algorithm used for encrypting the file. Supported algorithms: `aes-gcm`.
|
||||
- `file-type`: Specifies the MIME type of the attached file (e.g., `image/jpeg`, `audio/mpeg`, etc.).
|
||||
- `encryption-algorithm`: Indicates the encryption algorithm used for encrypting the file. Supported algorithms may include `aes-gcm`, `chacha20-poly1305`,`aes-cbc` etc.
|
||||
- `decryption-key`: The decryption key that will be used by the recipient to decrypt the file.
|
||||
- `decryption-nonce`: The decryption nonce that will be used by the recipient to decrypt the file.
|
||||
- `content`: The URL of the file (`<file-url>`).
|
||||
- `x` containing the SHA-256 hexencoded string of the encrypted file.
|
||||
- `ox` containing the SHA-256 hexencoded string of the file before encryption.
|
||||
- `size` (optional) size of the encrypted file in bytes
|
||||
- `dim` (optional) size in pixels in the form `<width>x<height>`
|
||||
- `x` containing the SHA-256 hexencoded string of the file.
|
||||
- `size` (optional) size of file in bytes
|
||||
- `dim` (optional) size of the file in pixels in the form `<width>x<height>`
|
||||
- `blurhash`(optional) the [blurhash](https://github.com/woltapp/blurhash) to show while the client is loading the file
|
||||
- `thumb` (optional) URL of thumbnail with same aspect ratio (encrypted with the same key, nonce)
|
||||
- `fallback` (optional) zero or more fallback file sources in case `url` fails (encrypted with the same key, nonce)
|
||||
- `fallback` (optional) zero or more fallback file sources in case `url` fails
|
||||
|
||||
Just like kind `14`, kind `15`s MUST never be signed.
|
||||
Just like kind 14, kind `15`s MUST never be signed.
|
||||
|
||||
## Chat Rooms
|
||||
|
||||
@@ -88,34 +87,34 @@ The set of `pubkey` + `p` tags defines a chat room. If a new `p` tag is added or
|
||||
|
||||
Clients SHOULD render messages of the same room in a continuous thread.
|
||||
|
||||
An optional `subject` tag defines the current name/topic of the conversation. Any member can change the topic by simply submitting a new `subject` to an existing `pubkey` + `p` tags room. There is no need to send `subject` in every message. The newest `subject` in the chat room is the subject of the conversation.
|
||||
An optional `subject` tag defines the current name/topic of the conversation. Any member can change the topic by simply submitting a new `subject` to an existing `pubkey` + `p`-tags room. There is no need to send `subject` in every message. The newest `subject` in the thread is the subject of the conversation.
|
||||
|
||||
## Encrypting
|
||||
|
||||
Following [NIP-59](59.md), the **unsigned** `kind:14` & `kind:15` chat messages must be sealed (`kind:13`) and then gift-wrapped (`kind:1059`) to each receiver and the sender individually.
|
||||
|
||||
```js
|
||||
```jsonc
|
||||
{
|
||||
"id": "<usual hash>",
|
||||
"pubkey": randomPublicKey,
|
||||
"created_at": randomTimeUpTo2DaysInThePast(),
|
||||
"pubkey": randomPublicKey,
|
||||
"created_at": randomTimeUpTo2DaysInThePast(),
|
||||
"kind": 1059, // gift wrap
|
||||
"tags": [
|
||||
["p", receiverPublicKey, "<relay-url>"] // receiver
|
||||
],
|
||||
"content": nip44Encrypt(
|
||||
{
|
||||
"tags": [
|
||||
["p", receiverPublicKey, "<relay-url>"] // receiver
|
||||
],
|
||||
"content": nip44Encrypt(
|
||||
{
|
||||
"id": "<usual hash>",
|
||||
"pubkey": senderPublicKey,
|
||||
"created_at": randomTimeUpTo2DaysInThePast(),
|
||||
"kind": 13, // seal
|
||||
"tags": [], // no tags
|
||||
"content": nip44Encrypt(unsignedKind14, senderPrivateKey, receiverPublicKey),
|
||||
"sig": "<signed by senderPrivateKey>"
|
||||
},
|
||||
randomPrivateKey, receiverPublicKey
|
||||
),
|
||||
"sig": "<signed by randomPrivateKey>"
|
||||
"pubkey": senderPublicKey,
|
||||
"created_at": randomTimeUpTo2DaysInThePast(),
|
||||
"kind": 13, // seal
|
||||
"tags": [], // no tags
|
||||
"content": nip44Encrypt(unsignedKind14, senderPrivateKey, receiverPublicKey),
|
||||
"sig": "<signed by senderPrivateKey>"
|
||||
},
|
||||
randomPrivateKey, receiverPublicKey
|
||||
),
|
||||
"sig": "<signed by randomPrivateKey>"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -125,7 +124,7 @@ Clients MUST verify if pubkey of the `kind:13` is the same pubkey on the `kind:1
|
||||
|
||||
Clients SHOULD randomize `created_at` in up to two days in the past in both the seal and the gift wrap to make sure grouping by `created_at` doesn't reveal any metadata.
|
||||
|
||||
The gift wrap's `p` tag can be the receiver's main pubkey or an alias key created to receive DMs without exposing the receiver's identity.
|
||||
The gift wrap's `p`-tag can be the receiver's main pubkey or an alias key created to receive DMs without exposing the receiver's identity.
|
||||
|
||||
Clients CAN offer disappearing messages by setting an `expiration` tag in the gift wrap of each receiver or by not generating a gift wrap to the sender's public key
|
||||
|
||||
@@ -189,7 +188,7 @@ The two final GiftWraps, one to the receiver and the other to the sender, respec
|
||||
"created_at":1703128320,
|
||||
"kind":1059,
|
||||
"tags":[
|
||||
["p", "918e2da906df4ccd12c8ac672d8335add131a4cf9d27ce42b3bb3625755f0788"]
|
||||
[ "p", "918e2da906df4ccd12c8ac672d8335add131a4cf9d27ce42b3bb3625755f0788"]
|
||||
],
|
||||
"content":"AsqzdlMsG304G8h08bE67dhAR1gFTzTckUUyuvndZ8LrGCvwI4pgC3d6hyAK0Wo9gtkLqSr2rT2RyHlE5wRqbCOlQ8WvJEKwqwIJwT5PO3l2RxvGCHDbd1b1o40ZgIVwwLCfOWJ86I5upXe8K5AgpxYTOM1BD+SbgI5jOMA8tgpRoitJedVSvBZsmwAxXM7o7sbOON4MXHzOqOZpALpS2zgBDXSAaYAsTdEM4qqFeik+zTk3+L6NYuftGidqVluicwSGS2viYWr5OiJ1zrj1ERhYSGLpQnPKrqDaDi7R1KrHGFGyLgkJveY/45y0rv9aVIw9IWF11u53cf2CP7akACel2WvZdl1htEwFu/v9cFXD06fNVZjfx3OssKM/uHPE9XvZttQboAvP5UoK6lv9o3d+0GM4/3zP+yO3C0NExz1ZgFmbGFz703YJzM+zpKCOXaZyzPjADXp8qBBeVc5lmJqiCL4solZpxA1865yPigPAZcc9acSUlg23J1dptFK4n3Tl5HfSHP+oZ/QS/SHWbVFCtq7ZMQSRxLgEitfglTNz9P1CnpMwmW/Y4Gm5zdkv0JrdUVrn2UO9ARdHlPsW5ARgDmzaxnJypkfoHXNfxGGXWRk0sKLbz/ipnaQP/eFJv/ibNuSfqL6E4BnN/tHJSHYEaTQ/PdrA2i9laG3vJti3kAl5Ih87ct0w/tzYfp4SRPhEF1zzue9G/16eJEMzwmhQ5Ec7jJVcVGa4RltqnuF8unUu3iSRTQ+/MNNUkK6Mk+YuaJJs6Fjw6tRHuWi57SdKKv7GGkr0zlBUU2Dyo1MwpAqzsCcCTeQSv+8qt4wLf4uhU9Br7F/L0ZY9bFgh6iLDCdB+4iABXyZwT7Ufn762195hrSHcU4Okt0Zns9EeiBOFxnmpXEslYkYBpXw70GmymQfJlFOfoEp93QKCMS2DAEVeI51dJV1e+6t3pCSsQN69Vg6jUCsm1TMxSs2VX4BRbq562+VffchvW2BB4gMjsvHVUSRl8i5/ZSDlfzSPXcSGALLHBRzy+gn0oXXJ/447VHYZJDL3Ig8+QW5oFMgnWYhuwI5QSLEyflUrfSz+Pdwn/5eyjybXKJftePBD9Q+8NQ8zulU5sqvsMeIx/bBUx0fmOXsS3vjqCXW5IjkmSUV7q54GewZqTQBlcx+90xh/LSUxXex7UwZwRnifvyCbZ+zwNTHNb12chYeNjMV7kAIr3cGQv8vlOMM8ajyaZ5KVy7HpSXQjz4PGT2/nXbL5jKt8Lx0erGXsSsazkdoYDG3U",
|
||||
"sig":"a3c6ce632b145c0869423c1afaff4a6d764a9b64dedaf15f170b944ead67227518a72e455567ca1c2a0d187832cecbde7ed478395ec4c95dd3e71749ed66c480"
|
||||
@@ -203,7 +202,7 @@ The two final GiftWraps, one to the receiver and the other to the sender, respec
|
||||
"created_at":1702711587,
|
||||
"kind":1059,
|
||||
"tags":[
|
||||
["p", "44900586091b284416a0c001f677f9c49f7639a55c3f1e2ec130a8e1a7998e1b"]
|
||||
[ "p", "44900586091b284416a0c001f677f9c49f7639a55c3f1e2ec130a8e1a7998e1b"]
|
||||
],
|
||||
"content":"AsTClTzr0gzXXji7uye5UB6LYrx3HDjWGdkNaBS6BAX9CpHa+Vvtt5oI2xJrmWLen+Fo2NBOFazvl285Gb3HSM82gVycrzx1HUAaQDUG6HI7XBEGqBhQMUNwNMiN2dnilBMFC3Yc8ehCJT/gkbiNKOpwd2rFibMFRMDKai2mq2lBtPJF18oszKOjA+XlOJV8JRbmcAanTbEK5nA/GnG3eGUiUzhiYBoHomj3vztYYxc0QYHOx0WxiHY8dsC6jPsXC7f6k4P+Hv5ZiyTfzvjkSJOckel1lZuE5SfeZ0nduqTlxREGeBJ8amOykgEIKdH2VZBZB+qtOMc7ez9dz4wffGwBDA7912NFS2dPBr6txHNxBUkDZKFbuD5wijvonZDvfWq43tZspO4NutSokZB99uEiRH8NAUdGTiNb25m9JcDhVfdmABqTg5fIwwTwlem5aXIy8b66lmqqz2LBzJtnJDu36bDwkILph3kmvaKPD8qJXmPQ4yGpxIbYSTCohgt2/I0TKJNmqNvSN+IVoUuC7ZOfUV9lOV8Ri0AMfSr2YsdZ9ofV5o82ClZWlWiSWZwy6ypa7CuT1PEGHzywB4CZ5ucpO60Z7hnBQxHLiAQIO/QhiBp1rmrdQZFN6PUEjFDloykoeHe345Yqy9Ke95HIKUCS9yJurD+nZjjgOxZjoFCsB1hQAwINTIS3FbYOibZnQwv8PXvcSOqVZxC9U0+WuagK7IwxzhGZY3vLRrX01oujiRrevB4xbW7Oxi/Agp7CQGlJXCgmRE8Rhm+Vj2s+wc/4VLNZRHDcwtfejogjrjdi8p6nfUyqoQRRPARzRGUnnCbh+LqhigT6gQf3sVilnydMRScEc0/YYNLWnaw9nbyBa7wFBAiGbJwO40k39wj+xT6HTSbSUgFZzopxroO3f/o4+ubx2+IL3fkev22mEN38+dFmYF3zE+hpE7jVxrJpC3EP9PLoFgFPKCuctMnjXmeHoiGs756N5r1Mm1ffZu4H19MSuALJlxQR7VXE/LzxRXDuaB2u9days/6muP6gbGX1ASxbJd/ou8+viHmSC/ioHzNjItVCPaJjDyc6bv+gs1NPCt0qZ69G+JmgHW/PsMMeL4n5bh74g0fJSHqiI9ewEmOG/8bedSREv2XXtKV39STxPweceIOh0k23s3N6+wvuSUAJE7u1LkDo14cobtZ/MCw/QhimYPd1u5HnEJvRhPxz0nVPz0QqL/YQeOkAYk7uzgeb2yPzJ6DBtnTnGDkglekhVzQBFRJdk740LEj6swkJ",
|
||||
"sig":"c94e74533b482aa8eeeb54ae72a5303e0b21f62909ca43c8ef06b0357412d6f8a92f96e1a205102753777fd25321a58fba3fb384eee114bd53ce6c06a1c22bab"
|
||||
|
||||
5
51.md
5
51.md
@@ -22,7 +22,6 @@ For example, _mute list_ can contain the public keys of spammers and bad actors
|
||||
|
||||
| name | kind | description | expected tag items |
|
||||
| --- | --- | --- | --- |
|
||||
| Follow list | 3 | microblogging basic follow list, see [NIP-02](02.md) | `"p"` (pubkeys -- with optional relay hint and petname) |
|
||||
| Mute list | 10000 | things the user doesn't want to see in their feeds | `"p"` (pubkeys), `"t"` (hashtags), `"word"` (lowercase string), `"e"` (threads) |
|
||||
| Pinned notes | 10001 | events the user intends to showcase in their profile page | `"e"` (kind:1 notes) |
|
||||
| Read/write relays | 10002 | where a user publishes to and where they expect mentions | see [NIP-65](65.md) |
|
||||
@@ -32,9 +31,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) |
|
||||
| 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) |
|
||||
| DM relays | 10050 | Where to receive [NIP-17](17.md) direct messages | `"relay"` (see [NIP-17](17.md)) |
|
||||
| Good wiki authors | 10101 | [NIP-54](54.md) user recommended wiki authors | `"p"` (pubkeys) |
|
||||
@@ -60,8 +57,6 @@ Aside from their main identifier, the `"d"` tag, sets can optionally have a `"ti
|
||||
| Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) |
|
||||
| Release artifact sets | 30063 | group of artifacts of a software release | `"e"` (kind:1063 [file metadata](94.md) events), `"a"` (software application event) |
|
||||
| App curation sets | 30267 | references to multiple software applications | `"a"` (software application event) |
|
||||
| Starter packs | 39089 | a named set of profiles to be shared around with the goal of being followed together | `"p"` (pubkeys) |
|
||||
| Media starter packs | 39092 | same as above, but specific to multimedia (photos, short video) clients | `"p"` (pubkeys) |
|
||||
|
||||
### Deprecated standard lists
|
||||
|
||||
|
||||
12
52.md
12
52.md
@@ -25,7 +25,7 @@ The format uses an _addressable event_ of `kind:31922`.
|
||||
The `.content` of these events should be a detailed description of the calendar event. It is required but can be an empty string.
|
||||
|
||||
The list of tags are as follows:
|
||||
* `d` (required) a short unique string identifier. Generated by the client creating the calendar event.
|
||||
* `d` (required) universally unique identifier (UUID). Generated by the client creating the calendar event.
|
||||
* `title` (required) title of the calendar event
|
||||
* `start` (required) inclusive start date in ISO 8601 format (YYYY-MM-DD). Must be less than `end`, if it exists.
|
||||
* `end` (optional) exclusive end date in ISO 8601 format (YYYY-MM-DD). If omitted, the calendar event ends on the same date as `start`.
|
||||
@@ -46,7 +46,7 @@ The following tags are deprecated:
|
||||
"kind": 31922,
|
||||
"content": "<description of calendar event>",
|
||||
"tags": [
|
||||
["d", "<random-identifier>"],
|
||||
["d", "<UUID>"],
|
||||
|
||||
["title", "<title of calendar event>"],
|
||||
|
||||
@@ -84,7 +84,7 @@ The format uses an _addressable event_ kind `31923`.
|
||||
The `.content` of these events should be a detailed description of the calendar event. It is required but can be an empty string.
|
||||
|
||||
The list of tags are as follows:
|
||||
* `d` (required) a short unique string identifier. Generated by the client creating the calendar event.
|
||||
* `d` (required) universally unique identifier (UUID). Generated by the client creating the calendar event.
|
||||
* `title` (required) title of the calendar event
|
||||
* `start` (required) inclusive start Unix timestamp in seconds. Must be less than `end`, if it exists.
|
||||
* `end` (optional) exclusive end Unix timestamp in seconds. If omitted, the calendar event ends instantaneously.
|
||||
@@ -110,7 +110,7 @@ The following tags are deprecated:
|
||||
"kind": 31923,
|
||||
"content": "<description of calendar event>",
|
||||
"tags": [
|
||||
["d", "<random-identifier>"],
|
||||
["d", "<UUID>"],
|
||||
|
||||
["title", "<title of calendar event>"],
|
||||
["summary", "<brief description of the calendar event>"],
|
||||
@@ -167,7 +167,7 @@ The format uses a custom replaceable list of kind `31924` with a list of tags as
|
||||
"kind": 31924,
|
||||
"content": "<description of calendar>",
|
||||
"tags": [
|
||||
["d", "<random-identifier>"],
|
||||
["d", "<UUID>"],
|
||||
["title", "<calendar title>"],
|
||||
["a", "<31922 or 31923>:<calendar event author pubkey>:<d-identifier of calendar event>", "<optional relay url>"],
|
||||
["a", "<31922 or 31923>:<calendar event author pubkey>:<d-identifier of calendar event>", "<optional relay url>"]
|
||||
@@ -215,7 +215,7 @@ The list of tags are as follows:
|
||||
"tags": [
|
||||
["e", "<kind 31922 or 31923 event id", "<optional recommended relay URL>"]
|
||||
["a", "<31922 or 31923>:<calendar event author pubkey>:<d-identifier of calendar event>", "<optional recommended relay URL>"],
|
||||
["d", "<random-identifier>"],
|
||||
["d", "<UUID>"],
|
||||
["status", "<accepted/declined/tentative>"],
|
||||
["fb", "<free/busy>"],
|
||||
["p", "<hex pubkey of kind 31922 or 31923 event>", "<optional recommended relay URL>"]
|
||||
|
||||
234
90.md
234
90.md
@@ -1,230 +1,44 @@
|
||||
NIP-90
|
||||
======
|
||||
|
||||
Data Vending Machine
|
||||
--------------------
|
||||
Data Vending Machines
|
||||
---------------------
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
This NIP defines the interaction between customers and Service Providers for performing on-demand computation.
|
||||
This NIP is a documentation effort and a hub for incentivizing the proliferation of DVMs on Nostr.
|
||||
|
||||
Money in, data out.
|
||||
A DVM is anything that can be interacted with programmatically, either to benefit Nostr clients in general or making use of the Nostr ecosystem.
|
||||
|
||||
## Kinds
|
||||
This NIP reserves the range `5000-7000` for data vending machine use.
|
||||
There are 3 types of DVM-related interaction:
|
||||
|
||||
| Kind | Description |
|
||||
| ---- | ----------- |
|
||||
| 5000-5999 | Job request kinds |
|
||||
| 6000-6999 | Job result |
|
||||
| 7000 | Job feedback |
|
||||
- A "bot", i.e. a Nostr profile, optionally with a `kind:0` metadata, that may or may not publish `kind:1`s with human-readable notes, that can be controlled by a human or by a computer program.
|
||||
- A "service", i.e., a server exposing a HTTP/JSON API (although other formats aren't out of scope either).
|
||||
- A "relay", i.e. a server exposing a [NIP-01](01.md) WebSocket endpoint.
|
||||
|
||||
Job results always use a kind number that is `1000` higher than the job request kind. (e.g. request: `kind:5001` gets a result: `kind:6001`).
|
||||
To qualify as a DVM entity a thing must:
|
||||
|
||||
Job request types are defined [separately](https://github.com/nostr-protocol/data-vending-machines/tree/master/kinds).
|
||||
- Accept inputs in some way, such as: by reading some specific event kind from one or more relays; by accept HTTP requests to its own HTTP API; or by receiving `EVENT` or `REQ` messages in its own WebSocket endpoint.
|
||||
- Produce outputs in some way, such as: by publishing some kind of event to one or more relays; by returning an HTTP response; or by returning `EVENT`s in its WebSocket connection.
|
||||
|
||||
## Rationale
|
||||
Nostr can act as a marketplace for data processing, where users request jobs to be processed in certain ways (e.g., "speech-to-text", "summarization", etc.), but they don't necessarily care about "who" processes the data.
|
||||
It's important to notice that such definition of DVM encompasses basically everything in the world -- including Nostr relays, Nostr clients and Nostr users (yes, we are all DVMs), but this NIP limits itself to describing standards that emerge naturally for interaction flows that:
|
||||
|
||||
This NIP is not to be confused with a 1:1 marketplace; instead, it describes a flow where a user announces a desired output, willingness to pay, and service providers compete to fulfill the job requirement in the best way possible.
|
||||
- Will benefit from standardization such that more than one DVM can exist fulfilling the same role and more than one client or consumer can exist that interacts with such DVM directly;
|
||||
- Aren't defined anywhere else and that would be difficult to define in other NIPs.
|
||||
|
||||
### Actors
|
||||
There are two actors in the workflow described in this NIP:
|
||||
* Customers (npubs who request a job)
|
||||
* Service providers (npubs who fulfill jobs)
|
||||
### DVMs
|
||||
|
||||
## Job request (`kind:5000-5999`)
|
||||
A request to process data, published by a customer. This event signals that a customer is interested in receiving the result of some kind of compute.
|
||||
#### Translation
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 5xxx, // kind in 5000-5999 range
|
||||
"content": "",
|
||||
"tags": [
|
||||
[ "i", "<data>", "<input-type>", "<relay>", "<marker>" ],
|
||||
[ "output", "<mime-type>" ],
|
||||
[ "relays", "wss://..." ],
|
||||
[ "bid", "<msat-amount>" ],
|
||||
[ "t", "bitcoin" ]
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
- TODO: nostr.wine HTTP translation
|
||||
- TODO: event-based translation?
|
||||
|
||||
All tags are optional.
|
||||
#### Trending feeds
|
||||
|
||||
* `i` tag: Input data for the job (zero or more inputs)
|
||||
* `<data>`: The argument for the input
|
||||
* `<input-type>`: The way this argument should be interpreted. MUST be one of:
|
||||
* `url`: A URL to be fetched of the data that should be processed.
|
||||
* `event`: A Nostr event ID.
|
||||
* `job`: The output of a previous job with the specified event ID. The dermination of which output to build upon is up to the service provider to decide (e.g. waiting for a signaling from the customer, waiting for a payment, etc.)
|
||||
* `text`: `<data>` is the value of the input, no resolution is needed
|
||||
* `<relay>`: If `event` or `job` input-type, the relay where the event/job was published, otherwise optional or empty string
|
||||
* `<marker>`: An optional field indicating how this input should be used within the context of the job
|
||||
* `output`: Expected output format. Different job request `kind` defines this more precisely.
|
||||
* `param`: Optional parameters for the job as key (first argument)/value (second argument). Different job request `kind` defines this more precisely. (e.g. `[ "param", "lang", "es" ]`)
|
||||
* `bid`: Customer MAY specify a maximum amount (in millisats) they are willing to pay
|
||||
* `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
|
||||
- TODO: primal HTTP trending feeds
|
||||
- TODO: nostr.band HTTP trending feeds
|
||||
- TODO: DVM-based trending feeds
|
||||
|
||||
## Encrypted Params
|
||||
#### Whatever
|
||||
|
||||
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
|
||||
|
||||
```json
|
||||
[
|
||||
["i", "what is the capital of France? ", "text"],
|
||||
["param", "model", "LLaMA-2"],
|
||||
["param", "max_tokens", "512"],
|
||||
["param", "temperature", "0.5"],
|
||||
["param", "top-k", "50"],
|
||||
["param", "top-p", "0.7"],
|
||||
["param", "frequency_penalty", "1"]
|
||||
]
|
||||
```
|
||||
|
||||
This param data will be encrypted and added to the `content` field and `p` tag should be present
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"content": "BE2Y4xvS6HIY7TozIgbEl3sAHkdZoXyLRRkZv4fLPh3R7LtviLKAJM5qpkC7D6VtMbgIt4iNcMpLtpo...",
|
||||
"tags": [
|
||||
["p", "04f74530a6ede6b24731b976b8e78fb449ea61f40ff10e3d869a3030c4edc91f"],
|
||||
["encrypted"]
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Job result (`kind:6000-6999`)
|
||||
|
||||
Service providers publish job results, providing the output of the job result. They should tag the original job request event id as well as the customer's pubkey.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"pubkey": "<service-provider pubkey>",
|
||||
"content": "<payload>",
|
||||
"kind": 6xxx,
|
||||
"tags": [
|
||||
["request", "<job-request>"],
|
||||
["e", "<job-request-id>", "<relay-hint>"],
|
||||
["i", "<input-data>"],
|
||||
["p", "<customer's-pubkey>"],
|
||||
["amount", "requested-payment-amount", "<optional-bolt11>"]
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
* `request`: The job request event stringified-JSON.
|
||||
* `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
|
||||
|
||||
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`
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"pubkey": "<service-provider pubkey>",
|
||||
"content": "<encrypted payload>",
|
||||
"kind": 6xxx,
|
||||
"tags": [
|
||||
["request", "<job-request>"],
|
||||
["e", "<job-request-id>", "<relay-hint>"],
|
||||
["p", "<customer's-pubkey>"],
|
||||
["amount", "requested-payment-amount", "<optional-bolt11>"],
|
||||
["encrypted"]
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
## Job feedback
|
||||
|
||||
Service providers can give feedback about a job back to the customer.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 7000,
|
||||
"content": "<empty-or-payload>",
|
||||
"tags": [
|
||||
["status", "<status>", "<extra-info>"],
|
||||
["amount", "requested-payment-amount", "<bolt11>"],
|
||||
["e", "<job-request-id>", "<relay-hint>"],
|
||||
["p", "<customer's-pubkey>"],
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
* `content`: Either empty or a job-result (e.g. for partial-result samples)
|
||||
* `amount` tag: as defined in the [Job Result](#job-result-kind6000-6999) section.
|
||||
* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Job Feedback Status](#job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
|
||||
|
||||
* NOTE: If the input params requires input to be encrypted, then `content` field will have encrypted payload with `p` tag as key.
|
||||
|
||||
### Job feedback status
|
||||
|
||||
| status | description |
|
||||
| -------- | ------------- |
|
||||
| `payment-required` | Service Provider requires payment before continuing. |
|
||||
| `processing` | Service Provider is processing the job. |
|
||||
| `error` | Service Provider was unable to process the job. |
|
||||
| `success` | Service Provider successfully processed the job. |
|
||||
| `partial` | Service Provider partially processed the job. The `.content` might include a sample of the partial results. |
|
||||
|
||||
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
|
||||
|
||||
* 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.).
|
||||
* Upon completion, the service provider publishes the result of the job with a `kind:6000` job-result event.
|
||||
* At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user.
|
||||
|
||||
Job feedback (`kind:7000`) and Job Results (`kind:6000-6999`) events MAY include an `amount` tag, this can be interpreted as a suggestion to pay. Service Providers MUST use the `payment-required` feedback event to signal that a payment is required and no further actions will be performed until the payment is sent.
|
||||
|
||||
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
|
||||
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
|
||||
A job request might be canceled by publishing a `kind:5` delete request event tagging the job request event.
|
||||
|
||||
# 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
|
||||
Service Providers MAY use NIP-89 announcements to advertise their support for job kinds:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"kind": 31990,
|
||||
"pubkey": "<pubkey>",
|
||||
"content": "{
|
||||
\"name\": \"Translating DVM\",
|
||||
\"about\": \"I'm a DVM specialized in translating Bitcoin content.\"
|
||||
}",
|
||||
"tags": [
|
||||
["k", "5005"], // e.g. translation
|
||||
["t", "bitcoin"] // e.g. optionally advertises it specializes in bitcoin audio transcription that won't confuse "Drivechains" with "Ridechains"
|
||||
],
|
||||
// other fields...
|
||||
}
|
||||
```
|
||||
|
||||
Customers can use NIP-89 to see what service providers their follows use.
|
||||
- TODO:
|
||||
|
||||
@@ -165,9 +165,6 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||
| `2004` | Torrent Comment | [35](35.md) |
|
||||
| `2022` | Coinjoin Pool | [joinstr][joinstr] |
|
||||
| `4550` | Community Post Approval | [72](72.md) |
|
||||
| `5000`-`5999` | Job Request | [90](90.md) |
|
||||
| `6000`-`6999` | Job Result | [90](90.md) |
|
||||
| `7000` | Job Feedback | [90](90.md) |
|
||||
| `7374` | Reserved Cashu Wallet Tokens | [60](60.md) |
|
||||
| `7375` | Cashu Wallet Tokens | [60](60.md) |
|
||||
| `7376` | Cashu Wallet History | [60](60.md) |
|
||||
@@ -187,11 +184,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||
| `10006` | Blocked relays list | [51](51.md) |
|
||||
| `10007` | Search relays list | [51](51.md) |
|
||||
| `10009` | User groups | [51](51.md), [29](29.md) |
|
||||
| `10012` | Favorite relays list | [51](51.md) |
|
||||
| `10013` | Private event relay list | [37](37.md) |
|
||||
| `10015` | Interests list | [51](51.md) |
|
||||
| `10019` | Nutzap Mint Recommendation | [61](61.md) |
|
||||
| `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) |
|
||||
| `10063` | User server list | [Blossom][blossom] |
|
||||
@@ -251,8 +246,6 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||
| `34550` | Community Definition | [72](72.md) |
|
||||
| `38383` | Peer-to-peer Order events | [69](69.md) |
|
||||
| `39000-9` | Group metadata events | [29](29.md) |
|
||||
| `39089` | Starter packs | [51](51.md) |
|
||||
| `39092` | Media starter packs | [51](51.md) |
|
||||
| `39701` | Web bookmarks | [B0](B0.md) |
|
||||
|
||||
[NUD: Custom Feeds]: https://wikifreedia.xyz/cip-01/
|
||||
@@ -333,7 +326,6 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
|
||||
| `dep` | Required dependency | -- | [C0](C0.md) |
|
||||
| `description` | description | -- | [34](34.md), [57](57.md), [58](58.md), [C0](C0.md) |
|
||||
| `emoji` | shortcode, image URL | -- | [30](30.md) |
|
||||
| `encrypted` | -- | -- | [90](90.md) |
|
||||
| `extension` | File extension | -- | [C0](C0.md) |
|
||||
| `expiration` | unix timestamp (string) | -- | [40](40.md) |
|
||||
| `file` | full path (string) | -- | [35](35.md) |
|
||||
|
||||
Reference in New Issue
Block a user