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:

  1. Client creates a zap request (kind 9734) and signs it
  2. Client sends the zap request to recipient's LNURL callback URL
  3. LNURL server returns a Lightning invoice
  4. Client pays the invoice
  5. 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.

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

build_callback_url(zap_request, callback_url)

@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=..."

create_zap_request(seckey, recipient, amount_sats, opts \\ [])

@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 satoshis
  • opts - 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"]
)

get_message(arg1)

@spec get_message(Nostr.Event.ZapReceipt.t()) :: binary()

Returns the zap message/comment from a receipt.

get_recipient(zap_receipt)

@spec get_recipient(Nostr.Event.ZapReceipt.t()) :: binary() | nil

Returns the zap recipient's pubkey from a receipt.

get_sender(arg1)

@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.

get_zap_amount(receipt)

@spec get_zap_amount(Nostr.Event.ZapReceipt.t()) :: non_neg_integer() | nil

Returns the zap amount in satoshis from a receipt.

get_zap_amount_msats(receipt)

@spec get_zap_amount_msats(Nostr.Event.ZapReceipt.t()) :: non_neg_integer() | nil

Returns the zap amount in millisatoshis from a receipt.

get_zap_request(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!"

supports_zaps?(arg1)

@spec supports_zaps?(map() | struct()) :: boolean()

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

validate_receipt(receipt, wallet_pubkey)

@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)