nostr-components 0.2.7 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -186
- package/dist/assets/{base-styles-BSEzBDsk.js → base-styles-Dmuzg8I4.js} +2 -2
- package/dist/assets/{base-styles-BSEzBDsk.js.map → base-styles-Dmuzg8I4.js.map} +1 -1
- package/dist/assets/{copy-delegation-B7y2q5Kn.js → copy-delegation-xzt-t_do.js} +2 -2
- package/dist/assets/{copy-delegation-B7y2q5Kn.js.map → copy-delegation-xzt-t_do.js.map} +1 -1
- package/dist/assets/dialog-component-Da1ZIYh9.js.map +1 -1
- package/dist/assets/{dialog-likers-BqDn2P_3.js → dialog-likers-B15m_NxI.js} +5 -5
- package/dist/assets/dialog-likers-B15m_NxI.js.map +1 -0
- package/dist/assets/index.esm-ByUtE_cm.js +2159 -0
- package/dist/assets/index.esm-ByUtE_cm.js.map +1 -0
- package/dist/assets/nip05-utils-BNBHUmkr.js.map +1 -1
- package/dist/assets/nostr-login-service-D2FmscPI.js +2 -0
- package/dist/assets/nostr-login-service-D2FmscPI.js.map +1 -0
- package/dist/assets/nostr-service-CA0Qx4nJ.js +266 -0
- package/dist/assets/nostr-service-CA0Qx4nJ.js.map +1 -0
- package/dist/assets/{nostr-user-component-Cbs97dlK.js → nostr-user-component-r-MUbTL6.js} +2 -2
- package/dist/assets/{nostr-user-component-Cbs97dlK.js.map → nostr-user-component-r-MUbTL6.js.map} +1 -1
- package/dist/assets/{pure-DPo-pzxM.js → pure-DOoUcNQv.js} +2 -2
- package/dist/assets/pure-DOoUcNQv.js.map +1 -0
- package/dist/assets/theme-BN1Bvweb.js.map +1 -1
- package/dist/assets/{user-resolver-CMmbtY9Y.js → user-resolver-ArI0680e.js} +2 -2
- package/dist/assets/{user-resolver-CMmbtY9Y.js.map → user-resolver-ArI0680e.js.map} +1 -1
- package/dist/assets/utils--bxLbhGF.js.map +1 -1
- package/dist/assets/zap-utils-QRxLBOst.js +2 -0
- package/dist/assets/zap-utils-QRxLBOst.js.map +1 -0
- package/dist/components/nostr-comment.es.js +26 -26
- package/dist/components/nostr-comment.es.js.map +1 -1
- package/dist/components/nostr-dm.es.js +2 -2
- package/dist/components/nostr-dm.es.js.map +1 -1
- package/dist/components/nostr-follow-button.es.js +6 -7
- package/dist/components/nostr-follow-button.es.js.map +1 -1
- package/dist/components/nostr-like.es.js +16 -16
- package/dist/components/nostr-like.es.js.map +1 -1
- package/dist/components/nostr-live-chat.es.js +3 -3
- package/dist/components/nostr-live-chat.es.js.map +1 -1
- package/dist/components/nostr-post.es.js +19 -19
- package/dist/components/nostr-post.es.js.map +1 -1
- package/dist/components/nostr-profile-badge.es.js +2 -2
- package/dist/components/nostr-profile-badge.es.js.map +1 -1
- package/dist/components/nostr-profile.es.js +5 -5
- package/dist/components/nostr-profile.es.js.map +1 -1
- package/dist/components/nostr-zap.es.js +24 -24
- package/dist/components/nostr-zap.es.js.map +1 -1
- package/dist/nostr-components.es.js +1 -1
- package/dist/nostr-components.es.js.map +1 -1
- package/dist/nostr-components.umd.js +2669 -301
- package/dist/nostr-components.umd.js.map +1 -1
- package/dist/src/common/constants.d.ts +1 -1
- package/dist/src/common/nostr-login-service.d.ts +26 -0
- package/dist/src/nostr-dm/nostr-dm.d.ts +1 -1
- package/dist/src/nostr-like/like-utils.d.ts +2 -6
- package/dist/src/nostr-live-chat/nostr-live-chat.d.ts +1 -1
- package/dist/src/nostr-zap/zap-utils.d.ts +4 -0
- package/package.json +5 -2
- package/dist/assets/dialog-likers-BqDn2P_3.js.map +0 -1
- package/dist/assets/nostr-service-CnaPxjc6.js +0 -78
- package/dist/assets/nostr-service-CnaPxjc6.js.map +0 -1
- package/dist/assets/pure-DPo-pzxM.js.map +0 -1
- package/dist/assets/zap-utils-KFUD_vTU.js +0 -2
- package/dist/assets/zap-utils-KFUD_vTU.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pure-DPo-pzxM.js","sources":["../../node_modules/nostr-tools/lib/esm/pure.js"],"sourcesContent":["// pure.ts\nimport { schnorr } from \"@noble/curves/secp256k1\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\n\n// core.ts\nvar verifiedSymbol = Symbol(\"verified\");\nvar isRecord = (obj) => obj instanceof Object;\nfunction validateEvent(event) {\n if (!isRecord(event))\n return false;\n if (typeof event.kind !== \"number\")\n return false;\n if (typeof event.content !== \"string\")\n return false;\n if (typeof event.created_at !== \"number\")\n return false;\n if (typeof event.pubkey !== \"string\")\n return false;\n if (!event.pubkey.match(/^[a-f0-9]{64}$/))\n return false;\n if (!Array.isArray(event.tags))\n return false;\n for (let i2 = 0; i2 < event.tags.length; i2++) {\n let tag = event.tags[i2];\n if (!Array.isArray(tag))\n return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] === \"object\")\n return false;\n }\n }\n return true;\n}\nfunction sortEvents(events) {\n return events.sort((a, b) => {\n if (a.created_at !== b.created_at) {\n return b.created_at - a.created_at;\n }\n return a.id.localeCompare(b.id);\n });\n}\n\n// pure.ts\nimport { sha256 } from \"@noble/hashes/sha256\";\n\n// utils.ts\nvar utf8Decoder = new TextDecoder(\"utf-8\");\nvar utf8Encoder = new TextEncoder();\n\n// pure.ts\nvar JS = class {\n generateSecretKey() {\n return schnorr.utils.randomPrivateKey();\n }\n getPublicKey(secretKey) {\n return bytesToHex(schnorr.getPublicKey(secretKey));\n }\n finalizeEvent(t, secretKey) {\n const event = t;\n event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey));\n event.id = getEventHash(event);\n event.sig = bytesToHex(schnorr.sign(getEventHash(event), secretKey));\n event[verifiedSymbol] = true;\n return event;\n }\n verifyEvent(event) {\n if (typeof event[verifiedSymbol] === \"boolean\")\n return event[verifiedSymbol];\n const hash = getEventHash(event);\n if (hash !== event.id) {\n event[verifiedSymbol] = false;\n return false;\n }\n try {\n const valid = schnorr.verify(event.sig, hash, event.pubkey);\n event[verifiedSymbol] = valid;\n return valid;\n } catch (err) {\n event[verifiedSymbol] = false;\n return false;\n }\n }\n};\nfunction serializeEvent(evt) {\n if (!validateEvent(evt))\n throw new Error(\"can't serialize event with wrong or missing properties\");\n return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content]);\n}\nfunction getEventHash(event) {\n let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)));\n return bytesToHex(eventHash);\n}\nvar i = new JS();\nvar generateSecretKey = i.generateSecretKey;\nvar getPublicKey = i.getPublicKey;\nvar finalizeEvent = i.finalizeEvent;\nvar verifyEvent = i.verifyEvent;\nexport {\n finalizeEvent,\n generateSecretKey,\n getEventHash,\n getPublicKey,\n serializeEvent,\n sortEvents,\n validateEvent,\n verifiedSymbol,\n verifyEvent\n};\n"],"names":["verifiedSymbol","isRecord","obj","validateEvent","event","i2","tag","j","utf8Encoder","JS","schnorr","secretKey","bytesToHex","t","getEventHash","hash","valid","serializeEvent","evt","eventHash","sha256","i","generateSecretKey","getPublicKey","finalizeEvent"],"mappings":"8DAKG,IAACA,EAAiB,OAAO,UAAU,EAClCC,EAAYC,GAAQA,aAAe,OACvC,SAASC,EAAcC,EAAO,CAa5B,GAZI,CAACH,EAASG,CAAK,GAEf,OAAOA,EAAM,MAAS,UAEtB,OAAOA,EAAM,SAAY,UAEzB,OAAOA,EAAM,YAAe,UAE5B,OAAOA,EAAM,QAAW,UAExB,CAACA,EAAM,OAAO,MAAM,gBAAgB,GAEpC,CAAC,MAAM,QAAQA,EAAM,IAAI,EAC3B,MAAO,GACT,QAASC,EAAK,EAAGA,EAAKD,EAAM,KAAK,OAAQC,IAAM,CAC7C,IAAIC,EAAMF,EAAM,KAAKC,CAAE,EACvB,GAAI,CAAC,MAAM,QAAQC,CAAG,EACpB,MAAO,GACT,QAASC,EAAI,EAAGA,EAAID,EAAI,OAAQC,IAC9B,GAAI,OAAOD,EAAIC,CAAC,GAAM,SACpB,MAAO,EAEf,CACE,MAAO,EACT,CAckB,IAAI,YAAY,OAAO,EACzC,IAAIC,EAAc,IAAI,YAGlBC,EAAK,KAAM,CACb,mBAAoB,CAClB,OAAOC,EAAQ,MAAM,iBAAkB,CAC3C,CACE,aAAaC,EAAW,CACtB,OAAOC,EAAWF,EAAQ,aAAaC,CAAS,CAAC,CACrD,CACE,cAAcE,EAAGF,EAAW,CAC1B,MAAMP,EAAQS,EACd,OAAAT,EAAM,OAASQ,EAAWF,EAAQ,aAAaC,CAAS,CAAC,EACzDP,EAAM,GAAKU,EAAaV,CAAK,EAC7BA,EAAM,IAAMQ,EAAWF,EAAQ,KAAKI,EAAaV,CAAK,EAAGO,CAAS,CAAC,EACnEP,EAAMJ,CAAc,EAAI,GACjBI,CACX,CACE,YAAYA,EAAO,CACjB,GAAI,OAAOA,EAAMJ,CAAc,GAAM,UACnC,OAAOI,EAAMJ,CAAc,EAC7B,MAAMe,EAAOD,EAAaV,CAAK,EAC/B,GAAIW,IAASX,EAAM,GACjB,OAAAA,EAAMJ,CAAc,EAAI,GACjB,GAET,GAAI,CACF,MAAMgB,EAAQN,EAAQ,OAAON,EAAM,IAAKW,EAAMX,EAAM,MAAM,EAC1D,OAAAA,EAAMJ,CAAc,EAAIgB,EACjBA,CACR,MAAa,CACZ,OAAAZ,EAAMJ,CAAc,EAAI,GACjB,EACb,CACA,CACA,EACA,SAASiB,EAAeC,EAAK,CAC3B,GAAI,CAACf,EAAce,CAAG,EACpB,MAAM,IAAI,MAAM,wDAAwD,EAC1E,OAAO,KAAK,UAAU,CAAC,EAAGA,EAAI,OAAQA,EAAI,WAAYA,EAAI,KAAMA,EAAI,KAAMA,EAAI,OAAO,CAAC,CACxF,CACA,SAASJ,EAAaV,EAAO,CAC3B,IAAIe,EAAYC,EAAOZ,EAAY,OAAOS,EAAeb,CAAK,CAAC,CAAC,EAChE,OAAOQ,EAAWO,CAAS,CAC7B,CACA,IAAIE,EAAI,IAAIZ,EACRa,EAAoBD,EAAE,kBACtBE,EAAeF,EAAE,aACjBG,EAAgBH,EAAE,cACJA,EAAE","x_google_ignoreList":[0]}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{S as E,h as N,i as P}from"./nostr-service-CnaPxjc6.js";import{n as k}from"./utils--bxLbhGF.js";const m={},$=async t=>{if(m[t])return m[t];const n=new E,e=["wss://relay.nostr.band","wss://purplepag.es","wss://relay.damus.io","wss://nostr.wine"];try{const a=await n.get(e,{authors:[t],kinds:[0]});return m[t]=a,a}finally{n.close(e)}},O=async t=>{const n=t.filter(r=>!m[r]);if(n.length===0)return t.map(r=>({id:r,profile:m[r]}));const e=new E,a=["wss://relay.nostr.band","wss://purplepag.es","wss://relay.damus.io","wss://nostr.wine"];try{return(await e.querySync(a,{authors:n,kinds:[0]})).forEach(o=>{m[o.pubkey]=o}),t.map(o=>({id:o,profile:m[o]||null}))}finally{e.close(a)}},x=t=>{try{return JSON.parse((t==null?void 0:t.content)||"{}")}catch{return{}}},z=async t=>{const n=await N.getZapEndpoint(t);if(!n)throw new Error("Failed to retrieve zap LNURL");return n},S=async(t,n)=>{if(R())try{const e=window.nostr;if(e!=null&&e.signEvent)return await e.signEvent(t)}catch{}return P(t,C())},Z=async({profile:t,nip19Target:n,amount:e,relays:a,comment:r,anon:c,url:o})=>{const p={profile:t,amount:e,relays:a,comment:r||""},i=N.makeZapRequest(p);return o&&(i.tags.push(["k","web"]),i.tags.push(["i",k(o)])),(!R()||c)&&i.tags.push(["anon"]),S(i)},D=async({zapEndpoint:t,amount:n,comment:e,authorId:a,nip19Target:r,normalizedRelays:c,anon:o,url:p})=>{const i=await Z({profile:a,nip19Target:r,amount:n,relays:c,comment:e??"",anon:o,url:p});let d=`${t}?amount=${n}&nostr=${encodeURIComponent(JSON.stringify(i))}`;e&&(d+=`&comment=${encodeURIComponent(e??"")}`);const l=await fetch(d,{method:"GET"});if(!l.ok)throw new Error(`LNURL request failed: ${l.status} ${l.statusText}`);let u;try{u=await l.json()}catch{throw new Error("Invalid JSON from LNURL endpoint")}const{pr:h,reason:v,status:g}=u||{};if(h)return h;throw g==="ERROR"?new Error(v??"Unable to fetch invoice"):new Error("Unable to fetch invoice")},C=()=>{const t=new Uint8Array(32);if(typeof crypto<"u"&&typeof crypto.getRandomValues=="function")crypto.getRandomValues(t);else{console.warn("crypto.getRandomValues not available, using Math.random as fallback");for(let n=0;n<32;n++)t[n]=Math.floor(Math.random()*256)}return t},R=()=>typeof window<"u"&&!!window.nostr,J=async({pubkey:t,relays:n,url:e})=>{var p,i,d,l;const a=e?k(e):void 0,r=new E;let c=0;const o=[];try{const u={kinds:[9735],"#p":[t],limit:1e3},h=await r.querySync(n,u);for(const v of h){const g=(p=v.tags)==null?void 0:p.find(s=>s[0]==="description");if(g!=null&&g[1])try{const s=JSON.parse(g[1]),w=(i=s==null?void 0:s.tags)==null?void 0:i.find(f=>f[0]==="amount");if(a){const f=(d=s==null?void 0:s.tags)==null?void 0:d.find(y=>y[0]==="k"),b=(l=s==null?void 0:s.tags)==null?void 0:l.find(y=>y[0]==="i"),U=b!=null&&b[1]?k(b[1]):"";if((f==null?void 0:f[1])==="web"&&U===a&&(w!=null&&w[1])){const y=parseInt(w[1],10);y>0&&(c+=y,o.push({amount:y/1e3,date:new Date(v.created_at*1e3),authorPubkey:s.pubkey,comment:s.content}))}}else if(w!=null&&w[1]){const f=parseInt(w[1],10);f>0&&(c+=f,o.push({amount:f/1e3,date:new Date(v.created_at*1e3),authorPubkey:s.pubkey,comment:s.content}))}}catch(s){console.error("Nostr-Components: Zap button: Could not parse zap request from description tag",s)}}}catch(u){console.error("Nostr-Components: Zap button: Error fetching zap receipts",u)}finally{r.close(n)}return o.sort((u,h)=>h.date.getTime()-u.date.getTime()),{totalAmount:c/1e3,zapDetails:o}},M=({relays:t,receiversPubKey:n,invoice:e,onSuccess:a})=>{const r=new E,c=Array.from(new Set([...t,"wss://relay.nostr.band"])),o=Math.floor((Date.now()-24*60*60*1e3)/1e3);r.subscribe(c,{kinds:[9735],"#p":[n],since:o},{onevent(i){i.tags.some(l=>l[0]==="bolt11"&&l[1]===e)&&(a(),p())}});const p=()=>{r.close(c)};return p};export{x as extractProfileMetadataContent,D as fetchInvoice,J as fetchTotalZapAmount,O as getBatchedProfileMetadata,$ as getProfileMetadata,z as getZapEndpoint,R as isNip07ExtAvailable,M as listenForZapReceipt};
|
|
2
|
-
//# sourceMappingURL=zap-utils-KFUD_vTU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"zap-utils-KFUD_vTU.js","sources":["../../src/nostr-zap/zap-utils.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n\nimport {\n nip57,\n nip05,\n finalizeEvent,\n SimplePool,\n} from 'nostr-tools';\nimport { decodeNip19Entity } from '../common/utils';\n\n/**\n * Helper utilities for Nostr zap operations (adapted from the original `nostr-zap` repo).\n * These are deliberately kept self-contained so `nostr-zap` Web Component can import\n * everything from a single module without polluting the rest of the codebase.\n */\n\n// Basic in-memory cache – sufficient for component lifetime.\nconst profileCache: Record<string, any> = {};\n\nexport const getProfileMetadata = async (authorId: string) => {\n if (profileCache[authorId]) return profileCache[authorId];\n\n const pool = new SimplePool();\n const relays = [\n 'wss://relay.nostr.band',\n 'wss://purplepag.es',\n 'wss://relay.damus.io',\n 'wss://nostr.wine',\n ];\n\n try {\n const event = await pool.get(relays, {\n authors: [authorId],\n kinds: [0],\n });\n profileCache[authorId] = event;\n return event;\n } finally {\n pool.close(relays);\n }\n};\n\nexport const getBatchedProfileMetadata = async (authorIds: string[]) => {\n // Filter out already cached profiles\n const uncachedIds = authorIds.filter(id => !profileCache[id]);\n\n // If all profiles are cached, return them\n if (uncachedIds.length === 0) {\n return authorIds.map(id => ({ id, profile: profileCache[id] }));\n }\n\n const pool = new SimplePool();\n const relays = [\n 'wss://relay.nostr.band',\n 'wss://purplepag.es',\n 'wss://relay.damus.io',\n 'wss://nostr.wine',\n ];\n\n try {\n // Fetch all uncached profiles in a single query\n const events = await pool.querySync(relays, {\n authors: uncachedIds,\n kinds: [0],\n });\n\n // Cache the fetched profiles\n events.forEach(event => {\n profileCache[event.pubkey] = event;\n });\n\n // Combine cached and newly fetched profiles\n const allProfiles = authorIds.map(id => ({\n id,\n profile: profileCache[id] || null\n }));\n\n return allProfiles;\n } finally {\n pool.close(relays);\n }\n};\n\nexport const extractProfileMetadataContent = (profileMetadata: any) => {\n try {\n return JSON.parse(profileMetadata?.content || '{}');\n } catch {\n return {};\n }\n};\n\nexport const getZapEndpoint = async (profileMetadata: any) => {\n const endpoint = await nip57.getZapEndpoint(profileMetadata);\n if (!endpoint) throw new Error('Failed to retrieve zap LNURL');\n return endpoint;\n};\n\ninterface NostrExtension {\n signEvent(event: any): Promise<{\n id: string;\n sig: string;\n kind: number;\n tags: string[][];\n pubkey: string;\n content: string;\n created_at: number;\n }>;\n}\n\nconst signEvent = async (zapEvent: any, anon?: boolean) => {\n if (isNip07ExtAvailable() && !anon) {\n try {\n const ext = (window as { nostr?: NostrExtension }).nostr;\n if (ext?.signEvent) return await ext.signEvent(zapEvent);\n } catch {\n /* fall-through -> anonymous */\n }\n }\n return finalizeEvent(zapEvent, generateRandomPrivKey());\n};\n\nconst makeZapEvent = async ({\n profile,\n nip19Target,\n amount,\n relays,\n comment,\n anon,\n url,\n}: {\n profile: string;\n nip19Target?: string;\n amount: number;\n relays: string[];\n comment?: string;\n anon?: boolean;\n url?: string;\n}) => {\n const req: any = {\n profile,\n amount,\n relays,\n comment: comment || '',\n };\n if (nip19Target?.startsWith('note')) {\n req.event = decodeNip19Entity(nip19Target);\n }\n const event = nip57.makeZapRequest(req);\n\n if (nip19Target?.startsWith('naddr')) {\n const naddrData: any = decodeNip19Entity(nip19Target);\n const relayTag = naddrData?.relays?.join(',') ?? '';\n event.tags.push(['a', `${naddrData.kind}:${naddrData.pubkey}:${naddrData.identifier}`, relayTag]);\n }\n\n // Add URL-based zap tags if URL is provided\n if (url) {\n event.tags.push(['k', 'web']);\n event.tags.push(['i', normalizeURL(url)]);\n }\n\n if (!isNip07ExtAvailable() || anon) {\n event.tags.push(['anon']);\n }\n\n return signEvent(event, anon);\n};\n\nexport const fetchInvoice = async ({\n zapEndpoint,\n amount,\n comment,\n authorId,\n nip19Target,\n normalizedRelays,\n anon,\n url,\n}: {\n zapEndpoint: string;\n amount: number;\n comment?: string;\n authorId: string;\n nip19Target?: string;\n normalizedRelays: string[];\n anon?: boolean;\n url?: string;\n}): Promise<string> => {\n const zapEvent = await makeZapEvent({\n profile: authorId,\n nip19Target,\n amount,\n relays: normalizedRelays,\n comment: comment ?? '',\n anon,\n url,\n });\n\n\n let invoiceUrl = `${zapEndpoint}?amount=${amount}&nostr=${encodeURIComponent(\n JSON.stringify(zapEvent)\n )}`;\n if (comment) invoiceUrl += `&comment=${encodeURIComponent(comment ?? '')}`;\n\n const res = await fetch(invoiceUrl, { method: 'GET' });\n if (!res.ok) {\n throw new Error(`LNURL request failed: ${res.status} ${res.statusText}`);\n }\n let json: any;\n try {\n json = await res.json();\n } catch {\n throw new Error('Invalid JSON from LNURL endpoint');\n }\n const { pr: invoice, reason, status } = json || {};\n if (invoice) return invoice;\n if (status === 'ERROR') throw new Error(reason ?? 'Unable to fetch invoice');\n throw new Error('Unable to fetch invoice');\n};\n\nconst generateRandomPrivKey = (): Uint8Array => {\n const bytes = new Uint8Array(32);\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(bytes);\n } else {\n // Node.js fallback during build – use Math.random (not cryptographically strong but acceptable for anon zaps)\n console.warn('crypto.getRandomValues not available, using Math.random as fallback');\n for (let i = 0; i < 32; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n return bytes;\n};\n\nexport const isNip07ExtAvailable = (): boolean => typeof window !== 'undefined' && !!(window as any).nostr;\n\n// ---------------------------------------------------------------------------\n// nip05 resolution helper – very lightweight fetch to /.well-known/nostr.json\n// ---------------------------------------------------------------------------\n\n\n\nexport async function resolveNip05(nip05Identifier: string): Promise<string | null> {\n try {\n const profile = await nip05.queryProfile(nip05Identifier);\n return profile?.pubkey || null;\n } catch (error) {\n console.error(`Failed to resolve NIP-05 ${nip05Identifier}:`, error);\n return null;\n }\n}\n\n// Import necessary types from nostr-tools\nimport type { Filter, Event } from 'nostr-tools';\nimport { normalizeURL } from '../nostr-comment/utils';\n\n// Augment the SimplePool type to include our usage\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ndeclare module 'nostr-tools' {\n interface SimplePool {\n subscribe(\n relays: string[],\n filter: Filter,\n params: {\n onevent: (event: Event) => void;\n onclose?: () => void;\n id?: string;\n maxWait?: number;\n }\n ): {\n close: () => void;\n };\n }\n}\n\nexport interface ZapDetails {\n amount: number;\n date: Date;\n authorPubkey: string;\n comment?: string;\n}\n\nexport interface ZapAmountResult {\n totalAmount: number;\n zapDetails: ZapDetails[];\n}\n\nexport const fetchTotalZapAmount = async ({\n pubkey,\n relays,\n url,\n}: {\n pubkey: string;\n relays: string[];\n url?: string;\n}): Promise<ZapAmountResult> => {\n // Normalize URL at the beginning for consistent comparison with tags\n const normalizedUrl = url ? normalizeURL(url) : undefined;\n \n const pool = new SimplePool();\n let totalAmount = 0;\n const zapDetails: ZapDetails[] = [];\n\n try {\n // Build filter for zap receipt events\n const filter: any = {\n kinds: [9735], // Zap receipt\n '#p': [pubkey],\n limit: 1000,\n };\n\n // Add URL-based filtering if URL is provided\n // TODO: These tags doesn't appear in zap receipt event.\n // They goes into the description tag, which has the zap request JSON.\n /*\n if (normalizedUrl) {\n filter['#k'] = ['web'];\n filter['#i'] = [normalizedUrl];\n }\n */\n\n // Use pool.querySync to fetch multiple zap receipt events\n const events = await pool.querySync(relays, filter);\n\n for (const event of events) {\n const descriptionTag = event.tags?.find((tag: string[]) => tag[0] === 'description');\n if (descriptionTag?.[1]) {\n try {\n const zapRequest = JSON.parse(descriptionTag[1]);\n const amountTag = zapRequest?.tags?.find((tag: string[]) => tag[0] === 'amount');\n \n // If URL is provided, check for URL-based zap tags\n // TODO: Too much work, since #k and #i tags doesn't appear in zap receipt event.\n // This is not a practical solution, but it's working for now!\n if (normalizedUrl) {\n const kTag = zapRequest?.tags?.find((tag: string[]) => tag[0] === 'k');\n const iTag = zapRequest?.tags?.find((tag: string[]) => tag[0] === 'i');\n \n const iTagNormalized = iTag?.[1] ? normalizeURL(iTag[1]) : '';\n if (kTag?.[1] === 'web' && iTagNormalized === normalizedUrl && amountTag?.[1]) {\n const amount = parseInt(amountTag[1], 10);\n if (amount > 0) {\n totalAmount += amount;\n zapDetails.push({\n amount: amount / 1000, // convert from msats to sats\n date: new Date(event.created_at * 1000),\n authorPubkey: zapRequest.pubkey,\n comment: zapRequest.content,\n });\n }\n }\n } else {\n // No URL filtering - count all zaps\n if (amountTag?.[1]) {\n const amount = parseInt(amountTag[1], 10);\n if (amount > 0) {\n totalAmount += amount;\n zapDetails.push({\n amount: amount / 1000, // convert from msats to sats\n date: new Date(event.created_at * 1000),\n authorPubkey: zapRequest.pubkey,\n comment: zapRequest.content,\n });\n }\n }\n }\n } catch (e) {\n console.error(\"Nostr-Components: Zap button: Could not parse zap request from description tag\", e);\n }\n }\n }\n } catch (error) {\n console.error(\"Nostr-Components: Zap button: Error fetching zap receipts\", error);\n } finally {\n pool.close(relays);\n }\n\n // Sort zap details by date (newest first)\n zapDetails.sort((a, b) => b.date.getTime() - a.date.getTime());\n\n return {\n totalAmount: totalAmount / 1000, // convert from msats to sats\n zapDetails,\n };\n};\n\nexport const listenForZapReceipt = ({\n relays,\n receiversPubKey,\n invoice,\n onSuccess,\n}: {\n relays: string[];\n receiversPubKey: string,\n invoice: string;\n onSuccess: () => void;\n}) => {\n const pool = new SimplePool();\n const normalizedRelays = Array.from(new Set([...relays, 'wss://relay.nostr.band']));\n const since = Math.floor((Date.now() - 24 * 60 * 60 * 1000) / 1000); // current time - 24 hours\n\n pool.subscribe(\n normalizedRelays,\n {\n kinds: [9735],\n '#p': [receiversPubKey],\n since,\n },\n {\n onevent(event: Event) {\n const tags = event.tags as [string, string][];\n if (tags.some(t => t[0] === 'bolt11' && t[1] === invoice)) {\n onSuccess();\n cleanup();\n }\n }\n }\n );\n\n const cleanup = () => {\n pool.close(normalizedRelays);\n };\n\n return cleanup;\n};\n"],"names":["profileCache","getProfileMetadata","authorId","pool","SimplePool","relays","event","getBatchedProfileMetadata","authorIds","uncachedIds","id","extractProfileMetadataContent","profileMetadata","getZapEndpoint","endpoint","nip57","signEvent","zapEvent","anon","isNip07ExtAvailable","ext","finalizeEvent","generateRandomPrivKey","makeZapEvent","profile","nip19Target","amount","comment","url","req","normalizeURL","fetchInvoice","zapEndpoint","normalizedRelays","invoiceUrl","res","json","invoice","reason","status","bytes","i","fetchTotalZapAmount","pubkey","normalizedUrl","totalAmount","zapDetails","filter","events","descriptionTag","_a","tag","zapRequest","amountTag","_b","kTag","_c","iTag","_d","iTagNormalized","e","error","a","b","listenForZapReceipt","receiversPubKey","onSuccess","since","t","cleanup"],"mappings":"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"}
|