update nostr-tools

This commit is contained in:
Shusui MOYATANI
2023-12-21 02:51:51 +09:00
parent 4df42cea0a
commit 47eb2fc57d
48 changed files with 216 additions and 162 deletions

77
package-lock.json generated
View File

@@ -26,7 +26,7 @@
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nostr-tools": "^1.16.0", "nostr-tools": "^2.0.3",
"solid-js": "^1.8.7", "solid-js": "^1.8.7",
"tailwindcss": "^3.4.0", "tailwindcss": "^3.4.0",
"zod": "^3.22.4" "zod": "^3.22.4"
@@ -5494,16 +5494,17 @@
} }
}, },
"node_modules/nostr-tools": { "node_modules/nostr-tools": {
"version": "1.16.0", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.16.0.tgz", "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.0.3.tgz",
"integrity": "sha512-sx/aOl0gmkeHVoIVbyOhEQhzF88NsrBXMC8bsjhPASqA6oZ8uSOAyEGgRLMfC3SKgzQD5Gr6KvDoAahaD6xKcg==", "integrity": "sha512-A7/sBaeBA7Vmi3q1Or62FYbU4OuNBOfQmSxn4/sEK5Z6L4Ql9dwSq8H/mrxsiCQHfbLaVHBOmxLOOd3070/xCA==",
"dependencies": { "dependencies": {
"@noble/ciphers": "^0.2.0", "@noble/ciphers": "0.2.0",
"@noble/curves": "1.1.0", "@noble/curves": "1.2.0",
"@noble/hashes": "1.3.1", "@noble/hashes": "1.3.1",
"@scure/base": "1.1.1", "@scure/base": "1.1.1",
"@scure/bip32": "1.3.1", "@scure/bip32": "1.3.1",
"@scure/bip39": "1.2.1" "@scure/bip39": "1.2.1",
"nostr-wasm": "v0.0.3"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=5.0.0" "typescript": ">=5.0.0"
@@ -5514,6 +5515,33 @@
} }
} }
}, },
"node_modules/nostr-tools/node_modules/@noble/curves": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
"dependencies": {
"@noble/hashes": "1.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/nostr-wasm": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.0.3.tgz",
"integrity": "sha512-zz5INXiuya10s+zsNmW2k4xH47j+Ikgxn5SL8xt/quGBNWn/A6+blVqT3J6yjkZim/gyVC/9GXd0jH4w3w1HZA=="
},
"node_modules/npm-normalize-package-bin": { "node_modules/npm-normalize-package-bin": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
@@ -12599,18 +12627,41 @@
"dev": true "dev": true
}, },
"nostr-tools": { "nostr-tools": {
"version": "1.16.0", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-1.16.0.tgz", "resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.0.3.tgz",
"integrity": "sha512-sx/aOl0gmkeHVoIVbyOhEQhzF88NsrBXMC8bsjhPASqA6oZ8uSOAyEGgRLMfC3SKgzQD5Gr6KvDoAahaD6xKcg==", "integrity": "sha512-A7/sBaeBA7Vmi3q1Or62FYbU4OuNBOfQmSxn4/sEK5Z6L4Ql9dwSq8H/mrxsiCQHfbLaVHBOmxLOOd3070/xCA==",
"requires": { "requires": {
"@noble/ciphers": "^0.2.0", "@noble/ciphers": "0.2.0",
"@noble/curves": "1.1.0", "@noble/curves": "1.2.0",
"@noble/hashes": "1.3.1", "@noble/hashes": "1.3.1",
"@scure/base": "1.1.1", "@scure/base": "1.1.1",
"@scure/bip32": "1.3.1", "@scure/bip32": "1.3.1",
"@scure/bip39": "1.2.1" "@scure/bip39": "1.2.1",
"nostr-wasm": "v0.0.3"
},
"dependencies": {
"@noble/curves": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
"requires": {
"@noble/hashes": "1.3.2"
},
"dependencies": {
"@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="
}
}
}
} }
}, },
"nostr-wasm": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.0.3.tgz",
"integrity": "sha512-zz5INXiuya10s+zsNmW2k4xH47j+Ikgxn5SL8xt/quGBNWn/A6+blVqT3J6yjkZim/gyVC/9GXd0jH4w3w1HZA=="
},
"npm-normalize-package-bin": { "npm-normalize-package-bin": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",

View File

@@ -68,7 +68,7 @@
"i18next-browser-languagedetector": "^7.2.0", "i18next-browser-languagedetector": "^7.2.0",
"idb-keyval": "^6.2.1", "idb-keyval": "^6.2.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nostr-tools": "^1.16.0", "nostr-tools": "^2.0.3",
"solid-js": "^1.8.7", "solid-js": "^1.8.7",
"tailwindcss": "^3.4.0", "tailwindcss": "^3.4.0",
"zod": "^3.22.4" "zod": "^3.22.4"

View File

@@ -16,7 +16,8 @@ import EllipsisHorizontal from 'heroicons/24/outline/ellipsis-horizontal.svg';
import HeartOutlined from 'heroicons/24/outline/heart.svg'; import HeartOutlined from 'heroicons/24/outline/heart.svg';
import Plus from 'heroicons/24/outline/plus.svg'; import Plus from 'heroicons/24/outline/plus.svg';
import HeartSolid from 'heroicons/24/solid/heart.svg'; import HeartSolid from 'heroicons/24/solid/heart.svg';
import { type Event as NostrEvent, nip19 } from 'nostr-tools'; import { noteEncode } from 'nostr-tools/nip19';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import ContextMenu, { MenuItem } from '@/components/ContextMenu'; import ContextMenu, { MenuItem } from '@/components/ContextMenu';
import EmojiDisplay from '@/components/EmojiDisplay'; import EmojiDisplay from '@/components/EmojiDisplay';
@@ -41,8 +42,6 @@ export type ActionProps = {
onClickReply: () => void; onClickReply: () => void;
}; };
const { noteEncode } = nip19;
const emojiDataToReactionTypes = (emoji: EmojiData): ReactionTypes => { const emojiDataToReactionTypes = (emoji: EmojiData): ReactionTypes => {
if (emoji.native != null) { if (emoji.native != null) {
return { type: 'Emoji', content: emoji.native }; return { type: 'Emoji', content: emoji.native };

View File

@@ -1,12 +1,10 @@
import { Show, type Component } from 'solid-js'; import { Show, type Component } from 'solid-js';
import { Kind, nip19 } from 'nostr-tools'; import { noteEncode, neventEncode } from 'nostr-tools/nip19';
const { noteEncode, neventEncode } = nip19;
type EventLinkProps = { type EventLinkProps = {
eventId: string; eventId: string;
kind?: Kind; kind?: number;
}; };
const tryEncodeNote = (eventId: string) => { const tryEncodeNote = (eventId: string) => {
@@ -29,10 +27,7 @@ const tryEncodeNevent = (eventId: string) => {
const EventLink: Component<EventLinkProps> = (props) => ( const EventLink: Component<EventLinkProps> = (props) => (
<button class="text-blue-500 underline"> <button class="text-blue-500 underline">
<Show <Show when={props.kind == null || props.kind === 1} fallback={tryEncodeNevent(props.eventId)}>
when={props.kind == null || props.kind === Kind.Text}
fallback={tryEncodeNevent(props.eventId)}
>
{tryEncodeNote(props.eventId)} {tryEncodeNote(props.eventId)}
</Show> </Show>
</button> </button>

View File

@@ -6,7 +6,7 @@ import Photo from 'heroicons/24/outline/photo.svg';
import XMark from 'heroicons/24/outline/x-mark.svg'; import XMark from 'heroicons/24/outline/x-mark.svg';
import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg'; import PaperAirplane from 'heroicons/24/solid/paper-airplane.svg';
import uniq from 'lodash/uniq'; import uniq from 'lodash/uniq';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import EmojiPicker, { EmojiData } from '@/components/EmojiPicker'; import EmojiPicker, { EmojiData } from '@/components/EmojiPicker';
import UserNameDisplay from '@/components/UserDisplayName'; import UserNameDisplay from '@/components/UserDisplayName';

View File

@@ -1,7 +1,7 @@
import { Component } from 'solid-js'; import { Component } from 'solid-js';
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg'; import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
import { Kind } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import BasicColumnHeader from '@/components/column/BasicColumnHeader'; import BasicColumnHeader from '@/components/column/BasicColumnHeader';
import Column from '@/components/column/Column'; import Column from '@/components/column/Column';

View File

@@ -1,7 +1,7 @@
import { Component, Show } from 'solid-js'; import { Component, Show } from 'solid-js';
import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg'; import ChatBubbleLeftRight from 'heroicons/24/outline/chat-bubble-left-right.svg';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import { parseChannelMeta } from '@/nostr/event/channel'; import { parseChannelMeta } from '@/nostr/event/channel';

View File

@@ -1,6 +1,7 @@
import { Switch, Match, Component } from 'solid-js'; import { Switch, Match, Component } from 'solid-js';
import { Kind, type Event as NostrEvent } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
// import ChannelInfo from '@/components/event/ChannelInfo'; // import ChannelInfo from '@/components/event/ChannelInfo';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
@@ -13,7 +14,7 @@ export type EventDisplayProps = {
event: NostrEvent; event: NostrEvent;
embedding?: boolean; embedding?: boolean;
actions?: boolean; actions?: boolean;
ensureKinds?: Kind[]; ensureKinds?: number[];
}; };
const EventDisplay: Component<EventDisplayProps> = (props) => { const EventDisplay: Component<EventDisplayProps> = (props) => {
@@ -39,10 +40,10 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
<EventLink eventId={props.event.id} kind={props.event.kind} /> <EventLink eventId={props.event.id} kind={props.event.kind} />
</span> </span>
</Match> </Match>
<Match when={props.event.kind === (Kind.Text as number)}> <Match when={props.event.kind === Kind.ShortTextNote}>
<TextNote event={props.event} embedding={props.actions} actions={props.actions} /> <TextNote event={props.event} embedding={props.actions} actions={props.actions} />
</Match> </Match>
<Match when={props.event.kind === (Kind.Repost as number)}> <Match when={props.event.kind === Kind.Repost}>
<Repost event={props.event} /> <Repost event={props.event} />
</Match> </Match>
</Switch> </Switch>

View File

@@ -1,6 +1,6 @@
import { type Component, Show } from 'solid-js'; import { type Component, Show } from 'solid-js';
import { type Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import EmojiDisplay from '@/components/EmojiDisplay'; import EmojiDisplay from '@/components/EmojiDisplay';
import TextNote from '@/components/event/TextNote'; import TextNote from '@/components/event/TextNote';

View File

@@ -2,7 +2,7 @@
import { type Component, createMemo } from 'solid-js'; import { type Component, createMemo } from 'solid-js';
import ArrowPathRoundedSquare from 'heroicons/24/outline/arrow-path-rounded-square.svg'; import ArrowPathRoundedSquare from 'heroicons/24/outline/arrow-path-rounded-square.svg';
import { Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import EventDisplayById from '@/components/event/EventDisplayById'; import EventDisplayById from '@/components/event/EventDisplayById';

View File

@@ -1,6 +1,6 @@
import { Show, For, createSignal, createMemo, type Component } from 'solid-js'; import { Show, For, createSignal, createMemo, type Component } from 'solid-js';
import { type Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import Actions from '@/components/Actions'; import Actions from '@/components/Actions';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle

View File

@@ -1,6 +1,6 @@
import { Show } from 'solid-js'; import { Show } from 'solid-js';
import { Kind } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import EventDisplayById from '@/components/event/EventDisplayById'; import EventDisplayById from '@/components/event/EventDisplayById';
@@ -24,7 +24,7 @@ const MentionedEventDisplay = (props: MentionedEventDisplayProps) => (
eventId={props.mentionedEvent.eventId} eventId={props.mentionedEvent.eventId}
embedding={false} embedding={false}
actions={false} actions={false}
ensureKinds={[Kind.Text]} ensureKinds={[Kind.ShortTextNote]}
/> />
)} )}
</LazyLoad> </LazyLoad>

View File

@@ -1,6 +1,6 @@
import { For } from 'solid-js'; import { For } from 'solid-js';
import { Kind } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import EventDisplayById from '@/components/event/EventDisplayById'; import EventDisplayById from '@/components/event/EventDisplayById';
@@ -88,7 +88,7 @@ const TextNoteContentDisplay = (props: TextNoteContentDisplayProps) => {
eventId={item.data.data} eventId={item.data.data}
actions={false} actions={false}
embedding={false} embedding={false}
ensureKinds={[Kind.Text]} ensureKinds={[Kind.ShortTextNote]}
/> />
</div> </div>
); );

View File

@@ -1,6 +1,6 @@
import { Component, createMemo } from 'solid-js'; import { Component, createMemo } from 'solid-js';
import { type Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import BasicModal from '@/components/modal/BasicModal'; import BasicModal from '@/components/modal/BasicModal';
import Copy from '@/components/utils/Copy'; import Copy from '@/components/utils/Copy';

View File

@@ -1,6 +1,7 @@
import { For, type Component, createMemo } from 'solid-js'; import { For, type Component, createMemo } from 'solid-js';
import { Kind, type Event as NostrEvent } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import ColumnItem from '@/components/ColumnItem'; import ColumnItem from '@/components/ColumnItem';
import EventDisplayById from '@/components/event/EventDisplayById'; import EventDisplayById from '@/components/event/EventDisplayById';
@@ -40,7 +41,7 @@ const Bookmark: Component<BookmarkProps> = (props) => {
<For each={[...bookmarkedEventIds(), ...bookmarkedEventIdsPrivate()]}> <For each={[...bookmarkedEventIds(), ...bookmarkedEventIdsPrivate()]}>
{(eventId) => ( {(eventId) => (
<ColumnItem> <ColumnItem>
<EventDisplayById eventId={eventId} ensureKinds={[Kind.Text]} /> <EventDisplayById eventId={eventId} ensureKinds={[Kind.ShortTextNote]} />
</ColumnItem> </ColumnItem>
)} )}
</For> </For>

View File

@@ -1,6 +1,7 @@
import { For, Switch, Match, type Component, Show } from 'solid-js'; import { For, Switch, Match, type Component, Show } from 'solid-js';
import { Kind, type Event as NostrEvent } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import ColumnItem from '@/components/ColumnItem'; import ColumnItem from '@/components/ColumnItem';
import Reaction from '@/components/event/Reaction'; import Reaction from '@/components/event/Reaction';
@@ -20,18 +21,18 @@ const Notification: Component<NotificationProps> = (props) => {
{(event) => ( {(event) => (
<Show when={!shouldMuteEvent(event)}> <Show when={!shouldMuteEvent(event)}>
<Switch fallback={<div>unknown event</div>}> <Switch fallback={<div>unknown event</div>}>
<Match when={event.kind === (Kind.Text as number)}> <Match when={event.kind === Kind.ShortTextNote}>
<ColumnItem> <ColumnItem>
<TextNote event={event} /> <TextNote event={event} />
</ColumnItem> </ColumnItem>
</Match> </Match>
<Match when={event.kind === (Kind.Reaction as number)}> <Match when={event.kind === Kind.Reaction}>
<ColumnItem> <ColumnItem>
<Reaction event={event} /> <Reaction event={event} />
</ColumnItem> </ColumnItem>
</Match> </Match>
{/* TODO ちゃんとnotification用のコンポーネント使う */} {/* TODO ちゃんとnotification用のコンポーネント使う */}
<Match when={event.kind === (Kind.Repost as number)}> <Match when={event.kind === Kind.Repost}>
<ColumnItem> <ColumnItem>
<Repost event={event} /> <Repost event={event} />
</ColumnItem> </ColumnItem>

View File

@@ -1,6 +1,6 @@
import { For, type Component, Show } from 'solid-js'; import { For, type Component, Show } from 'solid-js';
import { type Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import ColumnItem from '@/components/ColumnItem'; import ColumnItem from '@/components/ColumnItem';
import EventDisplay from '@/components/event/EventDisplay'; import EventDisplay from '@/components/event/EventDisplay';

View File

@@ -1,7 +1,8 @@
import { Switch, Match, type Component } from 'solid-js'; import { Switch, Match, type Component } from 'solid-js';
import uniq from 'lodash/uniq'; import uniq from 'lodash/uniq';
import { Filter, Event as NostrEvent } from 'nostr-tools'; import { type Filter } from 'nostr-tools/filter';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import Timeline from '@/components/timeline/Timeline'; import Timeline from '@/components/timeline/Timeline';
import { type TimelineContent } from '@/components/timeline/TimelineContext'; import { type TimelineContent } from '@/components/timeline/TimelineContext';

View File

@@ -1,6 +1,6 @@
import { createContext, useContext } from 'solid-js'; import { createContext, useContext } from 'solid-js';
import { Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import { createStore } from 'solid-js/store'; import { createStore } from 'solid-js/store';
export type TimelineContent = { export type TimelineContent = {

View File

@@ -1,5 +1,5 @@
// import { z } from 'zod'; // import { z } from 'zod';
import { type Filter } from 'nostr-tools'; import { type Filter } from 'nostr-tools/filter';
import { type ColumnProps } from '@/components/column/Column'; import { type ColumnProps } from '@/components/column/Column';
import { ContentFilter } from '@/core/contentFilter'; import { ContentFilter } from '@/core/contentFilter';

View File

@@ -2,7 +2,8 @@ import { type Accessor, type Setter } from 'solid-js';
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import uniq from 'lodash/uniq'; import uniq from 'lodash/uniq';
import { Kind, type Event as NostrEvent } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import { import {
ColumnType, ColumnType,
@@ -194,7 +195,7 @@ const useConfig = (): UseConfig => {
const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey); const isPubkeyMuted = (pubkey: string) => config.mutedPubkeys.includes(pubkey);
const hasMutedKeyword = (event: NostrEvent) => { const hasMutedKeyword = (event: NostrEvent) => {
if (event.kind === (Kind.Text as number)) { if (event.kind === Kind.ShortTextNote) {
return config.mutedKeywords.some((keyword) => event.content.includes(keyword)); return config.mutedKeywords.some((keyword) => event.content.includes(keyword));
} }
return false; return false;
@@ -205,7 +206,7 @@ const useConfig = (): UseConfig => {
return ( return (
isPubkeyMuted(event.pubkey) || isPubkeyMuted(event.pubkey) ||
ev.taggedPubkeys().some(isPubkeyMuted) || ev.taggedPubkeys().some(isPubkeyMuted) ||
(event.kind === (Kind.Text as number) && hasMutedKeyword(event)) (event.kind === Kind.ShortTextNote && hasMutedKeyword(event))
); );
}; };

View File

@@ -1,4 +1,4 @@
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import GenericEvent from '@/nostr/event/GenericEvent'; import GenericEvent from '@/nostr/event/GenericEvent';
import Reaction from '@/nostr/event/Reaction'; import Reaction from '@/nostr/event/Reaction';

View File

@@ -1,4 +1,4 @@
import { Kind, Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import TagsBase from '@/nostr/event/TagsBase'; import TagsBase from '@/nostr/event/TagsBase';
@@ -15,7 +15,7 @@ export default class GenericEvent extends TagsBase {
return this.rawEvent.sig; return this.rawEvent.sig;
} }
get kind(): Kind { get kind(): number {
return this.rawEvent.kind; return this.rawEvent.kind;
} }

View File

@@ -1,4 +1,5 @@
import { Event as NostrEvent, Kind } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { Event as NostrEvent } from 'nostr-tools/pure';
import GenericEvent from '@/nostr/event/GenericEvent'; import GenericEvent from '@/nostr/event/GenericEvent';
@@ -30,7 +31,7 @@ const reactionToReactionTypes = (event: Reaction): ReactionTypes => {
export default class Reaction extends GenericEvent { export default class Reaction extends GenericEvent {
constructor(rawEvent: NostrEvent) { constructor(rawEvent: NostrEvent) {
if (rawEvent.kind !== (Kind.Reaction as number)) { if (rawEvent.kind !== Kind.Reaction) {
throw new TypeError('kind should be 7'); throw new TypeError('kind should be 7');
} }
super(rawEvent); super(rawEvent);

View File

@@ -1,6 +1,6 @@
import assert from 'assert'; import assert from 'assert';
import { Kind } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { describe, it } from 'vitest'; import { describe, it } from 'vitest';
import TextNote from '@/nostr/event/TextNote'; import TextNote from '@/nostr/event/TextNote';
@@ -142,7 +142,7 @@ describe('TextNote', () => {
it('should return true if content of the event includes a NIP-19-styled note ID', () => { it('should return true if content of the event includes a NIP-19-styled note ID', () => {
const textnote = new TextNote({ const textnote = new TextNote({
id: '', id: '',
kind: Kind.Text, kind: Kind.ShortTextNote,
content: 'nostr:note1qpwq08jv0sgrz68qev6eyu9vj6n2gmjl7n8g73jruzp37mguy3gq8d7asa', content: 'nostr:note1qpwq08jv0sgrz68qev6eyu9vj6n2gmjl7n8g73jruzp37mguy3gq8d7asa',
created_at: 0, created_at: 0,
pubkey: '', pubkey: '',
@@ -159,7 +159,7 @@ describe('TextNote', () => {
it('should return true if content of the event includes a NIP-19-styled nevent ID', () => { it('should return true if content of the event includes a NIP-19-styled nevent ID', () => {
const textnote = new TextNote({ const textnote = new TextNote({
id: '', id: '',
kind: Kind.Text, kind: Kind.ShortTextNote,
content: 'nostr:nevent1qqsttdc4rmxn8fqmk9s6823fqvpcmlm8ry6dmtu4m2snv0cm9sv70kq6urpy5', content: 'nostr:nevent1qqsttdc4rmxn8fqmk9s6823fqvpcmlm8ry6dmtu4m2snv0cm9sv70kq6urpy5',
created_at: 0, created_at: 0,
pubkey: '', pubkey: '',
@@ -178,7 +178,7 @@ describe('TextNote', () => {
it('should return a reply MarkedEventTag if the event has a reply tag', () => { it('should return a reply MarkedEventTag if the event has a reply tag', () => {
const textnote = new TextNote({ const textnote = new TextNote({
id: '', id: '',
kind: Kind.Text, kind: Kind.ShortTextNote,
content: '', content: '',
created_at: 0, created_at: 0,
pubkey: '', pubkey: '',

View File

@@ -1,11 +1,12 @@
import { type Event as NostrEvent, Kind } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import TextNoteLike from '@/nostr/event/TextNoteLike'; import TextNoteLike from '@/nostr/event/TextNoteLike';
export default class TextNote extends TextNoteLike { export default class TextNote extends TextNoteLike {
constructor(rawEvent: NostrEvent) { constructor(rawEvent: NostrEvent) {
if (rawEvent.kind !== (Kind.Text as number)) { if (rawEvent.kind !== Kind.ShortTextNote) {
throw new TypeError('kind should be 1'); throw new TypeError(`kind should be 1 but it was ${rawEvent.kind}`);
} }
super(rawEvent); super(rawEvent);
} }

View File

@@ -1,6 +1,6 @@
import assert from 'assert'; import assert from 'assert';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import { describe, it } from 'vitest'; import { describe, it } from 'vitest';
import { compareEvents, pickLatestEvent } from '@/nostr/event/comparator'; import { compareEvents, pickLatestEvent } from '@/nostr/event/comparator';

View File

@@ -1,4 +1,4 @@
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
/** /**
* compareEvents compares events by created_at and id. * compareEvents compares events by created_at and id.

View File

@@ -1,11 +1,8 @@
import { nip19 } from 'nostr-tools'; import { decode, type DecodeResult } from 'nostr-tools/nip19';
import { DecodeResult } from 'nostr-tools/lib/nip19';
import isValidId from '@/nostr/event/isValidId'; import isValidId from '@/nostr/event/isValidId';
import TagsBase from '@/nostr/event/TagsBase'; import TagsBase from '@/nostr/event/TagsBase';
const { decode } = nip19;
export type PlainText = { export type PlainText = {
type: 'PlainText'; type: 'PlainText';
content: string; content: string;

View File

@@ -1,6 +1,6 @@
import { QueryClient, QueryKey } from '@tanstack/solid-query'; import { QueryClient, QueryKey } from '@tanstack/solid-query';
import { uniqBy } from 'lodash'; import { uniqBy } from 'lodash';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/comparator'; import { compareEvents, pickLatestEvent, sortEvents } from '@/nostr/event/comparator';
import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents'; import { BatchedEventsTask, registerTask } from '@/nostr/useBatchedEvents';

View File

@@ -1,4 +1,7 @@
import { type Event as NostrEvent, type Filter, Kind, utils } from 'nostr-tools'; import { type Filter } from 'nostr-tools/filter';
import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import { insertEventIntoDescendingList } from 'nostr-tools/utils';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import { genericEvent } from '@/nostr/event'; import { genericEvent } from '@/nostr/event';
@@ -35,7 +38,7 @@ type TaskArg = TaskArgs[number];
export class BatchedEventsTask<T = TaskArg> extends ObservableTask<T, NostrEvent[]> { export class BatchedEventsTask<T = TaskArg> extends ObservableTask<T, NostrEvent[]> {
addEvent(event: NostrEvent) { addEvent(event: NostrEvent) {
this.updateWith((current) => utils.insertEventIntoDescendingList(current ?? [], event)); this.updateWith((current) => insertEventIntoDescendingList(current ?? [], event));
} }
firstEventPromise(): Promise<NostrEvent> { firstEventPromise(): Promise<NostrEvent> {
@@ -64,9 +67,6 @@ setInterval(() => {
setActiveBatchSubscriptions(count); setActiveBatchSubscriptions(count);
}, 1000); }, 1000);
const isParameterizedReplaceableEvent = (event: NostrEvent) =>
event.kind >= 30000 && event.kind < 40000;
const keyForParameterizedReplaceableEvent = ({ const keyForParameterizedReplaceableEvent = ({
kind, kind,
author, author,
@@ -220,22 +220,22 @@ export const tasksRequestBuilder = (tasks: BatchedEventsTask[]) => {
]; ];
const resolve = (event: NostrEvent) => { const resolve = (event: NostrEvent) => {
if (event.kind === (Kind.Metadata as number)) { if (event.kind === Kind.Metadata) {
if (profileTasks.resolve(event)) return; if (profileTasks.resolve(event)) return;
} }
if (event.kind === (Kind.Contacts as number)) { if (event.kind === Kind.Contacts) {
if (followingsTasks.resolve(event)) return; if (followingsTasks.resolve(event)) return;
} }
if (event.kind === (Kind.Repost as number)) { if (event.kind === Kind.Repost) {
if (repostsTasks.resolve(event)) return; if (repostsTasks.resolve(event)) return;
} }
if (event.kind === (Kind.Reaction as number)) { if (event.kind === Kind.Reaction) {
if (reactionsTasks.resolve(event)) return; if (reactionsTasks.resolve(event)) return;
} }
if (event.kind === (Kind.Zap as number)) { if (event.kind === Kind.Zap) {
if (zapReceiptsTasks.resolve(event)) return; if (zapReceiptsTasks.resolve(event)) return;
} }
if (isParameterizedReplaceableEvent(event)) { if (Kind.isParameterizedReplaceableKind(event.kind)) {
if (parameterizedReplaceableEventsTasks.resolve(event)) return; if (parameterizedReplaceableEventsTasks.resolve(event)) return;
} }
eventTasks.resolve(event); eventTasks.resolve(event);
@@ -279,18 +279,17 @@ const { addTask, removeTask } = useBatch<BatchedEventsTask>(() => ({
const { config } = useConfig(); const { config } = useConfig();
const pool = usePool(); const pool = usePool();
const sub = pool().sub(config().relayUrls, filters, {});
count += 1; count += 1;
const sub = pool().subscribeMany(config().relayUrls, filters, {
sub.on('event', (event: NostrEvent & { id: string }) => { eoseTimeout: 15000,
builder.resolve(event); onevent: (event: NostrEvent) => {
}); builder.resolve(event);
},
sub.on('eose', () => { oneose: () => {
finalizeTasks(); finalizeTasks();
sub.unsub(); sub.close();
count -= 1; count -= 1;
},
}); });
}, },
})); }));

View File

@@ -1,7 +1,5 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { Kind } from 'nostr-tools';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import useSubscription from '@/nostr/useSubscription'; import useSubscription from '@/nostr/useSubscription';
@@ -15,7 +13,7 @@ export default function useBookmarks(propsProvider: () => UseBookmarksProps) {
const { events } = useSubscription(() => ({ const { events } = useSubscription(() => ({
relayUrls: config().relayUrls, relayUrls: config().relayUrls,
filters: [{ kinds: [30001 as Kind], authors: [props().pubkey] }], filters: [{ kinds: [30001], authors: [props().pubkey] }],
continuous: true, continuous: true,
})); }));

View File

@@ -1,6 +1,6 @@
import { getEventHash, Kind, verifySignature, type UnsignedEvent } from 'nostr-tools'; import * as Kind from 'nostr-tools/kinds';
import { verifyEvent, getEventHash, type UnsignedEvent } from 'nostr-tools/pure';
// import '@/types/nostr.d';
import { ProfileWithOtherProperties, Profile } from '@/nostr/event/Profile'; import { ProfileWithOtherProperties, Profile } from '@/nostr/event/Profile';
import { ReactionTypes } from '@/nostr/event/Reaction'; import { ReactionTypes } from '@/nostr/event/Reaction';
import usePool from '@/nostr/usePool'; import usePool from '@/nostr/usePool';
@@ -87,7 +87,7 @@ const useCommands = () => {
throw new Error('NIP-07 implementation not found'); throw new Error('NIP-07 implementation not found');
} }
const signedEvent = await window.nostr.signEvent(preSignedEvent); const signedEvent = await window.nostr.signEvent(preSignedEvent);
if (!verifySignature({ ...signedEvent, id })) { if (!verifyEvent({ ...signedEvent, id })) {
throw new Error('nostr.signEvent returned invalid data'); throw new Error('nostr.signEvent returned invalid data');
} }
@@ -109,7 +109,7 @@ const useCommands = () => {
const tags = buildTags(params); const tags = buildTags(params);
const preSignedEvent: UnsignedEvent = { const preSignedEvent: UnsignedEvent = {
kind: 1, kind: Kind.ShortTextNote,
pubkey, pubkey,
created_at: epoch(), created_at: epoch(),
tags, tags,
@@ -145,7 +145,7 @@ const useCommands = () => {
} }
const preSignedEvent: UnsignedEvent = { const preSignedEvent: UnsignedEvent = {
kind: 7, kind: Kind.Reaction,
pubkey, pubkey,
created_at: epoch(), created_at: epoch(),
tags, tags,

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import { registerTask, BatchedEventsTask, EventTask } from '@/nostr/useBatchedEvents'; import { registerTask, BatchedEventsTask, EventTask } from '@/nostr/useBatchedEvents';
import timeout from '@/utils/timeout'; import timeout from '@/utils/timeout';

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import uniq from 'lodash/uniq'; import uniq from 'lodash/uniq';
import { Kind } from 'nostr-tools'; import { Metadata } from 'nostr-tools/kinds';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import useSubscription from '@/nostr/useSubscription'; import useSubscription from '@/nostr/useSubscription';
@@ -16,7 +16,7 @@ export default function useFollowers(propsProvider: () => UseFollowersProps) {
const { events } = useSubscription(() => ({ const { events } = useSubscription(() => ({
relayUrls: config().relayUrls, relayUrls: config().relayUrls,
filters: [{ kinds: [Kind.Contacts], '#p': [props().pubkey] }], filters: [{ kinds: [Metadata], '#p': [props().pubkey] }],
limit: Number.MAX_SAFE_INTEGER, limit: Number.MAX_SAFE_INTEGER,
continuous: true, continuous: true,
})); }));

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import { genericEvent } from '@/nostr/event'; import { genericEvent } from '@/nostr/event';
import { latestEventQuery } from '@/nostr/query'; import { latestEventQuery } from '@/nostr/query';

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import { pickLatestEvent } from '@/nostr/event/comparator'; import { pickLatestEvent } from '@/nostr/event/comparator';
import { import {

View File

@@ -1,8 +1,8 @@
import { createSignal } from 'solid-js'; import { createSignal } from 'solid-js';
import { SimplePool } from 'nostr-tools'; import { SimplePool } from 'nostr-tools/pool';
const [pool] = createSignal<SimplePool>(new SimplePool({ eoseSubTimeout: 12000 })); const [pool] = createSignal<SimplePool>(new SimplePool());
const usePool = () => pool; const usePool = () => pool;

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import { Profile, ProfileWithOtherProperties, safeParseProfile } from '@/nostr/event/Profile'; import { Profile, ProfileWithOtherProperties, safeParseProfile } from '@/nostr/event/Profile';
import { latestEventQuery } from '@/nostr/query'; import { latestEventQuery } from '@/nostr/query';

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools'; import { type Event as NostrEvent } from 'nostr-tools/pure';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import { reaction } from '@/nostr/event'; import { reaction } from '@/nostr/event';

View File

@@ -1,7 +1,7 @@
import { createMemo } from 'solid-js'; import { createMemo } from 'solid-js';
import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, useQueryClient, type CreateQueryResult } from '@tanstack/solid-query';
import { Event as NostrEvent } from 'nostr-tools'; import { Event as NostrEvent } from 'nostr-tools/pure';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import { eventsQuery } from '@/nostr/query'; import { eventsQuery } from '@/nostr/query';

View File

@@ -1,7 +1,10 @@
import { createSignal, createEffect, onMount, onCleanup, on } from 'solid-js'; import { createSignal, createEffect, onMount, onCleanup, on } from 'solid-js';
import uniqBy from 'lodash/uniqBy'; import uniqBy from 'lodash/uniqBy';
import { utils } from 'nostr-tools'; import { type Filter } from 'nostr-tools/filter';
import { type SubscribeManyParams } from 'nostr-tools/pool';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import { insertEventIntoDescendingList } from 'nostr-tools/utils';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import { sortEvents } from '@/nostr/event/comparator'; import { sortEvents } from '@/nostr/event/comparator';
@@ -9,12 +12,10 @@ import usePool from '@/nostr/usePool';
import useStats from '@/nostr/useStats'; import useStats from '@/nostr/useStats';
import epoch from '@/utils/epoch'; import epoch from '@/utils/epoch';
import type { Event as NostrEvent, Filter, SubscriptionOptions } from 'nostr-tools';
export type UseSubscriptionProps = { export type UseSubscriptionProps = {
relayUrls: string[]; relayUrls: string[];
filters: Filter[]; filters: Filter[];
options?: SubscriptionOptions; options?: SubscribeManyParams;
/** /**
* subscribe not only stored events but also new events published after the subscription * subscribe not only stored events but also new events published after the subscription
* default is true * default is true
@@ -72,7 +73,7 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
} }
setEvents((current) => { setEvents((current) => {
const sorted = utils.insertEventIntoDescendingList(current, event).slice(0, limit); const sorted = insertEventIntoDescendingList(current, event).slice(0, limit);
// FIXME なぜか重複して取得される問題があるが一旦uniqByで対処 // FIXME なぜか重複して取得される問題があるが一旦uniqByで対処
// https://github.com/syusui-s/rabbit/issues/5 // https://github.com/syusui-s/rabbit/issues/5
const deduped = uniqBy(sorted, (e) => e.id); const deduped = uniqBy(sorted, (e) => e.id);
@@ -89,8 +90,6 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
const props = propsProvider(); const props = propsProvider();
if (props == null) return; if (props == null) return;
const { relayUrls, filters, options, onEvent, onEOSE, continuous = true } = props; const { relayUrls, filters, options, onEvent, onEOSE, continuous = true } = props;
const sub = pool().sub(relayUrls, filters, options);
let subscribing = true; let subscribing = true;
count += 1; count += 1;
@@ -98,38 +97,45 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
let eose = false; let eose = false;
const storedEvents: NostrEvent[] = []; const storedEvents: NostrEvent[] = [];
sub.on('event', (event: NostrEvent) => { const sub = pool().subscribeMany(
if (onEvent != null) { relayUrls,
onEvent(event as NostrEvent & { id: string }); filters,
} options ?? {
if (props.clientEventFilter != null && !props.clientEventFilter(event)) { eoseTimeout: 12000,
return; maxWait: 6000,
} onevent: (event: NostrEvent) => {
if (onEvent != null) {
onEvent(event as NostrEvent & { id: string });
}
if (props.clientEventFilter != null && !props.clientEventFilter(event)) {
return;
}
if (!eose) { if (!eose) {
pushed = true; pushed = true;
storedEvents.push(event); storedEvents.push(event);
} else { } else {
addEvent(event); addEvent(event);
} }
}); },
oneose: () => {
if (onEOSE != null) {
onEOSE();
}
sub.on('eose', () => { eose = true;
if (onEOSE != null) { setEvents(sortEvents(storedEvents));
onEOSE();
}
eose = true; if (!continuous) {
setEvents(sortEvents(storedEvents)); sub.close();
if (subscribing) {
if (!continuous) { subscribing = false;
sub.unsub(); count -= 1;
if (subscribing) { }
subscribing = false; }
count -= 1; },
} },
} );
});
// avoid updating an array too rapidly while this is fetching stored events // avoid updating an array too rapidly while this is fetching stored events
let updating = false; let updating = false;
@@ -150,7 +156,7 @@ const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
onCleanup(() => { onCleanup(() => {
console.debug('startSubscription: end'); console.debug('startSubscription: end');
sub.unsub(); sub.close();
if (subscribing) { if (subscribing) {
subscribing = false; subscribing = false;
count -= 1; count -= 1;

View File

@@ -1,15 +1,16 @@
import { createMemo, type Accessor } from 'solid-js'; import { createMemo, type Accessor } from 'solid-js';
import { createQuery, type CreateQueryResult } from '@tanstack/solid-query'; import { createQuery, type CreateQueryResult } from '@tanstack/solid-query';
import { nip05, nip19 } from 'nostr-tools'; import { queryProfile } from 'nostr-tools/nip05';
import { type ProfilePointer } from 'nostr-tools/nip19';
export type UseVerificationProps = { export type UseVerificationProps = {
nip05: string; nip05: string;
}; };
export type UseVerification = { export type UseVerification = {
verification: Accessor<nip19.ProfilePointer | null>; verification: Accessor<ProfilePointer | null>;
query: CreateQueryResult<nip19.ProfilePointer | null>; query: CreateQueryResult<ProfilePointer | null>;
}; };
const useVerification = (propsProvider: () => UseVerificationProps | null): UseVerification => { const useVerification = (propsProvider: () => UseVerificationProps | null): UseVerification => {
@@ -22,7 +23,7 @@ const useVerification = (propsProvider: () => UseVerificationProps | null): UseV
const [, currentProps] = queryKey; const [, currentProps] = queryKey;
if (currentProps == null) return Promise.resolve(null); if (currentProps == null) return Promise.resolve(null);
const { nip05: nip05string } = currentProps; const { nip05: nip05string } = currentProps;
return nip05.queryProfile(nip05string); return queryProfile(nip05string);
}, },
staleTime: 30 * 60 * 1000, // 30 min staleTime: 30 * 60 * 1000, // 30 min
cacheTime: 24 * 60 * 60 * 1000, // 24 hour cacheTime: 24 * 60 * 60 * 1000, // 24 hour

View File

@@ -25,9 +25,12 @@ const Home: Component = () => {
config().relayUrls.map(async (relayUrl) => { config().relayUrls.map(async (relayUrl) => {
try { try {
const relay = await pool().ensureRelay(relayUrl); const relay = await pool().ensureRelay(relayUrl);
relay.on('notice', (msg: string) => { relay.onnotice = (msg: string) => {
console.error(`NOTICE: ${relayUrl}: ${msg}`); console.error(`NOTICE: ${relayUrl}: ${msg}`);
}); };
relay.onclose = () => {
console.warn(`CLOSE: ${relayUrl}`);
};
} catch (err) { } catch (err) {
console.error('ensureRelay failed', err); console.error('ensureRelay failed', err);
} }

View File

@@ -1,7 +1,7 @@
import { createEffect, onMount } from 'solid-js'; import { createEffect, onMount } from 'solid-js';
import { useNavigate, useParams } from '@solidjs/router'; import { useNavigate, useParams } from '@solidjs/router';
import { nip19 } from 'nostr-tools'; import { decode } from 'nostr-tools/nip19';
import GlobalModal from '@/components/modal/GlobalModal'; import GlobalModal from '@/components/modal/GlobalModal';
import SideBar from '@/components/SideBar'; import SideBar from '@/components/SideBar';
@@ -25,7 +25,7 @@ const Permalink = () => {
onMount(() => { onMount(() => {
if (params.id != null) { if (params.id != null) {
try { try {
const decoded = nip19.decode(params.id); const decoded = decode(params.id);
if (decoded.type === 'npub') { if (decoded.type === 'npub') {
showProfile(decoded.data); showProfile(decoded.data);
} }

View File

@@ -1,6 +1,6 @@
// The original code was published under the public domain license (CC0-1.0). // The original code was published under the public domain license (CC0-1.0).
// https://gist.github.com/syusui-s/cd5482ddfc83792b54a756759acbda55 // https://gist.github.com/syusui-s/cd5482ddfc83792b54a756759acbda55
import { type UnsignedEvent, type Event as NostrEvent } from 'nostr-tools'; import { type UnsignedEvent, type Event as NostrEvent } from 'nostr-tools/pure';
type NostrAPI = { type NostrAPI = {
/** returns a public key as hex */ /** returns a public key as hex */

View File

@@ -1,6 +1,4 @@
import { nip19 } from 'nostr-tools'; import { npubEncode } from 'nostr-tools/nip19';
const { npubEncode } = nip19;
const npubEncodeFallback = (pubkey: string): string => { const npubEncodeFallback = (pubkey: string): string => {
try { try {

View File

@@ -3,7 +3,7 @@
"strict": true, "strict": true,
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"moduleResolution": "node", "moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,