This NIP describes a way for clients to access a remote lightning wallet through a standardized protocol. Custodians may implement this, or the user may run a bridge that bridges their wallet/node and the Nostr Wallet Connect protocol.
* **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.
1.**Users** who wish to use this NIP to allow **client(s)** to interact with their wallet 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** (or the **client** on the user's behalf) wants to interact with the wallet. 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.
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`.
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.
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.
**Important note for backwards-compatibility:** v0 of the protocol used [NIP04](04.md). If a **wallet service** or client app does not include the `v` tag in the
`info` or request events, it should be assumed that the connection is using v0 of the protocol and NIP04 should be used for encryption. See the [Versioning](#versioning) section for more information.
The `error` field MUST contain a `message` field with a human readable error message and a `code` field with the error code if the command was not successful.
If the command was successful, the `error` field must be null.
The notification event SHOULD contain one `p` tag, the public key of the **user**.
The content of notifications 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:
```jsonc
{
"notification_type": "payment_received", //indicates the structure of the notification field
"notification": {
"payment_hash": "0123456789abcdef..." // notification-related data
The **wallet service** generates this connection URI with protocol `nostr+walletconnect://` and base path it's hex-encoded `pubkey` with the following query string parameters:
-`secret` Required. 32-byte randomly generated hex encoded string. The **client** MUST use this to sign events and encrypt payloads when communicating with the **wallet service**.
-`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.
"network": "string", // mainnet, testnet, signet, or regtest
"block_height": 1,
"block_hash": "hex string",
"methods": ["pay_invoice", "get_balance", "make_invoice", "lookup_invoice", "list_transactions", "get_info"], // list of supported methods for this connection
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 the **wallet 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.
Versioning for NIP-47 allows the protocol to evolve and even make breaking changes while maintaining backwards-compatibility where needed. Versions are represented as `<major>.<minor>` (e.g. 1.3).
Major version bumps imply breaking changes that are incompatible with the previous major version. Minor version bumps, however, only include non-breaking feature additions or improvements which
can maintain full compatibility with the previous minor version.
**Note:** Version 0.0 or absence of a version specification implies the version of NIP-47 prior to adding the versioning system. This is the protocol as defined at commit hash `e655247`.
Versioning works as follows.
1. The **wallet service** includes a `v` tag in the `info` event. This tag contains a space-separated list of versions that the **wallet service** supports.
2. The **client application** includes a `v` tag in each request event. This tag contains the highest version that the **client application** supports and is compatible with the **wallet service**.
### Info event
First, the **wallet service** adds a `v` tag to its `info` event containing a list of versions it supports. This list should be a space-separated list in decreasing order with the format
`<major>.<minor>`. There should be one entry in the list for each major version supported by the wallet, where the minor version is the highest minor version for that major version. For example,
if a wallet service supports version 1.0-1.3 and version 0.0, their `v` tag in the `info` event might look something like:
```jsonc
{
"kind": 13194,
"tags": [
["v", "1.3 0.0"], // List of supported versions as described in the Versioning section.
When a **client application** establishes a connection, it should read the info event and look for the v tag.
**Absence of this tag implies that the wallet only supports version 0.**
If the `v` tag is present, the **client application** will choose the highest version supported by both itself, and the **wallet service**. Note that minor version bumps are non-breaking. For example,
if the client application supports a highest version of 1.2, and the wallet published the info event shown above, it would select version 1.2 since the wallet’s support for v1.3 implies support for v1.2.
### Request events
When a **client application** sends a request event, it should include a `v` tag with the version it is using. This tag should contain the highest version that the **client application** supports
and is compatible with the **wallet service**. The version MUST be supported by the **wallet service** as indicated by the info event. For example, if the client application supports version 1.2,
the request event might look like:
```jsonc
{
"kind": 23194,
"tags": [
["v", "1.2"], // Version tag
// ...
],
// ...
}
```
If the **wallet service** does not support the specified version, it will return an `UNSUPPORTED_VERSION` error. Absence of the `v` tag indicates use of version 0.
### Changelog
- **0.0**:
- Initial version using the protocol as defined at commit hash `e655247`. Uses NIP-04 for encryption.
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.