diff options
| author | frnandu <frnandu@atomicmail.io> | 2026-02-03 19:41:08 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-03 13:41:08 -0500 |
| commit | 01838f302ddf639b2cfc1bfbe6232401e82eac58 (patch) | |
| tree | e80530498a051cf421c3f08f45c51d6a2e8199fa /47.md | |
| parent | 90a60bd210670787afb1f14caab8fd8d70028ea6 (diff) | |
NIP-47 Add Hold Invoice Support (#1913)
Co-authored-by: Fmar <frnandu@gmail.com>
Co-authored-by: Roland <33993199+rolznz@users.noreply.github.com>
Diffstat (limited to '47.md')
| -rw-r--r-- | 47.md | 121 |
1 files changed, 119 insertions, 2 deletions
| @@ -371,7 +371,7 @@ Response: | |||
| 371 | "result_type": "lookup_invoice", | 371 | "result_type": "lookup_invoice", |
| 372 | "result": { | 372 | "result": { |
| 373 | "type": "incoming", // "incoming" for invoices, "outgoing" for payments | 373 | "type": "incoming", // "incoming" for invoices, "outgoing" for payments |
| 374 | "state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments), optional | 374 | "state": "pending", // can be "pending", "settled", "accepted" (for hold invoices), "expired" (for invoices) or "failed" (for payments), optional |
| 375 | "invoice": "string", // encoded invoice, optional | 375 | "invoice": "string", // encoded invoice, optional |
| 376 | "description": "string", // invoice's description, optional | 376 | "description": "string", // invoice's description, optional |
| 377 | "description_hash": "string", // invoice's description hash, optional | 377 | "description_hash": "string", // invoice's description hash, optional |
| @@ -420,7 +420,7 @@ Response: | |||
| 420 | "transactions": [ | 420 | "transactions": [ |
| 421 | { | 421 | { |
| 422 | "type": "incoming", // "incoming" for invoices, "outgoing" for payments | 422 | "type": "incoming", // "incoming" for invoices, "outgoing" for payments |
| 423 | "state": "pending", // can be "pending", "settled", "expired" (for invoices) or "failed" (for payments), optional | 423 | "state": "pending", // can be "pending", "settled", "accepted" (for hold invoices), "expired" (for invoices) or "failed" (for payments), optional |
| 424 | "invoice": "string", // encoded invoice, optional | 424 | "invoice": "string", // encoded invoice, optional |
| 425 | "description": "string", // invoice's description, optional | 425 | "description": "string", // invoice's description, optional |
| 426 | "description_hash": "string", // invoice's description hash, optional | 426 | "description_hash": "string", // invoice's description hash, optional |
| @@ -485,6 +485,89 @@ Response: | |||
| 485 | } | 485 | } |
| 486 | ``` | 486 | ``` |
| 487 | 487 | ||
| 488 | ### `make_hold_invoice` | ||
| 489 | |||
| 490 | Creates a hold invoice using a pre-generated preimage. | ||
| 491 | |||
| 492 | Request: | ||
| 493 | ```jsonc | ||
| 494 | { | ||
| 495 | "method": "make_hold_invoice", | ||
| 496 | "params": { | ||
| 497 | "amount": 123, // value in msats | ||
| 498 | "description": "string", // invoice's description, optional | ||
| 499 | "description_hash": "string", // invoice's description hash, optional | ||
| 500 | "expiry": 213 // expiry in seconds from time invoice is created for a payment to be initiated, optional. This does not determine how long a payment can be held (see `settle_deadline`) | ||
| 501 | "payment_hash": "string" // Payment hash for the payment generated from the preimage | ||
| 502 | "min_cltv_expiry_delta": 144 // The minimum CLTV delta to use for the final hop, optional | ||
| 503 | } | ||
| 504 | } | ||
| 505 | ``` | ||
| 506 | |||
| 507 | Response: | ||
| 508 | ```jsonc | ||
| 509 | { | ||
| 510 | "result_type": "make_hold_invoice", | ||
| 511 | "result": { | ||
| 512 | "type": "incoming", // "incoming" for invoices, "outgoing" for payments | ||
| 513 | "invoice": "string", // encoded invoice, optional | ||
| 514 | "description": "string", // invoice's description, optional | ||
| 515 | "description_hash": "string", // invoice's description hash, optional | ||
| 516 | "payment_hash": "string", // Payment hash for the payment | ||
| 517 | "amount": 123, // value in msats | ||
| 518 | "created_at": unixtimestamp, // invoice/payment creation time | ||
| 519 | "expires_at": unixtimestamp, // invoice expiration time, optional if not applicable | ||
| 520 | "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc. | ||
| 521 | } | ||
| 522 | } | ||
| 523 | ``` | ||
| 524 | |||
| 525 | ### `cancel_hold_invoice` | ||
| 526 | |||
| 527 | Cancels a hold invoice using the payment hash | ||
| 528 | |||
| 529 | Request: | ||
| 530 | ```jsonc | ||
| 531 | { | ||
| 532 | "method": "cancel_hold_invoice", | ||
| 533 | "params": { | ||
| 534 | "payment_hash": "string" // Payment hash for the payment generated from the preimage | ||
| 535 | } | ||
| 536 | } | ||
| 537 | ``` | ||
| 538 | |||
| 539 | Response: | ||
| 540 | ```jsonc | ||
| 541 | { | ||
| 542 | "result_type": "cancel_hold_invoice", | ||
| 543 | "result": {} | ||
| 544 | } | ||
| 545 | ``` | ||
| 546 | |||
| 547 | ### `settle_hold_invoice` | ||
| 548 | |||
| 549 | Settles a hold invoice using the preimage | ||
| 550 | |||
| 551 | |||
| 552 | Request: | ||
| 553 | ```jsonc | ||
| 554 | { | ||
| 555 | "method": "settle_hold_invoice", | ||
| 556 | "params": { | ||
| 557 | "preimage": "string" // preimage for the payment | ||
| 558 | } | ||
| 559 | } | ||
| 560 | ``` | ||
| 561 | |||
| 562 | Response: | ||
| 563 | ```jsonc | ||
| 564 | { | ||
| 565 | "result_type": "settle_hold_invoice", | ||
| 566 | "result": {} | ||
| 567 | } | ||
| 568 | ``` | ||
| 569 | |||
| 570 | |||
| 488 | ## Notifications | 571 | ## Notifications |
| 489 | 572 | ||
| 490 | ### `payment_received` | 573 | ### `payment_received` |
| @@ -539,6 +622,30 @@ Notification: | |||
| 539 | } | 622 | } |
| 540 | ``` | 623 | ``` |
| 541 | 624 | ||
| 625 | ### `hold_invoice_accepted` | ||
| 626 | |||
| 627 | Description: Sent when a payer accepts (locks in) a hold invoice. To avoid locking up funds in channels the hold invoice SHOULD be settled or canceled within a few minutes of receiving this event. | ||
| 628 | |||
| 629 | Notification: | ||
| 630 | ```jsonc | ||
| 631 | { | ||
| 632 | "notification_type": "hold_invoice_accepted", | ||
| 633 | "notification": { | ||
| 634 | "type": "incoming", | ||
| 635 | "state": "accepted", // optional | ||
| 636 | "invoice": "string", // encoded invoice | ||
| 637 | "description": "string", // invoice's description, optional | ||
| 638 | "description_hash": "string", // invoice's description hash, optional | ||
| 639 | "payment_hash": "string", // Payment hash for the payment | ||
| 640 | "amount": 123, // value in msats | ||
| 641 | "created_at": unixtimestamp, // invoice/payment creation time | ||
| 642 | "expires_at": unixtimestamp, // invoice expiration time | ||
| 643 | "settle_deadline": blocknumber, // invoice can only be safely settled or canceled before this block number. | ||
| 644 | "metadata": {} // generic metadata that can be used to add things like zap/boostagram details for a payer name/comment/etc. | ||
| 645 | } | ||
| 646 | } | ||
| 647 | ``` | ||
| 648 | |||
| 542 | ## Example pay invoice flow | 649 | ## Example pay invoice flow |
| 543 | 650 | ||
| 544 | 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. | 651 | 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. |
| @@ -668,6 +775,16 @@ Here are some properties that are recognized by some NWC clients: | |||
| 668 | } | 775 | } |
| 669 | ``` | 776 | ``` |
| 670 | 777 | ||
| 778 | ### Example Hold Invoice Support Flow | ||
| 779 | |||
| 780 | 1. Client generates a 32-byte hex-encoded preimage. | ||
| 781 | 2. Computes SHA-256 to derive payment hash. | ||
| 782 | 3. Sends `make_hold_invoice` with payment hash and desired parameters. | ||
| 783 | 4. Waits for `hold_invoice_accepted` notification. | ||
| 784 | 5. Upon receiving notification, either: | ||
| 785 | |||
| 786 | * Calls `settle_hold_invoice` with the original preimage to release funds, or | ||
| 787 | * Calls `cancel_hold_invoice` with payment hash to abort. | ||
| 671 | ### Deep-links | 788 | ### Deep-links |
| 672 | 789 | ||
| 673 | Wallet applications can register deeplinks in mobile systems to make it possible to create a linking UX that doesn't require the user scanning a QR code or pasting some code. | 790 | Wallet applications can register deeplinks in mobile systems to make it possible to create a linking UX that doesn't require the user scanning a QR code or pasting some code. |