# Zaps The Zaps module provides utilities for working with Lightning Network payments (zaps) in Nostr, including LNURL handling, invoice amount parsing, and zap validation. ## Zapper Interface The Zapper interface represents a Lightning Network payment provider that can process zaps: ```typescript interface Zapper { // LNURL for payment processing lnurl: string // User's pubkey on the payment service pubkey?: string // LNURL callback endpoint callback?: string // Minimum payment amount in millisatoshis minSendable?: number // Maximum payment amount in millisatoshis maxSendable?: number // Pubkey used to sign zap receipts nostrPubkey?: string // Whether provider supports Nostr zaps allowsNostr?: boolean } ``` ### Finding Nostr Zappers #### Getting Lightning Info First, check the user's profile for Lightning addresses: ```typescript function getLightningInfo(profile: Profile) { // Check for Lightning Address (NIP-57) if (profile.lud16) { return { type: 'lud16', address: profile.lud16 } } // Check for LNURL if (profile.lud06) { return { type: 'lud06', url: profile.lud06 } } return null } ``` #### Fetching LNURL Metadata Once you have the Lightning address or LNURL, fetch the metadata: ```typescript async function fetchZapper(address: string): Promise { // Convert Lightning address to LNURL if needed const lnurl = getLnUrl(address) if (!lnurl) return null try { // Decode and fetch LNURL metadata const url = new URL(bech32.decode(lnurl).data) const response = await fetch(url.toString()) const metadata = await response.json() // Extract zapper details return { lnurl, callback: metadata.callback, minSendable: metadata.minSendable, maxSendable: metadata.maxSendable, nostrPubkey: metadata.nostrPubkey, allowsNostr: Boolean(metadata.allowsNostr), } } catch (error) { console.error('Failed to fetch zapper:', error) return null } } ``` ```typescript // Example Alby zapper configuration const albyZapper: Zapper = { lnurl: "lnurl1...", pubkey: "alby_user_pubkey", nostrPubkey: "alby_signing_key", allowsNostr: true, minSendable: 1000, // 1 sat minimum maxSendable: 100000000 // 100k sats maximum } // Example LNbits zapper const lnbitsZapper: Zapper = { lnurl: "lnurl1...", callback: "https://lnbits.com/callback", nostrPubkey: "lnbits_signing_key", allowsNostr: true } ``` ### Zap Structure ```typescript interface Zap { request: TrustedEvent // Zap request event kind 9734 response: TrustedEvent // Zap receipt/response event kind 9735 sent by the zapper invoiceAmount: number // Amount in millisats } ``` ## Core Functions ### Lightning Address Handling ```typescript // Convert address to LNURL function getLnUrl(address: string): string | null // Examples: getLnUrl("user@domain.com") // => lnurl1... getLnUrl("https://domain.com/.well-known/lnurlp/user") // => lnurl1... getLnUrl("lnurl1...") // => returns unchanged ``` ### Invoice Processing ```typescript // Parse amount from BOLT11 invoice function getInvoiceAmount(bolt11: string): number // Convert human readable amount to millisats function hrpToMillisat(hrpString: string): bigint ``` ### Zap Validation The `zapFromEvent` function validates a zap receipt event, against an expected zapper. It returns a `Zap` object if the zap is valid, or `null` if not. ```typescript function zapFromEvent( response: TrustedEvent, zapper: Zapper | undefined ): Zap | null ``` ## Usage Examples ### Processing Lightning Addresses ```typescript // Get LNURL from various formats const lnurl1 = getLnUrl("user@getalby.com") const lnurl2 = getLnUrl("https://getalby.com/.well-known/lnurlp/user") const lnurl3 = getLnUrl("lnurl1...") // Check if conversion was successful if (lnurl1) { // Process LNURL processLnurl(lnurl1) } ``` ### Invoice Amount Handling ```typescript // Get invoice amount in millisats const amount = getInvoiceAmount(bolt11Invoice) // Convert string amount to millisats const millisats = hrpToMillisat("1000") // 1000 sats const millisats = hrpToMillisat("1m") // 1 million sats ``` ### Zap Validation ```typescript // Validate zap event const zap = zapFromEvent(zapResponse, albyZapper) if (zap) { // Process valid zap processZap(zap) } ```