feat: make sig checks optional
This commit is contained in:
parent
87bb9dafeb
commit
93e8e0bbae
@ -19,7 +19,7 @@ export interface DMProps {
|
||||
|
||||
export default function DM(props: DMProps) {
|
||||
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const msg = props.data;
|
||||
const [content, setContent] = useState<string>();
|
||||
const { ref, inView } = useInView({ triggerOnce: true });
|
||||
|
@ -6,7 +6,6 @@ import { useState } from "react";
|
||||
import useFileUpload from "Upload";
|
||||
import { openFile } from "SnortUtils";
|
||||
import Textarea from "../Textarea";
|
||||
import { System } from "index";
|
||||
import { Chat } from "chat";
|
||||
|
||||
export default function WriteMessage({ chat }: { chat: Chat }) {
|
||||
@ -15,7 +14,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [otherEvents, setOtherEvents] = useState<Array<NostrEvent>>([]);
|
||||
const [error, setError] = useState("");
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const uploader = useFileUpload();
|
||||
|
||||
async function attachFile() {
|
||||
@ -59,7 +58,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
|
||||
if (msg && publisher && chat) {
|
||||
setSending(true);
|
||||
const ev = await chat.createMessage(msg, publisher);
|
||||
await chat.sendMessage(ev, System);
|
||||
await chat.sendMessage(ev, system);
|
||||
setMsg("");
|
||||
setSending(false);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import { WalletInvoiceState } from "Wallet";
|
||||
export default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {
|
||||
const wallet = useWallet();
|
||||
const login = useLogin();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const ids = dedupe(ev.tags.filter(a => a[0] === "p").map(a => a[1]));
|
||||
|
||||
async function zapAll() {
|
||||
|
@ -6,7 +6,6 @@ import { NostrEvent, OkResponse } from "@snort/system";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import Icon from "Icons/Icon";
|
||||
import { getRelayName, sanitizeRelayUrl } from "SnortUtils";
|
||||
import { System } from "index";
|
||||
import { removeRelay } from "Login";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
@ -23,7 +22,7 @@ export function NoteBroadcaster({
|
||||
const [results, setResults] = useState<Array<OkResponse>>([]);
|
||||
const { formatMessage } = useIntl();
|
||||
const login = useLogin();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
|
||||
async function sendEventToRelays(ev: NostrEvent) {
|
||||
if (customRelays) {
|
||||
@ -31,7 +30,7 @@ export function NoteBroadcaster({
|
||||
await Promise.all(
|
||||
customRelays.map(async r => {
|
||||
try {
|
||||
return await System.WriteOnceToRelay(r, ev);
|
||||
return await system.WriteOnceToRelay(r, ev);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@ -39,7 +38,7 @@ export function NoteBroadcaster({
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return await System.BroadcastEvent(ev, r => setResults(x => [...x, r]));
|
||||
return await system.BroadcastEvent(ev, r => setResults(x => [...x, r]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +57,7 @@ export function NoteBroadcaster({
|
||||
if (publisher) {
|
||||
removeRelay(login, unwrap(sanitizeRelayUrl(r.relay)));
|
||||
const ev = await publisher.contactList(login.follows.item, login.relays.item);
|
||||
await System.BroadcastEvent(ev);
|
||||
await system.BroadcastEvent(ev);
|
||||
setResults(s => s.filter(a => a.relay !== r.relay));
|
||||
}
|
||||
}
|
||||
@ -66,7 +65,7 @@ export function NoteBroadcaster({
|
||||
async function retryPublish(r: OkResponse) {
|
||||
const ev = evs.find(a => a.id === r.id);
|
||||
if (ev) {
|
||||
const rsp = await System.WriteOnceToRelay(unwrap(sanitizeRelayUrl(r.relay)), ev);
|
||||
const rsp = await system.WriteOnceToRelay(unwrap(sanitizeRelayUrl(r.relay)), ev);
|
||||
setResults(s =>
|
||||
s.map(x => {
|
||||
if (x.relay === r.relay && x.id === r.id) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { HexKey, Lists, NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||
|
||||
import { TranslateHost } from "Const";
|
||||
import { System } from "index";
|
||||
import Icon from "Icons/Icon";
|
||||
import { setPinned, setBookmarked } from "Login";
|
||||
import messages from "Element/messages";
|
||||
@ -11,7 +11,6 @@ import useLogin from "Hooks/useLogin";
|
||||
import useModeration from "Hooks/useModeration";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import { ReBroadcaster } from "../ReBroadcaster";
|
||||
import { useState } from "react";
|
||||
|
||||
export interface NoteTranslation {
|
||||
text: string;
|
||||
@ -30,7 +29,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
const login = useLogin();
|
||||
const { mute, block } = useModeration();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const [showBroadcast, setShowBroadcast] = useState(false);
|
||||
const lang = window.navigator.language;
|
||||
const langNames = new Intl.DisplayNames([...window.navigator.languages], {
|
||||
@ -41,7 +40,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
||||
async function deleteEvent() {
|
||||
if (window.confirm(formatMessage(messages.ConfirmDeletion, { id: ev.id.substring(0, 8) })) && publisher) {
|
||||
const evDelete = await publisher.delete(ev.id);
|
||||
System.BroadcastEvent(evDelete);
|
||||
system.BroadcastEvent(evDelete);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +89,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
||||
if (publisher) {
|
||||
const es = [...login.pinned.item, id];
|
||||
const ev = await publisher.noteList(es, Lists.Pinned);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
setPinned(login, es, ev.created_at * 1000);
|
||||
}
|
||||
}
|
||||
@ -99,7 +98,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
||||
if (publisher) {
|
||||
const es = [...login.bookmarked.item, id];
|
||||
const ev = await publisher.noteList(es, Lists.Bookmarked);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
setBookmarked(login, es, ev.created_at * 1000);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ export function NoteCreator() {
|
||||
const { formatMessage } = useIntl();
|
||||
const uploader = useFileUpload();
|
||||
const login = useLogin(s => ({ relays: s.relays, publicKey: s.publicKey, pow: s.preferences.pow }));
|
||||
const publisher = login.pow ? useEventPublisher()?.pow(login.pow, GetPowWorker()) : useEventPublisher();
|
||||
const { publisher: pub } = useEventPublisher();
|
||||
const publisher = login.pow ? pub?.pow(login.pow, GetPowWorker()) : pub;
|
||||
const note = useNoteCreator();
|
||||
const relays = login.relays;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { HTMLProps, useContext, useEffect, useState } from "react";
|
||||
import React, { HTMLProps, useEffect, useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useLongPress } from "use-long-press";
|
||||
import { TaggedNostrEvent, ParsedZap, countLeadingZeros, NostrLink } from "@snort/system";
|
||||
import { SnortContext, useUserProfile } from "@snort/system-react";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||
|
||||
import { formatShort } from "Number";
|
||||
@ -17,7 +17,6 @@ import { useWallet } from "Wallet";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { useInteractionCache } from "Hooks/useInteractionCache";
|
||||
import { ZapPoolController } from "ZapPoolController";
|
||||
import { System } from "index";
|
||||
import { Zapper, ZapTarget } from "Zapper";
|
||||
import { getDisplayName } from "Element/User/DisplayName";
|
||||
import { useNoteCreator } from "State/NoteCreator";
|
||||
@ -48,7 +47,6 @@ export interface NoteFooterProps {
|
||||
|
||||
export default function NoteFooter(props: NoteFooterProps) {
|
||||
const { ev, positive, reposts, zaps } = props;
|
||||
const system = useContext(SnortContext);
|
||||
const { formatMessage } = useIntl();
|
||||
const {
|
||||
publicKey,
|
||||
@ -57,7 +55,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
} = useLogin(s => ({ preferences: s.preferences, publicKey: s.publicKey, readonly: s.readonly }));
|
||||
const author = useUserProfile(ev.pubkey);
|
||||
const interactionCache = useInteractionCache(publicKey, ev.id);
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update, quote: n.quote }));
|
||||
const willRenderNoteCreator = note.show && (note.replyTo?.id === ev.id || note.quote);
|
||||
const [tip, setTip] = useState(false);
|
||||
@ -93,7 +91,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
async function react(content: string) {
|
||||
if (!hasReacted(content) && publisher) {
|
||||
const evLike = await publisher.react(ev, content);
|
||||
System.BroadcastEvent(evLike);
|
||||
system.BroadcastEvent(evLike);
|
||||
await interactionCache.react();
|
||||
}
|
||||
}
|
||||
@ -102,7 +100,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
||||
if (!hasReposted() && publisher) {
|
||||
if (!prefs.confirmReposts || window.confirm(formatMessage(messages.ConfirmRepost, { id: ev.id }))) {
|
||||
const evRepost = await publisher.repost(ev);
|
||||
System.BroadcastEvent(evRepost);
|
||||
system.BroadcastEvent(evRepost);
|
||||
await interactionCache.repost();
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import { NoteContextMenu, NoteTranslation } from "./NoteContextMenu";
|
||||
import { UserCache } from "../../Cache";
|
||||
import messages from "../messages";
|
||||
import { System } from "../../index";
|
||||
import { setBookmarked, setPinned } from "../../Login";
|
||||
import Text from "../Text";
|
||||
import Reveal from "./Reveal";
|
||||
@ -37,7 +36,7 @@ export function NoteInner(props: NoteProps) {
|
||||
const { reactions, reposts, deletions, zaps } = useEventReactions(ev, related);
|
||||
const login = useLogin();
|
||||
const { pinned, bookmarked } = login;
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const [translated, setTranslated] = useState<NoteTranslation>();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
@ -58,7 +57,7 @@ export function NoteInner(props: NoteProps) {
|
||||
if (window.confirm(formatMessage(messages.ConfirmUnpin))) {
|
||||
const es = pinned.item.filter(e => e !== id);
|
||||
const ev = await publisher.noteList(es, Lists.Pinned);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
setPinned(login, es, ev.created_at * 1000);
|
||||
}
|
||||
}
|
||||
@ -69,7 +68,7 @@ export function NoteInner(props: NoteProps) {
|
||||
if (window.confirm(formatMessage(messages.ConfirmUnbookmark))) {
|
||||
const es = bookmarked.item.filter(e => e !== id);
|
||||
const ev = await publisher.noteList(es, Lists.Bookmarked);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
setBookmarked(login, es, ev.created_at * 1000);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ type PollTally = "zaps" | "pubkeys";
|
||||
|
||||
export default function Poll(props: PollProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const { wallet } = useWallet();
|
||||
const { preferences: prefs, publicKey: myPubKey, relays } = useLogin();
|
||||
const pollerProfile = useUserProfile(props.ev.pubkey);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { mapEventToProfile } from "@snort/system";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
|
||||
import AccountName from "./AccountName";
|
||||
import useLogin from "../../Hooks/useLogin";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
import { System } from "../../index";
|
||||
import { UserCache } from "../../Cache";
|
||||
import useEventPublisher from "../../Hooks/useEventPublisher";
|
||||
import { mapEventToProfile } from "@snort/system";
|
||||
import FormattedMessage from "Element/FormattedMessage";
|
||||
|
||||
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
||||
@ -13,7 +13,7 @@ export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
||||
readonly: s.readonly,
|
||||
}));
|
||||
const profile = useUserProfile(publicKey);
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
|
||||
async function saveProfile(nip05: string) {
|
||||
if (readonly) {
|
||||
@ -35,7 +35,7 @@ export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
||||
|
||||
if (publisher) {
|
||||
const ev = await publisher.metadata(userCopy);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
|
||||
const newProfile = mapEventToProfile(ev);
|
||||
if (newProfile) {
|
||||
|
@ -25,7 +25,6 @@ import SnortServiceProvider from "Nip05/SnortServiceProvider";
|
||||
import { UserCache } from "Cache";
|
||||
|
||||
import messages from "./messages";
|
||||
import { System } from "index";
|
||||
|
||||
type Nip05ServiceProps = {
|
||||
name: string;
|
||||
@ -45,7 +44,7 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
||||
const user = useUserProfile(publicKey);
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const svc = useMemo(() => new ServiceProvider(props.service), [props.service]);
|
||||
const [serviceConfig, setServiceConfig] = useState<ServiceConfig>();
|
||||
const [error, setError] = useState<ServiceError>();
|
||||
@ -216,7 +215,7 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
||||
nip05,
|
||||
} as UserMetadata;
|
||||
const ev = await publisher.metadata(newProfile);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
if (props.onSuccess) {
|
||||
props.onSuccess(nip05);
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ export function PinPrompt({
|
||||
|
||||
export function LoginUnlock() {
|
||||
const login = useLogin();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
|
||||
async function encryptMigration(pin: string) {
|
||||
const k = unwrap(login.privateKey);
|
||||
|
@ -1,12 +1,12 @@
|
||||
import "./Relay.css";
|
||||
import { useMemo } from "react";
|
||||
import { useContext, useMemo } from "react";
|
||||
import FormattedMessage from "Element/FormattedMessage";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { RelaySettings } from "@snort/system";
|
||||
import { unixNowMs } from "@snort/shared";
|
||||
|
||||
import useRelayState from "Feed/RelayState";
|
||||
import { System } from "index";
|
||||
import { SnortContext } from "@snort/system-react";
|
||||
import { getRelayName, unwrap } from "SnortUtils";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { setRelays } from "Login";
|
||||
@ -20,9 +20,11 @@ export interface RelayProps {
|
||||
|
||||
export default function Relay(props: RelayProps) {
|
||||
const navigate = useNavigate();
|
||||
const system = useContext(SnortContext);
|
||||
const login = useLogin();
|
||||
|
||||
const relaySettings = unwrap(
|
||||
login.relays.item[props.addr] ?? System.Sockets.find(a => a.address === props.addr)?.settings ?? {},
|
||||
login.relays.item[props.addr] ?? system.Sockets.find(a => a.address === props.addr)?.settings ?? {},
|
||||
);
|
||||
const state = useRelayState(props.addr);
|
||||
const name = useMemo(() => getRelayName(props.addr), [props.addr]);
|
||||
|
@ -1,9 +1,8 @@
|
||||
import "./SendSats.css";
|
||||
import React, { ReactNode, useContext, useEffect, useState } from "react";
|
||||
import React, { ReactNode, useEffect, useState } from "react";
|
||||
import { useIntl, FormattedMessage } from "react-intl";
|
||||
|
||||
import { HexKey } from "@snort/system";
|
||||
import { SnortContext } from "@snort/system-react";
|
||||
import { LNURLSuccessAction } from "@snort/shared";
|
||||
|
||||
import { formatShort } from "Number";
|
||||
@ -48,8 +47,7 @@ export default function SendSats(props: SendSatsProps) {
|
||||
const [success, setSuccess] = useState<LNURLSuccessAction>();
|
||||
const [amount, setAmount] = useState<SendSatsInputSelection>();
|
||||
|
||||
const system = useContext(SnortContext);
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const walletState = useWallet();
|
||||
const wallet = walletState.wallet;
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
.sub-debug {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
opacity: 0.8;
|
||||
border: 1px solid;
|
||||
padding: 5px;
|
||||
font-family: monospace;
|
||||
font-size: x-small;
|
||||
background-color: black;
|
||||
z-index: 999999;
|
||||
color: white;
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
import "./SubDebug.css";
|
||||
import { useState } from "react";
|
||||
import { ReqFilter } from "@snort/system";
|
||||
import { useSystemState } from "@snort/system-react";
|
||||
|
||||
import useRelayState from "Feed/RelayState";
|
||||
import Tabs, { Tab } from "Element/Tabs";
|
||||
import { unwrap } from "SnortUtils";
|
||||
import { useCopy } from "useCopy";
|
||||
import { System } from "index";
|
||||
|
||||
function RelayInfo({ id }: { id: string }) {
|
||||
const state = useRelayState(id);
|
||||
return <div key={id}>{state?.connected ? <>{id}</> : <s>{id}</s>}</div>;
|
||||
}
|
||||
|
||||
function Queries() {
|
||||
const qs = useSystemState(System);
|
||||
const { copy } = useCopy();
|
||||
|
||||
function countElements(filters: Array<ReqFilter>) {
|
||||
let total = 0;
|
||||
for (const f of filters) {
|
||||
for (const v of Object.values(f)) {
|
||||
if (Array.isArray(v)) {
|
||||
total += v.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
function queryInfo(q: { id: string; filters: Array<ReqFilter>; subFilters: Array<ReqFilter> }) {
|
||||
return (
|
||||
<div key={q.id}>
|
||||
{q.id}
|
||||
<br />
|
||||
<span onClick={() => copy(JSON.stringify(q.filters))} className="pointer">
|
||||
Filters: {q.filters.length} ({countElements(q.filters)} elements)
|
||||
</span>
|
||||
<br />
|
||||
<span onClick={() => copy(JSON.stringify(q.subFilters))} className="pointer">
|
||||
SubQueries: {q.subFilters.length} ({countElements(q.subFilters)} elements)
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<b>Queries</b>
|
||||
{qs?.queries.map(v => queryInfo(v))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const SubDebug = () => {
|
||||
const [onTab, setTab] = useState(0);
|
||||
|
||||
function connections() {
|
||||
return (
|
||||
<>
|
||||
<b>Connections:</b>
|
||||
{System.Sockets.map(k => (
|
||||
<RelayInfo id={k.address} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const tabs: Tab[] = [
|
||||
{
|
||||
text: "Connections",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
text: "Queries",
|
||||
value: 1,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="sub-debug">
|
||||
<Tabs tabs={tabs} setTab={v => setTab(v.value)} tab={unwrap(tabs.find(a => a.value === onTab))} />
|
||||
{(() => {
|
||||
switch (onTab) {
|
||||
case 0:
|
||||
return connections();
|
||||
case 1:
|
||||
return <Queries />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SubDebug;
|
@ -5,7 +5,6 @@ import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import { parseId } from "SnortUtils";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import { System } from "index";
|
||||
|
||||
import messages from "../messages";
|
||||
import { FollowsFeed } from "Cache";
|
||||
@ -16,7 +15,7 @@ export interface FollowButtonProps {
|
||||
}
|
||||
export default function FollowButton(props: FollowButtonProps) {
|
||||
const pubkey = parseId(props.pubkey);
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const { follows, relays, readonly } = useLogin(s => ({ follows: s.follows, relays: s.relays, readonly: s.readonly }));
|
||||
const isFollowing = follows.item.includes(pubkey);
|
||||
const baseClassname = props.className ? `${props.className} ` : "";
|
||||
@ -24,8 +23,8 @@ export default function FollowButton(props: FollowButtonProps) {
|
||||
async function follow(pubkey: HexKey) {
|
||||
if (publisher) {
|
||||
const ev = await publisher.contactList([pubkey, ...follows.item], relays.item);
|
||||
System.BroadcastEvent(ev);
|
||||
await FollowsFeed.backFill(System, [pubkey]);
|
||||
system.BroadcastEvent(ev);
|
||||
await FollowsFeed.backFill(system, [pubkey]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +34,7 @@ export default function FollowButton(props: FollowButtonProps) {
|
||||
follows.item.filter(a => a !== pubkey),
|
||||
relays.item,
|
||||
);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,16 @@
|
||||
import { ReactNode } from "react";
|
||||
import FormattedMessage from "Element/FormattedMessage";
|
||||
import { HexKey } from "@snort/system";
|
||||
import { dedupe } from "@snort/shared";
|
||||
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import ProfilePreview from "Element/User/ProfilePreview";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { System } from "index";
|
||||
|
||||
import messages from "../messages";
|
||||
import { FollowsFeed } from "Cache";
|
||||
import AsyncButton from "../AsyncButton";
|
||||
import { setFollows } from "Login";
|
||||
import { dedupe } from "@snort/shared";
|
||||
|
||||
export interface FollowListBaseProps {
|
||||
pubkeys: HexKey[];
|
||||
@ -32,15 +31,15 @@ export default function FollowListBase({
|
||||
actions,
|
||||
profileActions,
|
||||
}: FollowListBaseProps) {
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const login = useLogin();
|
||||
|
||||
async function followAll() {
|
||||
if (publisher) {
|
||||
const newFollows = dedupe([...pubkeys, ...login.follows.item]);
|
||||
const ev = await publisher.contactList(newFollows, login.relays.item);
|
||||
System.BroadcastEvent(ev);
|
||||
await FollowsFeed.backFill(System, pubkeys);
|
||||
system.BroadcastEvent(ev);
|
||||
await FollowsFeed.backFill(system, pubkeys);
|
||||
setFollows(login, newFollows, ev.created_at);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import { SnortPubKey } from "Const";
|
||||
import { SubscriptionEvent } from "Subscription";
|
||||
import useRelaysFeedFollows from "./RelaysFeedFollows";
|
||||
import { FollowsFeed, GiftsCache, Notifications, UserRelays } from "Cache";
|
||||
import { System } from "index";
|
||||
import { Nip28Chats, Nip4Chats } from "chat";
|
||||
import { useRefreshFeedCache } from "Hooks/useRefreshFeedcache";
|
||||
|
||||
@ -35,12 +34,16 @@ export default function useLoginFeed() {
|
||||
const login = useLogin();
|
||||
const { publicKey: pubKey, readNotifications, follows } = login;
|
||||
const { isMuted } = useModeration();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
|
||||
useRefreshFeedCache(Notifications, true);
|
||||
useRefreshFeedCache(FollowsFeed, true);
|
||||
useRefreshFeedCache(GiftsCache, true);
|
||||
|
||||
useEffect(() => {
|
||||
system.checkSigs = login.preferences.checkSigs;
|
||||
}, [login]);
|
||||
|
||||
const subLogin = useMemo(() => {
|
||||
if (!login || !pubKey) return null;
|
||||
|
||||
@ -88,7 +91,7 @@ export default function useLoginFeed() {
|
||||
const pTags = contactList.tags.filter(a => a[0] === "p").map(a => a[1]);
|
||||
setFollows(login, pTags, contactList.created_at * 1000);
|
||||
|
||||
FollowsFeed.backFillIfMissing(System, pTags);
|
||||
FollowsFeed.backFillIfMissing(system, pTags);
|
||||
}
|
||||
|
||||
Nip4Chats.onEvent(loginFeed.data);
|
||||
@ -202,7 +205,7 @@ export default function useLoginFeed() {
|
||||
|
||||
useEffect(() => {
|
||||
UserRelays.buffer(follows.item).catch(console.error);
|
||||
System.ProfileLoader.TrackMetadata(follows.item); // always track follows profiles
|
||||
system.ProfileLoader.TrackMetadata(follows.item); // always track follows profiles
|
||||
}, [follows.item]);
|
||||
|
||||
const fRelays = useRelaysFeedFollows(follows.item);
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { System } from "index";
|
||||
import { useContext } from "react";
|
||||
import { SnortContext } from "@snort/system-react";
|
||||
|
||||
export default function useRelayState(addr: string) {
|
||||
const c = System.Sockets.find(a => a.address === addr);
|
||||
const system = useContext(SnortContext);
|
||||
const c = system.Sockets.find(a => a.address === addr);
|
||||
return c;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
|
||||
const rb = createBuilder();
|
||||
if (rb) {
|
||||
if (options.method === "LIMIT_UNTIL") {
|
||||
rb.filter.until(until).limit(200);
|
||||
rb.filter.until(until).limit(100);
|
||||
} else {
|
||||
rb.filter.since(since).until(until);
|
||||
if (since === undefined) {
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { useContext } from "react";
|
||||
import { SnortContext } from "@snort/system-react";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
|
||||
|
||||
export default function useEventPublisher() {
|
||||
const login = useLogin();
|
||||
const system = useContext(SnortContext);
|
||||
|
||||
let existing = LoginStore.getPublisher(login.id);
|
||||
|
||||
@ -12,5 +15,8 @@ export default function useEventPublisher() {
|
||||
LoginStore.setPublisher(login.id, existing);
|
||||
}
|
||||
}
|
||||
return existing;
|
||||
return {
|
||||
publisher: existing,
|
||||
system,
|
||||
};
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
import { System } from "index";
|
||||
import { useEffect } from "react";
|
||||
import useLogin from "./useLogin";
|
||||
import useEventPublisher from "./useEventPublisher";
|
||||
|
||||
export function useLoginRelays() {
|
||||
const { relays } = useLogin();
|
||||
const { system } = useEventPublisher();
|
||||
|
||||
useEffect(() => {
|
||||
if (relays) {
|
||||
(async () => {
|
||||
for (const [k, v] of Object.entries(relays.item)) {
|
||||
await System.ConnectToRelay(k, v);
|
||||
await system.ConnectToRelay(k, v);
|
||||
}
|
||||
for (const v of System.Sockets) {
|
||||
for (const v of system.Sockets) {
|
||||
if (!relays.item[v.address] && !v.ephemeral) {
|
||||
System.DisconnectRelay(v.address);
|
||||
system.DisconnectRelay(v.address);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -3,17 +3,16 @@ import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { setBlocked, setMuted } from "Login";
|
||||
import { appendDedupe } from "SnortUtils";
|
||||
import { System } from "index";
|
||||
|
||||
export default function useModeration() {
|
||||
const login = useLogin();
|
||||
const { muted, blocked, appData } = login;
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
|
||||
async function setMutedList(pub: HexKey[], priv: HexKey[]) {
|
||||
if (publisher) {
|
||||
const ev = await publisher.muted(pub, priv);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
return ev.created_at * 1000;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { SnortContext } from "@snort/system-react";
|
||||
import { useContext, useEffect, useMemo } from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { NoopStore, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||
|
||||
import { RefreshFeedCache } from "Cache/RefreshFeedCache";
|
||||
@ -8,9 +7,8 @@ import useEventPublisher from "./useEventPublisher";
|
||||
import { unwrap } from "@snort/shared";
|
||||
|
||||
export function useRefreshFeedCache<T>(c: RefreshFeedCache<T>, leaveOpen = false) {
|
||||
const system = useContext(SnortContext);
|
||||
const login = useLogin();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
|
||||
const sub = useMemo(() => {
|
||||
if (login.publicKey) {
|
||||
|
@ -1,4 +1,12 @@
|
||||
import { RelaySettings, EventPublisher, Nip46Signer, Nip7Signer, PrivateKeySigner, KeyStorage } from "@snort/system";
|
||||
import {
|
||||
RelaySettings,
|
||||
EventPublisher,
|
||||
Nip46Signer,
|
||||
Nip7Signer,
|
||||
PrivateKeySigner,
|
||||
KeyStorage,
|
||||
SystemInterface,
|
||||
} from "@snort/system";
|
||||
import { unixNowMs } from "@snort/shared";
|
||||
import * as secp from "@noble/curves/secp256k1";
|
||||
import * as utils from "@noble/curves/abstract/utils";
|
||||
@ -8,7 +16,6 @@ import { LoginStore, UserPreferences, LoginSession, LoginSessionType, SnortAppDa
|
||||
import { generateBip39Entropy, entropyToPrivateKey } from "nip6";
|
||||
import { bech32ToHex, dedupeById, randomSample, sanitizeRelayUrl, unwrap } from "SnortUtils";
|
||||
import { SubscriptionEvent } from "Subscription";
|
||||
import { System } from "index";
|
||||
import { Chats, FollowsFeed, GiftsCache, Notifications } from "Cache";
|
||||
import { Nip7OsSigner } from "./Nip7OsSigner";
|
||||
|
||||
@ -63,7 +70,7 @@ export function clearEntropy(state: LoginSession) {
|
||||
/**
|
||||
* Generate a new key and login with this generated key
|
||||
*/
|
||||
export async function generateNewLogin(pin: (key: string) => Promise<KeyStorage>) {
|
||||
export async function generateNewLogin(system: SystemInterface, pin: (key: string) => Promise<KeyStorage>) {
|
||||
const ent = generateBip39Entropy();
|
||||
const entropy = utils.bytesToHex(ent);
|
||||
const privateKey = entropyToPrivateKey(ent);
|
||||
@ -87,7 +94,7 @@ export async function generateNewLogin(pin: (key: string) => Promise<KeyStorage>
|
||||
const publicKey = utils.bytesToHex(secp.schnorr.getPublicKey(privateKey));
|
||||
const publisher = EventPublisher.privateKey(privateKey);
|
||||
const ev = await publisher.contactList([bech32ToHex(SnortPubKey), publicKey], newRelays);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
LoginStore.loginWithPrivateKey(await pin(privateKey), entropy, newRelays);
|
||||
}
|
||||
|
||||
|
@ -74,11 +74,12 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
||||
if (!this.#activeAccount) {
|
||||
this.#activeAccount = this.#accounts.keys().next().value;
|
||||
}
|
||||
// reset readonly on load
|
||||
for (const [, v] of this.#accounts) {
|
||||
// reset readonly on load
|
||||
if (v.type === LoginSessionType.PrivateKey && v.readonly) {
|
||||
v.readonly = false;
|
||||
}
|
||||
// fill possibly undefined (migrate up)
|
||||
v.appData ??= {
|
||||
item: {
|
||||
mutedWords: [],
|
||||
@ -86,6 +87,7 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
||||
timestamp: 0,
|
||||
};
|
||||
v.extraChats ??= [];
|
||||
v.preferences.checkSigs ??= true;
|
||||
if (v.privateKeyData) {
|
||||
v.privateKeyData = KeyStorage.fromPayload(v.privateKeyData as object);
|
||||
}
|
||||
|
@ -86,6 +86,11 @@ export interface UserPreferences {
|
||||
* Show user status messages on profiles
|
||||
*/
|
||||
showStatus?: boolean;
|
||||
|
||||
/**
|
||||
* Check event signatures
|
||||
*/
|
||||
checkSigs: boolean;
|
||||
}
|
||||
|
||||
export const DefaultPreferences = {
|
||||
@ -105,4 +110,5 @@ export const DefaultPreferences = {
|
||||
telemetry: true,
|
||||
showBadges: false,
|
||||
showStatus: true,
|
||||
checkSigs: true,
|
||||
} as UserPreferences;
|
||||
|
@ -1,9 +0,0 @@
|
||||
import SubDebug from "Element/SubDebug";
|
||||
|
||||
export default function DebugPage() {
|
||||
return (
|
||||
<>
|
||||
<SubDebug />
|
||||
</>
|
||||
);
|
||||
}
|
@ -6,7 +6,6 @@ import Timeline from "Element/Feed/Timeline";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { setTags } from "Login";
|
||||
import { System } from "index";
|
||||
|
||||
const HashTagsPage = () => {
|
||||
const params = useParams();
|
||||
@ -15,12 +14,12 @@ const HashTagsPage = () => {
|
||||
const isFollowing = useMemo(() => {
|
||||
return login.tags.item.includes(tag);
|
||||
}, [login, tag]);
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
|
||||
async function followTags(ts: string[]) {
|
||||
if (publisher) {
|
||||
const ev = await publisher.tags(ts);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
setTags(login, ts, ev.created_at * 1000);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import QrCode from "Element/QrCode";
|
||||
import Copy from "Element/Copy";
|
||||
import { delay } from "SnortUtils";
|
||||
import { PinPrompt } from "Element/PinPrompt";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -85,6 +86,7 @@ export default function LoginPage() {
|
||||
const { proxy } = useImgProxy();
|
||||
const loginHandler = useLoginHandler();
|
||||
const hasNip7 = "nostr" in window;
|
||||
const { system } = useEventPublisher();
|
||||
const hasSubtleCrypto = window.crypto.subtle !== undefined;
|
||||
const [nostrConnect, setNostrConnect] = useState("");
|
||||
|
||||
@ -123,7 +125,7 @@ export default function LoginPage() {
|
||||
|
||||
async function makeRandomKey(pin?: string) {
|
||||
try {
|
||||
await generateNewLogin(key => makeKeyStore(key, pin));
|
||||
await generateNewLogin(system, key => makeKeyStore(key, pin));
|
||||
window.plausible?.("Generate Account");
|
||||
navigate("/new");
|
||||
} catch (e) {
|
||||
|
@ -3,9 +3,9 @@ import { Link, Outlet, RouteObject, useParams } from "react-router-dom";
|
||||
import FormattedMessage from "Element/FormattedMessage";
|
||||
import { unixNow } from "@snort/shared";
|
||||
import { NostrLink } from "@snort/system";
|
||||
import { SnortContext } from "@snort/system-react";
|
||||
|
||||
import Timeline from "Element/Feed/Timeline";
|
||||
import { System } from "index";
|
||||
import { TimelineSubject } from "Feed/TimelineFeed";
|
||||
import { debounce, getRelayName, sha256 } from "SnortUtils";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
@ -63,6 +63,7 @@ export const GlobalTab = () => {
|
||||
const [relay, setRelay] = useState<RelayOption>();
|
||||
const [allRelays, setAllRelays] = useState<RelayOption[]>();
|
||||
const [now] = useState(unixNow());
|
||||
const system = useContext(SnortContext);
|
||||
|
||||
const subject: TimelineSubject = {
|
||||
type: "global",
|
||||
@ -111,7 +112,7 @@ export const GlobalTab = () => {
|
||||
useEffect(() => {
|
||||
return debounce(500, () => {
|
||||
const ret: RelayOption[] = [];
|
||||
System.Sockets.forEach(v => {
|
||||
system.Sockets.forEach(v => {
|
||||
ret.push({
|
||||
url: v.address,
|
||||
paid: v.info?.limitation?.payment_required ?? false,
|
||||
|
@ -12,7 +12,7 @@ import { bech32ToHex, getRelayName, unwrap } from "SnortUtils";
|
||||
import { ZapPoolController, ZapPoolRecipient, ZapPoolRecipientType } from "ZapPoolController";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import { useWallet } from "Wallet";
|
||||
import { System } from "index";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
|
||||
const DataProviders = [
|
||||
{
|
||||
@ -71,6 +71,7 @@ function ZapTarget({ target }: { target: ZapPoolRecipient }) {
|
||||
|
||||
export default function ZapPoolPage() {
|
||||
const login = useLogin();
|
||||
const { system } = useEventPublisher();
|
||||
const zapPool = useSyncExternalStore(
|
||||
c => ZapPoolController.hook(c),
|
||||
() => ZapPoolController.snapshot(),
|
||||
@ -78,7 +79,7 @@ export default function ZapPoolPage() {
|
||||
const { wallet } = useWallet();
|
||||
|
||||
const relayConnections = useMemo(() => {
|
||||
return System.Sockets.map(a => {
|
||||
return system.Sockets.map(a => {
|
||||
if (a.info?.pubkey && !a.ephemeral) {
|
||||
return {
|
||||
address: a.address,
|
||||
|
@ -10,7 +10,6 @@ import useLogin from "Hooks/useLogin";
|
||||
import { UserCache } from "Cache";
|
||||
import AvatarEditor from "Element/User/AvatarEditor";
|
||||
import { DISCOVER } from ".";
|
||||
import { System } from "index";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
@ -20,7 +19,7 @@ export default function ProfileSetup() {
|
||||
const [username, setUsername] = useState("");
|
||||
const [picture, setPicture] = useState("");
|
||||
const { formatMessage } = useIntl();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
@ -37,7 +36,7 @@ export default function ProfileSetup() {
|
||||
name: username,
|
||||
picture,
|
||||
});
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
const profile = mapEventToProfile(ev);
|
||||
if (profile) {
|
||||
UserCache.set(profile);
|
||||
|
@ -176,6 +176,23 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex f-space w-max">
|
||||
<div className="flex-column g8">
|
||||
<h4>
|
||||
<FormattedMessage defaultMessage="Check Signatures" />
|
||||
</h4>
|
||||
<small>
|
||||
<FormattedMessage defaultMessage="Check all event signatures received from relays" />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={perf.checkSigs}
|
||||
onChange={e => updatePreferences(login, { ...perf, checkSigs: e.target.checked })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex f-space w-max">
|
||||
<div className="flex-column g8">
|
||||
<h4>
|
||||
|
@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom";
|
||||
import { mapEventToProfile } from "@snort/system";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
|
||||
import { System } from "index";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import { openFile } from "SnortUtils";
|
||||
import useFileUpload from "Upload";
|
||||
@ -24,7 +23,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
const navigate = useNavigate();
|
||||
const { publicKey: id, readonly } = useLogin(s => ({ publicKey: s.publicKey, readonly: s.readonly }));
|
||||
const user = useUserProfile(id ?? "");
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const uploader = useFileUpload();
|
||||
|
||||
const [name, setName] = useState<string>();
|
||||
@ -70,7 +69,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
|
||||
if (publisher) {
|
||||
const ev = await publisher.metadata(userCopy);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
|
||||
const newProfile = mapEventToProfile(ev);
|
||||
if (newProfile) {
|
||||
|
@ -3,18 +3,19 @@ import ProfilePreview from "Element/User/ProfilePreview";
|
||||
import useRelayState from "Feed/RelayState";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { parseId, unwrap } from "SnortUtils";
|
||||
import { System } from "index";
|
||||
import { removeRelay } from "Login";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
|
||||
import messages from "./messages";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
|
||||
const RelayInfo = () => {
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const login = useLogin();
|
||||
const { system } = useEventPublisher();
|
||||
|
||||
const conn = System.Sockets.find(a => a.id === params.id);
|
||||
const conn = system.Sockets.find(a => a.id === params.id);
|
||||
const stats = useRelayState(conn?.address ?? "");
|
||||
|
||||
return (
|
||||
|
@ -5,7 +5,6 @@ import { unixNowMs } from "@snort/shared";
|
||||
import { randomSample } from "SnortUtils";
|
||||
import Relay from "Element/Relay/Relay";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import { System } from "index";
|
||||
import useLogin from "Hooks/useLogin";
|
||||
import { setRelays } from "Login";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
@ -13,25 +12,25 @@ import AsyncButton from "Element/AsyncButton";
|
||||
import messages from "./messages";
|
||||
|
||||
const RelaySettingsPage = () => {
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher, system } = useEventPublisher();
|
||||
const login = useLogin();
|
||||
const relays = login.relays;
|
||||
const [newRelay, setNewRelay] = useState<string>();
|
||||
|
||||
const otherConnections = useMemo(() => {
|
||||
return System.Sockets.filter(a => relays.item[a.address] === undefined);
|
||||
return system.Sockets.filter(a => relays.item[a.address] === undefined);
|
||||
}, [relays]);
|
||||
|
||||
async function saveRelays() {
|
||||
if (publisher) {
|
||||
const ev = await publisher.contactList(login.follows.item, login.relays.item);
|
||||
System.BroadcastEvent(ev);
|
||||
system.BroadcastEvent(ev);
|
||||
try {
|
||||
const onlineRelays = await fetch("https://api.nostr.watch/v1/online").then(r => r.json());
|
||||
const relayList = await publisher.relayList(login.relays.item);
|
||||
const rs = Object.keys(relays.item).concat(randomSample(onlineRelays, 20));
|
||||
rs.forEach(r => {
|
||||
System.WriteOnceToRelay(r, relayList);
|
||||
system.WriteOnceToRelay(r, relayList);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
@ -9,7 +9,7 @@ import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
||||
|
||||
export default function LNForwardAddress({ handle }: { handle: ManageHandle }) {
|
||||
const { formatMessage } = useIntl();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
|
||||
const [newAddress, setNewAddress] = useState(handle.lnAddress ?? "");
|
||||
const [error, setError] = useState("");
|
||||
|
@ -8,7 +8,7 @@ import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
||||
|
||||
export default function ListHandles() {
|
||||
const navigate = useNavigate();
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const [handles, setHandles] = useState<Array<ManageHandle>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { ApiHost } from "Const";
|
||||
import AsyncButton from "Element/AsyncButton";
|
||||
import useEventPublisher from "Hooks/useEventPublisher";
|
||||
import { ServiceError } from "Nip05/ServiceProvider";
|
||||
import SnortServiceProvider, { ManageHandle } from "Nip05/SnortServiceProvider";
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
export default function TransferHandle({ handle }: { handle: ManageHandle }) {
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const navigate = useNavigate();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { mapSubscriptionErrorCode } from ".";
|
||||
import SubscriptionCard from "./SubscriptionCard";
|
||||
|
||||
export default function ManageSubscriptionPage() {
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const api = new SnortApi(undefined, publisher);
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
@ -12,7 +12,7 @@ import { SnortNostrAddressService } from "Pages/NostrAddressPage";
|
||||
import Nip05 from "Element/User/Nip05";
|
||||
|
||||
export default function SubscriptionCard({ sub }: { sub: Subscription }) {
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const created = new Date(sub.created * 1000);
|
||||
|
@ -58,7 +58,7 @@ export function mapSubscriptionErrorCode(c: SubscriptionError) {
|
||||
}
|
||||
|
||||
export function SubscribePage() {
|
||||
const publisher = useEventPublisher();
|
||||
const { publisher } = useEventPublisher();
|
||||
const api = new SnortApi(undefined, publisher);
|
||||
const [invoice, setInvoice] = useState("");
|
||||
const [error, setError] = useState<SubscriptionError>();
|
||||
|
@ -41,7 +41,6 @@ export interface Uploader {
|
||||
|
||||
export default function useFileUpload(): Uploader {
|
||||
const fileUploader = useLogin().preferences.fileUploader;
|
||||
//const publisher = useEventPublisher();
|
||||
|
||||
switch (fileUploader) {
|
||||
case "nostr.build": {
|
||||
|
@ -43,7 +43,6 @@ import NostrLinkHandler from "Pages/NostrLinkHandler";
|
||||
import { ThreadRoute } from "Element/Event/Thread";
|
||||
import { SubscribeRoutes } from "Pages/subscribe";
|
||||
import ZapPoolPage from "Pages/ZapPool";
|
||||
import DebugPage from "Pages/Debug";
|
||||
import { db } from "Db";
|
||||
import { preload, RelayMetrics, SystemDb, UserCache, UserRelays } from "Cache";
|
||||
import { LoginStore } from "Login";
|
||||
@ -80,7 +79,7 @@ export const GetPowWorker = () => (hasWasm ? new WasmPowWorker() : unwrap(Defaul
|
||||
/**
|
||||
* Singleton nostr system
|
||||
*/
|
||||
export const System = new NostrSystem({
|
||||
const System = new NostrSystem({
|
||||
relayCache: UserRelays,
|
||||
profileCache: UserCache,
|
||||
relayMetrics: RelayMetrics,
|
||||
@ -229,10 +228,6 @@ export const router = createBrowserRouter([
|
||||
...NewUserRoutes,
|
||||
...WalletRoutes,
|
||||
...(CONFIG.features.subscriptions ? SubscribeRoutes : []),
|
||||
{
|
||||
path: "/debug",
|
||||
element: <DebugPage />,
|
||||
},
|
||||
{
|
||||
path: "/*",
|
||||
element: <NostrLinkHandler />,
|
||||
|
@ -90,6 +90,9 @@
|
||||
"1nYUGC": {
|
||||
"defaultMessage": "{n} Following"
|
||||
},
|
||||
"1o2BgB": {
|
||||
"defaultMessage": "Check Signatures"
|
||||
},
|
||||
"1udzha": {
|
||||
"defaultMessage": "Conversations"
|
||||
},
|
||||
@ -832,6 +835,9 @@
|
||||
"UJTWqI": {
|
||||
"defaultMessage": "Remove from my relays"
|
||||
},
|
||||
"UNjfWJ": {
|
||||
"defaultMessage": "Check all event signatures received from relays"
|
||||
},
|
||||
"UT7Nkj": {
|
||||
"defaultMessage": "New Chat"
|
||||
},
|
||||
|
@ -29,6 +29,7 @@
|
||||
"1c4YST": "Connected to: {node} 🎉",
|
||||
"1iQ8GN": "Toggle Preview",
|
||||
"1nYUGC": "{n} Following",
|
||||
"1o2BgB": "Check Signatures",
|
||||
"1udzha": "Conversations",
|
||||
"2/2yg+": "Add",
|
||||
"25V4l1": "Banner",
|
||||
@ -272,6 +273,7 @@
|
||||
"Tpy00S": "People",
|
||||
"UDYlxu": "Pending Subscriptions",
|
||||
"UJTWqI": "Remove from my relays",
|
||||
"UNjfWJ": "Check all event signatures received from relays",
|
||||
"UT7Nkj": "New Chat",
|
||||
"UUPFlt": "Users must accept the content warning to show the content of your note.",
|
||||
"Up5U7K": "Block",
|
||||
|
@ -176,6 +176,6 @@ export abstract class EventExt {
|
||||
if (type === EventType.ParameterizedReplaceable) {
|
||||
if (!findTag(ev, "d")) return false;
|
||||
}
|
||||
return EventExt.verify(ev);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,11 @@ export * from "./cache/user-metadata";
|
||||
export * from "./cache/relay-metric";
|
||||
|
||||
export interface SystemInterface {
|
||||
/**
|
||||
* Check event signatures (reccomended)
|
||||
*/
|
||||
checkSigs: boolean;
|
||||
|
||||
/**
|
||||
* Handler function for NIP-42
|
||||
*/
|
||||
|
@ -81,6 +81,11 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
||||
*/
|
||||
#queryOptimizer: QueryOptimizer;
|
||||
|
||||
/**
|
||||
* Check event signatures (reccomended)
|
||||
*/
|
||||
checkSigs: boolean;
|
||||
|
||||
constructor(props: {
|
||||
authHandler?: AuthHandler;
|
||||
relayCache?: FeedCache<UsersRelays>;
|
||||
@ -89,6 +94,7 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
||||
eventsCache?: FeedCache<NostrEvent>;
|
||||
queryOptimizer?: QueryOptimizer;
|
||||
db?: SnortSystemDb;
|
||||
checkSigs?: boolean;
|
||||
}) {
|
||||
super();
|
||||
this.#handleAuth = props.authHandler;
|
||||
@ -100,6 +106,7 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
||||
|
||||
this.#profileLoader = new ProfileLoaderService(this, this.#profileCache);
|
||||
this.#relayMetrics = new RelayMetricHandler(this.#relayMetricsCache);
|
||||
this.checkSigs = props.checkSigs ?? true;
|
||||
this.#cleanup();
|
||||
}
|
||||
|
||||
@ -183,6 +190,10 @@ export class NostrSystem extends ExternalStore<SystemSnapshot> implements System
|
||||
this.#log("Rejecting invalid event %O", ev);
|
||||
return;
|
||||
}
|
||||
if (this.checkSigs && !EventExt.verify(ev)) {
|
||||
this.#log("Invalid sig %O", ev);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [, v] of this.Queries) {
|
||||
v.handleEvent(sub, ev);
|
||||
|
Loading…
x
Reference in New Issue
Block a user