remove ore dependencies on legacy relay pool

This commit is contained in:
hzrd149 2025-02-04 11:50:43 -06:00
parent 3e0cd807c2
commit d44e989195
9 changed files with 57 additions and 74 deletions

View File

@ -23,13 +23,12 @@ import { encodeDecodeResult } from "applesauce-core/helpers";
import { ExternalLinkIcon, SearchIcon } from "./icons";
import UserLink from "./user/user-link";
import relayPoolService from "../services/relay-pool";
import { isValidRelayURL } from "../helpers/relay";
import relayScoreboardService from "../services/relay-scoreboard";
import RelayFavicon from "./relay-favicon";
import singleEventLoader from "../services/single-event-loader";
import replaceableEventLoader from "../services/replaceable-loader";
import { AppHandlerContext } from "../providers/route/app-handler-provider";
import { useObservable } from "applesauce-react/hooks";
import { connections$ } from "../services/rx-nostr";
function SearchOnRelaysModal({
isOpen,
@ -39,11 +38,9 @@ function SearchOnRelaysModal({
const [loading, setLoading] = useState(false);
const [filter, setFilter] = useState("");
const discoveredRelays = relayScoreboardService.getRankedRelays(
relayPoolService
.getRelays()
.map((r) => r.url)
.filter(isValidRelayURL),
const discoveredRelays = Object.entries(useObservable(connections$)).reduce<string[]>(
(arr, [relay, status]) => (status !== "error" ? [...arr, relay] : arr),
[],
);
const [relays, actions] = useSet<string>(new Set(discoveredRelays.slice(0, 4)));

View File

@ -7,13 +7,13 @@ import hash from "hash-sum";
import rxNostr from "../services/rx-nostr";
import { useEventStore } from "applesauce-react/hooks/use-event-store";
export default function useForwardSubscription(relays: string[], filters?: Filter | Filter[]) {
export default function useForwardSubscription(relays?: string[], filters?: Filter | Filter[]) {
const eventStore = useEventStore();
const id = useMemo(() => nanoid(10), []);
const rxReq = useMemo(() => createRxForwardReq(id), [id]);
// attach to rxNostr
const observable = useMemo(() => rxNostr.use(rxReq, { on: { relays } }), [rxReq, relays.join(",")]);
const observable = useMemo(() => rxNostr.use(rxReq, { on: { relays } }), [rxReq, relays?.join(",")]);
// subscribe
// NOTE: have to subscribe before emitting filter

View File

@ -2,9 +2,4 @@ import RelayPool from "../classes/relay-pool";
const relayPoolService = new RelayPool();
if (import.meta.env.DEV) {
// @ts-expect-error debug
window.relayPoolService = relayPoolService;
}
export default relayPoolService;

View File

@ -1,6 +1,6 @@
import _throttle from "lodash.throttle";
import { Filter } from "nostr-tools";
import { BehaviorSubject, mergeMap } from "rxjs";
import { BehaviorSubject } from "rxjs";
import SuperMap from "../classes/super-map";
import { NostrEvent } from "../types/nostr-event";

View File

@ -2,16 +2,16 @@ import { kinds } from "nostr-tools";
import { IAccount } from "applesauce-accounts";
import { combineLatest, distinct } from "rxjs";
import { USER_BLOSSOM_SERVER_LIST_KIND } from "blossom-client-sdk";
import { createRxOneshotReq } from "rx-nostr";
import { COMMON_CONTACT_RELAYS } from "../const";
import { logger } from "../helpers/debug";
import replaceableEventLoader from "./replaceable-loader";
import { eventStore, queryStore } from "./event-store";
import { MultiSubscription } from "applesauce-net/subscription";
import relayPoolService from "./relay-pool";
import { APP_SETTING_IDENTIFIER, APP_SETTINGS_KIND } from "../helpers/app-settings";
import accounts from "./accounts";
import localSettings from "./local-settings";
import rxNostr from "./rx-nostr";
const log = logger.extend("UserEventSync");
function downloadEvents(account: IAccount, relays: string[]) {
@ -41,14 +41,15 @@ function downloadEvents(account: IAccount, relays: string[]) {
if (mailboxes?.outboxes && mailboxes.outboxes.length > 0) {
log(`Loading delete events`);
const sub = new MultiSubscription(relayPoolService);
sub.setRelays(mailboxes.outboxes);
sub.setFilters([{ kinds: [kinds.EventDeletion], authors: [account.pubkey] }]);
const req = createRxOneshotReq({
filters: [{ kinds: [kinds.EventDeletion], authors: [account.pubkey] }],
rxReqId: "delete-events",
});
const sub = rxNostr.use(req, { on: { relays: mailboxes.outboxes } }).subscribe((packet) => {
eventStore.add(packet.event, packet.from);
});
sub.open();
sub.onEvent.subscribe((e) => eventStore.add(e));
cleanup.push(() => sub.close());
cleanup.push(() => sub.unsubscribe());
}
});

View File

@ -110,13 +110,18 @@ export function DVMStatusCard({ status, pointer }: { status?: NostrEvent; pointe
switch (statusType) {
case "payment-required":
const [_, msats, invoice] = status.tags.find((t) => t[0] === "amount") ?? [];
const amount = parseInt(msats) / 1000;
return (
<Card {...cardProps}>
{cardHeader}
<CardBody px="4" pb="4" pt="0" gap="2" display="flex" flexDirection="column">
<Heading size="sm">{status.content}</Heading>
{invoice && <InlineInvoiceCard paymentRequest={invoice} />}
{invoice ? (
<InlineInvoiceCard paymentRequest={invoice} />
) : (
<EventZapButton event={status} showEventPreview={false} allowComment={false} />
)}
</CardBody>
</Card>
);

View File

@ -1,4 +1,4 @@
import { Button, Card, Flex, Heading, Text, useToast } from "@chakra-ui/react";
import { Button, Card, Flex, Heading, Text } from "@chakra-ui/react";
import {
Chart as ChartJS,
@ -13,19 +13,20 @@ import {
LinearScale,
CategoryScale,
} from "chart.js";
import { Filter } from "nostr-tools";
import { useAppTitle } from "../../../hooks/use-app-title";
import VerticalPageLayout from "../../../components/vertical-page-layout";
import { NostrEvent } from "../../../types/nostr-event";
import { groupByTime } from "../../../helpers/notification";
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { getSortedKinds } from "../../../helpers/nostr/event";
import relayPoolService from "../../../services/relay-pool";
import EventKindsPieChart from "../../../components/charts/event-kinds-pie-chart";
import EventKindsTable from "../../../components/charts/event-kinds-table";
import { unixNow } from "applesauce-core/helpers";
import { eventStore } from "../../../services/event-store";
import { RelayTimelineLoader } from "applesauce-loaders";
import rxNostr from "../../../services/rx-nostr";
import { useObservable } from "applesauce-react/hooks";
ChartJS.register(
ArcElement,
@ -95,35 +96,33 @@ function buildLineChartData(events: NostrEvent[], timeBlock = 60 * 60): ChartDat
}
export default function RelayDetailsTab({ relay }: { relay: string }) {
const toast = useToast();
useAppTitle(`${relay} - Details`);
const last = useRef(unixNow());
const events = useRef(new Map());
const [_, update] = useState<object>();
const [loading, setLoading] = useState(false);
const loadMore = useCallback(() => {
setLoading(true);
const query: Filter = { limit: 500 };
if (last.current) query.until = last.current;
const loader = useMemo(() => new RelayTimelineLoader(rxNostr, relay, [{}], { limit: 500 }), [relay]);
const sub = relayPoolService.requestRelay(relay).subscribe([query], {
onevent: (event) => {
events.current.set(event.id, event);
last.current = event.created_at;
eventStore.add(event, relay);
},
oneose: () => sub.close(),
onclose: (reason) => {
if (reason !== "closed by caller") toast({ status: "error", description: reason });
setLoading(false);
},
// start the loader
useEffect(() => {
const sub = loader.subscribe((packet) => {
events.current.set(packet.event.id, packet.event);
last.current = packet.event.created_at;
eventStore.add(packet.event, packet.from);
});
}, [relay, update]);
useEffect(() => loadMore(), [relay, loadMore]);
return () => sub.unsubscribe();
}, [loader]);
// load first batch when mounted
useEffect(() => loader.next(), [loader]);
const loadMore = useCallback(() => {
loader.next(-Infinity);
}, [loader]);
const loading = useObservable(loader.loading$);
const kinds = getSortedKinds(Array.from(events.current.values()));
return (

View File

@ -1,5 +1,6 @@
import { lazy } from "react";
import { RouteObject } from "react-router-dom";
import RelaysView from ".";
import AppRelaysView from "../settings/relays";
import CacheRelayView from "../settings/cache";
@ -13,10 +14,10 @@ const WebRtcRelaysView = lazy(() => import("./webrtc"));
const WebRtcConnectView = lazy(() => import("./webrtc/connect"));
const WebRtcPairView = lazy(() => import("./webrtc/pair"));
import BrowseRelaySetsView from "./browse-sets";
import RelaySetView from "./relay-set";
const RelayDetailsView = lazy(() => import("./relay-details"));
export default [
{ path: ":relay", element: <RelayDetailsView /> },
{
element: <RelaysView />,
children: [
@ -43,7 +44,6 @@ export default [
],
},
{ path: "sets", element: <BrowseRelaySetsView /> },
{ path: ":relay", element: <RelayDetailsView /> },
],
},
] satisfies RouteObject[];

View File

@ -1,18 +1,15 @@
import { useEffect, useState } from "react";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { Button, Flex, Spinner, Text, Textarea, useToast } from "@chakra-ui/react";
import { EventTemplate, NostrEvent } from "nostr-tools";
import { MultiSubscription } from "applesauce-net/subscription";
import { useStoreQuery } from "applesauce-react/hooks";
import { getEventUID, unixNow } from "applesauce-core/helpers";
import { useUserInbox } from "../../../../../hooks/use-user-mailboxes";
import { useActiveAccount } from "applesauce-react/hooks";
import { usePublishEvent } from "../../../../../providers/global/publish-provider";
import relayPoolService from "../../../../../services/relay-pool";
import { eventStore } from "../../../../../services/event-store";
import DVMResponsesQuery from "../../../../../queries/dvm-responses";
import { DVMStatusCard } from "../../../../discovery/dvm-feed/components/feed-status";
import useForwardSubscription from "../../../../../hooks/use-forward-subscription";
import { useReadRelays } from "../../../../../hooks/use-client-relays";
function PromptForm({ onSubmit }: { onSubmit: (prompt: string) => void | Promise<void> }) {
const { register, handleSubmit } = useForm({ defaultValues: { prompt: "" } });
@ -37,18 +34,17 @@ export default function EventSummarizePage({ event }: { event: NostrEvent }) {
const [request, setRequest] = useState<NostrEvent>();
const publish = usePublishEvent();
const account = useActiveAccount();
const inbox = useUserInbox(account?.pubkey);
const relays = useReadRelays();
const newRequest = async (prompt: string) => {
try {
if (!inbox) throw new Error("Missing user inbox relays");
if (relays.length) throw new Error("Missing relays");
const draft: EventTemplate = {
kind: 5001,
content: "",
tags: [
["relays", ...inbox],
["relays", ...relays],
["i", event.id, "event"],
["output", "text/plain"],
],
@ -66,18 +62,8 @@ export default function EventSummarizePage({ event }: { event: NostrEvent }) {
}
};
useEffect(() => {
if (!inbox || !request) return;
const sub = new MultiSubscription(relayPoolService);
sub.onEvent.subscribe((e) => eventStore.add(e));
sub.setFilters([{ kinds: [7000, 6001], "#e": [request.id] }]);
sub.setRelays(inbox);
sub.open();
return () => sub.close();
}, [request]);
// subscribe to dvm responses
useForwardSubscription(relays, request ? { kinds: [7000, 6001], "#e": [request.id] } : undefined);
const responses = useStoreQuery(DVMResponsesQuery, request ? [request] : undefined);