diff --git a/packages/app/config/default.json b/packages/app/config/default.json
index a9a0b496..51247c11 100644
--- a/packages/app/config/default.json
+++ b/packages/app/config/default.json
@@ -13,5 +13,6 @@
"subscriptions": true,
"deck": true,
"zapPool": true
- }
+ },
+ "eventLinkPrefix": "nevent"
}
diff --git a/packages/app/config/iris.json b/packages/app/config/iris.json
index cc5f1e0b..29f9b85c 100644
--- a/packages/app/config/iris.json
+++ b/packages/app/config/iris.json
@@ -13,5 +13,6 @@
"subscriptions": false,
"deck": true,
"zapPool": true
- }
+ },
+ "eventLinkPrefix": "note"
}
diff --git a/packages/app/custom.d.ts b/packages/app/custom.d.ts
index d2df8418..d3310863 100644
--- a/packages/app/custom.d.ts
+++ b/packages/app/custom.d.ts
@@ -52,4 +52,5 @@ declare const CONFIG: {
deck: boolean;
zapPool: boolean;
};
+ eventLinkPrefix: NostrPrefix;
};
diff --git a/packages/app/src/Element/Chat/WriteMessage.tsx b/packages/app/src/Element/Chat/WriteMessage.tsx
index 1e1c1bbb..3a03812b 100644
--- a/packages/app/src/Element/Chat/WriteMessage.tsx
+++ b/packages/app/src/Element/Chat/WriteMessage.tsx
@@ -1,4 +1,4 @@
-import { NostrPrefix, NostrEvent, NostrLink } from "@snort/system";
+import { NostrEvent, NostrLink } from "@snort/system";
import useEventPublisher from "Hooks/useEventPublisher";
import Icon from "Icons/Icon";
import Spinner from "Icons/Spinner";
@@ -36,7 +36,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
if (file) {
const rx = await uploader.upload(file, file.name);
if (rx.header) {
- const link = `nostr:${new NostrLink(NostrPrefix.Event, rx.header.id, rx.header.kind).encode()}`;
+ const link = `nostr:${new NostrLink(CONFIG.eventLinkPrefix, rx.header.id, rx.header.kind).encode()}`;
setMsg(`${msg ? `${msg}\n` : ""}${link}`);
setOtherEvents([...otherEvents, rx.header]);
} else if (rx.url) {
diff --git a/packages/app/src/Element/Deck/Articles.tsx b/packages/app/src/Element/Deck/Articles.tsx
index 8c7eff25..7c5eb398 100644
--- a/packages/app/src/Element/Deck/Articles.tsx
+++ b/packages/app/src/Element/Deck/Articles.tsx
@@ -9,7 +9,10 @@ import { DeckContext } from "Pages/DeckLayout";
export default function Articles() {
const data = useArticles();
const deck = useContext(DeckContext);
- const related = useReactions("articles:reactions", data.data?.map(v => NostrLink.fromEvent(v)) ?? []);
+ const related = useReactions(
+ "articles:reactions",
+ data.data?.map(v => NostrLink.fromEvent(v, CONFIG.eventLinkPrefix)) ?? [],
+ );
return (
<>
diff --git a/packages/app/src/Element/Embed/ZapstrEmbed.tsx b/packages/app/src/Element/Embed/ZapstrEmbed.tsx
index 0ca0f7cc..ce33c677 100644
--- a/packages/app/src/Element/Embed/ZapstrEmbed.tsx
+++ b/packages/app/src/Element/Embed/ZapstrEmbed.tsx
@@ -12,7 +12,7 @@ export default function ZapstrEmbed({ ev }: { ev: NostrEvent }) {
const subject = ev.tags.find(a => a[0] === "subject");
const refPersons = ev.tags.filter(a => a[0] === "p");
- const link = NostrLink.fromEvent(ev).encode();
+ const link = NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix).encode();
return (
<>
diff --git a/packages/app/src/Element/Event/NoteCreator.tsx b/packages/app/src/Element/Event/NoteCreator.tsx
index baade7d6..8a6bad0b 100644
--- a/packages/app/src/Element/Event/NoteCreator.tsx
+++ b/packages/app/src/Element/Event/NoteCreator.tsx
@@ -168,7 +168,7 @@ export function NoteCreator() {
const rx = await uploader.upload(file, file.name);
note.update(v => {
if (rx.header) {
- const link = `nostr:${new NostrLink(NostrPrefix.Event, rx.header.id, rx.header.kind).encode()}`;
+ const link = `nostr:${new NostrLink(CONFIG.eventLinkPrefix, rx.header.id, rx.header.kind).encode()}`;
v.note = `${v.note ? `${v.note}\n` : ""}${link}`;
v.otherEvents = [...(v.otherEvents ?? []), rx.header];
} else if (rx.url) {
diff --git a/packages/app/src/Element/Event/NoteFooter.tsx b/packages/app/src/Element/Event/NoteFooter.tsx
index 1d587d14..64a8b75e 100644
--- a/packages/app/src/Element/Event/NoteFooter.tsx
+++ b/packages/app/src/Element/Event/NoteFooter.tsx
@@ -123,7 +123,7 @@ export default function NoteFooter(props: NoteFooterProps) {
name: getDisplayName(author, ev.pubkey),
zap: {
pubkey: ev.pubkey,
- event: NostrLink.fromEvent(ev),
+ event: NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix),
},
} as ZapTarget,
];
diff --git a/packages/app/src/Element/Event/NoteInner.tsx b/packages/app/src/Element/Event/NoteInner.tsx
index 2bca6c3d..098912e8 100644
--- a/packages/app/src/Element/Event/NoteInner.tsx
+++ b/packages/app/src/Element/Event/NoteInner.tsx
@@ -151,7 +151,7 @@ export function NoteInner(props: NoteProps) {
return;
}
- const link = NostrLink.fromEvent(eTarget);
+ const link = NostrLink.fromEvent(eTarget, CONFIG.eventLinkPrefix);
// detect cmd key and open in new tab
if (e.metaKey) {
window.open(`/${link.encode()}`, "_blank");
diff --git a/packages/app/src/Element/Event/Poll.tsx b/packages/app/src/Element/Event/Poll.tsx
index 482c0a01..eb96fd28 100644
--- a/packages/app/src/Element/Event/Poll.tsx
+++ b/packages/app/src/Element/Event/Poll.tsx
@@ -58,8 +58,13 @@ export default function Poll(props: PollProps) {
setVoting(opt);
const r = Object.keys(relays.item);
- const zap = await publisher.zap(amount * 1000, props.ev.pubkey, r, NostrLink.fromEvent(props.ev), undefined, eb =>
- eb.tag(["poll_option", opt.toString()]),
+ const zap = await publisher.zap(
+ amount * 1000,
+ props.ev.pubkey,
+ r,
+ NostrLink.fromEvent(props.ev, CONFIG.eventLinkPrefix),
+ undefined,
+ eb => eb.tag(["poll_option", opt.toString()]),
);
const lnurl = props.ev.tags.find(a => a[0] === "zap")?.[1] || pollerProfile?.lud16 || pollerProfile?.lud06;
diff --git a/packages/app/src/Element/Event/Thread.tsx b/packages/app/src/Element/Event/Thread.tsx
index 96392ec6..5a6dba40 100644
--- a/packages/app/src/Element/Event/Thread.tsx
+++ b/packages/app/src/Element/Event/Thread.tsx
@@ -283,7 +283,7 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
notes={replies}
related={getAllLinkReactions(
thread.reactions,
- replies.map(a => NostrLink.fromEvent(a)),
+ replies.map(a => NostrLink.fromEvent(a, CONFIG.eventLinkPrefix)),
)}
chains={thread.chains}
onNavigate={navigateThread}
diff --git a/packages/app/src/Element/Event/ZapGoal.tsx b/packages/app/src/Element/Event/ZapGoal.tsx
index 9cc40a76..fc04d7d7 100644
--- a/packages/app/src/Element/Event/ZapGoal.tsx
+++ b/packages/app/src/Element/Event/ZapGoal.tsx
@@ -12,7 +12,7 @@ import { FormattedNumber } from "react-intl";
export function ZapGoal({ ev }: { ev: NostrEvent }) {
const [zap, setZap] = useState(false);
- const zaps = useZapsFeed(NostrLink.fromEvent(ev));
+ const zaps = useZapsFeed(NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix));
const target = Number(findTag(ev, "amount"));
const amount = zaps.reduce((acc, v) => (acc += v.amount * 1000), 0);
const progress = amount / target;
diff --git a/packages/app/src/Element/LiveEvent.tsx b/packages/app/src/Element/LiveEvent.tsx
index 0ae46f89..af44d757 100644
--- a/packages/app/src/Element/LiveEvent.tsx
+++ b/packages/app/src/Element/LiveEvent.tsx
@@ -44,7 +44,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
}
function cta() {
- const link = `https://zap.stream/${NostrLink.fromEvent(ev).encode()}`;
+ const link = `https://zap.stream/${NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix).encode()}`;
switch (status) {
case "live": {
return (
diff --git a/packages/app/src/Element/User/ProfileLink.tsx b/packages/app/src/Element/User/ProfileLink.tsx
index 67531293..4c05690b 100644
--- a/packages/app/src/Element/User/ProfileLink.tsx
+++ b/packages/app/src/Element/User/ProfileLink.tsx
@@ -36,7 +36,7 @@ export function ProfileLink({
const [username] = user.nip05.split("@");
return `/${username}`;
}
- return `/p/${new NostrLink(
+ return `/${new NostrLink(
NostrPrefix.Profile,
pubkey,
undefined,
@@ -45,7 +45,7 @@ export function ProfileLink({
).encode()}`;
}
if (link && (link.type === NostrPrefix.Profile || link.type === NostrPrefix.PublicKey)) {
- return `/p/${link.encode()}`;
+ return `/${link.encode()}`;
}
return "#";
}
diff --git a/packages/app/src/Feed/ThreadFeed.ts b/packages/app/src/Feed/ThreadFeed.ts
index 6eef9946..4921cca7 100644
--- a/packages/app/src/Feed/ThreadFeed.ts
+++ b/packages/app/src/Feed/ThreadFeed.ts
@@ -39,7 +39,7 @@ export default function useThreadFeed(link: NostrLink) {
const links = store.data
.map(a => [
NostrLink.fromEvent(a),
- ...a.tags.filter(a => a[0] === "e" || a[0] === "a").map(v => NostrLink.fromTag(v)),
+ ...a.tags.filter(a => a[0] === "e" || a[0] === "a").map(v => NostrLink.fromTag(v, CONFIG.eventLinkPrefix)),
])
.flat();
setAllEvents(links);
@@ -51,12 +51,15 @@ export default function useThreadFeed(link: NostrLink) {
const rootOrReplyAsRoot = t?.root ?? t?.replyTo;
if (rootOrReplyAsRoot) {
setRoot(
- NostrLink.fromTag([
- rootOrReplyAsRoot.key,
- rootOrReplyAsRoot.value ?? "",
- rootOrReplyAsRoot.relay ?? "",
- ...(rootOrReplyAsRoot.marker ?? []),
- ]),
+ NostrLink.fromTag(
+ [
+ rootOrReplyAsRoot.key,
+ rootOrReplyAsRoot.value ?? "",
+ rootOrReplyAsRoot.relay ?? "",
+ ...(rootOrReplyAsRoot.marker ?? []),
+ ],
+ CONFIG.eventLinkPrefix,
+ ),
);
}
}
diff --git a/packages/app/src/Feed/TimelineFeed.ts b/packages/app/src/Feed/TimelineFeed.ts
index f00d9de1..797d4094 100644
--- a/packages/app/src/Feed/TimelineFeed.ts
+++ b/packages/app/src/Feed/TimelineFeed.ts
@@ -46,7 +46,7 @@ export default function useTimelineFeed(subject: TimelineSubject, options: Timel
);
if (subject.relay) {
- f.relay(subject.relay);
+ subject.relay.forEach(r => f.relay(r));
}
switch (subject.type) {
case "pubkey": {
diff --git a/packages/app/src/Pages/DeckLayout.tsx b/packages/app/src/Pages/DeckLayout.tsx
index 2334b0c3..e43e568f 100644
--- a/packages/app/src/Pages/DeckLayout.tsx
+++ b/packages/app/src/Pages/DeckLayout.tsx
@@ -185,7 +185,7 @@ function MediaCol({ setThread }: { setThread: (e: NostrLink) => void }) {
"--img": `url(${proxy(images[0].content)})`,
} as CSSProperties
}
- onClick={() => setThread(NostrLink.fromEvent(e))}>
+ onClick={() => setThread(NostrLink.fromEvent(e, CONFIG.eventLinkPrefix))}>
);
}}
/>
diff --git a/packages/app/src/Pages/MessagesPage.tsx b/packages/app/src/Pages/MessagesPage.tsx
index 0675bfe0..7f6bcdf9 100644
--- a/packages/app/src/Pages/MessagesPage.tsx
+++ b/packages/app/src/Pages/MessagesPage.tsx
@@ -3,7 +3,7 @@ import "./MessagesPage.css";
import React, { useEffect, useMemo, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { useNavigate, useParams } from "react-router-dom";
-import { NostrLink, NostrPrefix, TLVEntryType, UserMetadata, decodeTLV } from "@snort/system";
+import { NostrLink, TLVEntryType, UserMetadata, decodeTLV } from "@snort/system";
import { useUserProfile, useUserSearch } from "@snort/system-react";
import UnreadCount from "Element/UnreadCount";
@@ -285,7 +285,7 @@ function NewChatWindow() {
}
export function Nip28ChatProfile({ id, onClick }: { id: string; onClick: (id: string) => void }) {
- const channel = useEventFeed(new NostrLink(NostrPrefix.Event, id, 40));
+ const channel = useEventFeed(new NostrLink(CONFIG.eventLinkPrefix, id, 40));
if (channel?.data) {
const meta = JSON.parse(channel.data.content) as UserMetadata;
return (
diff --git a/packages/app/src/Pages/Notifications.tsx b/packages/app/src/Pages/Notifications.tsx
index 5dc17c69..43ccff78 100644
--- a/packages/app/src/Pages/Notifications.tsx
+++ b/packages/app/src/Pages/Notifications.tsx
@@ -36,7 +36,7 @@ function notificationContext(ev: TaggedNostrEvent) {
}
const eTag = findTag(ev, "e");
if (eTag) {
- return new NostrLink(NostrPrefix.Event, eTag);
+ return new NostrLink(CONFIG.eventLinkPrefix, eTag);
}
const pTag = ev.tags.filter(a => a[0] === "p").slice(-1)?.[0];
if (pTag) {
@@ -49,7 +49,7 @@ function notificationContext(ev: TaggedNostrEvent) {
const thread = EventExt.extractThread(ev);
const tag = unwrap(thread?.replyTo ?? thread?.root ?? { value: ev.id, key: "e" });
if (tag.key === "e") {
- return new NostrLink(NostrPrefix.Event, unwrap(tag.value));
+ return new NostrLink(CONFIG.eventLinkPrefix, unwrap(tag.value));
} else if (tag.key === "a") {
const [kind, author, d] = unwrap(tag.value).split(":");
return new NostrLink(NostrPrefix.Address, d, Number(kind), author);
diff --git a/packages/app/src/Pages/Profile/ProfilePage.tsx b/packages/app/src/Pages/Profile/ProfilePage.tsx
index 09dd6587..c3f4dfeb 100644
--- a/packages/app/src/Pages/Profile/ProfilePage.tsx
+++ b/packages/app/src/Pages/Profile/ProfilePage.tsx
@@ -238,7 +238,7 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
);
diff --git a/packages/app/src/Pages/Root.tsx b/packages/app/src/Pages/Root.tsx
index 593c2b1b..13d57174 100644
--- a/packages/app/src/Pages/Root.tsx
+++ b/packages/app/src/Pages/Root.tsx
@@ -148,7 +148,7 @@ export const NotesTab = () => {
noteOnClick={
deckContext
? ev => {
- deckContext.setThread(NostrLink.fromEvent(ev));
+ deckContext.setThread(NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix));
}
: undefined
}
diff --git a/packages/app/src/Zapper.ts b/packages/app/src/Zapper.ts
index 2950294c..ba89c841 100644
--- a/packages/app/src/Zapper.ts
+++ b/packages/app/src/Zapper.ts
@@ -56,7 +56,7 @@ export class Zapper {
weight: Number(v[3] ?? 0),
zap: {
pubkey: v[1],
- event: NostrLink.fromEvent(ev),
+ event: NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix),
},
} as ZapTarget;
} else {
@@ -67,7 +67,7 @@ export class Zapper {
weight: 1,
zap: {
pubkey: ev.pubkey,
- event: NostrLink.fromEvent(ev),
+ event: NostrLink.fromEvent(ev, CONFIG.eventLinkPrefix),
},
} as ZapTarget;
}
diff --git a/packages/system/src/nostr-link.ts b/packages/system/src/nostr-link.ts
index 4e88d696..f341bbc6 100644
--- a/packages/system/src/nostr-link.ts
+++ b/packages/system/src/nostr-link.ts
@@ -128,12 +128,12 @@ export class NostrLink {
}
}
- static fromThreadTag(tag: Tag) {
+ static fromThreadTag(tag: Tag, eventLinkPrefix = NostrPrefix.Event) {
const relay = tag.relay ? [tag.relay] : undefined;
switch (tag.key) {
case "e": {
- return new NostrLink(NostrPrefix.Event, unwrap(tag.value), undefined, undefined, relay);
+ return new NostrLink(eventLinkPrefix, unwrap(tag.value), undefined, undefined, relay);
}
case "p": {
return new NostrLink(NostrPrefix.Profile, unwrap(tag.value), undefined, undefined, relay);
@@ -146,11 +146,11 @@ export class NostrLink {
throw new Error(`Unknown tag kind ${tag.key}`);
}
- static fromTag(tag: Array) {
+ static fromTag(tag: Array, eventLinkPrefix = NostrPrefix.Event) {
const relays = tag.length > 2 ? [tag[2]] : undefined;
switch (tag[0]) {
case "e": {
- return new NostrLink(NostrPrefix.Event, tag[1], undefined, undefined, relays);
+ return new NostrLink(eventLinkPrefix, tag[1], undefined, undefined, relays);
}
case "p": {
return new NostrLink(NostrPrefix.Profile, tag[1], undefined, undefined, relays);
@@ -163,14 +163,14 @@ export class NostrLink {
throw new Error(`Unknown tag kind ${tag[0]}`);
}
- static fromEvent(ev: TaggedNostrEvent | NostrEvent) {
+ static fromEvent(ev: TaggedNostrEvent | NostrEvent, prefixHint = NostrPrefix.Event) {
const relays = "relays" in ev ? ev.relays : undefined;
if (ev.kind >= 30_000 && ev.kind < 40_000) {
const dTag = unwrap(findTag(ev, "d"));
return new NostrLink(NostrPrefix.Address, dTag, ev.kind, ev.pubkey, relays);
}
- return new NostrLink(NostrPrefix.Event, ev.id, ev.kind, ev.pubkey, relays);
+ return new NostrLink(prefixHint, ev.id, ev.kind, ev.pubkey, relays);
}
}