upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/47.md
diff options
context:
space:
mode:
authorJeremy Klein <jklein24@gmail.com>2025-07-31 06:21:18 -0700
committerGitHub <noreply@github.com>2025-07-31 09:21:18 -0400
commitf30a43bd37e08516923b96dd0d860122c9ffe04e (patch)
tree737238d9bdd091d35937ac2271ca7ff9e4dd7060 /47.md
parentfaba3f016df141781f6328a3f0ac398ee8a03a3c (diff)
[NWC] Add an encryption tag to negotiate upgrading to NIP44. (#1780)
Co-authored-by: Roland <33993199+rolznz@users.noreply.github.com>
Diffstat (limited to '47.md')
-rw-r--r--47.md148
1 files changed, 127 insertions, 21 deletions
diff --git a/47.md b/47.md
index 84f710e..298b399 100644
--- a/47.md
+++ b/47.md
@@ -28,15 +28,16 @@ Fundamentally NWC is communication between a **client** and **wallet service** b
28 28
29 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. 29 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.
30 30
31 5. The **wallet service** may send encrypted notifications (kind 23196) of wallet events (such as a received payment) to the **client**. 31 5. The **wallet service** may send encrypted notifications (kind 23197 or 23196) of wallet events (such as a received payment) to the **client**.
32 32
33## Events 33## Events
34 34
35There are four event kinds: 35There are four event kinds:
36
36- `NIP-47 info event`: 13194 37- `NIP-47 info event`: 13194
37- `NIP-47 request`: 23194 38- `NIP-47 request`: 23194
38- `NIP-47 response`: 23195 39- `NIP-47 response`: 23195
39- `NIP-47 notification event`: 23196 40- `NIP-47 notification event`: 23197 (23196 for backwards compatibility with NIP-04)
40 41
41### Info Event 42### Info Event
42 43
@@ -46,34 +47,71 @@ The content should be a plaintext string with the supported capabilities space-s
46 47
47If the **wallet service** supports notifications, the info event SHOULD contain a `notifications` tag with the supported notification types space-separated, eg. `payment_received payment_sent`. 48If the **wallet service** supports notifications, the info event SHOULD contain a `notifications` tag with the supported notification types space-separated, eg. `payment_received payment_sent`.
48 49
50It should also contain supported encryption modes as described in the [Encryption](#encryption) section. For example:
51
52```jsonc
53{
54 "kind": 13194,
55 "tags": [
56 ["encryption", "nip44_v2 nip04"], // List of supported encryption schemes as described in the Encryption section.
57 ["notifications", "payment_received payment_sent"]
58 // ...
59 ],
60 "content": "pay_invoice get_balance make_invoice lookup_invoice list_transactions get_info notifications",
61 // ...
62}
63```
64
49### Request and Response Events 65### Request and Response Events
50 66
51Both 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. 67Both 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.
52Optionally, a request can have an `expiration` tag that has a unix timestamp in seconds. If the request is received after this timestamp, it should be ignored. 68Optionally, a request can have an `expiration` tag that has a unix timestamp in seconds. If the request is received after this timestamp, it should be ignored.
53 69
54The content of requests and responses is encrypted with [NIP04](04.md), and is a JSON-RPCish object with a semi-fixed structure: 70The content of requests and responses is encrypted with [NIP44](44.md), and is a JSON-RPCish object with a semi-fixed structure.
55 71
56Request: 72**Important note for backwards-compatibility:** The initial version of the protocol used [NIP04](04.md). If a **wallet service** or client app does not include the `encryption` tag in the
57```jsonc 73`info` or request events, it should be assumed that the connection is using NIP04 for encryption. See the [Encryption](#encryption) section for more information.
74
75Example request:
76
77```js
58{ 78{
59 "method": "pay_invoice", // method, string 79 "kind" 23194,
60 "params": { // params, object 80 "tags": [
61 "invoice": "lnbc50n1..." // command-related data 81 ["encryption", "nip44_v2"],
62 } 82 ["p", "03..." ] // public key of the wallet service.
83 // ...
84 ],
85 "content": nip44_encrypt({ // Encryption type corresponds to the `encryption` tag.
86 "method": "pay_invoice", // method, string
87 "params": { // params, object
88 "invoice": "lnbc50n1..." // command-related data
89 }
90 }),
63} 91}
64``` 92```
65 93
66Response: 94Example response:
67```jsonc 95
96```js
68{ 97{
69 "result_type": "pay_invoice", //indicates the structure of the result field 98 "kind" 23195,
70 "error": { //object, non-null in case of error 99 "tags": [
71 "code": "UNAUTHORIZED", //string error code, see below 100 ["p", "03..." ] // public key of the requesting client app
72 "message": "human readable error message" 101 ["e", "1234"] // id of the request event this is responding to
73 }, 102 // ...
74 "result": { // result, object. null in case of error. 103 ],
75 "preimage": "0123456789abcdef..." // command-related data 104 "content": nip44_encrypt({ // Encrypted using the scheme requested by the client.
76 } 105 "result_type": "pay_invoice", //indicates the structure of the result field
106 "error": { //object, non-null in case of error
107 "code": "UNAUTHORIZED", //string error code, see below
108 "message": "human readable error message"
109 },
110 "result": { // result, object. null in case of error.
111 "preimage": "0123456789abcdef..." // command-related data
112 }
113 })
114 // ...
77} 115}
78``` 116```
79 117
@@ -83,9 +121,9 @@ If the command was successful, the `error` field must be null.
83 121
84### Notification Events 122### Notification Events
85 123
86The notification event SHOULD contain one `p` tag, the public key of the **client**. 124The notification event is a kind 23197 event SHOULD contain one `p` tag, the public key of the **client**.
87 125
88The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPCish object with a semi-fixed structure: 126The content of notifications is encrypted with [NIP44](44.md) (or NIP-04 for legacy client apps), and is a JSON-RPCish object with a semi-fixed structure:
89 127
90```jsonc 128```jsonc
91{ 129{
@@ -96,6 +134,7 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC
96} 134}
97``` 135```
98 136
137_Note on backwards-compatibility:_ If a **wallet service** supports both nip44 and nip04 for legacy client apps, it should publish both notification events for each notification - kind 23196 encrypted with NIP-04, and kind 23197 encrypted with NIP-44. It is up to the **client** to decide which event to listen to based on its supported encryption and declared supported encryption schemes of the **wallet service** in the `info` event.
99 138
100### Error codes 139### Error codes
101- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds. 140- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds.
@@ -105,6 +144,7 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC
105- `RESTRICTED`: This public key is not allowed to do this operation. 144- `RESTRICTED`: This public key is not allowed to do this operation.
106- `UNAUTHORIZED`: This public key has no wallet connected. 145- `UNAUTHORIZED`: This public key has no wallet connected.
107- `INTERNAL`: An internal error. 146- `INTERNAL`: An internal error.
147- `UNSUPPORTED_ENCRYPTION`: The encryption type of the request is not supported by the wallet service.
108- `OTHER`: Other error. 148- `OTHER`: Other error.
109 149
110## Nostr Wallet Connect URI 150## Nostr Wallet Connect URI
@@ -499,6 +539,71 @@ Notification:
4992. **wallet service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment. 5392. **wallet service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment.
5003. **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. 5403. **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.
501 541
542## Encryption
543
544The initial version of NWC used [NIP-04](04.md) for encryption which has been deprecated and replaced by [NIP-44](44.md). NIP-44 should always be preferred for encryption, but there may be legacy cases
545where the **wallet service** or **client** has not yet migrated to NIP-44. The **wallet service** and **client** should negotiate the encryption method to use based on the `encryption` tag in the `info` event.
546
547The encryption tag can contain either `nip44_v2` or `nip04`. The absence of this tag implies that the wallet only supports `nip04`.
548
549| Encryption code | Use | Notes |
550|-----------------|----------------------|---------------------------------------------------------|
551| `nip44_v2` | NIP-44 | Required |
552| `nip04` | NIP-04 | Deprecated and only here for backward compatibility |
553| `<not present>` | NIP-04 | Deprecated and only here for backward compatibility |
554
555The negotiation works as follows.
556
5571. The **wallet service** includes an `encryption` tag in the `info` event. This tag contains a space-separated list of encryption schemes that the **wallet service** supports (eg. `nip44_v2 nip04`)
5582. The **client application** includes an `encryption` tag in each request event. This tag contains the encryption scheme which should be used for the request. The **client application** should always prefer nip44 if supported by the **wallet service**.
559
560### Info event
561
562First, the **wallet service** adds an `encryption` tag to its `info` event containing a space-separated list of encryption schemes it supports. For example,
563if a wallet service supports nip44, but also allows backwards-compatibility to nip04 client applications, its `encryption` tag in the `info` event might look something like:
564
565```jsonc
566{
567 "kind": 13194,
568 "tags": [
569 ["encryption", "nip44_v2 nip04"],
570 // ...
571 ],
572 "content": "pay_invoice get_balance make_invoice lookup_invoice list_transactions get_info",
573 // ...
574}
575```
576
577When a **client application** establishes a connection, it should read the info event and look for the `encryption` tag.
578
579**Absence of this tag implies that the wallet only supports nip04.**
580
581If the `encryption` tag is present, the **client application** will choose optimal encryption supported by both itself, and the **wallet service**, which should always be nip44 if possible.
582
583### Request events
584
585When a **client application** sends a request event, it should include a `encryption` tag with the encryption scheme it is using. The scheme MUST be supported by the **wallet service** as indicated by the info event.
586For example, if the client application supports nip44, the request event might look like:
587
588```jsonc
589{
590 "kind": 23194,
591 "tags": [
592 ["encryption", "nip44_v2"],
593 // ...
594 ],
595 // ...
596}
597```
598
599If the **wallet service** does not support the specified encryption scheme, it will return an `UNSUPPORTED_ENCRYPTION` error. Absence of the `encryption` tag indicates use of nip04 for encryption.
600
601### Notification events
602
603As described above in the [Notifications](#notifications) section, if a **wallet service** supports both nip04 and nip44, it should publish two notification events for each notification - kind 23196 encrypted with NIP-04, and kind 23197 encrypted with NIP-44. If the **wallet service** only supports nip44, it should only publish kind 23197 events.
604
605The **client** should check the `encryption` tag in the `info` event to determine which encryption schemes the **wallet service** supports, and listen to the appropriate notification event.
606
502## Using a dedicated relay 607## Using a dedicated relay
503This NIP does not specify any requirements on the type of relays used. However, if the user is using a custodial service it might make sense to use a relay that is hosted by the custodial service. The relay may then enforce authentication to prevent metadata leaks. Not depending on a 3rd party relay would also improve reliability in this case. 608This NIP does not specify any requirements on the type of relays used. However, if the user is using a custodial service it might make sense to use a relay that is hosted by the custodial service. The relay may then enforce authentication to prevent metadata leaks. Not depending on a 3rd party relay would also improve reliability in this case.
504 609
@@ -513,6 +618,7 @@ This NIP does not specify any requirements on the type of relays used. However,
513 "created_at": 1713883677, 618 "created_at": 1713883677,
514 "kind": 13194, 619 "kind": 13194,
515 "tags": [ 620 "tags": [
621 [ "encryption", "nip44_v2 nip04" ],
516 [ 622 [
517 "notifications", 623 "notifications",
518 "payment_received payment_sent" 624 "payment_received payment_sent"