From 62c18d5bbee7bf04dbb1b9fb5df22417d406ae53 Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Mon, 3 Mar 2025 23:15:33 +0700 Subject: [PATCH 1/2] docs: NIP-47 client-created secret --- 47.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/47.md b/47.md index 84f710e2..5c66133e 100644 --- a/47.md +++ b/47.md @@ -111,6 +111,8 @@ The content of notifications is encrypted with [NIP04](04.md), and is a JSON-RPC Communication between the **client** and **wallet service** requires two keys in order to encrypt and decrypt messages. The connection URI includes the secret key of the **client** and only the public key of the **wallet service**. +> This is the original flow for initiating a NWC connection, however is less secure and prone to user error as the secret must be copy-pasted into the **client** to initiate the connection. Please see the client-created secret flows below as an alternative. + The **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 its 32-byte hex-encoded `pubkey`, which SHOULD be unique per client connection. @@ -135,6 +137,95 @@ The **client** should then store this connection and use it when the user wants nostr+walletconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&secret=71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c ``` +## Client-Created Secret + +The client MAY generate its own secret and co-ordinate only public keys with the wallet service so that secrets are never exposed. + +### HTTP Confirmation Page + +A **wallet service** MAY host a publicly accessible confirmation page that the **client** may open (e.g. in a webview or popup window) and allow the **user** to confirm the creation of a new connection, with the following parameters: + +- `pubkey` Required. The corresponding pubkey of the secret generated by the **client**. + +The **wallet service** MAY ignore all the below optional parameters. + +- `name`: Optional. The name of the client app. +- `icon`: Optional. The URL of an icon of the client app to display on the confirmation page. +- `return_to` Optional. URI to open after the connection is created. The **wallet service** SHOULD add the `relay_url`, `wallet_pubkey` and `lud16` parameters to the URI. +- `expires_at` Optional. The connection cannot be used after this date. Unix timestamp in seconds. +- `max_amount` Optional. The maximum amount in millisats that can be sent per renewal period +- `budget_renewal` Optional. The reset the budget at the end of the given budget renewal. Can be `never` (default), `daily`, `weekly`, `monthly`, `yearly` +- `request_methods` Optional. The url encoded, space separated list of request types that you need permission for. For example: `..&request_methods=pay_invoice%20get_balance` +- `notification_types` Optional. The url encoded, space separated list of notification types that you need permission for. For example: `..¬ification_types=payment_received%20payment_sent` +- `isolated` Optional. The makes an isolated app connection / sub-wallet with its own balance and only access to its own transaction list. e.g. `&isolated=true`. +- `metadata` Optional. Url encoded, JSON-serialized metadata that describes the app connection. + +The **user** MUST be presented with a confirmation page to be able to review and approve or decline the connection. + +If the **user** approves the request, a new connection should be created for **client**'s public key (specified in the `pubkey` parameter). + +#### Communicating the wallet pubkey and relay to the client via popup/webview + +The confirmation page MAY dispatch an event and post a message to the window and window opener (if present) so that the **client** can discover the pubkey and preferred relay url of the **wallet service**. + +```javascript +window.dispatchEvent(new CustomEvent("nwc:success", { + detail: { + relayUrl, + walletPubkey, + lud16, // optional + }, +})); + +window.opener?.postMessage({ + type: "nwc:success", + relayUrl, + walletPubkey, + lud16, // optional +}, "*"); +``` + +At this point, both the **client** and **wallet service** have all information required to communicate over NWC. + +#### Example HTTP confirmation URL + +`https://example.com/connections/new?pubkey=b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4` + +### Nostr Flow + +The **client** MAY generate an authorization URI with protocol `nostr+walletauth://` and base path its hex-encoded `pubkey` with the following query string parameters: + +- `relay` Required. URL of the relay where the **client** intends to communicate with the **wallet service**. May be more than one. + +The **wallet service** MAY ignore all the below optional parameters. + +- `name`: Optional. The name of the client app. +- `icon`: Optional. The URL of an icon of the client app to display on the confirmation page. +- `return_to` Optional. URI to open after the connection is created. +- `expires_at` Optional. The connection cannot be used after this date. Unix timestamp in seconds. +- `max_amount` Optional. The maximum amount in millisats that can be sent per renewal period +- `budget_renewal` Optional. The reset the budget at the end of the given budget renewal. Can be `never` (default), `daily`, `weekly`, `monthly`, `yearly` +- `request_methods` Optional. The url encoded, space separated list of request types that you need permission for. For example: `..&request_methods=pay_invoice%20get_balance` +- `notification_types` Optional. The url encoded, space separated list of notification types that you need permission for. For example: `..¬ification_types=payment_received%20payment_sent` +- `isolated` Optional. The makes an isolated app connection / sub-wallet with its own balance and only access to its own transaction list. e.g. `&isolated=true`. +- `metadata` Optional. Url encoded, JSON-serialized metadata that describes the app connection. + +The **user** opens the URL in the **wallet service** by scanning a QR code, handling a deeplink or pasting in a URI, and MUST be presented with a confirmation page. + +If the **user** approves the request, a new connection should be created for the **client**'s public key (specified in the base path of the authorization URI). Once the connection is created, the NIP-47 info event MUST be broadcasted to the relays specified in the authorization URI, and the info event MUST include a `p` tag containing the public key of the **client** this info is for, so that the **client** can discover the public key of the **wallet service**. The `p` tag MAY contain the recommended relay url of the **wallet service**. + +The **client** is then able to subscribe to the NIP-47 info event (kind 13194) filtered by setting the `p` tag to the pubkey of the **client**. The **client** will then know the public key of the **wallet service** (as the publisher of the info event). + +At this point, both the **client** and **wallet service** have all information required to communicate over NWC. + +The `lud16` field cannot be immediately communicated via the NIP-47 event to avoid metadata leaks. To discover the lightning address, the **client** MAY look for the presence of the `lud16` parameter in the `get_info` response. + +#### Example Authorization URI + +`nostr+walletauth://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.example.com%2Fv1` + +To target a specific wallet, a `nostr+walletauth+walletname` scheme may be used. + ## Commands ### `pay_invoice` @@ -436,6 +527,7 @@ Response: "block_hash": "hex string", "methods": ["pay_invoice", "get_balance", "make_invoice", "lookup_invoice", "list_transactions", "get_info"], // list of supported methods for this connection "notifications": ["payment_received", "payment_sent"], // list of supported notifications for this connection, optional. + "lud16": "string" // lightning address for this connection, optional } } ``` @@ -516,7 +608,8 @@ This NIP does not specify any requirements on the type of relays used. However, [ "notifications", "payment_received payment_sent" - ] + ], + ["p", "3ba6db4896124383fdaa5f7d42c25f9df1b128a280928baeb3f3fa36d25506f9"] ], "content": "pay_invoice pay_keysend get_balance get_info make_invoice lookup_invoice list_transactions multi_pay_invoice multi_pay_keysend sign_message notifications", "sig": "31f57b369459b5306a5353aa9e03be7fbde169bc881c3233625605dd12f53548179def16b9fe1137e6465d7e4d5bb27ce81fd6e75908c46b06269f4233c845d8" From 89fe83d5ebb7755a021c68b0aa643f79706f01aa Mon Sep 17 00:00:00 2001 From: Roland Bewick Date: Thu, 31 Jul 2025 20:58:39 +0700 Subject: [PATCH 2/2] docs: clarify usage of recommended relay url --- 47.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/47.md b/47.md index 5c66133e..4f6038b0 100644 --- a/47.md +++ b/47.md @@ -212,7 +212,7 @@ The **wallet service** MAY ignore all the below optional parameters. The **user** opens the URL in the **wallet service** by scanning a QR code, handling a deeplink or pasting in a URI, and MUST be presented with a confirmation page. -If the **user** approves the request, a new connection should be created for the **client**'s public key (specified in the base path of the authorization URI). Once the connection is created, the NIP-47 info event MUST be broadcasted to the relays specified in the authorization URI, and the info event MUST include a `p` tag containing the public key of the **client** this info is for, so that the **client** can discover the public key of the **wallet service**. The `p` tag MAY contain the recommended relay url of the **wallet service**. +If the **user** approves the request, a new connection should be created for the **client**'s public key (specified in the base path of the authorization URI). Once the connection is created, the NIP-47 info event MUST be broadcasted to the relays specified in the authorization URI, and the info event MUST include a `p` tag containing the public key of the **client** this info is for, so that the **client** can discover the public key of the **wallet service**. The `p` tag MAY contain the recommended relay url of the **wallet service**. If provided, the recommended relay url MUST be used. The **client** is then able to subscribe to the NIP-47 info event (kind 13194) filtered by setting the `p` tag to the pubkey of the **client**. The **client** will then know the public key of the **wallet service** (as the publisher of the info event).