upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--47.md128
1 files changed, 116 insertions, 12 deletions
diff --git a/47.md b/47.md
index 9033847..97b06ab 100644
--- a/47.md
+++ b/47.md
@@ -8,32 +8,42 @@ Nostr Wallet Connect
8 8
9## Rationale 9## Rationale
10 10
11This 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. 11This 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.
12 12
13## Terms 13## Terms
14 14
15* **client**: Nostr app on any platform that wants to pay Lightning invoices. 15* **client**: Nostr app on any platform that wants to interact with a lightning wallet.
16* **user**: The person using the **client**, and want's to connect their wallet app to their **client**. 16* **user**: The person using the **client**, and wants to connect their wallet to their **client**.
17* **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. 17* **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.
18 18
19## Theory of Operation 19## Theory of Operation
20 1. **Users** who wish 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. 20 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.
21 21
22 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. 22 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.
23 23
24 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. 24 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.
25 25
26 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. 26 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.
27
28 5. The **wallet service** may send encrypted notifications (kind 23196) of wallet events (such as a received payment) to the **client**.
27 29
28## Events 30## Events
29 31
30There are three event kinds: 32There are four event kinds:
31- `NIP-47 info event`: 13194 33- `NIP-47 info event`: 13194
32- `NIP-47 request`: 23194 34- `NIP-47 request`: 23194
33- `NIP-47 response`: 23195 35- `NIP-47 response`: 23195
36- `NIP-47 notification event`: 23196
37
38### Info Event
39
40The info event should be a replaceable event that is published by the **wallet service** on the relay to indicate which capabilities it supports.
41
42The content should be a plaintext string with the supported capabilities space-separated, eg. `pay_invoice get_balance notifications`.
34 43
35The 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 44If 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`.
36a plaintext string with the supported commands, space-separated, eg. `pay_invoice get_balance`. Only the `pay_invoice` command is described in this NIP, but other commands might be defined in different NIPs. 45
46### Request and Response Events
37 47
38Both 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. 48Both 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.
39Optionally, 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. 49Optionally, 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.
@@ -68,6 +78,22 @@ The `result_type` field MUST contain the name of the method that this event is r
68The `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. 78The `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.
69If the command was successful, the `error` field must be null. 79If the command was successful, the `error` field must be null.
70 80
81### Notification Events
82
83The notification event SHOULD contain one `p` tag, the public key of the **user**.
84
85The 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:
86
87```jsonc
88{
89 "notification_type": "payment_received", //indicates the structure of the notification field
90 "notification": {
91 "payment_hash": "0123456789abcdef..." // notification-related data
92 }
93}
94```
95
96
71### Error codes 97### Error codes
72- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds. 98- `RATE_LIMITED`: The client is sending commands too fast. It should retry in a few seconds.
73- `NOT_IMPLEMENTED`: The command is not known or is intentionally not implemented. 99- `NOT_IMPLEMENTED`: The command is not known or is intentionally not implemented.
@@ -120,7 +146,8 @@ Response:
120{ 146{
121 "result_type": "pay_invoice", 147 "result_type": "pay_invoice",
122 "result": { 148 "result": {
123 "preimage": "0123456789abcdef..." // preimage of the payment 149 "preimage": "0123456789abcdef...", // preimage of the payment
150 "fees_paid": 123, // value in msats, optional
124 } 151 }
125} 152}
126``` 153```
@@ -155,7 +182,8 @@ payment hash of the invoice should be used.
155{ 182{
156 "result_type": "multi_pay_invoice", 183 "result_type": "multi_pay_invoice",
157 "result": { 184 "result": {
158 "preimage": "0123456789abcdef..." // preimage of the payment 185 "preimage": "0123456789abcdef...", // preimage of the payment
186 "fees_paid": 123, // value in msats, optional
159 } 187 }
160} 188}
161``` 189```
@@ -189,6 +217,7 @@ Response:
189 "result_type": "pay_keysend", 217 "result_type": "pay_keysend",
190 "result": { 218 "result": {
191 "preimage": "0123456789abcdef...", // preimage of the payment 219 "preimage": "0123456789abcdef...", // preimage of the payment
220 "fees_paid": 123, // value in msats, optional
192 } 221 }
193} 222}
194``` 223```
@@ -225,7 +254,8 @@ pubkey should be used.
225{ 254{
226 "result_type": "multi_pay_keysend", 255 "result_type": "multi_pay_keysend",
227 "result": { 256 "result": {
228 "preimage": "0123456789abcdef..." // preimage of the payment 257 "preimage": "0123456789abcdef...", // preimage of the payment
258 "fees_paid": 123, // value in msats, optional
229 } 259 }
230} 260}
231``` 261```
@@ -396,6 +426,59 @@ Response:
396 "block_height": 1, 426 "block_height": 1,
397 "block_hash": "hex string", 427 "block_hash": "hex string",
398 "methods": ["pay_invoice", "get_balance", "make_invoice", "lookup_invoice", "list_transactions", "get_info"], // list of supported methods for this connection 428 "methods": ["pay_invoice", "get_balance", "make_invoice", "lookup_invoice", "list_transactions", "get_info"], // list of supported methods for this connection
429 "notifications": ["payment_received", "payment_sent"], // list of supported notifications for this connection, optional.
430 }
431}
432```
433
434## Notifications
435
436### `payment_received`
437
438Description: A payment was successfully received by the wallet.
439
440Notification:
441```jsonc
442{
443 "notification_type": "payment_received",
444 "notification": {
445 "type": "incoming",
446 "invoice": "string", // encoded invoice
447 "description": "string", // invoice's description, optional
448 "description_hash": "string", // invoice's description hash, optional
449 "preimage": "string", // payment's preimage
450 "payment_hash": "string", // Payment hash for the payment
451 "amount": 123, // value in msats
452 "fees_paid": 123, // value in msats
453 "created_at": unixtimestamp, // invoice/payment creation time
454 "expires_at": unixtimestamp, // invoice expiration time, optional if not applicable
455 "settled_at": unixtimestamp, // invoice/payment settlement time
456 "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc.
457 }
458}
459```
460
461### `payment_sent`
462
463Description: A payment was successfully sent by the wallet.
464
465Notification:
466```jsonc
467{
468 "notification_type": "payment_sent",
469 "notification": {
470 "type": "outgoing",
471 "invoice": "string", // encoded invoice
472 "description": "string", // invoice's description, optional
473 "description_hash": "string", // invoice's description hash, optional
474 "preimage": "string", // payment's preimage
475 "payment_hash": "string", // Payment hash for the payment
476 "amount": 123, // value in msats
477 "fees_paid": 123, // value in msats
478 "created_at": unixtimestamp, // invoice/payment creation time
479 "expires_at": unixtimestamp, // invoice expiration time, optional if not applicable
480 "settled_at": unixtimestamp, // invoice/payment settlement time
481 "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc.
399 } 482 }
400} 483}
401``` 484```
@@ -409,3 +492,24 @@ Response:
409 492
410## Using a dedicated relay 493## Using a dedicated relay
411This 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. 494This 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.
495
496## Appendix
497
498### Example NIP-47 info event
499
500```jsonc
501{
502 "id": "df467db0a9f9ec77ffe6f561811714ccaa2e26051c20f58f33c3d66d6c2b4d1c",
503 "pubkey": "c04ccd5c82fc1ea3499b9c6a5c0a7ab627fbe00a0116110d4c750faeaecba1e2",
504 "created_at": 1713883677,
505 "kind": 13194,
506 "tags": [
507 [
508 "notifications",
509 "payment_received payment_sent"
510 ]
511 ],
512 "content": "pay_invoice pay_keysend get_balance get_info make_invoice lookup_invoice list_transactions multi_pay_invoice multi_pay_keysend sign_message notifications",
513 "sig": "31f57b369459b5306a5353aa9e03be7fbde169bc881c3233625605dd12f53548179def16b9fe1137e6465d7e4d5bb27ce81fd6e75908c46b06269f4233c845d8"
514}
515```