mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-11-14 15:59:07 -05:00
123 lines
4.8 KiB
Markdown
123 lines
4.8 KiB
Markdown
|
NIP-69
|
||
|
======
|
||
|
|
||
|
Nostr Offer STRings
|
||
|
-------------------
|
||
|
|
||
|
`wip` `optional`
|
||
|
|
||
|
This NIP proposes a format for static payment codes in Nostr as a successor to LNURL-Pay, enabling users to initiate Lightning Network payments by scanning or clicking a string.
|
||
|
|
||
|
## Motivation
|
||
|
|
||
|
Reliance on LNURL has led to centralization via custodial solutions due to the legacy baggage of IP4-NAT/Domain/SSL requirements. Nostr's use-cases are already centered around Lightning, whether as a wallet connector, zap receipts, or its overlapping network effects, rendering Nostr as a de facto "3rd layer" for Lightning and a natural successor to LNURL.
|
||
|
|
||
|
When layered over kind 21000, NWC, or other potential Lightning RPCs, this specification enables a seamless user experience similar to legacy LNURL-Pay, without the domain and SSL requirements. Additionally, the signed nature of Nostr communications eliminates the trust requirements inherent in LNURL when a node must outsource the serving of web requests.
|
||
|
|
||
|
## Specification
|
||
|
|
||
|
### Static Payment Code Format
|
||
|
|
||
|
The static payment code is a bech32 (per NIP-19) encoded string prefixed with `noffer`. The encoded string will include the following TLV (Type-Length-Value) items:
|
||
|
|
||
|
- `0`: The 32 bytes of the receiving services public key, encoded in hex.
|
||
|
- `1`: The relay URL where the receiving service subscribes to payment requests
|
||
|
- `2`: The offer string
|
||
|
|
||
|
## Process Flow
|
||
|
|
||
|
1. **Payer Scans or Clicks the Static Payment Code**
|
||
|
|
||
|
2. **Payers wallet decodes the payment code**
|
||
|
|
||
|
3. **Payers wallet sends a Nostr event to the specified relay, addressed to the receiver's public key, containing the identifier string.**
|
||
|
- Event Type: Ephemeral Kind 21001 | NIP-44 Encrypted
|
||
|
- Optional: Include additional payer data
|
||
|
|
||
|
4. **Receiver Responds with Lightning Invoice**
|
||
|
- Upon receiving the payment request event, the receiver generates a Lightning invoice and responds with a Nostr event containing the invoice details.
|
||
|
- Event Type: Ephemeral Kind 21001 | NIP-44 Encrypted
|
||
|
- Optional: Include additional purchase data
|
||
|
|
||
|
5. **Payer Pays the Invoice**
|
||
|
- The payer completes the payment by settling the Lightning invoice.
|
||
|
|
||
|
6. **Optional: Receiver Emits Payment Receipt**
|
||
|
- This step is out of scope for this NIP, but potential receipt considerations include:
|
||
|
a. Nostr Event as Receipt: Emitting a public Nostr event as a "zap" receipt for verifiable record-keeping.
|
||
|
b. Lightning Pre-Image: Sharing the Lightning pre-image as proof of payment.
|
||
|
c. External / WebHook: The receiver may finalize the flow out-of-band.
|
||
|
|
||
|
### Nostr Event
|
||
|
|
||
|
This NIP specifies the use of event kind `21001` with the following structure:
|
||
|
|
||
|
- `content`: NIP-44 encrypted payment details
|
||
|
- `tags`:
|
||
|
- `p`: Receiver's public key (encoded in hex)
|
||
|
- `relay`: URL of the relay for receiving payment requests
|
||
|
- `offer`: Unique identifier for the payment purpose
|
||
|
|
||
|
Example event:
|
||
|
```json
|
||
|
{
|
||
|
"id": "<event_id>",
|
||
|
"pubkey": "<sender_pubkey>",
|
||
|
"created_at": 1234567890,
|
||
|
"kind": 21001,
|
||
|
"tags": [
|
||
|
["p", "<receiver_pubkey>"],
|
||
|
["e", "<event_id>"] // used only in response by the receiver to identify the original payment request
|
||
|
],
|
||
|
"content": "<NIP-44 encrypted offer id and optional payer data>",
|
||
|
"sig": "<signature>"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The `content` field should contain a stringified JSON object with the following structure:
|
||
|
|
||
|
```json
|
||
|
{
|
||
|
"offer_id": "<offer_id>",
|
||
|
"payer_data": "<payer_data>"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Client Behavior
|
||
|
|
||
|
Clients implementing this NIP must:
|
||
|
|
||
|
1. Decode and validate the structure of the `noffer` bech32-encoded static payment code.
|
||
|
2. Use NIP-44 encryption for all communication between payer and receiver.
|
||
|
3. Generate and send kind 21001 events as specified in this NIP.
|
||
|
4. Parse the `content` field of received events by decrypting and JSON-parsing the stringified content.
|
||
|
5. Handle potential errors gracefully, providing clear feedback to users.
|
||
|
6. Respect the `relay` tag specified in the static payment code for sending payment request events.
|
||
|
|
||
|
Clients implementing this NIP may:
|
||
|
|
||
|
1. Support both this protocol and LNURL for backward compatibility during the transition period.
|
||
|
2. Implement additional features such as multi-recipient payments or integration with other Lightning-related NIPs.
|
||
|
|
||
|
Clients implementing this NIP MUST NOT:
|
||
|
|
||
|
1. Send unencrypted sensitive information in event content or tags.
|
||
|
2. Ignore or modify any fields from the encoded static payment code.
|
||
|
|
||
|
## Notes
|
||
|
|
||
|
### Transition from LNURL
|
||
|
|
||
|
LNURL services wishing to migrate to Nostr Offer STRings should consider adding a `noffer` tag to their responses.
|
||
|
|
||
|
### Future Considerations
|
||
|
|
||
|
Future versions of this NIP may consider additional features such as:
|
||
|
|
||
|
1. Multi-recipient payments
|
||
|
2. Integration with other Lightning-related NIPs
|
||
|
3. Extended metadata for more complex payment scenarios
|
||
|
|
||
|
## Reference Implementation
|
||
|
|
||
|
Lightning.Pub / ShockWallet offers branch
|