feat: negentropy
This commit is contained in:
5
packages/app/custom.d.ts
vendored
5
packages/app/custom.d.ts
vendored
@ -106,11 +106,6 @@ declare const CONFIG: {
|
||||
}>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Single relay (Debug)
|
||||
*/
|
||||
declare const SINGLE_RELAY: string | undefined;
|
||||
|
||||
/**
|
||||
* Build git hash
|
||||
*/
|
||||
|
@ -24,9 +24,7 @@ export default function Relay(props: RelayProps) {
|
||||
const system = useContext(SnortContext);
|
||||
const login = useLogin();
|
||||
|
||||
const relaySettings = unwrap(
|
||||
login.relays.item[props.addr] ?? system.Sockets.find(a => a.address === props.addr)?.settings ?? {},
|
||||
);
|
||||
const relaySettings = unwrap(login.relays.item[props.addr] ?? system.pool.getConnection(props.addr)?.Settings ?? {});
|
||||
const state = useRelayState(props.addr);
|
||||
const name = useMemo(() => getRelayName(props.addr), [props.addr]);
|
||||
|
||||
@ -44,14 +42,14 @@ export default function Relay(props: RelayProps) {
|
||||
return (
|
||||
<>
|
||||
<div className="relay bg-dark">
|
||||
<div className={classNames("flex items-center", state?.connected ? "bg-success" : "bg-error")}>
|
||||
<div className={classNames("flex items-center", state?.IsClosed === false ? "bg-success" : "bg-error")}>
|
||||
<RelayFavicon url={props.addr} />
|
||||
</div>
|
||||
<div className="flex flex-col g8">
|
||||
<div>
|
||||
<b>{name}</b>
|
||||
</div>
|
||||
{!state?.ephemeral && (
|
||||
{!state?.Ephemeral && (
|
||||
<div className="flex g8">
|
||||
<AsyncIcon
|
||||
iconName="write"
|
||||
@ -85,7 +83,7 @@ export default function Relay(props: RelayProps) {
|
||||
iconName="gear"
|
||||
iconSize={16}
|
||||
className="button-icon-sm transparent"
|
||||
onClick={() => navigate(state?.id ?? "")}
|
||||
onClick={() => navigate(state?.Id ?? "")}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
@ -3,6 +3,6 @@ import { useContext } from "react";
|
||||
|
||||
export default function useRelayState(addr: string) {
|
||||
const system = useContext(SnortContext);
|
||||
const c = system.Sockets.find(a => a.address === addr);
|
||||
const c = system.pool.getConnection(addr);
|
||||
return c;
|
||||
}
|
||||
|
@ -5,27 +5,27 @@ import useEventPublisher from "./useEventPublisher";
|
||||
import useLogin from "./useLogin";
|
||||
|
||||
export function useLoginRelays() {
|
||||
const { relays } = useLogin();
|
||||
const relays = useLogin(s => s.relays.item);
|
||||
const { system } = useEventPublisher();
|
||||
|
||||
useEffect(() => {
|
||||
if (relays) {
|
||||
updateRelayConnections(system, relays.item).catch(console.error);
|
||||
updateRelayConnections(system, relays).catch(console.error);
|
||||
}
|
||||
}, [relays]);
|
||||
}
|
||||
|
||||
export async function updateRelayConnections(system: SystemInterface, relays: Record<string, RelaySettings>) {
|
||||
if (SINGLE_RELAY) {
|
||||
system.ConnectToRelay(SINGLE_RELAY, { read: true, write: true });
|
||||
if (import.meta.env.VITE_SINGLE_RELAY) {
|
||||
system.ConnectToRelay(import.meta.env.VITE_SINGLE_RELAY, { read: true, write: true });
|
||||
} else {
|
||||
for (const [k, v] of Object.entries(relays)) {
|
||||
// note: don't awit this, causes race condition with sending requests to relays
|
||||
system.ConnectToRelay(k, v);
|
||||
}
|
||||
for (const v of system.Sockets) {
|
||||
if (!relays[v.address] && !v.ephemeral) {
|
||||
system.DisconnectRelay(v.address);
|
||||
for (const [k, v] of system.pool) {
|
||||
if (!relays[k] && !v.Ephemeral) {
|
||||
system.DisconnectRelay(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { useContext, useEffect, useMemo, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import Timeline from "@/Components/Feed/Timeline";
|
||||
import { TimelineSubject } from "@/Feed/TimelineFeed";
|
||||
import useHistoryState from "@/Hooks/useHistoryState";
|
||||
import useLogin from "@/Hooks/useLogin";
|
||||
import { debounce, getRelayName, sha256 } from "@/Utils";
|
||||
@ -15,8 +16,8 @@ interface RelayOption {
|
||||
|
||||
export const GlobalTab = () => {
|
||||
const { relays } = useLogin();
|
||||
const [relay, setRelay] = useHistoryState<RelayOption>(undefined, "global-relay");
|
||||
const [allRelays, setAllRelays] = useHistoryState<RelayOption[]>(undefined, "global-relay-options");
|
||||
const [relay, setRelay] = useHistoryState(undefined, "global-relay");
|
||||
const [allRelays, setAllRelays] = useHistoryState(undefined, "global-relay-options");
|
||||
const [now] = useState(unixNow());
|
||||
const system = useContext(SnortContext);
|
||||
|
||||
@ -62,11 +63,11 @@ export const GlobalTab = () => {
|
||||
useEffect(() => {
|
||||
return debounce(500, () => {
|
||||
const ret: RelayOption[] = [];
|
||||
system.Sockets.forEach(v => {
|
||||
if (v.connected) {
|
||||
[...system.pool].forEach(([, v]) => {
|
||||
if (!v.IsClosed) {
|
||||
ret.push({
|
||||
url: v.address,
|
||||
paid: v.info?.limitation?.payment_required ?? false,
|
||||
url: v.Address,
|
||||
paid: v.Info?.limitation?.payment_required ?? false,
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -80,12 +81,13 @@ export const GlobalTab = () => {
|
||||
}, [relays, relay]);
|
||||
|
||||
const subject = useMemo(
|
||||
() => ({
|
||||
type: "global",
|
||||
items: [],
|
||||
relay: [relay?.url],
|
||||
discriminator: `all-${sha256(relay?.url ?? "")}`,
|
||||
}),
|
||||
() =>
|
||||
({
|
||||
type: "global",
|
||||
items: [],
|
||||
relay: [relay?.url],
|
||||
discriminator: `all-${sha256(relay?.url ?? "")}`,
|
||||
}) as TimelineSubject,
|
||||
[relay?.url],
|
||||
);
|
||||
|
||||
|
@ -75,14 +75,15 @@ function ZapPoolPageInner() {
|
||||
const { wallet } = useWallet();
|
||||
|
||||
const relayConnections = useMemo(() => {
|
||||
return system.Sockets.map(a => {
|
||||
if (a.info?.pubkey && !a.ephemeral) {
|
||||
return {
|
||||
address: a.address,
|
||||
pubkey: a.info.pubkey,
|
||||
};
|
||||
}
|
||||
})
|
||||
return [...system.pool]
|
||||
.map(([, a]) => {
|
||||
if (a.Info?.pubkey && !a.Ephemeral) {
|
||||
return {
|
||||
address: a.Address,
|
||||
pubkey: a.Info.pubkey,
|
||||
};
|
||||
}
|
||||
})
|
||||
.filter(a => a !== undefined)
|
||||
.map(unwrap);
|
||||
}, [login.relays]);
|
||||
@ -131,7 +132,7 @@ function ZapPoolPageInner() {
|
||||
nOut: (
|
||||
<b>
|
||||
<FormattedNumber
|
||||
value={ZapPoolController.calcAllocation(login.appData.item.preferences.defaultZapAmount)}
|
||||
value={ZapPoolController?.calcAllocation(login.appData.item.preferences.defaultZapAmount) ?? 0}
|
||||
/>
|
||||
</b>
|
||||
),
|
||||
|
@ -16,66 +16,66 @@ const RelayInfo = () => {
|
||||
const login = useLogin();
|
||||
const { system } = useEventPublisher();
|
||||
|
||||
const conn = system.Sockets.find(a => a.id === params.id);
|
||||
const stats = useRelayState(conn?.address ?? "");
|
||||
const conn = [...system.pool].find(([, a]) => a.Id === params.id)?.[1];
|
||||
|
||||
const stats = useRelayState(conn?.Address ?? "");
|
||||
return (
|
||||
<>
|
||||
<h3 className="pointer" onClick={() => navigate("/settings/relays")}>
|
||||
<FormattedMessage {...messages.Relays} />
|
||||
</h3>
|
||||
<div>
|
||||
<h3>{stats?.info?.name}</h3>
|
||||
<p>{stats?.info?.description}</p>
|
||||
<h3>{stats?.Info?.name}</h3>
|
||||
<p>{stats?.Info?.description}</p>
|
||||
|
||||
{stats?.info?.pubkey && (
|
||||
{stats?.Info?.pubkey && (
|
||||
<>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.Owner} />
|
||||
</h4>
|
||||
<ProfilePreview pubkey={parseId(stats.info.pubkey)} />
|
||||
<ProfilePreview pubkey={parseId(stats.Info.pubkey)} />
|
||||
</>
|
||||
)}
|
||||
{stats?.info?.software && (
|
||||
{stats?.Info?.software && (
|
||||
<div className="flex">
|
||||
<h4 className="grow">
|
||||
<FormattedMessage {...messages.Software} />
|
||||
</h4>
|
||||
<div className="flex flex-col">
|
||||
{stats.info.software.startsWith("http") ? (
|
||||
<a href={stats.info.software} target="_blank" rel="noreferrer">
|
||||
{stats.info.software}
|
||||
{stats.Info.software.startsWith("http") ? (
|
||||
<a href={stats.Info.software} target="_blank" rel="noreferrer">
|
||||
{stats.Info.software}
|
||||
</a>
|
||||
) : (
|
||||
<>{stats.info.software}</>
|
||||
<>{stats.Info.software}</>
|
||||
)}
|
||||
<small>
|
||||
{!stats.info.version?.startsWith("v") && "v"}
|
||||
{stats.info.version}
|
||||
{!stats.Info.version?.startsWith("v") && "v"}
|
||||
{stats.Info.version}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{stats?.info?.contact && (
|
||||
{stats?.Info?.contact && (
|
||||
<div className="flex">
|
||||
<h4 className="grow">
|
||||
<FormattedMessage {...messages.Contact} />
|
||||
</h4>
|
||||
<a
|
||||
href={`${stats.info.contact.startsWith("mailto:") ? "" : "mailto:"}${stats.info.contact}`}
|
||||
href={`${stats.Info.contact.startsWith("mailto:") ? "" : "mailto:"}${stats.Info.contact}`}
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
{stats.info.contact}
|
||||
{stats.Info.contact}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
{stats?.info?.supported_nips && (
|
||||
{stats?.Info?.supported_nips && (
|
||||
<>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.Supports} />
|
||||
</h4>
|
||||
<div className="grow">
|
||||
{stats.info.supported_nips.map(a => (
|
||||
{stats.Info?.supported_nips?.map(a => (
|
||||
<a key={a} target="_blank" rel="noreferrer" href={`https://nips.be/${a}`} className="pill">
|
||||
NIP-{a.toString().padStart(2, "0")}
|
||||
</a>
|
||||
@ -87,7 +87,7 @@ const RelayInfo = () => {
|
||||
<FormattedMessage defaultMessage="Active Subscriptions" id="p85Uwy" />
|
||||
</h4>
|
||||
<div className="grow">
|
||||
{stats?.activeRequests.map(a => (
|
||||
{[...(stats?.ActiveRequests ?? [])].map(a => (
|
||||
<span className="pill" key={a}>
|
||||
{a}
|
||||
</span>
|
||||
@ -97,9 +97,9 @@ const RelayInfo = () => {
|
||||
<FormattedMessage defaultMessage="Pending Subscriptions" id="UDYlxu" />
|
||||
</h4>
|
||||
<div className="grow">
|
||||
{stats?.pendingRequests.map(a => (
|
||||
<span className="pill" key={a}>
|
||||
{a}
|
||||
{stats?.PendingRequests?.map(a => (
|
||||
<span className="pill" key={a.obj[1]}>
|
||||
{a.obj[1]}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
@ -107,7 +107,7 @@ const RelayInfo = () => {
|
||||
<div
|
||||
className="btn error"
|
||||
onClick={() => {
|
||||
removeRelay(login, unwrap(conn).address);
|
||||
removeRelay(login, unwrap(conn).Address);
|
||||
navigate("/settings/relays");
|
||||
}}>
|
||||
<FormattedMessage {...messages.Remove} />
|
||||
|
@ -21,7 +21,7 @@ const RelaySettingsPage = () => {
|
||||
const [newRelay, setNewRelay] = useState<string>();
|
||||
|
||||
const otherConnections = useMemo(() => {
|
||||
return system.Sockets.filter(a => relays.item[a.address] === undefined);
|
||||
return [...system.pool].filter(([k]) => relays.item[k] === undefined).map(([, v]) => v);
|
||||
}, [relays]);
|
||||
|
||||
const handleNewRelayChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@ -83,7 +83,7 @@ const RelaySettingsPage = () => {
|
||||
</h3>
|
||||
<div className="flex flex-col g8">
|
||||
{otherConnections.map(a => (
|
||||
<Relay addr={a.address} key={a.id} />
|
||||
<Relay addr={a.Address} key={a.Id} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,9 +23,9 @@ import { SubscriptionEvent } from "@/Utils/Subscription";
|
||||
import { Nip7OsSigner } from "./Nip7OsSigner";
|
||||
|
||||
export function setRelays(state: LoginSession, relays: Record<string, RelaySettings>, createdAt: number) {
|
||||
if (SINGLE_RELAY) {
|
||||
if (import.meta.env.VITE_SINGLE_RELAY) {
|
||||
state.relays.item = {
|
||||
[SINGLE_RELAY]: { read: true, write: true },
|
||||
[import.meta.env.VITE_SINGLE_RELAY]: { read: true, write: true },
|
||||
};
|
||||
state.relays.timestamp = 100;
|
||||
LoginStore.updateSession(state);
|
||||
|
@ -183,7 +183,7 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
||||
}
|
||||
|
||||
decideInitRelays(relays: Record<string, RelaySettings> | undefined): Record<string, RelaySettings> {
|
||||
if (SINGLE_RELAY) return { [SINGLE_RELAY]: { read: true, write: true } };
|
||||
if (import.meta.env.VITE_SINGLE_RELAY) return { [import.meta.env.VITE_SINGLE_RELAY]: { read: true, write: true } };
|
||||
if (relays && Object.keys(relays).length > 0) {
|
||||
return relays;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ export class Zapper {
|
||||
if (!svc) {
|
||||
throw new Error(`Failed to get invoice from ${t.value}`);
|
||||
}
|
||||
const relays = this.system.Sockets.filter(a => !a.ephemeral).map(v => v.address);
|
||||
const relays = [...this.system.pool].filter(([, v]) => !v.Ephemeral).map(([k]) => k);
|
||||
const pub = t.zap?.anon ?? false ? EventPublisher.privateKey(generateRandomKey().privateKey) : this.publisher;
|
||||
const zap =
|
||||
t.zap && svc.canZap
|
||||
@ -199,7 +199,7 @@ export class Zapper {
|
||||
await svc.load();
|
||||
return svc;
|
||||
} else if (t.type === "pubkey") {
|
||||
const profile = await this.system.ProfileLoader.fetchProfile(t.value);
|
||||
const profile = await this.system.profileLoader.fetch(t.value);
|
||||
if (profile) {
|
||||
const svc = new LNURL(profile.lud16 ?? profile.lud06 ?? "");
|
||||
await svc.load();
|
||||
|
@ -60,7 +60,6 @@ export default defineConfig({
|
||||
define: {
|
||||
CONFIG: JSON.stringify(appConfig),
|
||||
global: {}, // needed for custom-event lib
|
||||
SINGLE_RELAY: JSON.stringify(process.env.SINGLE_RELAY),
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
|
Reference in New Issue
Block a user