Compare commits

...

44 Commits

Author SHA1 Message Date
Pablo Fernandez
7ad40d5159 Recurring Subscriptions 2023-11-05 13:14:43 +02:00
fiatjaf
08d3eff350 52: fix kinds (as ints). 2023-11-04 16:55:28 -03:00
fiatjaf
b14b9d2120 nip-01: clarify that whitespace is allowed inside the strings.
closes https://github.com/nostr-protocol/nips/pull/861
2023-11-02 19:46:37 -03:00
Ryan Breen
cee6977347 Adding Nostore to NIP-07 extension list. 2023-11-01 12:53:43 -03:00
Ioan Bizău
a328831a07 Unlimited quantity possible in NIP-15. 2023-10-31 15:54:25 -03:00
Semisol
4b9f13d983 NIP-90: consistency changes 2023-10-31 00:21:53 +03:00
Akiomi Kamakura
ad019ee067 DVM kinds change on README (#850) 2023-10-29 23:00:57 -03:00
Pablo Fernandez
7a2de8ab25 Merge pull request #682 from nostr-protocol/vending-machine
NIP-90: Data Vending Machines
2023-10-29 12:48:57 +02:00
Pablo Fernandez
435147149a update readme 2023-10-29 11:45:49 +01:00
Pablo Fernandez
c88a620fe7 Merge branch 'master' into vending-machine 2023-10-29 11:43:19 +01:00
Mike O'Bank
ca73c5dd5e Clarify Unsigned Event Object type 2023-10-21 16:05:32 -03:00
Egge
4216f0bf2f added nodestr 2023-10-19 14:32:41 -03:00
fiatjaf
cf672b764b remove useless "block" tag on OTS. 2023-10-17 07:38:53 -03:00
Pablo Fernandez
a482f47ae4 Merge branch 'master' into vending-machine 2023-10-15 21:30:42 +03:00
Pablo Fernandez
d9400e1e7b big refactor
* use different kinds per response type
* remove examples
* remove specific job request definitions, moved to a separate repo for clarity
2023-10-14 16:15:00 +03:00
Mike O'Bank
202e18f2b2 Nip 06 test vectors (#819) 2023-10-12 10:31:58 -03:00
fiatjaf_
09ffb951c6 rework NIP-03 so it is actually usable (#804)
* rework nip-03 to be actually useful and usable.
* fixes.
* add ots verification flow.
2023-10-11 10:17:43 -03:00
Don
324c7aafdc Change wording to imply that reactions can target any event (#815)
* kind:17 generic reactions.

* `kind 7` is available for all kind events.

* `k` tag is not required.
2023-10-11 08:55:27 -03:00
Vic
21c6c12c52 Update 57.md (#808)
Clarify how multiple relays should be included in the zap request event
2023-10-10 21:57:12 -07:00
Nostr.Band
e9f8bc27b7 add spring.site to nip-07 (#810)
Add Spring.site as NIP07 implementation
2023-10-10 14:12:21 -03:00
mattn
acbdacb625 Merge pull request #801 from badonyx/65-normalize-uri
65: Normalize relay URIs
2023-10-07 13:57:35 +09:00
Asai Toshiya
aa1bf6d268 Add NIP-24 to list 2023-10-06 08:26:02 -03:00
git
0d267aab5a Better RFC reference 2023-10-02 15:34:24 -07:00
fiatjaf
b33409c099 make it clear that relays can keep multiple replaceable event versions. 2023-09-29 16:49:55 -03:00
git
4de43f65a1 Update RFC reference 2023-09-29 12:00:07 -07:00
git
3b5d3ca677 65: normalize relay uri 2023-09-29 11:46:30 -07:00
fiatjaf_
5026747008 Merge branch 'master' into vending-machine 2023-08-09 07:26:51 -03:00
pablof7z
9fa9045d19 remove duplicated output 2023-07-25 17:31:31 +03:00
pablof7z
948ee24775 rename file 2023-07-25 17:26:09 +03:00
pablof7z
7231035060 feed-generation kind and some more stuff 2023-07-25 01:29:02 +03:00
pablof7z
4cb3ac871f clarifications, hopefully 2023-07-24 00:38:47 +03:00
pablof7z
280483adc5 more clarifications 2023-07-23 23:58:12 +03:00
pablof7z
d8b0e7d757 wip 2023-07-23 23:37:20 +03:00
pablof7z
53bd97373b use different kinds per job request type 2023-07-23 21:28:59 +02:00
pablof7z
e9924bdcde add optional bolt11 2023-07-15 12:24:32 +02:00
pablof7z
def620e1ce more cleanup 2023-07-11 22:25:54 +02:00
pablof7z
a9dd557453 get rid of the kind:7 stuff 2023-07-11 15:22:30 +02:00
Pablo Fernandez
c1b8d98b26 Merge pull request #649 from believethehype/vending-machine
Fixed request input back to stringified json, added additional alignment parameter to text-to-speech
2023-07-11 01:57:51 +02:00
Believethehype
5f27121c98 Update vending-machine.md 2023-07-09 12:08:28 +02:00
Pablo Fernandez
83e9b58401 Merge pull request #644 from gazhayes/patch-1
Problem: some of the language is inconsistent
2023-07-08 13:01:39 +02:00
gsovereignty
667c700c1c Problem: some of the language is inconsistent 2023-07-08 18:51:30 +08:00
pablof7z
ce552554a0 wip, part 2 2023-07-05 11:14:50 +02:00
pablof7z
71803c21a6 Add examples 2023-07-03 14:33:17 +02:00
pablof7z
67e950a200 wip 2023-07-03 14:21:13 +02:00
12 changed files with 357 additions and 65 deletions

10
01.md
View File

@@ -29,9 +29,9 @@ The only object type that exists is the `event`, which has the following format
}
```
To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no white space or line breaks) of the following structure:
To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no white space or line breaks between the fields) of the following structure:
```json
```
[
0,
<pubkey, as a lowercase hex string>,
@@ -82,12 +82,14 @@ Kinds specify how clients should interpret the meaning of each event and the oth
And also a convention for kind ranges that allow for easier experimentation and flexibility of relay implementation:
- for kind `n` such that `1000 <= n < 10000`, events are **regular**, which means they're all expected to be stored by relays.
- for kind `n` such that `10000 <= n < 20000 || n == 0 || n == 3`, events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event is expected to (SHOULD) be stored by relays, older versions are expected to be discarded.
- for kind `n` such that `10000 <= n < 20000 || n == 0 || n == 3`, events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event MUST be stored by relays, older versions MAY be discarded.
- for kind `n` such that `20000 <= n < 30000`, events are **ephemeral**, which means they are not expected to be stored by relays.
- for kind `n` such that `30000 <= n < 40000`, events are **parameterized replaceable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag's first value, only the latest event is expected to be stored by relays, older versions are expected to be discarded.
- for kind `n` such that `30000 <= n < 40000`, events are **parameterized replaceable**, which means that, for each combination of `pubkey`, `kind` and the `d` tag's first value, only the latest event MUST be stored by relays, older versions MAY be discarded.
In case of replaceable events with the same timestamp, the event with the lowest id (first in lexical order) should be retained, and the other discarded.
When answering to `REQ` messages for replaceable events such as `{"kinds":[0],"authors":[<hex-key>]}`, even if the relay has more than one version stored, it SHOULD return just the latest one.
These are just conventions and relay implementations may differ.
## Communication between clients and relays

31
03.md
View File

@@ -4,20 +4,31 @@ NIP-03
OpenTimestamps Attestations for Events
--------------------------------------
`draft` `optional` `author:fiatjaf`
`draft` `optional` `author:fiatjaf` `author:constant`
When there is an OTS available it MAY be included in the existing event body under the `ots` key:
This NIP defines an event with `kind:1040` that can contain an [OpenTimestamps](https://opentimestamps.org/) proof for any other event:
```
```json
{
"id": ...,
"kind": ...,
...,
...,
"ots": <base64-encoded OTS file data>
"kind": 1040
"tags": [
["e", <event-id>, <relay-url>],
["alt", "opentimestamps attestation"]
],
"content": <base64-encoded OTS file data>
}
```
The _event id_ MUST be used as the raw hash to be included in the OpenTimestamps merkle tree.
- The OpenTimestamps proof MUST prove the referenced `e` event id as its digest.
- The `content` MUST be the full content of an `.ots` file containing at least one Bitcoin attestation. This file SHOULD contain a **single** Bitcoin attestation and no reference to "pending" attestations since they are useless in this context.
The attestation can be either provided by relays automatically (and the OTS binary contents just appended to the events it receives) or by clients themselves when they first upload the event to relays — and used by clients to show that an event is really "at least as old as [OTS date]".
### Example OpenTimestamps proof verification flow
Using [`nak`](https://github.com/fiatjaf/nak), [`jq`](https://jqlang.github.io/jq/) and [`ots`](https://github.com/fiatjaf/ots):
```bash
~> nak req -i e71c6ea722987debdb60f81f9ea4f604b5ac0664120dd64fb9d23abc4ec7c323 wss://nostr-pub.wellorder.net | jq -r .content | ots verify
> using an esplora server at https://blockstream.info/api
- sequence ending on block 810391 is valid
timestamp validated at block [810391]
```

16
06.md
View File

@@ -13,3 +13,19 @@ Basic key derivation from mnemonic seed phrase
A basic client can simply use an `account` of `0` to derive a single key. For more advanced use-cases you can increment `account`, allowing generation of practically infinite keys from the 5-level path with hardened derivation.
Other types of clients can still get fancy and use other derivation paths for their own other purposes.
### Test vectors
mnemonic: leader monkey parrot ring guide accident before fence cannon height naive bean\
private key (hex): 7f7ff03d123792d6ac594bfa67bf6d0c0ab55b6b1fdb6249303fe861f1ccba9a\
nsec: nsec10allq0gjx7fddtzef0ax00mdps9t2kmtrldkyjfs8l5xruwvh2dq0lhhkp\
public key (hex): 17162c921dc4d2518f9a101db33695df1afb56ab82f5ff3e5da6eec3ca5cd917\
npub: npub1zutzeysacnf9rru6zqwmxd54mud0k44tst6l70ja5mhv8jjumytsd2x7nu
---
mnemonic: what bleak badge arrange retreat wolf trade produce cricket blur garlic valid proud rude strong choose busy staff weather area salt hollow arm fade\
private key (hex): c15d739894c81a2fcfd3a2df85a0d2c0dbc47a280d092799f144d73d7ae78add\
nsec: nsec1c9wh8xy5eqdzln7n5t0ctgxjcrdug73gp5yj0x03gntn67h83twssdfhel\
public key (hex): d41b22899549e1f3d335a31002cfd382174006e166d3e658e3a5eecdb6463573\
npub: npub16sdj9zv4f8sl85e45vgq9n7nsgt5qphpvmf7vk8r5hhvmdjxx4es8rq74h

5
07.md
View File

@@ -12,7 +12,7 @@ That object must define the following methods:
```
async window.nostr.getPublicKey(): string // returns a public key as hex
async window.nostr.signEvent(event: Event): Event // takes an event object, adds `id`, `pubkey` and `sig` and returns it
async window.nostr.signEvent(event: { created_at: number, kind: number, tags: string[][], content: string }): Event // takes an event object, adds `id`, `pubkey` and `sig` and returns it
```
Aside from these two basic above, the following functions can also be implemented optionally:
@@ -33,3 +33,6 @@ async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext
- [AKA Profiles](https://github.com/neilck/aka-extension) (Chrome, stores multiple keys)
- [TokenPocket](https://www.tokenpocket.pro/) (Android, IOS, Chrome and derivatives)
- [Nostrmo](https://github.com/haorendashu/nostrmo_faq#download) (Android, IOS)
- [Spring Browser](https://spring.site) (Android)
- [nodestr](https://github.com/lightning-digital-entertainment/nodestr) (NodeJS polyfill)
- [Nostore](https://apps.apple.com/us/app/nostore/id1666553677) (Safari on iOS/MacOS)

3
15.md
View File

@@ -88,7 +88,7 @@ Fields that are not self-explanatory:
"images": <[String], array of image URLs, optional>,
"currency": <String, currency used>,
"price": <float, cost of product>,
"quantity": <int, available items>,
"quantity": <int or null, available items>,
"specs": [
[<String, spec key>, <String, spec value>]
],
@@ -102,6 +102,7 @@ Fields that are not self-explanatory:
```
Fields that are not self-explanatory:
- `quantity` can be null in the case of items with unlimited abailability, like digital items, or services
- `specs`:
- an optional array of key pair values. It allows for the Customer UI to present product specifications in a structure mode. It also allows comparison between products
- eg: `[["operating_system", "Android 12.0"], ["screen_size", "6.4 inches"], ["connector_type", "USB Type C"]]`

6
25.md
View File

@@ -7,7 +7,7 @@ Reactions
`draft` `optional` `author:jb55`
A reaction is a `kind 7` note that is used to react to other notes.
A reaction is a `kind 7` event that is used to react to other events.
The generic reaction, represented by the `content` set to a `+` string, SHOULD
be interpreted as a "like" or "upvote".
@@ -34,6 +34,9 @@ The last `e` tag MUST be the `id` of the note that is being reacted to.
The last `p` tag MUST be the `pubkey` of the event being reacted to.
The reaction event MAY include a `k` tag with the stringified kind number
of the reacted event as its value.
Example code
```swift
@@ -43,6 +46,7 @@ func make_like_event(pubkey: String, privkey: String, liked: NostrEvent) -> Nost
}
tags.append(["e", liked.id])
tags.append(["p", liked.pubkey])
tags.append(["k", liked.kind])
let ev = NostrEvent(content: "+", pubkey: pubkey, kind: 7, tags: tags)
ev.calculate_id()
ev.sign(privkey: privkey)

6
52.md
View File

@@ -40,7 +40,7 @@ The list of tags are as follows:
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
"created_at": <Unix timestamp in seconds>,
"kind": "31922",
"kind": 31922,
"content": "<description of calendar event>",
"tags": [
["d", "<UUID>"],
@@ -98,7 +98,7 @@ The list of tags are as follows:
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
"created_at": <Unix timestamp in seconds>,
"kind": "31923",
"kind": 31923,
"content": "<description of calendar event>",
"tags": [
["d", "<UUID>"],
@@ -183,7 +183,7 @@ The list of tags are as follows:
"id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>,
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
"created_at": <Unix timestamp in seconds>,
"kind": "31925",
"kind": 31925,
"content": "<note>",
"tags": [
["a", "<31922 or 31923>:<calendar event author pubkey>:<d-identifier of calendar event>", "<optional relay url>"],

4
57.md
View File

@@ -45,7 +45,7 @@ Example:
"kind": 9734,
"content": "Zap!",
"tags": [
["relays", "wss://nostr-pub.wellorder.com"],
["relays", "wss://nostr-pub.wellorder.com", "wss://anotherrelay.example.com"],
["amount", "21000"],
["lnurl", "lnurl1dp68gurn8ghj7um5v93kketj9ehx2amn9uh8wetvdskkkmn0wahz7mrww4excup0dajx2mrv92x9xp"],
["p", "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9"],
@@ -66,7 +66,7 @@ A signed `zap request` event is not published, but is instead sent using a HTTP
- `nostr` is the `9734` `zap request` event, JSON encoded then URI encoded
- `lnurl` is the lnurl pay url of the recipient, encoded using bech32 with the prefix `lnurl`
This request should return a JSON response with a `pr` key, which is the invoice the sender must pay to finalize his zap. Here is an example flow:
This request should return a JSON response with a `pr` key, which is the invoice the sender must pay to finalize his zap. Here is an example flow in javascript:
```javascript
const senderPubkey // The sender's pubkey

2
65.md
View File

@@ -60,4 +60,4 @@ This NIP allows Clients to connect directly with the most up-to-date relay set f
5. If a relay signals support for this NIP in their [NIP-11](11.md) document that means they're willing to accept kind 10002 events from a broad range of users, not only their paying customers or whitelisted group.
6. Clients SHOULD trim trailing slashes (`/`) from relay URIs to canonicalize connections.
6. Clients SHOULD deduplicate connections by normalizing relay URIs according to [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-6).

79
88.md Normal file
View File

@@ -0,0 +1,79 @@
NIP-88
======
Recurring Subscriptions
-----------------------
`draft` `optional` `author:pablof7z`
This NIP defines a way for a pubkey to create recurring subscription payments to another pubkey.
## Tier Event
A pubkey can create "tiers". These tiers might provide certain benefits to the supporters who subscribe to these.
```json
{
"kind": 7002,
"content": "<description of the tier>",
"tags": [
[ "title", "..." ],
[ "amount", "<amount-in-base-unit>", "currency", "<cadence>" ]
]
}
```
This event is generated by a pubkey who wants to allow users to support with different tiers.
`.content` SHOULD be a description of what users who subscribe can expect.
Tag `title` is an optional title for the tier.
Tag `amount` MUST specify the payment required for this tier and its cadence.
* The first argument should be the stringified amount and the second argument the currency
* The third argument SHOULD be one of `daily`, `monthly`, `yearly`
One or more `amount` tags MUST exist.
#### Examples
* `[ "amount", "100", "usd", "daily" ]`, $1.00 a day.
* `[ "amount", "1000000", "btc", "daily" ]`, 1000000 millisats a day.
## Subscribe Event
```json
{
"kind": 7001,
"content": "<optional-message>",
"tags": [
[ "p", "<recipient-pubkey>" ],
[ "e", "<supporting-tier-id>" ],
[ "amount", "<amount-in-base-unit>", "currency", "<cadence>" ]
]
}
```
When a user wants to subscribe to subscribe to support a user they create a `kind:7001` event.
* `.content` is an optional message the supporter can write.
* The `p` tag MUST tag the pubkey being supported.
* The `e` tag is optional, and should point to a `kind:7001` support tier event. There MUST be exactly 0 or 1 `e` tags.
* The `amount` tag specifies what the supporters is committing to pay to the supported pubkey and the candence.
The `kind:7001` event can be created without an `e` tag so that users can create recurring support events without the pubkey receiving the support having explicitly created a support tier.
## Paying
The supporting user should create a zap p-tagging the receiver and e-tagging the `kind:7001`. There MUST be a single `p` and a single `e` tag in the zap request.
```json
{
"kind": 9734,
"content": "",
"tags": [
[ "p", "<recipient-pubkey>" ],
[ "e", "<kind-7001-event-id>" ]
]
```
Clients supporting this NIP can check for zaps e-tagging the `kind:7001` event to find the pubkeys that have a valid, paid subscriptions at each different period.
The same `kind:7001` is re-zapped on a regular basis per the cadence specified in the event.
## Stopping a subscription
A user who wants to stop a subscription by publishing a `kind:5` deletion request of the `kind:7001` event.

171
90.md Normal file
View File

@@ -0,0 +1,171 @@
NIP-90
======
Data Vending Machine
--------------------
`draft` `optional` `author:pablof7z` `author:dontbelievethehype`
This NIP defines the interaction between customers and Service Providers for performing on-demand computation.
Money in, data out.
## Kinds
This NIP reserves the range `5000-7000` for data vending machine use.
| Kind | Description |
| ---- | ----------- |
| 5000-5999 | Job request kinds |
| 6000-6999 | Job result |
| 7000 | Job feedback |
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`).
Job request types are defined [separately](https://github.com/nostr-protocol/data-vending-machines/tree/master/kinds).
## 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.
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.
### Actors
There are two actors in the workflow described in this NIP:
* Customers (npubs who request a job)
* Service providers (npubs who fulfill jobs)
## Job request (`kind:5000-5999`)
A request to process data, published by a customer. This event signals that an customer is interested in receiving the result of some kind of compute.
```json
{
"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" ]
]
}
```
All tags are optional.
* `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
## 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.
```json
{
"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>" ]
]
}
```
* `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.
## Job feedback
Service providers can give feedback about a job back to the customer.
```json
{
"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>" ],
]
}
```
* `content`: Either empty or a job-result (e.g. for partial-result samples)
* `amount` tag: as defined in the [Job Result](#job-result) section.
* `status` tag: Service Providers SHOULD indicate what this feedback status refers to. [Appendix 1](#appendix-1-job-feedback-status) defines status. Extra human-readable information can be added as an extra argument.
### 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) 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 cancelled 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:
```json
{
"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"
]
}
```
Customers can use NIP-89 to see what service providers their follows use.

View File

@@ -38,6 +38,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-21: `nostr:` URI scheme](21.md)
- [NIP-22: Event `created_at` Limits](22.md)
- [NIP-23: Long-form Content](23.md)
- [NIP-24: Extra metadata fields and tags](24.md)
- [NIP-25: Reactions](25.md)
- [NIP-26: Delegated Event Signing](26.md)
- [NIP-27: Text Note References](27.md)
@@ -66,6 +67,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
- [NIP-75: Zap Goals](75.md)
- [NIP-78: Application-specific data](78.md)
- [NIP-89: Recommended Application Handlers](89.md)
- [NIP-90: Data Vending Machines](90.md)
- [NIP-94: File Metadata](94.md)
- [NIP-98: HTTP Auth](98.md)
- [NIP-99: Classified Listings](99.md)
@@ -91,9 +93,13 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `44` | Channel Mute User | [28](28.md) |
| `1063` | File Metadata | [94](94.md) |
| `1311` | Live Chat Message | [53](53.md) |
| `1040` | OpenTimestamps | [03](03.md) |
| `1984` | Reporting | [56](56.md) |
| `1985` | Label | [32](32.md) |
| `4550` | Community Post Approval | [72](72.md) |
| `7000` | Job Feedback | [90](90.md) |
| `7001` | Recurring Subscription | [88](88.md) |
| `7002` | Recurring Subscription Tier| [88](88.md) |
| `9041` | Zap Goal | [75](75.md) |
| `9734` | Zap Request | [57](57.md) |
| `9735` | Zap | [57](57.md) |
@@ -127,7 +133,6 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `31990` | Handler information | [89](89.md) |
| `34550` | Community Definition | [72](72.md) |
## Message types
### Client to Relay
@@ -155,47 +160,47 @@ Please update these lists when proposing NIPs introducing new event kinds.
## Standardized Tags
| name | value | other parameters | NIP |
| ----------------- | ------------------------------------ | -------------------- | ------------------------ |
| `e` | event id (hex) | relay URL, marker | [01](01.md), [10](10.md) |
| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
| `a` | coordinates to an event | relay URL | [01](01.md) |
| `d` | identifier | -- | [01](01.md) |
| `alt` | summary | -- | [31](31.md) |
| `g` | geohash | -- | [52](52.md) |
| `i` | identity | proof | [39](39.md) |
| `k` | kind number (string) | -- | [18](18.md), [72](72.md) |
| `l` | label, label namespace | annotations | [32](32.md) |
| `L` | label namespace | -- | [32](32.md) |
| `m` | MIME type | -- | [94](94.md) |
| `r` | a reference (URL, etc) | petname | |
| `r` | relay url | marker | [65](65.md) |
| `t` | hashtag | -- | |
| `amount` | millisatoshis, stringified | -- | [57](57.md) |
| `bolt11` | `bolt11` invoice | -- | [57](57.md) |
| `challenge` | challenge string | -- | [42](42.md) |
| `content-warning` | reason | -- | [36](36.md) |
| `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) |
| `description` | invoice/badge description | -- | [57](57.md), [58](58.md) |
| `emoji` | shortcode, image URL | -- | [30](30.md) |
| `expiration` | unix timestamp (string) | -- | [40](40.md) |
| `goal` | event id (hex) | relay URL | [75](75.md) |
| `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) |
| `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) |
| `location` | location string | -- | [52](52.md), [99](99.md) |
| `name` | badge name | -- | [58](58.md) |
| `nonce` | random | -- | [13](13.md) |
| `preimage` | hash of `bolt11` invoice | -- | [57](57.md) |
| `price` | price | currency, frequency | [99](99.md) |
| `proxy` | external ID | protocol | [48](48.md) |
| `published_at` | unix timestamp (string) | -- | [23](23.md) |
| `relay` | relay url | -- | [42](42.md) |
| `relays` | relay list | -- | [57](57.md) |
| `subject` | subject | -- | [14](14.md) |
| `summary` | article summary | -- | [23](23.md) |
| `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) |
| `title` | article title | -- | [23](23.md) |
| `zap` | pubkey (hex), relay URL | weight | [57](57.md) |
| name | value | other parameters | NIP |
| ----------------- | ------------------------------------ | -------------------- | ------------------------------------- |
| `e` | event id (hex) | relay URL, marker | [01](01.md), [10](10.md) |
| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
| `a` | coordinates to an event | relay URL | [01](01.md) |
| `d` | identifier | -- | [01](01.md) |
| `alt` | summary | -- | [31](31.md) |
| `g` | geohash | -- | [52](52.md) |
| `i` | identity | proof | [39](39.md) |
| `k` | kind number (string) | -- | [18](18.md), [25](25.md), [72](72.md) |
| `l` | label, label namespace | annotations | [32](32.md) |
| `L` | label namespace | -- | [32](32.md) |
| `m` | MIME type | -- | [94](94.md) |
| `r` | a reference (URL, etc) | petname | |
| `r` | relay url | marker | [65](65.md) |
| `t` | hashtag | -- | |
| `amount` | millisatoshis, stringified | -- | [57](57.md) |
| `bolt11` | `bolt11` invoice | -- | [57](57.md) |
| `challenge` | challenge string | -- | [42](42.md) |
| `content-warning` | reason | -- | [36](36.md) |
| `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) |
| `description` | invoice/badge description | -- | [57](57.md), [58](58.md) |
| `emoji` | shortcode, image URL | -- | [30](30.md) |
| `expiration` | unix timestamp (string) | -- | [40](40.md) |
| `goal` | event id (hex) | relay URL | [75](75.md) |
| `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) |
| `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) |
| `location` | location string | -- | [52](52.md), [99](99.md) |
| `name` | badge name | -- | [58](58.md) |
| `nonce` | random | -- | [13](13.md) |
| `preimage` | hash of `bolt11` invoice | -- | [57](57.md) |
| `price` | price | currency, frequency | [99](99.md) |
| `proxy` | external ID | protocol | [48](48.md) |
| `published_at` | unix timestamp (string) | -- | [23](23.md) |
| `relay` | relay url | -- | [42](42.md) |
| `relays` | relay list | -- | [57](57.md) |
| `subject` | subject | -- | [14](14.md) |
| `summary` | article summary | -- | [23](23.md) |
| `thumb` | badge thumbnail | dimensions in pixels | [58](58.md) |
| `title` | article title | -- | [23](23.md) |
| `zap` | pubkey (hex), relay URL | weight | [57](57.md) |
## Criteria for acceptance of NIPs