From 1c728516dfdc7508ce27eda222bde78466e3457d Mon Sep 17 00:00:00 2001 From: VictorieeMan <59509525+VictorieeMan@users.noreply.github.com> Date: Sat, 7 Jan 2023 11:11:19 +0100 Subject: [PATCH 01/18] NIP-05: Fixed some typos line 9: Added a hyphen line 53: Fixed the typo by a context appropriate reformulation. line 67: Removed an "are" line 79: Added a comma Great project, looking forward to more nostr :) --- 05.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/05.md b/05.md index a67f530e..56b9156b 100644 --- a/05.md +++ b/05.md @@ -6,7 +6,7 @@ Mapping Nostr keys to DNS-based internet identifiers `final` `optional` `author:fiatjaf` `author:mikedilger` -On events of kind `0` (`set_metadata`) one can specify the key `"nip05"` with an [internet identifier](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) (an email-like address) as the value. Although there is a link to a very liberal "internet identifier" specification above, NIP-05 assumes the `` part will be restricted to the characters `a-z0-9-_.`, case insensitive. +On events of kind `0` (`set_metadata`) one can specify the key `"nip05"` with an [internet identifier](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) (an email-like address) as the value. Although there is a link to a very liberal "internet identifier" specification above, NIP-05 assumes the `` part will be restricted to the characters `a-z0-9-_.`, case-insensitive. Upon seeing that, the client splits the identifier into `` and `` and use these values to make a GET request to `https:///.well-known/nostr.json?name=`. @@ -50,7 +50,7 @@ or with the **optional** `"relays"` attribute: If the pubkey matches the one given in `"names"` (as in the example above) that means the association is right and the `"nip05"` identifier is valid and can be displayed. -The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays a that user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. +The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays the specific user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. ## Finding users from their NIP-05 identifier @@ -64,7 +64,7 @@ For example, if after finding that `bob@bob.com` has the public key `abc...def`, ### Public keys must be in hex format -Keys must be returned in hex format. Keys in NIP-19 `npub` format are are only meant to be used for display in client UIs, not in this NIP. +Keys must be returned in hex format. Keys in NIP-19 `npub` format are only meant to be used for display in client UIs, not in this NIP. ### User Discovery implementation suggestion @@ -76,7 +76,7 @@ Clients may treat the identifier `_@domain` as the "root" identifier, and choose ### Reasoning for the `/.well-known/nostr.json?name=` format -By adding the `` as a query string instead of as part of the path the protocol can support both dynamic servers that can generate JSON on-demand and static servers with a JSON file in it that may contain multiple names. +By adding the `` as a query string instead of as part of the path, the protocol can support both dynamic servers that can generate JSON on-demand and static servers with a JSON file in it that may contain multiple names. ### Allowing access from JavaScript apps From e91ce3409e1ce8267fc07a21784d2538621267c3 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 29 Apr 2023 13:16:58 -0500 Subject: [PATCH 02/18] NIP-30: Custom Emoji --- 30.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 57 insertions(+) create mode 100644 30.md diff --git a/30.md b/30.md new file mode 100644 index 00000000..04689d0f --- /dev/null +++ b/30.md @@ -0,0 +1,56 @@ +NIP-30 +====== + +Custom Emoji +------------ + +`draft` `optional` `author:alexgleason` + +Custom emoji may be added to **kind 0** and **kind 1** events by including one or more `"emoji"` tags, in the form: + +``` +["emoji", , ] +``` + +Where: + +- `` is a name given for the emoji, which MUST be comprised of only alphanumeric characters. +- `` is a URL to the corresponding image file of the emoji. + +For each emoji tag, clients should parse emoji shortcodes (aka "emojify") like `:shortcode:` in the event to display custom emoji. + +Clients may allow users to add custom emoji to an event by including `:shortcode:` identifier in the event, and adding the relevant `"emoji"` tags. + +### Kind 0 events + +In kind 0 events, the `name` and `about` fields should be emojified. + +```json +{ + "kind": 0, + "content": "{\"name\":\"Alex Gleason :soapbox:\"}", + "tags": [ + ["emoji", "soapbox", "https://gleasonator.com/emoji/Gleasonator/soapbox.png"] + ], + "pubkey": "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6", + "created_at": 1682790000 +} +``` + +### Kind 1 events + +In kind 1 events, the `content` should be emojified. + +```json +{ + "kind": 1, + "content": "Hello :gleasonator: 😂 :ablobcatrainbow: :disputed: yolo", + "tags": [ + ["emoji", "ablobcatrainbow", "https://gleasonator.com/emoji/blobcat/ablobcatrainbow.png"], + ["emoji", "disputed", "https://gleasonator.com/emoji/Fun/disputed.png"], + ["emoji", "gleasonator", "https://gleasonator.com/emoji/Gleasonator/gleasonator.png"] + ], + "pubkey": "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6", + "created_at": 1682630000 +} +``` \ No newline at end of file diff --git a/README.md b/README.md index e7c89144..92be9a5a 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/fia - [NIP-26: Delegated Event Signing](26.md) - [NIP-27: Text Note References](27.md) - [NIP-28: Public Chat](28.md) +- [NIP-30: Custom Emoji](30.md) - [NIP-33: Parameterized Replaceable Events](33.md) - [NIP-36: Sensitive Content](36.md) - [NIP-39: External Identities in Profiles](39.md) From d5484a33bcaf717ef1ef54a0f9be1b76c4f70afa Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Sat, 6 May 2023 11:35:21 -0700 Subject: [PATCH 03/18] Clarify how NIP 45 works with multiple COUNT filters. (#504) --- 45.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/45.md b/45.md index 87e80002..a5253913 100644 --- a/45.md +++ b/45.md @@ -6,21 +6,21 @@ Event Counts `draft` `optional` `author:staab` -Relays may support the `COUNT` verb, which provides a mechanism for obtaining event counts. +Relays may support the verb `COUNT`, which provides a mechanism for obtaining event counts. ## Motivation -Some queries a client may want to execute against connected relays are prohibitively expensive, for example, in order to retrieve follower counts for a given pubkey, a client must query all kind-3 events referring to a given pubkey and count them. The result may be cached, either by a client or by a separate indexing server as an alternative, but both options erode the decentralization of the network by creating a second-layer protocol on top of Nostr. +Some queries a client may want to execute against connected relays are prohibitively expensive, for example, in order to retrieve follower counts for a given pubkey, a client must query all kind-3 events referring to a given pubkey only to count them. The result may be cached, either by a client or by a separate indexing server as an alternative, but both options erode the decentralization of the network by creating a second-layer protocol on top of Nostr. ## Filters and return values -This NIP defines a verb called `COUNT`, which accepts a subscription id and filters as specified in [NIP 01](01.md). +This NIP defines the verb `COUNT`, which accepts a subscription id and filters as specified in [NIP 01](01.md) for the verb `REQ`. Multiple filters are OR'd together and aggregated into a single count result. ``` ["COUNT", , ...] ``` -Counts are returned using a `COUNT` response in the form `{count: }`. Relays may use probabilistic counts to reduce compute requirements. +Counts are returned using a `COUNT` response in the form `{"count": }`. Relays may use probabilistic counts to reduce compute requirements. ``` ["COUNT", , {"count": }] From 1678c53dcd3a2cefcf953722d501c03920ce6092 Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 6 May 2023 23:31:22 +0200 Subject: [PATCH 04/18] Update old link to fiatjaf/nostr --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4a63a4a..94e945c5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # NIPs NIPs stand for **Nostr Implementation Possibilities**. -They exist to document what may be implemented by [Nostr](https://github.com/fiatjaf/nostr)-compatible _relay_ and _client_ software. +They exist to document what may be implemented by [Nostr](https://github.com/nostr-protocol/nostr)-compatible _relay_ and _client_ software. --- From ee018ef8a4af08dcf8f4c090bb3815ee13f4c627 Mon Sep 17 00:00:00 2001 From: Josua Schmid Date: Sun, 7 May 2023 21:53:35 +0200 Subject: [PATCH 05/18] Rephrase Markdown special rule --- 01.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/01.md b/01.md index a07a0dff..3d8c7450 100644 --- a/01.md +++ b/01.md @@ -99,7 +99,8 @@ This NIP defines no rules for how `NOTICE` messages should be sent or treated. ## Basic Event Kinds - `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: , about: , picture: }` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey. - - `1`: `text_note`: the `content` is set to the plaintext content of a note (anything the user wants to say). Markdown links (`[]()` stuff) are not plaintext. + - `1`: `text_note`: the `content` is set to the plaintext content of a note (anything the user wants to say).\ + Do not use Markdown! Clients should not have to guess how to interpret content like `[Example](https://example.com)`. Use different event kinds for parsable content. - `2`: `recommend_server`: the `content` is set to the URL (e.g., `wss://somerelay.com`) of a relay the event creator wants to recommend to its followers. A relay may choose to treat different message kinds differently, and it may or may not choose to have a default way to handle kinds it doesn't know about. From 89a7aa0ea0197b478e96d2a281ac4d096c44caad Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 8 May 2023 11:05:58 -0300 Subject: [PATCH 06/18] nip01: remove misleading markdown example. --- 01.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/01.md b/01.md index 3d8c7450..713e6550 100644 --- a/01.md +++ b/01.md @@ -99,8 +99,7 @@ This NIP defines no rules for how `NOTICE` messages should be sent or treated. ## Basic Event Kinds - `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: , about: , picture: }` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey. - - `1`: `text_note`: the `content` is set to the plaintext content of a note (anything the user wants to say).\ - Do not use Markdown! Clients should not have to guess how to interpret content like `[Example](https://example.com)`. Use different event kinds for parsable content. + - `1`: `text_note`: the `content` is set to the plaintext content of a note (anything the user wants to say). Do not use Markdown! Clients should not have to guess how to interpret content like `[]()`. Use different event kinds for parsable content. - `2`: `recommend_server`: the `content` is set to the URL (e.g., `wss://somerelay.com`) of a relay the event creator wants to recommend to its followers. A relay may choose to treat different message kinds differently, and it may or may not choose to have a default way to handle kinds it doesn't know about. From d70aa87f076f8609950fc96e4e66d86c711c66ac Mon Sep 17 00:00:00 2001 From: Asai Toshiya Date: Tue, 9 May 2023 22:09:45 +0900 Subject: [PATCH 07/18] Restore some lost changes c7711aa and 3cec80d. --- 11.md | 60 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/11.md b/11.md index 89518354..b0d6003f 100644 --- a/11.md +++ b/11.md @@ -69,18 +69,18 @@ are rejected or fail immediately. ```json { ... - limitation: { - max_message_length: 16384, - max_subscriptions: 20, - max_filters: 100, - max_limit: 5000, - max_subid_length: 100, - min_prefix: 4, - max_event_tags: 100, - max_content_length: 8196, - min_pow_difficulty: 30, - auth_required: true, - payment_required: true, + "limitation": { + "max_message_length": 16384, + "max_subscriptions": 20, + "max_filters": 100, + "max_limit": 5000, + "max_subid_length": 100, + "min_prefix": 4, + "max_event_tags": 100, + "max_content_length": 8196, + "min_pow_difficulty": 30, + "auth_required": true, + "payment_required": true, } ... } @@ -141,11 +141,11 @@ all, and preferably an error will be provided when those are received. ```json { ... - retention: [ - { kinds: [0, 1, [5, 7], [40, 49]], time: 3600 }, - { kinds: [[40000, 49999], time: 100 }, - { kinds: [[30000, 39999], count: 1000 }, - { time: 3600, count: 10000 } + "retention": [ + { "kinds": [0, 1, [5, 7], [40, 49]], "time": 3600 }, + { "kinds": [[40000, 49999]], "time": 100 }, + { "kinds": [[30000, 39999]], "count": 1000 }, + { "time": 3600, "count": 10000 } ] ... } @@ -154,7 +154,7 @@ all, and preferably an error will be provided when those are received. `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. +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. @@ -175,8 +175,8 @@ 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 -country's' laws might end up being enforced on them, and then -indirectly on their users's content. +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 favourable zones. Exposing this @@ -185,7 +185,7 @@ flexibility is up to the client software. ```json { ... - relay_countries: [ 'CA', 'US' ], + "relay_countries": [ "CA", "US" ], ... } ``` @@ -208,9 +208,9 @@ To support this goal, relays MAY specify some of the following values. ```json { ... - language_tags: [ 'en', 'en-419' ], - tags: [ 'sfw-only', 'bitcoin-only', 'anime' ], - posting_policy: 'https://example.com/posting-policy.html', + "language_tags": [ "en", "en-419" ], + "tags": [ "sfw-only", "bitcoin-only", "anime" ], + "posting_policy": "https://example.com/posting-policy.html", ... } ``` @@ -220,7 +220,7 @@ To support this goal, relays MAY specify some of the following values. the major languages spoken on the relay. - `tags` is a list of limitations on the topics to be discussed. - For example `sfw-only` indicates hat only "Safe For Work" content + 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 @@ -245,11 +245,11 @@ Relays that require payments may want to expose their fee schedules. ```json { ... - payments_url: "https://my-relay/payments", - fees: { - "admission": [{ amount: 1000000, unit: 'msats' }], - "subscription": [{ amount: 5000000, unit: 'msats', period: 2592000 }], - "publication": [{ kinds: [4], amount: 100, unit: 'msats' }], + "payments_url": "https://my-relay/payments", + "fees": { + "admission": [{ "amount": 1000000, "unit": "msats" }], + "subscription": [{ "amount": 5000000, "unit": "msats", "period": 2592000 }], + "publication": [{ "kinds": [4], "amount": 100, "unit": "msats" }], }, ... } From 60aa6ae168e8d71e4fd247e49f8ba70fbe511fda Mon Sep 17 00:00:00 2001 From: "Robert C. Martin" Date: Tue, 9 May 2023 10:17:15 -0500 Subject: [PATCH 08/18] A few changes to some nips. (#510) --- 01.md | 1 + 47.md | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/01.md b/01.md index 713e6550..e36f4f5d 100644 --- a/01.md +++ b/01.md @@ -109,3 +109,4 @@ A relay may choose to treat different message kinds differently, and it may or m - Clients should not open more than one websocket to each relay. One channel can support an unlimited number of subscriptions, so clients should do that. - The `tags` array can store a tag identifier as the first element of each subarray, plus arbitrary information afterward (always as strings). This NIP defines `"p"` — meaning "pubkey", which points to a pubkey of someone that is referred to in the event —, and `"e"` — meaning "event", which points to the id of an event this event is quoting, replying to or referring to somehow. See [NIP-10](https://github.com/nostr-protocol/nips/blob/127d5518bfa9a4e4e7510490c0b8d95e342dfa4b/10.md) for a detailed description of "e" and "p" tags. - The `` item present on the `"e"` and `"p"` tags is an optional (could be set to `""`) URL of a relay the client could attempt to connect to fetch the tagged event or other events from a tagged profile. It MAY be ignored, but it exists to increase censorship resistance and make the spread of relay addresses more seamless across clients. +- Clients should use the created_at field to judge the age of a metadata event and completely replace older metadata events with newer metadata events regardless of the order in which they arrive. Clients should not merge any filled fields within older metadata events into empty fields of newer metadata events. diff --git a/47.md b/47.md index aa58b5c4..fe3d5756 100644 --- a/47.md +++ b/47.md @@ -12,8 +12,18 @@ This NIP describes a way for clients to access a remote Lightning wallet through ## Terms -* **client**: Nostr app on any platform that wants to pay Lightning invoices -* **wallet service**: Nostr app that typically runs on an always-on computer (eg. in the cloud or on a Raspberry Pi). +* **client**: Nostr app on any platform that wants to pay Lightning invoices. +* **user**: The person using the **client**, and want's to connect their wallet app to their **client**. +* **wallet service**: Nostr app that typically runs on an always-on computer (eg. in the cloud or on a Raspberry Pi). This app has access to the APIs of the wallets it serves. + +## Theory of Operation + 1. **Users** who which to use this NIP to send lightning payments to other nostr users must first acquire a special "connection" URI from their NIP-47 compliant wallet application. The wallet application may provide this URI using a QR screen, or a pasteable string, or some other means. + + 2. The **user** should then copy this URI into their **client(s)** by pasting, or scanning the QR, etc. The **client(s)** should save this URI and use it later whenever the **user** makes a payment. The **client** should then request an `info` (13194) event from the relay(s) specified in the URI. The **wallet service** will have sent that event to those relays earlier, and the relays will hold it as a replaceable event. + + 3. When the **user** initiates a payment their nostr **client** create a `pay_invoice` request, encrypts it using a token from the URI, and sends it (kind 23194) to the relay(s) specified in the connection URI. The **wallet service** will be listening on those relays and will decrypt the request and then contact the **user's** wallet application to send the payment. The **wallet service** will know how to talk to the wallet application because the connection URI specified relay(s) that have access to the wallet app API. + + 4. Once the payment is complete the **wallet service** will send an encrypted `response` (kind 23195) to the **user** over the relay(s) in the URI. ## Events @@ -24,7 +34,8 @@ There are three event kinds: The info event should be a replaceable event that is published by the **wallet service** on the relay to indicate which commands it supports. The content should be a plaintext string with the supported commands, space-seperated, eg. `pay_invoice get_balance`. Only the `pay_invoice` command is described in this NIP, but other commands might be defined in different NIPs. -Both the request and response events SHOULD contain one `p` tag, containing the public key of the **wallet service** if this is a request, and the public key of the **client** if this is a response. The response event SHOULD contain an `e` tag with the id of the request event it is responding to. + +Both the request and response events SHOULD contain one `p` tag, containing the public key of the **wallet service** if this is a request, and the public key of the **user** if this is a response. The response event SHOULD contain an `e` tag with the id of the request event it is responding to. The content of requests and responses is encrypted with [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md), and is a JSON-RPCish object with a semi-fixed structure: @@ -117,7 +128,7 @@ Errors: ## Example pay invoice flow 0. The user scans the QR code generated by the **wallet service** with their **client** application, they follow a `nostr+walletconnect:` deeplink or configure the connection details manually. -1. **client** sends an event to with **wallet service** service with kind `23194`. The content is a `pay_invoice` request. The private key is the secret from the connection string above. +1. **client** sends an event to the **wallet service** service with kind `23194`. The content is a `pay_invoice` request. The private key is the secret from the connection string above. 2. **wallet service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment. 3. **wallet service** responds to the event by sending an event with kind `23195` and content being a response either containing an error message or a preimage. From 4208652dc7a39c63c39559b13c656ec30400fcba Mon Sep 17 00:00:00 2001 From: William Casarin Date: Tue, 9 May 2023 15:02:14 -0700 Subject: [PATCH 09/18] nip47: add lud16 parameter to connection string This adds an optional but recommended lud16 parameter to nostr wallet connection strings. This enables seamless onboarding of new users, allowing clients to automatically configure the receive address for zaps. --- 47.md | 1 + 1 file changed, 1 insertion(+) diff --git a/47.md b/47.md index fe3d5756..c884b978 100644 --- a/47.md +++ b/47.md @@ -88,6 +88,7 @@ The **wallet service** generates this connection URI with protocol `nostr+wallet - The user can have different keys for different applications. Keys can be revoked and created at will and have arbitrary constraints (eg. budgets). - The key is harder to leak since it is not shown to the user and backed up. - It improves privacy because the user's main key would not be linked to their payments. +- `lud16` Recommended. A lightning address that clients can use to automatically setup the `lud16` field on the user's profile if they have none configured. The **client** should then store this connection and use it when the user wants to perform actions like paying an invoice. Due to this NIP using ephemeral events, it is recommended to pick relays that do not close connections on inactivity to not drop events. From 4cbb672d1cf6e0af2b4c09c9b33e97f7964ce36e Mon Sep 17 00:00:00 2001 From: earonesty Date: Sat, 13 May 2023 07:39:01 -0700 Subject: [PATCH 10/18] Fix docs from kind0 to kind33 https://github.com/nostr-protocol/nips/issues/376 --- 28.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/28.md b/28.md index 169ae4f4..9f9302f1 100644 --- a/28.md +++ b/28.md @@ -37,7 +37,7 @@ In the channel creation `content` field, Client SHOULD include basic channel met Update a channel's public metadata. -Clients and relays SHOULD handle kind 41 events similar to kind 0 `metadata` events. +Clients and relays SHOULD handle kind 41 events similar to kind 33 replaceable events, where the information is used to update the metadata, without modifying the event id for the channel. Clients SHOULD ignore kind 41s from pubkeys other than the kind 40 pubkey. From 26194822005836a8ce690009fc636e0fe71802e6 Mon Sep 17 00:00:00 2001 From: earonesty Date: Sat, 13 May 2023 07:42:40 -0700 Subject: [PATCH 11/18] More explicit --- 28.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/28.md b/28.md index 9f9302f1..62ab398f 100644 --- a/28.md +++ b/28.md @@ -37,7 +37,7 @@ In the channel creation `content` field, Client SHOULD include basic channel met Update a channel's public metadata. -Clients and relays SHOULD handle kind 41 events similar to kind 33 replaceable events, where the information is used to update the metadata, without modifying the event id for the channel. +Clients and relays SHOULD handle kind 41 events similar to kind 33 replaceable events, where the information is used to update the metadata, without modifying the event id for the channel. Only the most recent kind 41 is needed to be stored. Clients SHOULD ignore kind 41s from pubkeys other than the kind 40 pubkey. From 64ac0710dea1af432051ef70698979bff106b9c2 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Sun, 14 May 2023 11:55:07 +0900 Subject: [PATCH 12/18] zap note -> zap receipt --- 57.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/57.md b/57.md index 17042ea4..538d7275 100644 --- a/57.md +++ b/57.md @@ -20,7 +20,7 @@ Having lightning receipts on nostr allows clients to display lightning payments 6. If the request is valid, the server should fetch a description hash invoice where the description is this note and this note only. No additional lnurl metadata is included in the description. This will be returned in the response according to [LUD06](https://github.com/lnurl/luds/blob/luds/06.md). 7. On receiving the invoice, the client MAY pay it or pass it to an app that can pay the invoice. 8. Once the invoice is paid, the recipient's lnurl server MUST generate a `zap receipt` as described in Appendix E, and publish it to the `relays` specified in the `zap request`. -9. Clients MAY fetch zap notes on posts and profiles, but MUST authorize their validity as described in Appendix F. If the zap request note contains a non-empty `content`, it may display a zap comment. Generally clients should show users the `zap request` note, and use the `zap note` to show "zap authorized by ..." but this is optional. +9. Clients MAY fetch `zap receipt`s on posts and profiles, but MUST authorize their validity as described in Appendix F. If the zap request note contains a non-empty `content`, it may display a zap comment. Generally clients should show users the `zap request` note, and use the `zap receipt` to show "zap authorized by ..." but this is optional. ## Reference and examples @@ -108,7 +108,7 @@ When a client sends a zap request event to a server's lnurl-pay callback URL, th 2. It MUST have tags 3. It MUST have only one `p` tag 4. It MUST have 0 or 1 `e` tags -5. There should be a `relays` tag with the relays to send the `zap` note to. +5. There should be a `relays` tag with the relays to send the `zap receipt` to. 6. If there is an `amount` tag, it MUST be equal to the `amount` query parameter. 7. If there is an `a` tag, it MUST be a valid NIP-33 event coordinate From 9076b8486da293f56e725ec593fcfb09a7bc2edf Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Sun, 14 May 2023 12:04:47 +0900 Subject: [PATCH 13/18] fix inconsistent quoting of zap request / receipt --- 57.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/57.md b/57.md index 538d7275..54141358 100644 --- a/57.md +++ b/57.md @@ -6,21 +6,21 @@ Lightning Zaps `draft` `optional` `author:jb55` `author:kieran` -This NIP defines two new event types for recording lightning payments between users. `9734` is a `zap request`, representing a payer's request to a recipient's lightning wallet for an invoice. `9735` is a `zap receipt`, representing the confirmation by the recipient's lightning wallet that the invoice issued in response to a zap request has been paid. +This NIP defines two new event types for recording lightning payments between users. `9734` is a `zap request`, representing a payer's request to a recipient's lightning wallet for an invoice. `9735` is a `zap receipt`, representing the confirmation by the recipient's lightning wallet that the invoice issued in response to a `zap request` has been paid. Having lightning receipts on nostr allows clients to display lightning payments from entities on the network. These can be used for fun or for spam deterrence. ## Protocol flow 1. Client calculates a recipient's lnurl pay request url from the `zap` tag on the event being zapped (see Appendix G), or by decoding their lud06 or lud16 field on their profile according to the [lnurl specifications](https://github.com/lnurl/luds). The client MUST send a GET request to this url and parse the response. If `allowsNostr` exists and it is `true`, and if `nostrPubkey` exists and is a valid BIP 340 public key in hex, the client should associate this information with the user, along with the response's `callback`, `minSendable`, and `maxSendable` values. -2. Clients may choose to display a lightning zap button on each post or on a user's profile. If the user's lnurl pay request endpoint supports nostr, the client SHOULD use this NIP to request a zap receipt rather than a normal lnurl invoice. +2. Clients may choose to display a lightning zap button on each post or on a user's profile. If the user's lnurl pay request endpoint supports nostr, the client SHOULD use this NIP to request a `zap receipt` rather than a normal lnurl invoice. 3. When a user (the "sender") indicates they want to send a zap to another user (the "recipient"), the client should create a `zap request` event as described in Appendix A of this NIP and sign it. 4. Instead of publishing the `zap request`, the `9734` event should instead be sent to the `callback` url received from the lnurl pay endpoint for the recipient using a GET request. See Appendix B for details and an example. -5. The recipient's lnurl server will receive this request and validate it. See Appendix C for details on how to properly configure an lnurl server to support zaps, and Appendix D for details on how to validate the `nostr` query parameter. -6. If the request is valid, the server should fetch a description hash invoice where the description is this note and this note only. No additional lnurl metadata is included in the description. This will be returned in the response according to [LUD06](https://github.com/lnurl/luds/blob/luds/06.md). +5. The recipient's lnurl server will receive this `zap request` and validate it. See Appendix C for details on how to properly configure an lnurl server to support zaps, and Appendix D for details on how to validate the `nostr` query parameter. +6. If the `zap request` is valid, the server should fetch a description hash invoice where the description is this `zap request` note and this note only. No additional lnurl metadata is included in the description. This will be returned in the response according to [LUD06](https://github.com/lnurl/luds/blob/luds/06.md). 7. On receiving the invoice, the client MAY pay it or pass it to an app that can pay the invoice. 8. Once the invoice is paid, the recipient's lnurl server MUST generate a `zap receipt` as described in Appendix E, and publish it to the `relays` specified in the `zap request`. -9. Clients MAY fetch `zap receipt`s on posts and profiles, but MUST authorize their validity as described in Appendix F. If the zap request note contains a non-empty `content`, it may display a zap comment. Generally clients should show users the `zap request` note, and use the `zap receipt` to show "zap authorized by ..." but this is optional. +9. Clients MAY fetch `zap receipt`s on posts and profiles, but MUST authorize their validity as described in Appendix F. If the `zap request` note contains a non-empty `content`, it may display a zap comment. Generally clients should show users the `zap request` note, and use the `zap receipt` to show "zap authorized by ..." but this is optional. ## Reference and examples @@ -60,10 +60,10 @@ Example: ### Appendix B: Zap Request HTTP Request -A signed zap request event is not published, but is instead sent using a HTTP GET request to the recipient's `callback` url, which was provided by the recipient's lnurl pay endpoint. This request should have the following query parameters defined: +A signed `zap request` event is not published, but is instead sent using a HTTP GET request to the recipient's `callback` url, which was provided by the recipient's lnurl pay endpoint. This request should have the following query parameters defined: - `amount` is the amount in _millisats_ the sender intends to pay -- `nostr` is the `9734` zap request event, JSON encoded then URI encoded +- `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: @@ -97,12 +97,12 @@ const {pr: invoice} = await fetchJson(`${callback}?amount=${amount}&nostr=${even The lnurl server will need some additional pieces of information so that clients can know that zap invoices are supported: -1. Add a `nostrPubkey` to the lnurl-pay static endpoint `/.well-known/lnurlp/`, where `nostrPubkey` is the nostr pubkey your server will use to sign `zap receipt` events. Clients will use this to validate zap receipts. +1. Add a `nostrPubkey` to the lnurl-pay static endpoint `/.well-known/lnurlp/`, where `nostrPubkey` is the nostr pubkey your server will use to sign `zap receipt` events. Clients will use this to validate `zap receipt`s. 2. Add an `allowsNostr` field and set it to true. ### Appendix D: LNURL Server Zap Request Validation -When a client sends a zap request event to a server's lnurl-pay callback URL, there will be a `nostr` query parameter where the contents of the event are URI- and JSON-encoded. If present, the zap request event must be validated in the following ways: +When a client sends a `zap request` event to a server's lnurl-pay callback URL, there will be a `nostr` query parameter where the contents of the event are URI- and JSON-encoded. If present, the `zap request` event must be validated in the following ways: 1. It MUST have a valid nostr signature 2. It MUST have tags @@ -116,29 +116,29 @@ The event MUST then be stored for use later, when the invoice is paid. ### Appendix E: Zap Receipt Event -A `zap receipt` is created by a lightning node when an invoice generated by a `zap request` is paid. Zap receipts are only created when the invoice description (committed to the description hash) contains a zap request note. +A `zap receipt` is created by a lightning node when an invoice generated by a `zap request` is paid. `Zap receipt`s are only created when the invoice description (committed to the description hash) contains a `zap request` note. When receiving a payment, the following steps are executed: 1. Get the description for the invoice. This needs to be saved somewhere during the generation of the description hash invoice. It is saved automatically for you with CLN, which is the reference implementation used here. 2. Parse the bolt11 description as a JSON nostr event. This SHOULD be validated based on the requirements in Appendix D, either when it is received, or before the invoice is paid. -3. Create a nostr event of kind `9735` as described below, and publish it to the `relays` declared in the zap request. +3. Create a nostr event of kind `9735` as described below, and publish it to the `relays` declared in the `zap request`. -The following should be true of the zap receipt event: +The following should be true of the `zap receipt` event: - The content SHOULD be empty. - The `created_at` date SHOULD be set to the invoice `paid_at` date for idempotency. -- `tags` MUST include the `p` tag AND optional `e` tag from the zap request. -- The zap receipt MUST have a `bolt11` tag containing the description hash bolt11 invoice. -- The zap receipt MUST contain a `description` tag which is the JSON-encoded invoice description. +- `tags` MUST include the `p` tag AND optional `e` tag from the `zap request`. +- The `zap receipt` MUST have a `bolt11` tag containing the description hash bolt11 invoice. +- The `zap receipt` MUST contain a `description` tag which is the JSON-encoded invoice description. - `SHA256(description)` MUST match the description hash in the bolt11 invoice. -- The zap receipt MAY contain a `preimage` tag to match against the payment hash of the bolt11 invoice. This isn't really a payment proof, there is no real way to prove that the invoice is real or has been paid. You are trusting the author of the zap receipt for the legitimacy of the payment. +- The `zap receipt` MAY contain a `preimage` tag to match against the payment hash of the bolt11 invoice. This isn't really a payment proof, there is no real way to prove that the invoice is real or has been paid. You are trusting the author of the `zap receipt` for the legitimacy of the payment. -The zap receipt is not a proof of payment, all it proves is that some nostr user fetched an invoice. The existence of the zap receipt implies the invoice as paid, but it could be a lie given a rogue implementation. +The `zap receipt` is not a proof of payment, all it proves is that some nostr user fetched an invoice. The existence of the `zap receipt` implies the invoice as paid, but it could be a lie given a rogue implementation. A reference implementation for a zap-enabled lnurl server can be found [here](https://github.com/jb55/cln-nostr-zapper). -Example zap receipt: +Example `zap receipt`: ```json { @@ -160,7 +160,7 @@ Example zap receipt: ### Appendix F: Validating Zap Receipts -A client can retrieve `zap receipts` on events and pubkeys using a NIP-01 filter, for example `{"kinds": [9735], "#e": [...]}`. Zaps MUST be validated using the following steps: +A client can retrieve `zap receipt`s on events and pubkeys using a NIP-01 filter, for example `{"kinds": [9735], "#e": [...]}`. Zaps MUST be validated using the following steps: - The `zap receipt` event's `pubkey` MUST be the same as the recipient's lnurl provider's `nostrPubkey` (retrieved in step 1 of the protocol flow). - The `invoiceAmount` contained in the `bolt11` tag of the `zap receipt` MUST equal the `amount` tag of the `zap request` (if present). @@ -180,4 +180,4 @@ When an event includes a `zap` tag, clients SHOULD calculate the lnurl pay reque ## Future Work -Zaps can be extended to be more private by encrypting zap request notes to the target user, but for simplicity it has been left out of this initial draft. +Zaps can be extended to be more private by encrypting `zap request` notes to the target user, but for simplicity it has been left out of this initial draft. From 89e3c01b1438cedfb8d1ebbed3e320b8a6f3a582 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Sun, 14 May 2023 13:16:10 +0900 Subject: [PATCH 14/18] fix description of nostr query param --- 57.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/57.md b/57.md index 54141358..cb1f126c 100644 --- a/57.md +++ b/57.md @@ -102,7 +102,7 @@ The lnurl server will need some additional pieces of information so that clients ### Appendix D: LNURL Server Zap Request Validation -When a client sends a `zap request` event to a server's lnurl-pay callback URL, there will be a `nostr` query parameter where the contents of the event are URI- and JSON-encoded. If present, the `zap request` event must be validated in the following ways: +When a client sends a `zap request` event to a server's lnurl-pay callback URL, there will be a `nostr` query parameter whose value is that event which is URI- and JSON-encoded. If present, the `zap request` event must be validated in the following ways: 1. It MUST have a valid nostr signature 2. It MUST have tags From 4ea0e8e9f276c03e298f466fb3074342f0ec01c3 Mon Sep 17 00:00:00 2001 From: Neil Date: Mon, 15 May 2023 09:30:27 -0700 Subject: [PATCH 15/18] Add new signing extension to NIP-07 --- 07.md | 1 + 1 file changed, 1 insertion(+) diff --git a/07.md b/07.md index 3b7a1d29..2a31f716 100644 --- a/07.md +++ b/07.md @@ -30,3 +30,4 @@ async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext - [Blockcore](https://www.blockcore.net/wallet) (Chrome and derivatives) - [nos2x-fox](https://diegogurpegui.com/nos2x-fox/) (Firefox) - [Flamingo](https://www.getflamingo.org/) (Chrome and derivatives) +- [AKA Profiles](https://github.com/neilck/aka-extension) (Chrome, stores multiple keys) From d9caf9d7b4ca5c3341b1262d5460a2e23630da5c Mon Sep 17 00:00:00 2001 From: jimbojw Date: Mon, 15 May 2023 08:15:53 -0400 Subject: [PATCH 16/18] fix: Updating links in NIP-15 to point to intended other NIPs. --- 15.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/15.md b/15.md index 617c0115..f8df3284 100644 --- a/15.md +++ b/15.md @@ -38,8 +38,8 @@ A merchant can publish these events: | `0 ` | `set_meta` | The merchant description (similar with any `nostr` public key). | [NIP01 ](https://github.com/nostr-protocol/nips/blob/master/01.md) | | `30017` | `set_stall` | Create or update a stall. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | | `30018` | `set_product` | Create or update a product. | [NIP33](https://github.com/nostr-protocol/nips/blob/master/33.md) (Parameterized Replaceable Event) | -| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON. | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) | -| `5 ` | `delete` | Delete a product or a stall. | [NIP05](https://github.com/nostr-protocol/nips/blob/master/05.md) | +| `4 ` | `direct_message` | Communicate with the customer. The messages can be plain-text or JSON. | [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md) | +| `5 ` | `delete` | Delete a product or a stall. | [NIP09](https://github.com/nostr-protocol/nips/blob/master/09.md) | ### Event `30017`: Create or update a stall. From 835ec2614164c593e686e829aae6cbac64997ae8 Mon Sep 17 00:00:00 2001 From: Asai Toshiya Date: Tue, 16 May 2023 22:40:41 +0900 Subject: [PATCH 17/18] Add emoji tag to list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b99f1d35..963fd791 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ When experimenting with kinds, keep in mind the classification introduced by [NI | `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) | | `description` | badge description | -- | [58](58.md) | | `description` | invoice description | -- | [57](57.md) | +| `emoji` | shortcode | image URL | [30](30.md) | | `expiration` | unix timestamp (string) | -- | [40](40.md) | | `image` | image URL | dimensions in pixels | [23](23.md), [58](58.md) | | `lnurl` | `bech32` encoded `lnurl` | -- | [57](57.md) | From ccbdfb95c198c385595c18edac09d9c830fd9406 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Tue, 16 May 2023 21:50:04 +0900 Subject: [PATCH 18/18] allow underscores in an emoji shortcode --- 30.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/30.md b/30.md index 04689d0f..ffc5aeb3 100644 --- a/30.md +++ b/30.md @@ -14,7 +14,7 @@ Custom emoji may be added to **kind 0** and **kind 1** events by including one o Where: -- `` is a name given for the emoji, which MUST be comprised of only alphanumeric characters. +- `` is a name given for the emoji, which MUST be comprised of only alphanumeric characters and underscores. - `` is a URL to the corresponding image file of the emoji. For each emoji tag, clients should parse emoji shortcodes (aka "emojify") like `:shortcode:` in the event to display custom emoji. @@ -53,4 +53,4 @@ In kind 1 events, the `content` should be emojified. "pubkey": "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6", "created_at": 1682630000 } -``` \ No newline at end of file +```