"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // nip57.ts var nip57_exports = {}; __export(nip57_exports, { getSatoshisAmountFromBolt11: () => getSatoshisAmountFromBolt11, getZapEndpoint: () => getZapEndpoint, makeZapReceipt: () => makeZapReceipt, makeZapRequest: () => makeZapRequest, useFetchImplementation: () => useFetchImplementation, validateZapRequest: () => validateZapRequest }); module.exports = __toCommonJS(nip57_exports); var import_base = require("@scure/base"); // pure.ts var import_secp256k1 = require("@noble/curves/secp256k1"); var import_utils2 = require("@noble/hashes/utils"); // core.ts var verifiedSymbol = Symbol("verified"); var isRecord = (obj) => obj instanceof Object; function validateEvent(event) { if (!isRecord(event)) return false; if (typeof event.kind !== "number") return false; if (typeof event.content !== "string") return false; if (typeof event.created_at !== "number") return false; if (typeof event.pubkey !== "string") return false; if (!event.pubkey.match(/^[a-f0-9]{64}$/)) return false; if (!Array.isArray(event.tags)) return false; for (let i2 = 0; i2 < event.tags.length; i2++) { let tag = event.tags[i2]; if (!Array.isArray(tag)) return false; for (let j = 0; j < tag.length; j++) { if (typeof tag[j] !== "string") return false; } } return true; } // pure.ts var import_sha256 = require("@noble/hashes/sha256"); // utils.ts var import_utils = require("@noble/hashes/utils"); var utf8Decoder = new TextDecoder("utf-8"); var utf8Encoder = new TextEncoder(); // pure.ts var JS = class { generateSecretKey() { return import_secp256k1.schnorr.utils.randomPrivateKey(); } getPublicKey(secretKey) { return (0, import_utils2.bytesToHex)(import_secp256k1.schnorr.getPublicKey(secretKey)); } finalizeEvent(t, secretKey) { const event = t; event.pubkey = (0, import_utils2.bytesToHex)(import_secp256k1.schnorr.getPublicKey(secretKey)); event.id = getEventHash(event); event.sig = (0, import_utils2.bytesToHex)(import_secp256k1.schnorr.sign(getEventHash(event), secretKey)); event[verifiedSymbol] = true; return event; } verifyEvent(event) { if (typeof event[verifiedSymbol] === "boolean") return event[verifiedSymbol]; const hash = getEventHash(event); if (hash !== event.id) { event[verifiedSymbol] = false; return false; } try { const valid = import_secp256k1.schnorr.verify(event.sig, hash, event.pubkey); event[verifiedSymbol] = valid; return valid; } catch (err) { event[verifiedSymbol] = false; return false; } } }; function serializeEvent(evt) { if (!validateEvent(evt)) throw new Error("can't serialize event with wrong or missing properties"); return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]); } function getEventHash(event) { let eventHash = (0, import_sha256.sha256)(utf8Encoder.encode(serializeEvent(event))); return (0, import_utils2.bytesToHex)(eventHash); } var i = new JS(); var generateSecretKey = i.generateSecretKey; var getPublicKey = i.getPublicKey; var finalizeEvent = i.finalizeEvent; var verifyEvent = i.verifyEvent; // kinds.ts function isReplaceableKind(kind) { return [0, 3].includes(kind) || 1e4 <= kind && kind < 2e4; } function isAddressableKind(kind) { return 3e4 <= kind && kind < 4e4; } // nip57.ts var _fetch; try { _fetch = fetch; } catch { } function useFetchImplementation(fetchImplementation) { _fetch = fetchImplementation; } async function getZapEndpoint(metadata) { try { let lnurl = ""; let { lud06, lud16 } = JSON.parse(metadata.content); if (lud06) { let { words } = import_base.bech32.decode(lud06, 1e3); let data = import_base.bech32.fromWords(words); lnurl = utf8Decoder.decode(data); } else if (lud16) { let [name, domain] = lud16.split("@"); lnurl = new URL(`/.well-known/lnurlp/${name}`, `https://${domain}`).toString(); } else { return null; } let res = await _fetch(lnurl); let body = await res.json(); if (body.allowsNostr && body.nostrPubkey) { return body.callback; } } catch (err) { } return null; } function makeZapRequest(params) { let zr = { kind: 9734, created_at: Math.round(Date.now() / 1e3), content: params.comment || "", tags: [ ["p", "pubkey" in params ? params.pubkey : params.event.pubkey], ["amount", params.amount.toString()], ["relays", ...params.relays] ] }; if ("event" in params) { zr.tags.push(["e", params.event.id]); if (isReplaceableKind(params.event.kind)) { const a = ["a", `${params.event.kind}:${params.event.pubkey}:`]; zr.tags.push(a); } else if (isAddressableKind(params.event.kind)) { let d = params.event.tags.find(([t, v]) => t === "d" && v); if (!d) throw new Error("d tag not found or is empty"); const a = ["a", `${params.event.kind}:${params.event.pubkey}:${d[1]}`]; zr.tags.push(a); } zr.tags.push(["k", params.event.kind.toString()]); } return zr; } function validateZapRequest(zapRequestString) { let zapRequest; try { zapRequest = JSON.parse(zapRequestString); } catch (err) { return "Invalid zap request JSON."; } if (!validateEvent(zapRequest)) return "Zap request is not a valid Nostr event."; if (!verifyEvent(zapRequest)) return "Invalid signature on zap request."; let p = zapRequest.tags.find(([t, v]) => t === "p" && v); if (!p) return "Zap request doesn't have a 'p' tag."; if (!p[1].match(/^[a-f0-9]{64}$/)) return "Zap request 'p' tag is not valid hex."; let e = zapRequest.tags.find(([t, v]) => t === "e" && v); if (e && !e[1].match(/^[a-f0-9]{64}$/)) return "Zap request 'e' tag is not valid hex."; let relays = zapRequest.tags.find(([t, v]) => t === "relays" && v); if (!relays) return "Zap request doesn't have a 'relays' tag."; return null; } function makeZapReceipt({ zapRequest, preimage, bolt11, paidAt }) { let zr = JSON.parse(zapRequest); let tagsFromZapRequest = zr.tags.filter(([t]) => t === "e" || t === "p" || t === "a"); let zap = { kind: 9735, created_at: Math.round(paidAt.getTime() / 1e3), content: "", tags: [...tagsFromZapRequest, ["P", zr.pubkey], ["bolt11", bolt11], ["description", zapRequest]] }; if (preimage) { zap.tags.push(["preimage", preimage]); } return zap; } function getSatoshisAmountFromBolt11(bolt11) { if (bolt11.length < 50) { return 0; } bolt11 = bolt11.substring(0, 50); const idx = bolt11.lastIndexOf("1"); if (idx === -1) { return 0; } const hrp = bolt11.substring(0, idx); if (!hrp.startsWith("lnbc")) { return 0; } const amount = hrp.substring(4); if (amount.length < 1) { return 0; } const char = amount[amount.length - 1]; const digit = char.charCodeAt(0) - "0".charCodeAt(0); const isDigit = digit >= 0 && digit <= 9; let cutPoint = amount.length - 1; if (isDigit) { cutPoint++; } if (cutPoint < 1) { return 0; } const num = parseInt(amount.substring(0, cutPoint)); switch (char) { case "m": return num * 1e5; case "u": return num * 100; case "n": return num / 10; case "p": return num / 1e4; default: return num * 1e8; } }