diff options
Diffstat (limited to '89.md')
| -rw-r--r-- | 89.md | 84 |
1 files changed, 43 insertions, 41 deletions
| @@ -9,10 +9,12 @@ Recommended Application Handlers | |||
| 9 | This NIP describes `kind:31989` and `kind:31990`: a way to discover applications that can handle unknown event-kinds. | 9 | This NIP describes `kind:31989` and `kind:31990`: a way to discover applications that can handle unknown event-kinds. |
| 10 | 10 | ||
| 11 | ## Rationale | 11 | ## Rationale |
| 12 | |||
| 12 | Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics. | 13 | Nostr's discoverability and transparent event interaction is one of its most interesting/novel mechanics. |
| 13 | 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. | 14 | 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. |
| 14 | 15 | ||
| 15 | ### Parties involved | 16 | ### Parties involved |
| 17 | |||
| 16 | There are three actors to this workflow: | 18 | There are three actors to this workflow: |
| 17 | 19 | ||
| 18 | * 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) | 20 | * 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) |
| @@ -22,18 +24,18 @@ There are three actors to this workflow: | |||
| 22 | * user B, who seeks a recommendation for an app that handles a specific event kind | 24 | * user B, who seeks a recommendation for an app that handles a specific event kind |
| 23 | * Queries for `kind:31989` and, based on results, queries for `kind:31990` | 25 | * Queries for `kind:31989` and, based on results, queries for `kind:31990` |
| 24 | 26 | ||
| 25 | # Events | 27 | ## Events |
| 26 | 28 | ||
| 27 | ## Recommendation event | 29 | ### Recommendation event |
| 28 | ```json | 30 | ```json |
| 29 | { | 31 | { |
| 30 | "kind": 31989, | 32 | "kind": 31989, |
| 31 | "pubkey": <recommender-user-pubkey>, | 33 | "pubkey": <recommender-user-pubkey>, |
| 32 | "tags": [ | 34 | "tags": [ |
| 33 | [ "d", <supported-event-kind> ], | 35 | ["d", <supported-event-kind>], |
| 34 | [ "a", "31990:app1-pubkey:<d-identifier>", "wss://relay1", "ios" ], | 36 | ["a", "31990:app1-pubkey:<d-identifier>", "wss://relay1", "ios"], |
| 35 | [ "a", "31990:app2-pubkey:<d-identifier>", "wss://relay2", "web" ] | 37 | ["a", "31990:app2-pubkey:<d-identifier>", "wss://relay2", "web"] |
| 36 | ] | 38 | ] |
| 37 | } | 39 | } |
| 38 | ``` | 40 | ``` |
| 39 | 41 | ||
| @@ -47,34 +49,32 @@ The third value of the tag SHOULD be the platform where this recommendation migh | |||
| 47 | ## Handler information | 49 | ## Handler information |
| 48 | ```json | 50 | ```json |
| 49 | { | 51 | { |
| 50 | "kind": 31990, | 52 | "kind": 31990, |
| 51 | "pubkey": <pubkey>, | 53 | "pubkey": "<application-pubkey>", |
| 52 | "content": "<optional-kind:0-style-metadata>", | 54 | "content": "<optional-kind:0-style-metadata>", |
| 53 | "tags": [ | 55 | "tags": [ |
| 54 | [ "d", <random-id> ], | 56 | ["d", <random-id>], |
| 55 | [ "k", <supported-event-kind> ], | 57 | ["k", <supported-event-kind>], |
| 56 | [ "web", "https://..../a/<bech32>", "nevent" ], | 58 | ["web", "https://..../a/<bech32>", "nevent"], |
| 57 | [ "web", "https://..../p/<bech32>", "nprofile" ], | 59 | ["web", "https://..../p/<bech32>", "nprofile"], |
| 58 | [ "web", "https://..../e/<bech32>" ], | 60 | ["web", "https://..../e/<bech32>"], |
| 59 | [ "ios", ".../<bech32>" ] | 61 | ["ios", ".../<bech32>"] |
| 60 | ] | 62 | ] |
| 61 | } | 63 | } |
| 62 | ``` | 64 | ``` |
| 63 | 65 | ||
| 64 | * `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.) | 66 | * `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.) |
| 65 | |||
| 66 | * `k` tags' value is the event kind that is supported by this `kind:31990`. | 67 | * `k` tags' value is the event kind that is supported by this `kind:31990`. |
| 67 | Using a `k` tag(s) (instead of having the kind onf the NIP-33 `d` tag) provides: | 68 | Using a `k` tag(s) (instead of having the kind onf the NIP-33 `d` tag) provides: |
| 68 | * 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. | 69 | * 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. |
| 69 | * The same pubkey can have multiple events with different apps that handle the same event kind. | 70 | * The same pubkey can have multiple events with different apps that handle the same event kind. |
| 70 | |||
| 71 | * `bech32` in a URL MUST be replaced by clients with the NIP-19-encoded entity that should be loaded by the application. | 71 | * `bech32` in a URL MUST be replaced by clients with the NIP-19-encoded entity that should be loaded by the application. |
| 72 | 72 | ||
| 73 | Multiple tags might be registered by the app, following NIP-19 nomenclature as the second value of the array. | 73 | Multiple tags might be registered by the app, following NIP-19 nomenclature as the second value of the array. |
| 74 | 74 | ||
| 75 | 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. | 75 | 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. |
| 76 | 76 | ||
| 77 | # Client tag | 77 | ## Client tag |
| 78 | When publishing events, clients MAY include a `client` tag in the same format as the recommendation event's `a` tags. This has privacy implications for users, so clients SHOULD allow users to opt-out of using this tag. | 78 | When publishing events, clients MAY include a `client` tag in the same format as the recommendation event's `a` tags. This has privacy implications for users, so clients SHOULD allow users to opt-out of using this tag. |
| 79 | 79 | ||
| 80 | ```json | 80 | ```json |
| @@ -87,43 +87,45 @@ When publishing events, clients MAY include a `client` tag in the same format as | |||
| 87 | } | 87 | } |
| 88 | ``` | 88 | ``` |
| 89 | 89 | ||
| 90 | # User flow | 90 | ## User flow |
| 91 | A user A who uses a non-`kind:1`-centric nostr app could choose to announce/recommend a certain kind-handler application. | 91 | A user A who uses a non-`kind:1`-centric nostr app could choose to announce/recommend a certain kind-handler application. |
| 92 | 92 | ||
| 93 | 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). | 93 | 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). |
| 94 | 94 | ||
| 95 | The client MIGHT query for the user's and the user's follows handler. | 95 | The client MIGHT query for the user's and the user's follows handler. |
| 96 | 96 | ||
| 97 | # Example | 97 | ## Example |
| 98 | 98 | ||
| 99 | ## User A recommends a `kind:31337`-handler | 99 | ### User A recommends a `kind:31337`-handler |
| 100 | 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. | 100 | 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. |
| 101 | 101 | ||
| 102 | ```json | 102 | ```json |
| 103 | { | 103 | { |
| 104 | "kind": 31989, | 104 | "kind": 31989, |
| 105 | "tags": [ | 105 | "tags": [ |
| 106 | [ "d", "31337" ], | 106 | ["d", "31337"], |
| 107 | [ "a", "31990:1743058db7078661b94aaf4286429d97ee5257d14a86d6bfa54cb0482b876fb0:abcd", <relay-url>, "web" ] | 107 | ["a", "31990:1743058db7078661b94aaf4286429d97ee5257d14a86d6bfa54cb0482b876fb0:abcd", <relay-url>, "web"] |
| 108 | ] | 108 | ], |
| 109 | ... | ||
| 109 | } | 110 | } |
| 110 | ``` | 111 | ``` |
| 111 | 112 | ||
| 112 | ## User B interacts with a `kind:31337`-handler | 113 | ### User B interacts with a `kind:31337`-handler |
| 113 | User B might see in their timeline an event referring to a `kind:31337` event | 114 | User B might see in their timeline an event referring to a `kind:31337` event (e.g. a `kind:1` tagging a `kind:31337`). |
| 114 | (e.g. a `kind:1` tagging a `kind:31337`). | ||
| 115 | 115 | ||
| 116 | User B's client, not knowing how to handle a `kind:31337` might display the event | 116 | 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`: |
| 117 | using its `alt` tag (as described in NIP-31). When the user clicks on the event, | ||
| 118 | the application queries for a handler for this `kind`: | ||
| 119 | 117 | ||
| 120 | `["REQ", <id>, '[{ "kinds": [31989], "#d": ["31337"], 'authors': [<user>, <users-contact-list>] }]']` | 118 | ```json |
| 119 | ["REQ", <id>, '[{ "kinds": [31989], "#d": ["31337"], 'authors': [<user>, <users-contact-list>] }]'] | ||
| 120 | ``` | ||
| 121 | 121 | ||
| 122 | User B, who follows User A, sees that `kind:31989` event and fetches the `a`-tagged event for the app and handler information. | 122 | User B, who follows User A, sees that `kind:31989` event and fetches the `a`-tagged event for the app and handler information. |
| 123 | 123 | ||
| 124 | 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. | 124 | 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. |
| 125 | 125 | ||
| 126 | ## Alternative query bypassing `kind:31989` | 126 | ### Alternative query bypassing `kind:31989` |
| 127 | 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 to avoid directing users to malicious handlers. | 127 | 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. |
| 128 | 128 | ||
| 129 | `["REQ", <id>, '[{ "kinds": [31990], "#k": [<desired-event-kind>], 'authors': [...] }]']` | 129 | ```json |
| 130 | ["REQ", <id>, '[{ "kinds": [31990], "#k": [<desired-event-kind>], 'authors': [...] }]'] | ||
| 131 | ``` | ||