mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-24 09:25:52 -05:00
132 lines
5.5 KiB
Markdown
132 lines
5.5 KiB
Markdown
NIP-89
|
|
======
|
|
|
|
Recommended Application Handlers
|
|
--------------------------------
|
|
|
|
`draft` `optional`
|
|
|
|
This NIP describes `kind:31989` and `kind:31990`: a way to discover applications that can handle unknown event-kinds.
|
|
|
|
## Rationale
|
|
|
|
Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics.
|
|
This NIP provides a simple way for clients to discover applications that handle events of a specific kind to ensure smooth cross-client and cross-kind interactions.
|
|
|
|
### Parties involved
|
|
|
|
There are three actors to this workflow:
|
|
|
|
* application that handles a specific event kind (note that an application doesn't necessarily need to be a distinct entity and it could just be the same pubkey as user A)
|
|
* Publishes `kind:31990`, detailing how apps should redirect to it
|
|
* user A, who recommends an app that handles a specific event kind
|
|
* Publishes `kind:31989`
|
|
* user B, who seeks a recommendation for an app that handles a specific event kind
|
|
* Queries for `kind:31989` and, based on results, queries for `kind:31990`
|
|
|
|
## Events
|
|
|
|
### Recommendation event
|
|
```json
|
|
{
|
|
"kind": 31989,
|
|
"pubkey": <recommender-user-pubkey>,
|
|
"tags": [
|
|
["d", <supported-event-kind>],
|
|
["a", "31990:app1-pubkey:<d-identifier>", "wss://relay1", "ios"],
|
|
["a", "31990:app2-pubkey:<d-identifier>", "wss://relay2", "web"]
|
|
]
|
|
}
|
|
```
|
|
|
|
The `d` tag in `kind:31989` is the supported event kind this event is recommending.
|
|
|
|
Multiple `a` tags can appear on the same `kind:31989`.
|
|
|
|
The second value of the tag SHOULD be a relay hint.
|
|
The third value of the tag SHOULD be the platform where this recommendation might apply.
|
|
|
|
## Handler information
|
|
```json
|
|
{
|
|
"kind": 31990,
|
|
"pubkey": "<application-pubkey>",
|
|
"content": "<optional-kind:0-style-metadata>",
|
|
"tags": [
|
|
["d", <random-id>],
|
|
["k", <supported-event-kind>],
|
|
["web", "https://..../a/<bech32>", "nevent"],
|
|
["web", "https://..../p/<bech32>", "nprofile"],
|
|
["web", "https://..../e/<bech32>"],
|
|
["ios", ".../<bech32>"]
|
|
]
|
|
}
|
|
```
|
|
|
|
* `content` is an optional `metadata`-like stringified JSON object, as described in NIP-01. This content is useful when the pubkey creating the `kind:31990` is not an application. If `content` is empty, the `kind:0` of the pubkey should be used to display application information (e.g. name, picture, web, LUD16, etc.)
|
|
* `k` tags' value is the event kind that is supported by this `kind:31990`.
|
|
Using a `k` tag(s) (instead of having the kind of the `d` tag) provides:
|
|
* Multiple `k` tags can exist in the same event if the application supports more than one event kind and their handler URLs are the same.
|
|
* The same pubkey can have multiple events with different apps that handle the same event kind.
|
|
* `bech32` in a URL MUST be replaced by clients with the NIP-19-encoded entity that should be loaded by the application.
|
|
|
|
Multiple tags might be registered by the app, following NIP-19 nomenclature as the second value of the array.
|
|
|
|
A tag without a second value in the array SHOULD be considered a generic handler for any NIP-19 entity that is not handled by a different tag.
|
|
|
|
# Client tag
|
|
When publishing events, clients MAY include a `client` tag. Identifying the client that published the note. This tag is a tuple of `name`, `address` identifying a handler event and, a relay `hint` for finding the handler event. This has privacy implications for users, so clients SHOULD allow users to opt-out of using this tag.
|
|
|
|
```json
|
|
{
|
|
"kind": 1,
|
|
"tags": [
|
|
["client", "My Client", "31990:app1-pubkey:<d-identifier>", "wss://relay1"]
|
|
]
|
|
...
|
|
}
|
|
```
|
|
|
|
## User flow
|
|
A user A who uses a non-`kind:1`-centric nostr app could choose to announce/recommend a certain kind-handler application.
|
|
|
|
When user B sees an unknown event kind, e.g. in a social-media centric nostr client, the client would allow user B to interact with the unknown-kind event (e.g. tapping on it).
|
|
|
|
The client MIGHT query for the user's and the user's follows handler.
|
|
|
|
## Example
|
|
|
|
### User A recommends a `kind:31337`-handler
|
|
User A might be a user of Zapstr, a `kind:31337`-centric client (tracks). Using Zapstr, user A publishes an event recommending Zapstr as a `kind:31337`-handler.
|
|
|
|
```json
|
|
{
|
|
"kind": 31989,
|
|
"tags": [
|
|
["d", "31337"],
|
|
["a", "31990:1743058db7078661b94aaf4286429d97ee5257d14a86d6bfa54cb0482b876fb0:abcd", <relay-url>, "web"]
|
|
],
|
|
...
|
|
}
|
|
```
|
|
|
|
### User B interacts with a `kind:31337`-handler
|
|
User B might see in their timeline an event referring to a `kind:31337` event (e.g. a `kind:1` tagging a `kind:31337`).
|
|
|
|
User B's client, not knowing how to handle a `kind:31337` might display the event using its `alt` tag (as described in NIP-31). When the user clicks on the event, the application queries for a handler for this `kind`:
|
|
|
|
```json
|
|
["REQ", <id>, { "kinds": [31989], "#d": ["31337"], "authors": [<user>, <users-contact-list>] }]
|
|
```
|
|
|
|
User B, who follows User A, sees that `kind:31989` event and fetches the `a`-tagged event for the app and handler information.
|
|
|
|
User B's client sees the application's `kind:31990` which includes the information to redirect the user to the relevant URL with the desired entity replaced in the URL.
|
|
|
|
### Alternative query bypassing `kind:31989`
|
|
Alternatively, users might choose to query directly for `kind:31990` for an event kind. Clients SHOULD be careful doing this and use spam-prevention mechanisms or querying high-quality restricted relays to avoid directing users to malicious handlers.
|
|
|
|
```json
|
|
["REQ", <id>, { "kinds": [31990], "#k": [<desired-event-kind>], "authors": [...] }]
|
|
```
|