4.8 KiB
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 requests2
: The offer string
Process Flow
-
Payer Scans or Clicks the Static Payment Code
-
Payers wallet decodes the payment code
-
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
-
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
-
Payer Pays the Invoice
- The payer completes the payment by settling the Lightning invoice.
-
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 detailstags
:p
: Receiver's public key (encoded in hex)relay
: URL of the relay for receiving payment requestsoffer
: Unique identifier for the payment purpose
Example event:
{
"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:
{
"offer_id": "<offer_id>",
"payer_data": "<payer_data>"
}
Client Behavior
Clients implementing this NIP must:
- Decode and validate the structure of the
noffer
bech32-encoded static payment code. - Use NIP-44 encryption for all communication between payer and receiver.
- Generate and send kind 21001 events as specified in this NIP.
- Parse the
content
field of received events by decrypting and JSON-parsing the stringified content. - Handle potential errors gracefully, providing clear feedback to users.
- Respect the
relay
tag specified in the static payment code for sending payment request events.
Clients implementing this NIP may:
- Support both this protocol and LNURL for backward compatibility during the transition period.
- Implement additional features such as multi-recipient payments or integration with other Lightning-related NIPs.
Clients implementing this NIP MUST NOT:
- Send unencrypted sensitive information in event content or tags.
- 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:
- Multi-recipient payments
- Integration with other Lightning-related NIPs
- Extended metadata for more complex payment scenarios
Reference Implementation
Lightning.Pub / ShockWallet offers branch