From 483141f847fcc93647a6a999ed254513c6d07597 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 9 Jun 2026 10:52:57 -0700 Subject: [PATCH] Try to make applesauce work --- package.json | 2 + pnpm-lock.yaml | 6 +++ src/Layout.tsx | 11 ++-- src/components/AccountPage.tsx | 64 ++++++---------------- src/components/Avatar.tsx | 3 +- src/components/PubkeyInput.tsx | 3 +- src/components/forms/DkgForms.tsx | 16 +++--- src/components/forms/ResharingForms.tsx | 13 ++--- src/components/forms/SigningForms.tsx | 4 +- src/hooks.ts | 40 ++++++++++++++ src/lib/profiles.ts | 19 ++----- src/lib/relays.ts | 67 +++++++++++------------ src/nostr.ts | 71 ++++++++----------------- src/store.ts | 14 ++--- 14 files changed, 146 insertions(+), 187 deletions(-) diff --git a/package.json b/package.json index 5432e24..e664e1a 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,14 @@ "@welshman/util": "^0.8.16", "applesauce-accounts": "^6.0.0", "applesauce-actions": "^6.1.0", + "applesauce-common": "^6.1.0", "applesauce-core": "^6.1.0", "applesauce-factory": "^4.0.0", "applesauce-relay": "^6.0.3", "applesauce-signers": "^6.0.1", "applesauce-solidjs": "^4.0.0", "idb": "^8.0.3", + "rxjs": "^7.8.2", "solid-js": "^1.9.13", "solid-toast": "^0.5.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 383f108..3e08351 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: applesauce-actions: specifier: ^6.1.0 version: 6.1.0(typescript@6.0.3) + applesauce-common: + specifier: ^6.1.0 + version: 6.1.0(typescript@6.0.3) applesauce-core: specifier: ^6.1.0 version: 6.1.0(typescript@6.0.3) @@ -44,6 +47,9 @@ importers: idb: specifier: ^8.0.3 version: 8.0.3 + rxjs: + specifier: ^7.8.2 + version: 7.8.2 solid-js: specifier: ^1.9.13 version: 1.9.13 diff --git a/src/Layout.tsx b/src/Layout.tsx index 81408df..862391c 100644 --- a/src/Layout.tsx +++ b/src/Layout.tsx @@ -8,17 +8,12 @@ import { ProposeQuorum } from "./components/forms/DkgForms" import { ProposeResharing } from "./components/forms/ResharingForms" import { ProposeSign } from "./components/forms/SigningForms" import Avatar from "./components/Avatar" -import { fetchProfile, getDisplayName, useProfileEvent } from "./lib/profiles" +import { getDisplayName } from "./lib/profiles" +import { useActivePubkey, useProfileEvent } from "./hooks" function SidebarContent(props: { onNew: () => void }) { - const pubkey = () => account()?.pubkey ?? "" + const pubkey = useActivePubkey() const shortKey = () => `${pubkey().slice(0, 8)}…${pubkey().slice(-4)}` - - createEffect(() => { - const pk = account()?.pubkey - if (pk) { fetchProfile(pk) } - }) - const profileEvent = useProfileEvent(pubkey) const displayName = () => getDisplayName(profileEvent(), shortKey()) diff --git a/src/components/AccountPage.tsx b/src/components/AccountPage.tsx index 603a132..4404c78 100644 --- a/src/components/AccountPage.tsx +++ b/src/components/AccountPage.tsx @@ -1,50 +1,27 @@ -import { createSignal, createEffect, onCleanup, For, Show } from "solid-js" +import { createSignal, For, Show } from "solid-js" import { now } from "@welshman/lib" import { publish, eventStore } from "../nostr" import { account } from "../store" -import { - parseRelayList, - parseOutboxRelays, - INDEXER_RELAYS, -} from "../lib/relays" -import { useProfileEvent, getDisplayName } from "../lib/profiles" +import { INDEXER_RELAYS } from "../lib/relays" +import { getDisplayName } from "../lib/profiles" +import { useActivePubkey, useProfileEvent, useMessagingRelays, useOutboxRelays } from "../hooks" import Avatar from "./Avatar" -import type { NostrEvent } from "applesauce-core/helpers/event" export default function AccountPage() { - const pubkey = () => account()?.pubkey ?? "" + const pubkey = useActivePubkey() const profileEvent = useProfileEvent(pubkey) + const messagingRelays = useMessagingRelays(pubkey) + const outboxRelays = useOutboxRelays(pubkey) const displayName = () => getDisplayName(profileEvent(), "") - const [relays, setRelays] = createSignal([]) - const [outboxEvent, setOutboxEvent] = createSignal() const [newRelay, setNewRelay] = createSignal("") const [publishing, setPublishing] = createSignal(false) const [copied, setCopied] = createSignal(false) const [addError, setAddError] = createSignal("") - // Sync relay list from kind 10050 in EventStore - createEffect(() => { - const pk = pubkey() - if (!pk) { setRelays([]); return } - const sub = eventStore.replaceable(10050, pk).subscribe(e => { - if (e) setRelays(parseRelayList(e)) - }) - onCleanup(() => sub.unsubscribe()) - }) - - // Track kind 10002 (outbox relay list) for publishing target - createEffect(() => { - const pk = pubkey() - if (!pk) { setOutboxEvent(undefined); return } - const sub = eventStore.replaceable(10002, pk).subscribe(e => setOutboxEvent(e ?? undefined)) - onCleanup(() => sub.unsubscribe()) - }) - async function publishRelays(updated: string[]): Promise { const acc = account() if (!acc) return - setPublishing(true) try { const signed = await acc.signEvent({ @@ -53,11 +30,8 @@ export default function AccountPage() { tags: updated.map(r => ["relay", r]), created_at: now(), }) - - const outbox = outboxEvent() - const targetRelays = outbox ? parseOutboxRelays(outbox) : INDEXER_RELAYS - - await publish(targetRelays, signed) + const targets = outboxRelays().length ? outboxRelays() : INDEXER_RELAYS + await publish(targets, signed) eventStore.add(signed) } finally { setPublishing(false) @@ -67,27 +41,21 @@ export default function AccountPage() { async function addRelay() { setAddError("") const relay = newRelay().trim() - if (!relay) return if (!relay.startsWith("wss://") && !relay.startsWith("ws://")) { setAddError("Relay URL must start with wss:// or ws://") return } - if (relays().includes(relay)) { + if (messagingRelays().includes(relay)) { setAddError("Already in your relay list") return } - - const updated = [...relays(), relay] - setRelays(updated) setNewRelay("") - await publishRelays(updated) + await publishRelays([...messagingRelays(), relay]) } async function removeRelay(relay: string) { - const updated = relays().filter(r => r !== relay) - setRelays(updated) - await publishRelays(updated) + await publishRelays(messagingRelays().filter(r => r !== relay)) } async function copyPubkey() { @@ -136,18 +104,18 @@ export default function AccountPage() { {/* Inbox relay list */}
-

Inbox Relays (kind 10050)

+

Messaging Relays (kind 10050)

0} + when={messagingRelays().length > 0} fallback={

- No inbox relays published yet. + No messaging relays published yet.

} >
    - + {(relay) => (
  • diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index 0085b27..ee35100 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -1,5 +1,6 @@ import { createSignal, Show, createEffect } from "solid-js" -import { getDisplayName, getProfilePicture, useProfileEvent } from "../lib/profiles" +import { getDisplayName, getProfilePicture } from "../lib/profiles" +import { useProfileEvent } from "../hooks" export default function Avatar(props: { pubkey: string; size?: string }) { const [imgError, setImgError] = createSignal(false) diff --git a/src/components/PubkeyInput.tsx b/src/components/PubkeyInput.tsx index a721635..f52940d 100644 --- a/src/components/PubkeyInput.tsx +++ b/src/components/PubkeyInput.tsx @@ -1,7 +1,8 @@ import { createSignal, createEffect, For, Show, onMount, onCleanup } from "solid-js" import { normalizeToPubkey } from "applesauce-core/helpers" import type { NostrEvent } from "applesauce-core/helpers/event" -import { fetchProfile, searchProfiles, getDisplayName, useProfileEvent } from "../lib/profiles" +import { fetchProfile, searchProfiles, getDisplayName } from "../lib/profiles" +import { useProfileEvent } from "../hooks" import Avatar from "./Avatar" interface Props { diff --git a/src/components/forms/DkgForms.tsx b/src/components/forms/DkgForms.tsx index 596949c..e391e56 100644 --- a/src/components/forms/DkgForms.tsx +++ b/src/components/forms/DkgForms.tsx @@ -1,8 +1,8 @@ -import { createSignal, createEffect, Show } from "solid-js" +import { createSignal, Show } from "solid-js" import type { DkgSession } from "../../models" import PubkeyInput from "../PubkeyInput" -import { account } from "../../store" -import { validateInboxRelays } from "../../lib/relays" +import { validateMessagingRelays } from "../../lib/relays" +import { useActivePubkey, useAutoThreshold } from "../../hooks" const inputClass = "w-full px-3 py-2 text-sm border border-gray-200 dark:border-neutral-600 rounded-lg bg-white dark:bg-neutral-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500" @@ -14,13 +14,9 @@ const secondaryButtonClass = "px-4 py-2 text-sm font-medium rounded-lg border border-gray-200 dark:border-neutral-600 text-gray-700 dark:text-neutral-300 hover:bg-gray-50 dark:hover:bg-neutral-700 transition-colors" export function ProposeQuorum(props: { onClose: () => void }) { - const selfPubkey = () => account()?.pubkey ?? "" + const selfPubkey = useActivePubkey() const [members, setMembers] = createSignal(selfPubkey() ? [selfPubkey()] : []) - const [threshold, setThreshold] = createSignal(1) - - createEffect(() => { - setThreshold(Math.max(1, Math.floor(members().length * 2 / 3))) - }) + const [threshold, setThreshold] = useAutoThreshold(members) const [error, setError] = createSignal("") const [submitting, setSubmitting] = createSignal(false) @@ -41,7 +37,7 @@ export function ProposeQuorum(props: { onClose: () => void }) { setError("") setSubmitting(true) - const relayError = await validateInboxRelays(pubkeys) + const relayError = await validateMessagingRelays(pubkeys) setSubmitting(false) if (relayError) { diff --git a/src/components/forms/ResharingForms.tsx b/src/components/forms/ResharingForms.tsx index a105320..3f63e25 100644 --- a/src/components/forms/ResharingForms.tsx +++ b/src/components/forms/ResharingForms.tsx @@ -1,15 +1,12 @@ -import { createSignal, createEffect, Show } from "solid-js" +import { createSignal, Show } from "solid-js" import type { ResharingSession } from "../../models" import PubkeyInput from "../PubkeyInput" -import { validateInboxRelays } from "../../lib/relays" +import { validateMessagingRelays } from "../../lib/relays" +import { useAutoThreshold } from "../../hooks" export function ProposeResharing(props: { quorumPubkey: string; onClose: () => void }) { const [newMembers, setNewMembers] = createSignal([]) - const [newThreshold, setNewThreshold] = createSignal(0) - - createEffect(() => { - setNewThreshold(Math.max(1, Math.floor(newMembers().length * 2 / 3))) - }) + const [newThreshold, setNewThreshold] = useAutoThreshold(newMembers) const [error, setError] = createSignal("") const [submitting, setSubmitting] = createSignal(false) @@ -30,7 +27,7 @@ export function ProposeResharing(props: { quorumPubkey: string; onClose: () => v } setSubmitting(true) - const relayError = await validateInboxRelays(members) + const relayError = await validateMessagingRelays(members) setSubmitting(false) if (relayError) { diff --git a/src/components/forms/SigningForms.tsx b/src/components/forms/SigningForms.tsx index 845c238..d8aa16a 100644 --- a/src/components/forms/SigningForms.tsx +++ b/src/components/forms/SigningForms.tsx @@ -1,7 +1,7 @@ import { createSignal } from "solid-js" import type { SigningSession } from "../../models" import { quora } from "../../store" -import { validateInboxRelays } from "../../lib/relays" +import { validateMessagingRelays } from "../../lib/relays" export function ProposeSign(props: { quorumPubkey: string; onClose: () => void }) { const [message, setMessage] = createSignal("") @@ -19,7 +19,7 @@ export function ProposeSign(props: { quorumPubkey: string; onClose: () => void } setError("") setSubmitting(true) - const relayError = await validateInboxRelays(memberPubkeys()) + const relayError = await validateMessagingRelays(memberPubkeys()) setSubmitting(false) if (relayError) { diff --git a/src/hooks.ts b/src/hooks.ts index e69de29..48f4824 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -0,0 +1,40 @@ +import { createSignal, createEffect, onCleanup } from "solid-js" +import type { NostrEvent } from "applesauce-core/helpers/event" +import { account } from "./store" +import { eventStore } from "./nostr" +import { parseRelayList, parseOutboxRelays } from "./lib/relays" + +export function useActivePubkey(): () => string { + return () => account()?.pubkey ?? "" +} + +export function useAutoThreshold(members: () => string[]): [() => number, (n: number) => void] { + const [threshold, setThreshold] = createSignal(1) + createEffect(() => setThreshold(Math.max(1, Math.floor(members().length * 2 / 3)))) + return [threshold, setThreshold] +} + +function useReplaceable(kind: number, pubkey: () => string): () => NostrEvent | undefined { + const [event, setEvent] = createSignal() + createEffect(() => { + const pk = pubkey() + if (!pk) { setEvent(undefined); return } + const sub = eventStore.replaceable(kind, pk).subscribe(e => setEvent(e ?? undefined)) + onCleanup(() => sub.unsubscribe()) + }) + return event +} + +export function useProfileEvent(pubkey: () => string): () => NostrEvent | undefined { + return useReplaceable(0, pubkey) +} + +export function useMessagingRelays(pubkey: () => string): () => string[] { + const event = useReplaceable(10050, pubkey) + return () => { const e = event(); return e ? parseRelayList(e) : [] } +} + +export function useOutboxRelays(pubkey: () => string): () => string[] { + const event = useReplaceable(10002, pubkey) + return () => { const e = event(); return e ? parseOutboxRelays(e) : [] } +} diff --git a/src/lib/profiles.ts b/src/lib/profiles.ts index a86f589..eb80353 100644 --- a/src/lib/profiles.ts +++ b/src/lib/profiles.ts @@ -1,16 +1,14 @@ -import { createSignal, createEffect, onCleanup } from "solid-js" import { getDisplayName, getProfilePicture } from "applesauce-core/helpers" import type { NostrEvent } from "applesauce-core/helpers/event" import { completeOnEose, onlyEvents, storeEvents } from "applesauce-relay" import { pool, eventStore } from "../nostr" -import { SEARCH_RELAYS, getOutboxRelays } from "./relays" +import { SEARCH_RELAYS, loadOutboxRelays } from "./relays" export { getDisplayName, getProfilePicture } export function fetchProfile(pubkey: string): void { - if (!pubkey || eventStore.hasReplaceable(0, pubkey)) return - - getOutboxRelays(pubkey).then(relays => { + if (!pubkey) return + loadOutboxRelays(pubkey).then(relays => { if (!relays.length) return pool.subscription(relays, { kinds: [0], authors: [pubkey], limit: 1 }) .pipe(storeEvents(eventStore), completeOnEose()) @@ -29,14 +27,3 @@ export function searchProfiles(query: string, onResult: (event: NostrEvent) => v const timeout = setTimeout(() => sub.unsubscribe(), 4000) return () => { clearTimeout(timeout); sub.unsubscribe() } } - -export function useProfileEvent(pubkey: () => string): () => NostrEvent | undefined { - const [event, setEvent] = createSignal() - createEffect(() => { - const pk = pubkey() - if (!pk) { setEvent(undefined); return } - const sub = eventStore.replaceable(0, pk).subscribe(e => setEvent(e ?? undefined)) - onCleanup(() => sub.unsubscribe()) - }) - return event -} diff --git a/src/lib/relays.ts b/src/lib/relays.ts index e591713..775f4e2 100644 --- a/src/lib/relays.ts +++ b/src/lib/relays.ts @@ -1,8 +1,11 @@ import { completeOnEose, onlyEvents, storeEvents } from "applesauce-relay" import { lastValueFrom } from "applesauce-core/observable" +import { timer, takeUntil } from "rxjs" import { pool, eventStore } from "../nostr" import type { NostrEvent } from "applesauce-core/helpers/event" +const RELAY_TIMEOUT_MS = 10_000 + export const SEARCH_RELAYS: string[] = (import.meta.env.VITE_SEARCH_RELAYS ?? "") .split(",") .map((r: string) => r.trim()) @@ -24,32 +27,29 @@ export function parseOutboxRelays(event: NostrEvent): string[] { .filter(Boolean) } -export async function getOutboxRelays(pubkey: string): Promise { - if (!eventStore.hasReplaceable(10002, pubkey) && INDEXER_RELAYS.length) { - await lastValueFrom( - pool.subscription(INDEXER_RELAYS, { kinds: [10002], authors: [pubkey], limit: 1 }) - .pipe(storeEvents(eventStore), completeOnEose()), - ).catch(() => {}) - } - const event = eventStore.getReplaceable(10002, pubkey) +// Fetch kind 10002 from the indexer for a single pubkey and return its write relays. +export async function loadOutboxRelays(pubkey: string): Promise { + if (!INDEXER_RELAYS.length) return [] + const event = await lastValueFrom( + pool.subscription(INDEXER_RELAYS, { kinds: [10002], authors: [pubkey], limit: 1 }) + .pipe(storeEvents(eventStore), completeOnEose(), onlyEvents(), takeUntil(timer(RELAY_TIMEOUT_MS))) as any, + ).catch((): NostrEvent | undefined => undefined) return event ? parseOutboxRelays(event) : [] } -export function fetchRelayLists(pubkeys: string[]): void { - const toFetch = pubkeys.filter(pk => pk && !eventStore.hasReplaceable(10002, pk)) - if (!toFetch.length || !INDEXER_RELAYS.length) return - - pool.subscription(INDEXER_RELAYS, { kinds: [10002], authors: toFetch }) +// Batch-fetch kind 10002 for multiple pubkeys (fire-and-forget). +export function loadRelayLists(pubkeys: string[]): void { + if (!pubkeys.length || !INDEXER_RELAYS.length) return + pool.subscription(INDEXER_RELAYS, { kinds: [10002], authors: pubkeys }) .pipe(storeEvents(eventStore), completeOnEose()) .subscribe() } -export function fetchInboxLists(pubkeys: string[]): void { - const toFetch = pubkeys.filter(pk => pk && !eventStore.hasReplaceable(10050, pk)) - if (!toFetch.length) return - - for (const pubkey of toFetch) { - getOutboxRelays(pubkey).then(relays => { +// Batch-fetch kind 10050 for multiple pubkeys via their outbox relays (fire-and-forget). +export function loadMessagingLists(pubkeys: string[]): void { + if (!pubkeys.length) return + for (const pubkey of pubkeys) { + loadOutboxRelays(pubkey).then(relays => { if (!relays.length) return pool.subscription(relays, { kinds: [10050], authors: [pubkey], limit: 1 }) .pipe(storeEvents(eventStore), completeOnEose()) @@ -58,29 +58,24 @@ export function fetchInboxLists(pubkeys: string[]): void { } } -export async function validateInboxRelays(pubkeys: string[]): Promise { +// Validate that all pubkeys have a published kind 10050 with at least one relay. +export async function validateMessagingRelays(pubkeys: string[]): Promise { if (!pubkeys.length) return null if (!INDEXER_RELAYS.length) { - return "No indexer relays configured — cannot verify member inbox relay lists" + return "No indexer relays configured — cannot verify member messaging relay lists" } - await Promise.all(pubkeys.map(async pubkey => { - if (eventStore.hasReplaceable(10050, pubkey)) return - - const relays = await getOutboxRelays(pubkey) - if (!relays.length) return - - await lastValueFrom( + const results = await Promise.all(pubkeys.map(async pubkey => { + const relays = await loadOutboxRelays(pubkey) + if (!relays.length) return false + const event = await lastValueFrom( pool.subscription(relays, { kinds: [10050], authors: [pubkey], limit: 1 }) - .pipe(storeEvents(eventStore), completeOnEose()), - ).catch(() => {}) + .pipe(storeEvents(eventStore), completeOnEose(), onlyEvents(), takeUntil(timer(RELAY_TIMEOUT_MS))) as any, + ).catch((): NostrEvent | undefined => undefined) + return !!event && parseRelayList(event).length > 0 })) - const missing = pubkeys.filter(pk => { - const event = eventStore.getReplaceable(10050, pk) - return !event || !parseRelayList(event).length - }) - + const missing = pubkeys.filter((_, i) => !results[i]) if (!missing.length) return null - return `No inbox relays found for: ${missing.map(pk => pk.slice(0, 8) + "…").join(", ")}` + return `No messaging relays found for: ${missing.map(pk => pk.slice(0, 8) + "…").join(", ")}` } diff --git a/src/nostr.ts b/src/nostr.ts index b23b1ac..a16988d 100644 --- a/src/nostr.ts +++ b/src/nostr.ts @@ -1,37 +1,21 @@ import { RelayPool, onlyEvents } from "applesauce-relay" import { EventStore } from "applesauce-core" import type { NostrEvent } from "applesauce-core/helpers/event" +import { unlockGiftWrap } from "applesauce-common/helpers/gift-wrap" import type { ISigner } from "applesauce-signers" -import { parseJson } from "@welshman/lib" -import { storeEvent, getAllEvents, demoteOldEvents } from "./storage" +import { demoteOldEvents, storeEvent } from "./storage" export const eventStore = new EventStore() -// Rumors are unsigned inner events — disable sig verification so they store cleanly. -eventStore.verifyEvent = undefined +// Maintain storage health on startup (fire-and-forget) +demoteOldEvents() -// On startup: run demotion pass then load all stored protocol events into memory. -;(async () => { - await demoteOldEvents() - const events = await getAllEvents() - for (const event of events) { - eventStore.add(event) - } -})() - -export function addEvent(event: NostrEvent): void { - eventStore.add(event) - storeEvent(event) -} - -// Shape of the object returned by Observable.subscribe() type Subscription = { unsubscribe(): void } export const pool = new RelayPool() -export const INBOX_RELAYS: string[] = [] +export const MESSAGING_RELAYS: string[] = [] -// Protocol event kinds produced by protocol.ts (inner rumor kinds) const PROTOCOL_KIND_MIN = 7050 const PROTOCOL_KIND_MAX = 7061 @@ -44,44 +28,31 @@ export function subscribeInbox( throw new Error("Signer does not support NIP-44 encryption") } - const subscription = pool + return pool .subscription(relays, { kinds: [1059], "#p": [pubkey], "#t": ["b7ed"] }) .pipe(onlyEvents()) .subscribe({ next: async (wrap: NostrEvent) => { + // Gift wraps are properly signed — add to EventStore as-is. + eventStore.add(wrap) + + let rumor try { - const sealJson = await signer.nip44!.decrypt(wrap.pubkey, wrap.content) - const seal = parseJson(sealJson) - if (!seal) { - return - } - - const rumorJson = await signer.nip44!.decrypt(seal.pubkey, seal.content) - const rumor = parseJson(rumorJson) - if (!rumor) { - return - } - - // NIP-59: the rumor's claimed author must match the seal's authenticated author. - // The seal is MAC-authenticated; the rumor's pubkey field is untrusted plaintext. - // Without this check a malicious sealer can forge any rumor.pubkey, - // which would let them impersonate a FROST participant. - if (seal.pubkey !== rumor.pubkey) { - return - } - - if (rumor.kind < PROTOCOL_KIND_MIN || rumor.kind > PROTOCOL_KIND_MAX) { - return - } - - addEvent(rumor as NostrEvent) + // NIP-59 unwrap: decrypts seal → rumor, verifies seal.pubkey === rumor.pubkey. + // Seal and rumor are cached in applesauce's internal gift-wrap memory, + // intentionally isolated from the main EventStore. + rumor = await unlockGiftWrap(wrap, signer) } catch { - // Silently skip events that fail to decrypt or parse + return } + + if (rumor.kind < PROTOCOL_KIND_MIN || rumor.kind > PROTOCOL_KIND_MAX) return + + // Persist the rumor for log display and session rebuilding. + // Rumors are unsigned (no sig); storage serialises to JSON and never verifies. + storeEvent(rumor as unknown as NostrEvent) }, }) - - return subscription } export async function publish(relays: string[], event: NostrEvent): Promise { diff --git a/src/store.ts b/src/store.ts index 6c60b3e..4c8ed9f 100644 --- a/src/store.ts +++ b/src/store.ts @@ -5,9 +5,9 @@ import { registerCommonAccountTypes } from "applesauce-accounts/accounts/common" import type { IAccount } from "applesauce-accounts" import { parseJson } from "@welshman/lib" import { toast } from "solid-toast" -import { subscribeInbox, INBOX_RELAYS } from "./nostr" +import { subscribeInbox, MESSAGING_RELAYS } from "./nostr" import type { QuorumRecord, DkgSession, ResharingSession, SigningSession } from "./models" -import { fetchRelayLists, fetchInboxLists } from "./lib/relays" +import { loadRelayLists, loadMessagingLists } from "./lib/relays" import { fetchProfile } from "./lib/profiles" // Shape of the object returned by Observable.subscribe() @@ -98,7 +98,7 @@ createEffect(() => { } try { - inboxSub = subscribeInbox(INBOX_RELAYS, acc.pubkey, acc) + inboxSub = subscribeInbox(MESSAGING_RELAYS, acc.pubkey, acc) } catch (err) { toast.error(err instanceof Error ? err.message : "Failed to subscribe to inbox") } @@ -108,8 +108,8 @@ createEffect(() => { createEffect(() => { const pk = account()?.pubkey if (pk) { - fetchRelayLists([pk]) - fetchInboxLists([pk]) + loadRelayLists([pk]) + loadMessagingLists([pk]) fetchProfile(pk) } }) @@ -118,8 +118,8 @@ createEffect(() => { createEffect(() => { const pubkeys = quora.flatMap(q => q.members.map(m => m.pubkey)) if (pubkeys.length > 0) { - fetchRelayLists(pubkeys) - fetchInboxLists(pubkeys) + loadRelayLists(pubkeys) + loadMessagingLists(pubkeys) for (const pk of pubkeys) { fetchProfile(pk) } } })