From c2f34817e38353245b17c586946ef2a354bf9a4c Mon Sep 17 00:00:00 2001 From: benthecarman Date: Wed, 6 Dec 2023 02:33:54 -0600 Subject: [PATCH] NIP-47: Nostr Wallet Connect Extensions --- 47.md | 278 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 276 insertions(+), 2 deletions(-) diff --git a/47.md b/47.md index b6a4f2bc..4cef6107 100644 --- a/47.md +++ b/47.md @@ -36,6 +36,7 @@ The info event should be a replaceable event that is published by the **wallet s a 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. 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. The content of requests and responses 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: @@ -108,7 +109,8 @@ Request: { "method": "pay_invoice", "params": { - "invoice": "lnbc50n1..." // bolt11 invoice + "invoice": "lnbc50n1...", // bolt11 invoice + "amount": 123, // invoice amount in msats, optional } } ``` @@ -117,7 +119,7 @@ Response: ```jsonc { "result_type": "pay_invoice", - "result": { + "result": { "preimage": "0123456789abcdef..." // preimage of the payment } } @@ -126,6 +128,278 @@ Response: Errors: - `PAYMENT_FAILED`: The payment failed. This may be due to a timeout, exhausting all routes, insufficient capacity or similar. +### `multi_pay_invoice` + +Description: Requests payment of multiple invoices. + +Request: +```jsonc +{ + "method": "multi_pay_invoice", + "params": { + "invoices": [ + {"id":"4da52c32a1", "invoice": "lnbc1...", "amount": 123}, // bolt11 invoice and amount in msats, amount is optional + {"id":"3da52c32a1", "invoice": "lnbc50n1..."}, + ], + } +} +``` + +Response: + +For every invoice in the request, a separate response event is sent. To differentiate between the responses, each +response event contains an `d` tag with the id of the invoice it is responding to, if no id was given, then the +payment hash of the invoice should be used. + +```jsonc +{ + "result_type": "multi_pay_invoice", + "result": { + "preimage": "0123456789abcdef..." // preimage of the payment + } +} +``` + +Errors: +- `PAYMENT_FAILED`: The payment failed. This may be due to a timeout, exhausting all routes, insufficient capacity or similar. + +### `pay_keysend` + +Request: +```jsonc +{ + "method": "pay_keysend", + "params": { + "amount": 123, // invoice amount in msats, required + "pubkey": "03...", // payee pubkey, required + "preimage": "0123456789abcdef...", // preimage of the payment, optional + "tlv_records: [ // tlv records, optional + { + "type": 5482373484, // tlv type + "value": "0123456789abcdef" // hex encoded tlv value + } + ] + } +} +``` + +Response: +```jsonc +{ + "result_type": "pay_keysend", + "result": { + "preimage": "0123456789abcdef...", // preimage of the payment + } +} +``` + +Errors: +- `PAYMENT_FAILED`: The payment failed. This may be due to a timeout, exhausting all routes, insufficient capacity or similar. + +### `multi_pay_keysend` + +Description: Requests multiple keysend payments. + +Has an array of keysends, these follow the same semantics as `pay_keysend`, just done in a batch + +Request: +```jsonc +{ + "method": "multi_pay_keysend", + "params": { + "keysends": [ + {"id": "4c5b24a351", pubkey": "03...", "amount": 123}, + {"id": "3da52c32a1", "pubkey": "02...", "amount": 567, "preimage": "abc123..", "tlv_records": [{"type": 696969, "value": "77616c5f6872444873305242454d353736"}]}, + ], + } +} +``` + +Response: + +For every keysend in the request, a separate response event is sent. To differentiate between the responses, each +response event contains an `d` tag with the id of the keysend it is responding to, if no id was given, then the +pubkey should be used. + +```jsonc +{ + "result_type": "multi_pay_keysend", + "result": { + "preimage": "0123456789abcdef..." // preimage of the payment + } +} +``` + +Errors: +- `PAYMENT_FAILED`: The payment failed. This may be due to a timeout, exhausting all routes, insufficient capacity or similar. + +### `make_invoice` + +Request: +```jsonc +{ + "method": "make_invoice", + "params": { + "amount": 123, // value in msats + "description": "string", // invoice's description, optional + "description_hash": "string", // invoice's description hash, optional + "expiry": 213 // expiry in seconds from time invoice is created, optional + } +} +``` + +Response: +```jsonc +{ + "result_type": "make_invoice", + "result": { + "type": "incoming", // "incoming" for invoices, "outgoing" for payments + "invoice": "string", // encoded invoice, optional + "description": "string", // invoice's description, optional + "description_hash": "string", // invoice's description hash, optional + "preimage": "string", // payment's preimage, optional if unpaid + "payment_hash": "string", // Payment hash for the payment + "amount": 123, // value in msats + "fees_paid": 123, // value in msats + "created_at": unixtimestamp, // invoice/payment creation time + "expires_at": unixtimestamp, // invoice expiration time, optional if not applicable + "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc. + } +} +``` + +### `lookup_invoice` + +Request: +```jsonc +{ + "method": "lookup_invoice", + "params": { + "payment_hash": "31afdf1..", // payment hash of the invoice, one of payment_hash or invoice is required + "invoice": "lnbc50n1..." // invoice to lookup + } +} +``` + +Response: +```jsonc +{ + "result_type": "lookup_invoice", + "result": { + "type": "incoming", // "incoming" for invoices, "outgoing" for payments + "invoice": "string", // encoded invoice, optional + "description": "string", // invoice's description, optional + "description_hash": "string", // invoice's description hash, optional + "preimage": "string", // payment's preimage, optional if unpaid + "payment_hash": "string", // Payment hash for the payment + "amount": 123, // value in msats + "fees_paid": 123, // value in msats + "created_at": unixtimestamp, // invoice/payment creation time + "expires_at": unixtimestamp, // invoice expiration time, optional if not applicable + "settled_at": unixtimestamp, // invoice/payment settlement time, optional if unpaid + "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc. + } +} +``` + +Errors: +- `NOT_FOUND`: The invoice could not be found by the given parameters. + +### `list_transactions` + +Lists invoices and payments. If `type` is not specified, both invoices and payments are returned. +The `from` and `until` parameters are timestamps in seconds since epoch. If `from` is not specified, it defaults to 0. +If `until` is not specified, it defaults to the current time. Transactions are returned in descending order of creation +time. + +Request: +```jsonc +{ + "method": "list_transactions", + "params": { + "from": 1693876973, // starting timestamp in seconds since epoch (inclusive), optional + "until": 1703225078, // ending timestamp in seconds since epoch (inclusive), optional + "limit": 10, // maximum number of invoices to return, optional + "offset": 0, // offset of the first invoice to return, optional + "unpaid": true, // include unpaid invoices, optional, default false + "type": "incoming", // "incoming" for invoices, "outgoing" for payments, undefined for both + } +} +``` + +Response: +```jsonc +{ + "result_type": "list_transactions", + "result": { + "transactions": [ + { + "type": "incoming", // "incoming" for invoices, "outgoing" for payments + "invoice": "string", // encoded invoice, optional + "description": "string", // invoice's description, optional + "description_hash": "string", // invoice's description hash, optional + "preimage": "string", // payment's preimage, optional if unpaid + "payment_hash": "string", // Payment hash for the payment + "amount": 123, // value in msats + "fees_paid": 123, // value in msats + "created_at": unixtimestamp, // invoice/payment creation time + "expires_at": unixtimestamp, // invoice expiration time, optional if not applicable + "settled_at": unixtimestamp, // invoice/payment settlement time, optional if unpaid + "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc. + } + ], + }, +} +``` + +### `get_balance` + +Request: +```jsonc +{ + "method": "get_balance", + "params": { + } +} +``` + +Response: +```jsonc +{ + "result_type": "get_balance", + "result": { + "balance": 10000, // user's balance in msats + } +} +``` + +### `get_info` + +Request: +```jsonc +{ + "method": "get_info", + "params": { + } +} +``` + +Response: +```jsonc +{ + "result_type": "get_info", + "result": { + "alias": "string", + "color": "hex string", + "pubkey": "hex string", + "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 + } +} +``` + ## Example pay invoice flow 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.