import { Nip59, Nip01Signer } from "@welshman/signer" import { signer, repository, publishThunk, getMessagingRelayList } from "@welshman/app" import { getRelaysFromList } from "@welshman/util" import type { HashedEvent } from "@welshman/util" import { Router } from "@welshman/router" const TOPIC = "b7ed" // TODO: PROTOCOL.md §Event Kinds requires at least 16 bits of proof-of-work (NIP-13) // on each kind 1059 gift wrap. PoW is out of scope for this pass; the ["t","b7ed"] // topic tag below IS required and is always present. function inboxRelays(pubkey: string): string[] { const relays = getRelaysFromList(getMessagingRelayList(pubkey)) return relays.length ? relays : Router.get().ForPubkey(pubkey).getUrls() } /** Gift-wrap a rumor to one recipient (with the b7ed topic tag) and publish to their inbox relays. */ export async function deliverTo(recipient: string, rumor: HashedEvent): Promise { const $signer = signer.get() if (!$signer) { throw new Error("Cannot send without a signer") } const nip59 = new Nip59($signer, Nip01Signer.ephemeral()) const wrap = await nip59.wrap(recipient, rumor, [["t", TOPIC]]) publishThunk({ event: wrap, relays: inboxRelays(recipient) }) } /** * Broadcast one rumor to many recipients. Stores a local copy in the repository (so our own derived * state reflects what we sent) unless storeLocal is false. Per-recipient payloads (round-2 shares) call * deliverTo directly with storeLocal handled by the caller. Recipients should EXCLUDE self. */ export async function sendProtocolEvent(rumor: HashedEvent, recipients: string[], opts: { storeLocal?: boolean } = {}): Promise { if (opts.storeLocal !== false) { repository.publish(rumor) } await Promise.all(recipients.map(r => deliverTo(r, rumor).catch(e => console.error("deliver failed", r, e)))) }