Nostr. NIP57
(Nostr Lib v0.2.1)
(nip57)
View Source
NIP-57: Lightning Zaps
High-level API for creating and validating Lightning zap payments on Nostr.
Overview
Zaps allow Nostr users to send Lightning payments to each other. The flow is:
- Client creates a zap request (kind 9734) and signs it
- Client sends the zap request to recipient's LNURL callback URL
- LNURL server returns a Lightning invoice
- Client pays the invoice
- Recipient's wallet publishes a zap receipt (kind 9735)
Examples
# Create and sign a zap request
{:ok, zap_request} = NIP57.create_zap_request(
sender_seckey,
recipient_pubkey,
1000, # sats
relays: ["wss://relay.example.com"],
event_id: "event_to_zap",
message: "Great post!"
)
# Build the LNURL callback URL
callback_url = NIP57.build_callback_url(zap_request, lnurl_callback)
# Validate a zap receipt
:ok = NIP57.validate_receipt(receipt, wallet_pubkey)See: https://github.com/nostr-protocol/nips/blob/master/57.md
Summary
Functions
Builds the LNURL callback URL with the zap request.
Creates and signs a zap request.
Returns the zap message/comment from a receipt.
Returns the zap recipient's pubkey from a receipt.
Returns the zap sender's pubkey from a receipt.
Returns the zap amount in satoshis from a receipt.
Returns the zap amount in millisatoshis from a receipt.
Returns the embedded zap request from a receipt.
Checks if a metadata event indicates the user supports zaps.
Validates a zap receipt against the wallet's pubkey.
Functions
@spec build_callback_url(Nostr.Event.ZapRequest.t(), binary()) :: binary()
Builds the LNURL callback URL with the zap request.
The zap request must be signed before calling this function.
Examples
url = NIP57.build_callback_url(zap_request, "https://lnurl.example.com/callback")
# => "https://lnurl.example.com/callback?amount=1000000&nostr=..."
@spec create_zap_request(binary(), binary(), non_neg_integer(), keyword()) :: {:ok, Nostr.Event.ZapRequest.t()} | {:error, String.t()}
Creates and signs a zap request.
Arguments
seckey- sender's secret key (hex string)recipient- recipient's pubkey (hex string)amount_sats- amount in satoshisopts- additional options
Options
:relays- list of relays for receipt publication (required):event_id- event being zapped:address- addressable event coordinate:kind- kind of the zapped event:message- optional message/comment:lnurl- bech32-encoded lnurl
Returns
{:ok, zap_request} on success, {:error, reason} on failure.
Examples
{:ok, request} = NIP57.create_zap_request(
seckey,
"pubkey",
1000,
relays: ["wss://relay.example.com"]
)
@spec get_message(Nostr.Event.ZapReceipt.t()) :: binary()
Returns the zap message/comment from a receipt.
@spec get_recipient(Nostr.Event.ZapReceipt.t()) :: binary() | nil
Returns the zap recipient's pubkey from a receipt.
@spec get_sender(Nostr.Event.ZapReceipt.t()) :: binary() | nil
Returns the zap sender's pubkey from a receipt.
Returns the P tag value (uppercase), or falls back to the zap request's pubkey.
@spec get_zap_amount(Nostr.Event.ZapReceipt.t()) :: non_neg_integer() | nil
Returns the zap amount in satoshis from a receipt.
@spec get_zap_amount_msats(Nostr.Event.ZapReceipt.t()) :: non_neg_integer() | nil
Returns the zap amount in millisatoshis from a receipt.
@spec get_zap_request(Nostr.Event.ZapReceipt.t()) :: {:ok, Nostr.Event.ZapRequest.t()} | {:error, String.t()}
Returns the embedded zap request from a receipt.
Examples
{:ok, request} = NIP57.get_zap_request(receipt)
request.message # => "Great post!"
Checks if a metadata event indicates the user supports zaps.
A user supports zaps if they have lud16 (Lightning address) or
lud06 (LNURL) in their metadata.
Examples
metadata = Nostr.Event.Metadata.parse(event)
NIP57.supports_zaps?(metadata) # => true/false
@spec validate_receipt(Nostr.Event.ZapReceipt.t(), binary()) :: :ok | {:error, String.t()}
Validates a zap receipt against the wallet's pubkey.
Per NIP-57 Appendix F:
- Receipt's pubkey must match the wallet's
nostrPubkey - Invoice amount must match the zap request's amount tag
- Zap request's lnurl tag should match recipient's lnurl
Examples
:ok = NIP57.validate_receipt(receipt, wallet_pubkey)
{:error, "Receipt pubkey does not match"} = NIP57.validate_receipt(bad_receipt, wallet_pubkey)