mirror of
https://github.com/nostr-protocol/nips.git
synced 2025-02-23 13:49:00 +00:00
[NWC] Add an encryption tag to negotiate upgrading to NIP44.
This is an alternative proposal to https://github.com/nostr-protocol/nips/pull/1531 to upgrade to nip44 without introducing a versioning system.
This commit is contained in:
parent
6e7a618e7f
commit
9c9b0b422f
141
47.md
141
47.md
@ -28,15 +28,16 @@ Fundamentally NWC is communication between a **client** and **wallet service** b
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
5. The **wallet service** may send encrypted notifications (kind 23196) of wallet events (such as a received payment) to the **client**.
|
5. The **wallet service** may send encrypted notifications (kind 23197 or 23196) of wallet events (such as a received payment) to the **client**.
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
There are four event kinds:
|
There are four event kinds:
|
||||||
|
|
||||||
- `NIP-47 info event`: 13194
|
- `NIP-47 info event`: 13194
|
||||||
- `NIP-47 request`: 23194
|
- `NIP-47 request`: 23194
|
||||||
- `NIP-47 response`: 23195
|
- `NIP-47 response`: 23195
|
||||||
- `NIP-47 notification event`: 23196
|
- `NIP-47 notification event`: 23197 (23196 for backwards compatibility with NIP-04)
|
||||||
|
|
||||||
### Info Event
|
### Info Event
|
||||||
|
|
||||||
@ -46,34 +47,72 @@ The content should be a plaintext string with the supported capabilities space-s
|
|||||||
|
|
||||||
If 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`.
|
If 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`.
|
||||||
|
|
||||||
|
It should also contain supported encryption modes as described in the [Encryption](#encryption) section. For example:
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 13194,
|
||||||
|
"tags": [
|
||||||
|
["encryption", "nip44 nip04"], // List of supported encryption schemes as described in the Encryption section.
|
||||||
|
["notifications", "payment_received payment_sent"]
|
||||||
|
// ...
|
||||||
|
],
|
||||||
|
"content": "pay_invoice get_balance make_invoice lookup_invoice list_transactions get_info notifications",
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Request and Response Events
|
### Request and Response Events
|
||||||
|
|
||||||
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 **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.
|
||||||
Optionally, 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.
|
Optionally, 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.
|
||||||
|
|
||||||
The content of requests and responses is encrypted with [NIP04](04.md), and is a JSON-RPCish object with a semi-fixed structure:
|
The content of requests and responses is encrypted with [NIP44](44.md), and is a JSON-RPCish object with a semi-fixed structure.
|
||||||
|
|
||||||
Request:
|
**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
|
||||||
```jsonc
|
`info` or request events, it should be assumed that the connection is using NIP04 for encryption. See the [Encryption](#encryption) section for more information.
|
||||||
|
|
||||||
|
Example request:
|
||||||
|
|
||||||
|
```js
|
||||||
{
|
{
|
||||||
"method": "pay_invoice", // method, string
|
"kind" 23194,
|
||||||
"params": { // params, object
|
"tags": [
|
||||||
"invoice": "lnbc50n1..." // command-related data
|
["encryption", "nip44"],
|
||||||
}
|
["p", "03..." ] // public key of the wallet service.
|
||||||
|
// ...
|
||||||
|
],
|
||||||
|
"content": nip44_encrypt({
|
||||||
|
"method": "pay_invoice", // method, string
|
||||||
|
"params": { // params, object
|
||||||
|
"invoice": "lnbc50n1..." // command-related data
|
||||||
|
}
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Response:
|
Example response:
|
||||||
```jsonc
|
|
||||||
|
```js
|
||||||
{
|
{
|
||||||
"result_type": "pay_invoice", //indicates the structure of the result field
|
"kind" 23195,
|
||||||
"error": { //object, non-null in case of error
|
"tags": [
|
||||||
"code": "UNAUTHORIZED", //string error code, see below
|
["encryption", "nip44"],
|
||||||
"message": "human readable error message"
|
["p", "03..." ] // public key of the requesting client app
|
||||||
},
|
["e", "1234"] // id of the request event this is responding to
|
||||||
"result": { // result, object. null in case of error.
|
// ...
|
||||||
"preimage": "0123456789abcdef..." // command-related data
|
],
|
||||||
}
|
"content": nip44_encrypt({
|
||||||
|
"result_type": "pay_invoice", //indicates the structure of the result field
|
||||||
|
"error": { //object, non-null in case of error
|
||||||
|
"code": "UNAUTHORIZED", //string error code, see below
|
||||||
|
"message": "human readable error message"
|
||||||
|
},
|
||||||
|
"result": { // result, object. null in case of error.
|
||||||
|
"preimage": "0123456789abcdef..." // command-related data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -83,9 +122,9 @@ If the command was successful, the `error` field must be null.
|
|||||||
|
|
||||||
### Notification Events
|
### Notification Events
|
||||||
|
|
||||||
The notification event SHOULD contain one `p` tag, the public key of the **client**.
|
The notification event is a kind 23197 event (23196 if using nip04) SHOULD contain one `p` tag, the public key of the **user**.
|
||||||
|
|
||||||
The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPCish object with a semi-fixed structure:
|
The 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:
|
||||||
|
|
||||||
```jsonc
|
```jsonc
|
||||||
{
|
{
|
||||||
@ -96,6 +135,7 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
_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.
|
||||||
|
|
||||||
### Error codes
|
### Error codes
|
||||||
- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds.
|
- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds.
|
||||||
@ -105,6 +145,7 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC
|
|||||||
- `RESTRICTED`: This public key is not allowed to do this operation.
|
- `RESTRICTED`: This public key is not allowed to do this operation.
|
||||||
- `UNAUTHORIZED`: This public key has no wallet connected.
|
- `UNAUTHORIZED`: This public key has no wallet connected.
|
||||||
- `INTERNAL`: An internal error.
|
- `INTERNAL`: An internal error.
|
||||||
|
- `UNSUPPORTED_ENCRYPTION`: The encryption type of the request is not supported by the wallet service.
|
||||||
- `OTHER`: Other error.
|
- `OTHER`: Other error.
|
||||||
|
|
||||||
## Nostr Wallet Connect URI
|
## Nostr Wallet Connect URI
|
||||||
@ -499,6 +540,63 @@ Notification:
|
|||||||
2. **wallet service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment.
|
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.
|
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.
|
||||||
|
|
||||||
|
## Encryption
|
||||||
|
|
||||||
|
The 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
|
||||||
|
where wither 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` tags in the `info` event.
|
||||||
|
|
||||||
|
The negotiation works as follows.
|
||||||
|
|
||||||
|
1. 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 nip04`)
|
||||||
|
2. 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**.
|
||||||
|
|
||||||
|
### Info event
|
||||||
|
|
||||||
|
First, the **wallet service** adds an `encryption` tag to its `info` event containing a space-separated list of encryption schemes it supports. For example,
|
||||||
|
if 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:
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 13194,
|
||||||
|
"tags": [
|
||||||
|
["encryption", "nip44 nip04"],
|
||||||
|
// ...
|
||||||
|
],
|
||||||
|
"content": "pay_invoice get_balance make_invoice lookup_invoice list_transactions get_info",
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When a **client application** establishes a connection, it should read the info event and look for the `encryption` tag.
|
||||||
|
|
||||||
|
**Absence of this tag implies that the wallet only supports nip04.**
|
||||||
|
|
||||||
|
If 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.
|
||||||
|
|
||||||
|
### Request events
|
||||||
|
|
||||||
|
When 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.
|
||||||
|
For example, if the client application supports nip44, the request event might look like:
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 23194,
|
||||||
|
"tags": [
|
||||||
|
["encryption", "nip44"],
|
||||||
|
// ...
|
||||||
|
],
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If 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.
|
||||||
|
|
||||||
|
### Notification events
|
||||||
|
|
||||||
|
As 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.
|
||||||
|
|
||||||
|
The **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. Clients that support both nip04 and nip44 can choose to only listen to 23197 events for simplicity.
|
||||||
|
|
||||||
## Using a dedicated relay
|
## Using a dedicated relay
|
||||||
This 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.
|
This 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.
|
||||||
|
|
||||||
@ -513,6 +611,7 @@ This NIP does not specify any requirements on the type of relays used. However,
|
|||||||
"created_at": 1713883677,
|
"created_at": 1713883677,
|
||||||
"kind": 13194,
|
"kind": 13194,
|
||||||
"tags": [
|
"tags": [
|
||||||
|
[ "encryption", "nip44 nip04" ],
|
||||||
[
|
[
|
||||||
"notifications",
|
"notifications",
|
||||||
"payment_received payment_sent"
|
"payment_received payment_sent"
|
||||||
|
Loading…
Reference in New Issue
Block a user