mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 16:31:04 +00:00
Move zapper commands over
This commit is contained in:
parent
dd39413208
commit
44f65c4580
@ -42,7 +42,7 @@
|
|||||||
{:else if m.type === "note/create"}
|
{:else if m.type === "note/create"}
|
||||||
<NoteCreate pubkey={m.pubkey} quote={m.quote} writeTo={m.relays} />
|
<NoteCreate pubkey={m.pubkey} quote={m.quote} writeTo={m.relays} />
|
||||||
{:else if m.type === "zap/create"}
|
{:else if m.type === "zap/create"}
|
||||||
<ZapModal pubkey={m.pubkey} note={m.note} author={m.author} zapper={m.zapper} />
|
<ZapModal pubkey={m.pubkey} note={m.note} />
|
||||||
{:else if m.type === "notification/info"}
|
{:else if m.type === "notification/info"}
|
||||||
<NotificationInfo zaps={m.zaps} likes={m.likes} replies={m.replies} />
|
<NotificationInfo zaps={m.zaps} likes={m.likes} replies={m.replies} />
|
||||||
{:else if m.type === "thread/detail"}
|
{:else if m.type === "thread/detail"}
|
||||||
|
@ -57,7 +57,6 @@ export const Nip05 = engine.Nip05
|
|||||||
export const Nip24 = engine.Nip24
|
export const Nip24 = engine.Nip24
|
||||||
export const Nip28 = engine.Nip28
|
export const Nip28 = engine.Nip28
|
||||||
export const Nip44 = engine.Nip44
|
export const Nip44 = engine.Nip44
|
||||||
export const Nip57 = engine.Nip57
|
|
||||||
export const Nip59 = engine.Nip59
|
export const Nip59 = engine.Nip59
|
||||||
export const Nip65 = engine.Nip65
|
export const Nip65 = engine.Nip65
|
||||||
export const Outbox = engine.Outbox
|
export const Outbox = engine.Outbox
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
||||||
import RelayCard from "src/app/shared/RelayCard.svelte"
|
import RelayCard from "src/app/shared/RelayCard.svelte"
|
||||||
import {toastProgress} from "src/app/state"
|
import {toastProgress} from "src/app/state"
|
||||||
import {getUserRelayUrls} from "src/engine2"
|
import {zappers, getUserRelayUrls, processZaps} from "src/engine2"
|
||||||
import {Env, Nip57, Builder, Nip65, Keys, Outbox, user} from "src/app/engine"
|
import {Env, Builder, Nip65, Keys, Outbox, user} from "src/app/engine"
|
||||||
|
|
||||||
export let note
|
export let note
|
||||||
export let reply
|
export let reply
|
||||||
@ -24,7 +24,7 @@
|
|||||||
export let showEntire
|
export let showEntire
|
||||||
export let setFeedRelay
|
export let setFeedRelay
|
||||||
|
|
||||||
const zapper = Nip57.zappers.key(note.pubkey)
|
const zapper = zappers.key(note.pubkey)
|
||||||
const nevent = nip19.neventEncode({id: note.id, relays: [note.seen_on]})
|
const nevent = nip19.neventEncode({id: note.id, relays: [note.seen_on]})
|
||||||
const interpolate = (a, b) => t => a + Math.round((b - a) * t)
|
const interpolate = (a, b) => t => a + Math.round((b - a) * t)
|
||||||
const likesCount = tweened(0, {interpolate})
|
const likesCount = tweened(0, {interpolate})
|
||||||
@ -82,16 +82,14 @@
|
|||||||
$: allLikes = like ? likes.filter(n => n.id !== like?.id).concat(like) : likes
|
$: allLikes = like ? likes.filter(n => n.id !== like?.id).concat(like) : likes
|
||||||
$: $likesCount = allLikes.length
|
$: $likesCount = allLikes.length
|
||||||
|
|
||||||
$: zaps = Nip57.processZaps(note.zaps, note.pubkey)
|
$: zaps = processZaps(note.zaps, note.pubkey)
|
||||||
$: zap = zap || find(z => z.request.pubkey === Keys.pubkey.get(), zaps)
|
$: zap = zap || find(z => z.request.pubkey === Keys.pubkey.get(), zaps)
|
||||||
|
|
||||||
$: $zapsTotal =
|
$: $zapsTotal =
|
||||||
sum(
|
sum(
|
||||||
pluck(
|
pluck(
|
||||||
"invoiceAmount",
|
"invoiceAmount",
|
||||||
zap
|
zap ? zaps.filter(n => n.id !== zap?.id).concat(processZaps([zap], note.pubkey)) : zaps
|
||||||
? zaps.filter(n => n.id !== zap?.id).concat(Nip57.processZaps([zap], note.pubkey))
|
|
||||||
: zaps
|
|
||||||
)
|
)
|
||||||
) / 1000
|
) / 1000
|
||||||
|
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import {pipe, assoc, assocPath} from "ramda"
|
||||||
import {modal} from "src/partials/state"
|
import {modal} from "src/partials/state"
|
||||||
import Popover from "src/partials/Popover.svelte"
|
import Popover from "src/partials/Popover.svelte"
|
||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Card from "src/partials/Card.svelte"
|
import Card from "src/partials/Card.svelte"
|
||||||
import Heading from "src/partials/Heading.svelte"
|
import Heading from "src/partials/Heading.svelte"
|
||||||
|
import {people} from "src/engine2"
|
||||||
|
|
||||||
document.title = "About"
|
document.title = "About"
|
||||||
|
|
||||||
const hash = import.meta.env.VITE_BUILD_HASH
|
const hash = import.meta.env.VITE_BUILD_HASH
|
||||||
const nprofile =
|
const nprofile =
|
||||||
"nprofile1qqsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgspz3mhxue69uhhyetvv9ujuerpd46hxtnfduq3xamnwvaz7tmjv4kxz7tpvfkx2tn0wfnszymhwden5te0dehhxarj9cmrswpwdaexwqgmwaehxw309a3ksunfwd68q6tvdshxummnw3erztnrdakszynhwden5te0danxvcmgv95kutnsw43qzrthwden5te0dehhxtnvdakqzynhwden5te0wp6hyurvv4cxzeewv4eszxrhwden5te0wfjkccte9eekummjwsh8xmmrd9skckx3ht0"
|
"nprofile1qqsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgspz3mhxue69uhhyetvv9ujuerpd46hxtnfduq3xamnwvaz7tmjv4kxz7tpvfkx2tn0wfnszymhwden5te0dehhxarj9cmrswpwdaexwqgmwaehxw309a3ksunfwd68q6tvdshxummnw3erztnrdakszynhwden5te0danxvcmgv95kutnsw43qzrthwden5te0dehhxtnvdakqzynhwden5te0wp6hyurvv4cxzeewv4eszxrhwden5te0wfjkccte9eekummjwsh8xmmrd9skckx3ht0"
|
||||||
|
const pubkey = "8ec86ac9e10979998652068ee6b00223b8e3265aabb3fe28fb6b3b6e294adc96"
|
||||||
const npub = "npub1jlrs53pkdfjnts29kveljul2sm0actt6n8dxrrzqcersttvcuv3qdjynqn"
|
const npub = "npub1jlrs53pkdfjnts29kveljul2sm0actt6n8dxrrzqcersttvcuv3qdjynqn"
|
||||||
|
|
||||||
// Provide complete details in case they haven't loaded coracle's profile
|
// Provide complete details in case they haven't loaded coracle's profile
|
||||||
const zap = () =>
|
people.key(pubkey).update(
|
||||||
modal.push({
|
pipe(
|
||||||
type: "zap/create",
|
assocPath(["profile", "name"], "Coracle"),
|
||||||
pubkey: "8ec86ac9e10979998652068ee6b00223b8e3265aabb3fe28fb6b3b6e294adc96",
|
assoc("zapper", {
|
||||||
author: {
|
|
||||||
pubkey: "8ec86ac9e10979998652068ee6b00223b8e3265aabb3fe28fb6b3b6e294adc96",
|
|
||||||
name: "Coracle",
|
|
||||||
},
|
|
||||||
zapper: {
|
|
||||||
pubkey: "8ec86ac9e10979998652068ee6b00223b8e3265aabb3fe28fb6b3b6e294adc96",
|
|
||||||
lnurl:
|
lnurl:
|
||||||
"lnurl1dp68gurn8ghj7em909ek2u3wve6kuep09emk2mrv944kummhdchkcmn4wfk8qtmrdaexzcmvv5tqwy7g",
|
"lnurl1dp68gurn8ghj7em909ek2u3wve6kuep09emk2mrv944kummhdchkcmn4wfk8qtmrdaexzcmvv5tqwy7g",
|
||||||
callback: "https://api.geyser.fund/.well-known/lnurlp/coracle",
|
callback: "https://api.geyser.fund/.well-known/lnurlp/coracle",
|
||||||
nostrPubkey: "b6dcdddf86675287d1a4e8620d92aa905c258d850bf8cc923d39df1edfee5ee7",
|
nostrPubkey: "b6dcdddf86675287d1a4e8620d92aa905c258d850bf8cc923d39df1edfee5ee7",
|
||||||
maxSendable: 5000000000,
|
maxSendable: 5000000000,
|
||||||
minSendable: 1000,
|
minSendable: 1000,
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const zap = () => modal.push({type: "zap/create", pubkey})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Content gap="8" class="gap-8">
|
<Content gap="8" class="gap-8">
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
import Textarea from "src/partials/Textarea.svelte"
|
import Textarea from "src/partials/Textarea.svelte"
|
||||||
import {getSetting, getUserRelayUrls} from "src/engine2"
|
import {getSetting, requestZap, collectInvoice, loadZapResponse} from "src/engine2"
|
||||||
import {Directory, Nip65, Outbox, Network, Builder, Nip57} from "src/app/engine"
|
import {Directory} from "src/app/engine"
|
||||||
|
|
||||||
export let pubkey
|
export let pubkey
|
||||||
export let note = null
|
export let note = null
|
||||||
export let zapper = null
|
|
||||||
export let author = null
|
|
||||||
|
|
||||||
let sub
|
let sub
|
||||||
let zap = {
|
let zap = {
|
||||||
@ -25,27 +23,15 @@
|
|||||||
confirmed: false,
|
confirmed: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
const _zapper = zapper || Nip57.zappers.key(pubkey).get()
|
|
||||||
const _author = author || Directory.getProfile(pubkey)
|
|
||||||
|
|
||||||
const loadZapInvoice = async () => {
|
const loadZapInvoice = async () => {
|
||||||
zap.loading = true
|
zap.loading = true
|
||||||
|
|
||||||
const amount = zap.amount * 1000
|
const {invoice, relays} = await requestZap({
|
||||||
const relayLimit = getSetting("relay_limit")
|
|
||||||
const relays = note
|
|
||||||
? Nip65.getPublishHints(relayLimit, note, getUserRelayUrls("write"))
|
|
||||||
: Nip65.getPubkeyHints(relayLimit, pubkey, "read")
|
|
||||||
const rawEvent = Builder.requestZap(
|
|
||||||
relays,
|
|
||||||
zap.message,
|
|
||||||
pubkey,
|
pubkey,
|
||||||
note?.id,
|
event: note,
|
||||||
amount,
|
amount: zap.amount,
|
||||||
_zapper.lnurl
|
content: zap.message,
|
||||||
)
|
})
|
||||||
const signedEvent = await Outbox.prep(rawEvent)
|
|
||||||
const invoice = await Nip57.fetchInvoice(_zapper, signedEvent, amount)
|
|
||||||
|
|
||||||
// If they closed the dialog before fetch resolved, we're done
|
// If they closed the dialog before fetch resolved, we're done
|
||||||
if (!zap) {
|
if (!zap) {
|
||||||
@ -55,21 +41,14 @@
|
|||||||
zap.invoice = invoice
|
zap.invoice = invoice
|
||||||
zap.loading = false
|
zap.loading = false
|
||||||
|
|
||||||
await Nip57.collectInvoice(invoice)
|
await collectInvoice(invoice)
|
||||||
|
|
||||||
// Listen for the zap confirmation
|
// Listen for the zap confirmation
|
||||||
sub = Network.subscribe({
|
sub = loadZapResponse({relays, pubkey})
|
||||||
relays,
|
|
||||||
filter: {
|
sub.on("event", event => {
|
||||||
kinds: [9735],
|
|
||||||
authors: [_zapper.nostrPubkey],
|
|
||||||
"#p": [pubkey],
|
|
||||||
since: zap.startedAt - 10,
|
|
||||||
},
|
|
||||||
onEvent: event => {
|
|
||||||
zap.confirmed = true
|
zap.confirmed = true
|
||||||
setTimeout(() => modal.pop(), 1000)
|
setTimeout(() => modal.pop(), 1000)
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +60,7 @@
|
|||||||
<Content size="lg">
|
<Content size="lg">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="staatliches text-2xl">Send a zap</h1>
|
<h1 class="staatliches text-2xl">Send a zap</h1>
|
||||||
<p>to {Directory.displayProfile(_author)}</p>
|
<p>to {Directory.displayPubkey(pubkey)}</p>
|
||||||
</div>
|
</div>
|
||||||
{#if zap.confirmed}
|
{#if zap.confirmed}
|
||||||
<div class="flex items-center justify-center gap-2 text-gray-1">
|
<div class="flex items-center justify-center gap-2 text-gray-1">
|
||||||
|
@ -12,7 +12,6 @@ import {Nip05} from "./components/Nip05"
|
|||||||
import {Nip24} from "./components/Nip24"
|
import {Nip24} from "./components/Nip24"
|
||||||
import {Nip28} from "./components/Nip28"
|
import {Nip28} from "./components/Nip28"
|
||||||
import {Nip44} from "./components/Nip44"
|
import {Nip44} from "./components/Nip44"
|
||||||
import {Nip57} from "./components/Nip57"
|
|
||||||
import {Nip59} from "./components/Nip59"
|
import {Nip59} from "./components/Nip59"
|
||||||
import {Nip65} from "./components/Nip65"
|
import {Nip65} from "./components/Nip65"
|
||||||
import {Outbox} from "./components/Outbox"
|
import {Outbox} from "./components/Outbox"
|
||||||
@ -33,7 +32,6 @@ export class Engine {
|
|||||||
Nip24 = new Nip24()
|
Nip24 = new Nip24()
|
||||||
Nip28 = new Nip28()
|
Nip28 = new Nip28()
|
||||||
Nip44 = new Nip44()
|
Nip44 = new Nip44()
|
||||||
Nip57 = new Nip57()
|
|
||||||
Nip59 = new Nip59()
|
Nip59 = new Nip59()
|
||||||
Nip65 = new Nip65()
|
Nip65 = new Nip65()
|
||||||
Outbox = new Outbox()
|
Outbox = new Outbox()
|
||||||
|
@ -1,147 +0,0 @@
|
|||||||
import {Fetch, tryFunc} from "hurdak"
|
|
||||||
import {now, tryJson, hexToBech32, bech32ToHex} from "src/util/misc"
|
|
||||||
import {invoiceAmount} from "src/util/lightning"
|
|
||||||
import {warn} from "src/util/logger"
|
|
||||||
import {Tags} from "src/util/nostr"
|
|
||||||
import type {Engine} from "src/engine/Engine"
|
|
||||||
import type {Zapper, ZapEvent, Event} from "src/engine/types"
|
|
||||||
import {collection} from "src/engine/util/store"
|
|
||||||
|
|
||||||
export class Nip57 {
|
|
||||||
zappers = collection<Zapper>("pubkey")
|
|
||||||
|
|
||||||
processZaps = (zaps: Event[], pubkey: string) => {
|
|
||||||
const zapper = this.zappers.key(pubkey).get()
|
|
||||||
|
|
||||||
if (!zapper) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return zaps
|
|
||||||
.map((zap: Event) => {
|
|
||||||
const zapMeta = Tags.from(zap).asMeta() as {
|
|
||||||
bolt11: string
|
|
||||||
description: string
|
|
||||||
}
|
|
||||||
|
|
||||||
return tryJson(() => ({
|
|
||||||
...zap,
|
|
||||||
invoiceAmount: invoiceAmount(zapMeta.bolt11),
|
|
||||||
request: JSON.parse(zapMeta.description),
|
|
||||||
})) as ZapEvent
|
|
||||||
})
|
|
||||||
.filter((zap: ZapEvent) => {
|
|
||||||
if (!zap) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't count zaps that the user sent himself
|
|
||||||
if (zap.request.pubkey === pubkey) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const {invoiceAmount, request} = zap
|
|
||||||
const reqMeta = Tags.from(request).asMeta() as {
|
|
||||||
amount?: string
|
|
||||||
lnurl?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the zapper actually sent the requested amount (if it was supplied)
|
|
||||||
if (reqMeta.amount && parseInt(reqMeta.amount) !== invoiceAmount) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the sending client provided an lnurl tag, verify that too
|
|
||||||
if (reqMeta.lnurl && reqMeta.lnurl !== zapper.lnurl) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the zap note actually came from the recipient's zapper
|
|
||||||
if (zapper.nostrPubkey !== zap.pubkey) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getLnUrl(address: string): string {
|
|
||||||
// Try to parse it as a lud06 LNURL
|
|
||||||
if (address.startsWith("lnurl1")) {
|
|
||||||
return tryFunc(() => bech32ToHex(address)) as string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse it as a lud16 address
|
|
||||||
if (address.includes("@")) {
|
|
||||||
const [name, domain] = address.split("@")
|
|
||||||
|
|
||||||
if (domain && name) {
|
|
||||||
return `https://${domain}/.well-known/lnurlp/${name}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchInvoice(zapper, event, amount) {
|
|
||||||
const {callback, lnurl} = zapper
|
|
||||||
const s = encodeURI(JSON.stringify(event))
|
|
||||||
const res = await Fetch.fetchJson(`${callback}?amount=${amount}&nostr=${s}&lnurl=${lnurl}`)
|
|
||||||
|
|
||||||
if (!res.pr) {
|
|
||||||
warn(JSON.stringify(res))
|
|
||||||
}
|
|
||||||
|
|
||||||
return res?.pr
|
|
||||||
}
|
|
||||||
|
|
||||||
async collectInvoice(invoice) {
|
|
||||||
const {webln} = window as {webln?: any}
|
|
||||||
|
|
||||||
if (webln) {
|
|
||||||
await webln.enable()
|
|
||||||
|
|
||||||
try {
|
|
||||||
webln.sendPayment(invoice)
|
|
||||||
} catch (e) {
|
|
||||||
warn(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initialize(engine: Engine) {
|
|
||||||
engine.Events.addHandler(0, (e: Event) => {
|
|
||||||
tryJson(async () => {
|
|
||||||
const kind0 = JSON.parse(e.content)
|
|
||||||
const zapper = this.zappers.key(e.pubkey)
|
|
||||||
const address = (kind0.lud16 || kind0.lud06 || "").toLowerCase()
|
|
||||||
|
|
||||||
if (!address || e.created_at < zapper.get()?.created_at) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const lnurl = this.getLnUrl(address)
|
|
||||||
|
|
||||||
if (!lnurl) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = engine.Settings.dufflepud("zapper/info")
|
|
||||||
const result = (await tryFunc(() => Fetch.postJson(url, {lnurl}))) as any
|
|
||||||
|
|
||||||
if (!result?.allowsNostr || !result?.nostrPubkey) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
zapper.set({
|
|
||||||
pubkey: e.pubkey,
|
|
||||||
lnurl: hexToBech32("lnurl", lnurl),
|
|
||||||
callback: result.callback,
|
|
||||||
minSendable: result.minSendable,
|
|
||||||
maxSendable: result.maxSendable,
|
|
||||||
nostrPubkey: result.nostrPubkey,
|
|
||||||
created_at: e.created_at,
|
|
||||||
updated_at: now(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,7 +13,6 @@ export {Nip04} from "./components/Nip04"
|
|||||||
export {Nip05} from "./components/Nip05"
|
export {Nip05} from "./components/Nip05"
|
||||||
export {Nip28} from "./components/Nip28"
|
export {Nip28} from "./components/Nip28"
|
||||||
export {Nip44} from "./components/Nip44"
|
export {Nip44} from "./components/Nip44"
|
||||||
export {Nip57} from "./components/Nip57"
|
|
||||||
export {Nip65} from "./components/Nip65"
|
export {Nip65} from "./components/Nip65"
|
||||||
|
|
||||||
export {User} from "./util/User"
|
export {User} from "./util/User"
|
||||||
|
@ -4,4 +4,5 @@ export * from "./nip04"
|
|||||||
export * from "./nip24"
|
export * from "./nip24"
|
||||||
export * from "./nip28"
|
export * from "./nip28"
|
||||||
export * from "./nip32"
|
export * from "./nip32"
|
||||||
|
export * from "./nip57"
|
||||||
export * from "./nip95"
|
export * from "./nip95"
|
||||||
|
56
src/engine2/commands/nip57.ts
Normal file
56
src/engine2/commands/nip57.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import {Fetch} from "hurdak"
|
||||||
|
import {warn} from "src/util/logger"
|
||||||
|
import {people} from "src/engine2/state"
|
||||||
|
import {signer, getSetting, getPubkeyHints, getPublishHints} from "src/engine2/queries"
|
||||||
|
import {buildEvent} from "./util"
|
||||||
|
|
||||||
|
export async function requestZap({content, amount, pubkey, event}) {
|
||||||
|
const person = people.key(pubkey).get()
|
||||||
|
|
||||||
|
if (!person?.zapper) {
|
||||||
|
throw new Error("Can't zap a person without a zapper")
|
||||||
|
}
|
||||||
|
|
||||||
|
const {callback, lnurl} = person.zapper
|
||||||
|
const msats = amount * 1000
|
||||||
|
const relays = event
|
||||||
|
? getPublishHints(getSetting("relay_limit"), event)
|
||||||
|
: getPubkeyHints(getSetting("relay_limit"), pubkey, "read")
|
||||||
|
|
||||||
|
const tags = [
|
||||||
|
["relays", ...relays],
|
||||||
|
["amount", msats.toString()],
|
||||||
|
["lnurl", lnurl],
|
||||||
|
["p", pubkey],
|
||||||
|
]
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
tags.push(["e", event.id])
|
||||||
|
}
|
||||||
|
|
||||||
|
const zap = signer.get().prepAsUser(buildEvent(9734, {content, tags}))
|
||||||
|
const zapString = encodeURI(JSON.stringify(zap))
|
||||||
|
const res = await Fetch.fetchJson(
|
||||||
|
`${callback}?amount=${amount}&nostr=${zapString}&lnurl=${lnurl}`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!res.pr) {
|
||||||
|
warn(JSON.stringify(res))
|
||||||
|
}
|
||||||
|
|
||||||
|
return {relays, invoice: res?.pr}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function collectInvoice(invoice) {
|
||||||
|
const {webln} = window as {webln?: any}
|
||||||
|
|
||||||
|
if (webln) {
|
||||||
|
await webln.enable()
|
||||||
|
|
||||||
|
try {
|
||||||
|
webln.sendPayment(invoice)
|
||||||
|
} catch (e) {
|
||||||
|
warn(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
import {Fetch} from "hurdak"
|
|
||||||
import {tryJson} from "src/util/misc"
|
import {tryJson} from "src/util/misc"
|
||||||
import {invoiceAmount} from "src/util/lightning"
|
import {invoiceAmount} from "src/util/lightning"
|
||||||
import {warn} from "src/util/logger"
|
|
||||||
import {Tags} from "src/util/nostr"
|
import {Tags} from "src/util/nostr"
|
||||||
import type {Event, ZapEvent} from "src/engine2/model"
|
import type {Event, ZapEvent} from "src/engine2/model"
|
||||||
import {people} from "src/engine2/state"
|
import {people} from "src/engine2/state"
|
||||||
@ -60,29 +58,3 @@ export function processZaps(zaps: Event[], pubkey: string) {
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchInvoice(zapper, event, amount) {
|
|
||||||
const {callback, lnurl} = zapper
|
|
||||||
const s = encodeURI(JSON.stringify(event))
|
|
||||||
const res = await Fetch.fetchJson(`${callback}?amount=${amount}&nostr=${s}&lnurl=${lnurl}`)
|
|
||||||
|
|
||||||
if (!res.pr) {
|
|
||||||
warn(JSON.stringify(res))
|
|
||||||
}
|
|
||||||
|
|
||||||
return res?.pr
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function collectInvoice(invoice) {
|
|
||||||
const {webln} = window as {webln?: any}
|
|
||||||
|
|
||||||
if (webln) {
|
|
||||||
await webln.enable()
|
|
||||||
|
|
||||||
try {
|
|
||||||
webln.sendPayment(invoice)
|
|
||||||
} catch (e) {
|
|
||||||
warn(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -125,12 +125,12 @@ export const getRootHints = hintSelector(function* (event) {
|
|||||||
// anyone else who is tagged in the original event or the reply. Get everyone's read
|
// anyone else who is tagged in the original event or the reply. Get everyone's read
|
||||||
// relays. Limit how many per pubkey we publish to though. We also want to advertise
|
// relays. Limit how many per pubkey we publish to though. We also want to advertise
|
||||||
// our content to our followers, so publish to our write relays as well.
|
// our content to our followers, so publish to our write relays as well.
|
||||||
export const getPublishHints = (limit: number, event: Event, extraRelays: string[] = []) => {
|
export const getPublishHints = (limit: number, event: Event) => {
|
||||||
const pubkeys = Tags.from(event).type("p").values().all()
|
const pubkeys = Tags.from(event).type("p").values().all()
|
||||||
const hintGroups = pubkeys.map(pubkey => getPubkeyRelayUrls(pubkey, RelayMode.Read))
|
const hintGroups = pubkeys.map(pubkey => getPubkeyRelayUrls(pubkey, RelayMode.Read))
|
||||||
const authorRelays = getPubkeyRelayUrls(event.pubkey, RelayMode.Write)
|
const authorRelays = getPubkeyRelayUrls(event.pubkey, RelayMode.Write)
|
||||||
|
|
||||||
return mergeHints(limit, hintGroups.concat([extraRelays, authorRelays]))
|
return mergeHints(limit, [...hintGroups, authorRelays, getUserRelayUrls(RelayMode.Write)])
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getInboxHints = (limit: number, pubkeys: string[]) =>
|
export const getInboxHints = (limit: number, pubkeys: string[]) =>
|
||||||
|
@ -5,4 +5,5 @@ export * from "./pubkeys"
|
|||||||
export * from "./subscription"
|
export * from "./subscription"
|
||||||
export * from "./thread"
|
export * from "./thread"
|
||||||
export * from "./nip04"
|
export * from "./nip04"
|
||||||
|
export * from "./nip57"
|
||||||
export * from "./nip59"
|
export * from "./nip59"
|
||||||
|
19
src/engine2/requests/nip57.ts
Normal file
19
src/engine2/requests/nip57.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {now} from "src/util/misc"
|
||||||
|
import {people} from "src/engine2/state"
|
||||||
|
import {Subscription} from "./subscription"
|
||||||
|
|
||||||
|
export function loadZapResponse({pubkey, relays}) {
|
||||||
|
const {zapper} = people.key(pubkey).get()
|
||||||
|
|
||||||
|
return new Subscription({
|
||||||
|
relays,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
kinds: [9735],
|
||||||
|
authors: [zapper.nostrPubkey],
|
||||||
|
"#p": [pubkey],
|
||||||
|
since: now() - 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user