mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-13 19:06:24 +00:00
113 lines
4.7 KiB
Markdown
113 lines
4.7 KiB
Markdown
|
NIP-47
|
||
|
======
|
||
|
|
||
|
Nostr Wallet Connect
|
||
|
--------------------
|
||
|
|
||
|
`draft` `optional` `author:kiwiidb` `author:bumi` `author:semisol` `author:vitorpamplona`
|
||
|
|
||
|
## Rationale
|
||
|
|
||
|
Paying zaps should be possible without the user needing to open a different app to only pay a Lightning invoice.
|
||
|
This NIP describes a way for users to control a remote Lightning node or a custodial Lightning wallet. When self-hosting, this setup does not require the user to run their own server, thereby bypassing certain hurdles that are commonly encountered when trying to connect to a Lightning node remotely.
|
||
|
|
||
|
## 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).
|
||
|
|
||
|
## Events
|
||
|
|
||
|
There are two event kinds:
|
||
|
- `NIP-47 request`: 23194
|
||
|
- `NIP-47 response`: 23195
|
||
|
|
||
|
Both the request and response events SHOULD only 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 content is encrypted with [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md), and is a JSON object. The content depends on the kind.
|
||
|
|
||
|
Request:
|
||
|
```jsonc
|
||
|
{
|
||
|
"cmd": "pay_invoice", // command, string
|
||
|
"data": { // data, object
|
||
|
"invoice": "lnbc50n1..." // command-related data
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Response:
|
||
|
```jsonc
|
||
|
{
|
||
|
"status": "ok", // status, "ok" | "error"
|
||
|
"event": "0123456789abcdef...", // event the command is in response to, string
|
||
|
"data": { // response data
|
||
|
"preimage": "0123456789abcdef..." // command-related data
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The data field SHOULD contain a `message` field with a human readable error message if the status is `error`.
|
||
|
|
||
|
## Nostr Wallet Connect URI
|
||
|
**client** discovers **wallet service** by scanning a QR code, handling a deeplink or pasting in a URI.
|
||
|
|
||
|
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:
|
||
|
|
||
|
- `relay` Required. URL of the relay where the **wallet service** is connected and will be listening for events. May be more than one.
|
||
|
- `secret` Required. 32-byte randomly generated hex encoded string. The **client** should use this to sign events when communicating with the **wallet service**.
|
||
|
- Authorization does not require passing keys back and forth.
|
||
|
- 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.
|
||
|
|
||
|
The **client** should then store this connection and use it when the user wants to perform actions like paying an invoice. Optionally it can display metadata about the connected **wallet service** from it's profile (name, image, url).
|
||
|
|
||
|
### Example connection string
|
||
|
```sh
|
||
|
nostrwalletconnect:b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c
|
||
|
```
|
||
|
|
||
|
## Commands
|
||
|
|
||
|
### `pay_invoice`
|
||
|
|
||
|
Description: Requests payment of an invoice.
|
||
|
|
||
|
Request:
|
||
|
```jsonc
|
||
|
{
|
||
|
"invoice": "lnbc50n1..." // BOLT11 invoice, string
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Response:
|
||
|
```jsonc
|
||
|
{
|
||
|
"preimage": "0123456789abcdef..." // preimage after payment, string
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### `balance`
|
||
|
|
||
|
Description: Requests the balance of the wallet.
|
||
|
|
||
|
Request: an empty JSON object.
|
||
|
|
||
|
Response:
|
||
|
```jsonc
|
||
|
{
|
||
|
"balance": 100000 // balance in msat, int
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Example pay invoice flow
|
||
|
|
||
|
0. The user scans the QR code generated by the **wallet service** with their **client** application, they follow a `nostrwalletconnect:` 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.
|
||
|
2. **nostr-wallet-connect-service** verifies that the author's key is authorized to perform the payment, decrypts the payload and sends the payment.
|
||
|
3. **nostr-wallet-connect-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.
|
||
|
|
||
|
## 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.
|