mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-21 14:09:17 +02:00
Add option to use nostr-wasm to verify events
This commit is contained in:
5
.changeset/sixty-dancers-admire.md
Normal file
5
.changeset/sixty-dancers-admire.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"nostrudel": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add option to use nostr-wasm to verify events
|
@@ -66,7 +66,8 @@
|
|||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"ngeohash": "^0.6.3",
|
"ngeohash": "^0.6.3",
|
||||||
"nostr-idb": "^2.1.1",
|
"nostr-idb": "^2.1.1",
|
||||||
"nostr-tools": "^2.4.0",
|
"nostr-tools": "^2.5.0",
|
||||||
|
"nostr-wasm": "^0.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-chartjs-2": "^5.2.0",
|
"react-chartjs-2": "^5.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import { AbstractRelay, verifyEvent } from "nostr-tools";
|
import { AbstractRelay } from "nostr-tools";
|
||||||
import { logger } from "../helpers/debug";
|
import { logger } from "../helpers/debug";
|
||||||
import { validateRelayURL } from "../helpers/relay";
|
import { validateRelayURL } from "../helpers/relay";
|
||||||
import { offlineMode } from "../services/offline-mode";
|
import { offlineMode } from "../services/offline-mode";
|
||||||
import Subject from "./subject";
|
import Subject from "./subject";
|
||||||
|
import verifyEventMethod from "../services/verify-event";
|
||||||
|
|
||||||
export default class RelayPool {
|
export default class RelayPool {
|
||||||
relays = new Map<string, AbstractRelay>();
|
relays = new Map<string, AbstractRelay>();
|
||||||
@@ -28,7 +29,7 @@ export default class RelayPool {
|
|||||||
url = validateRelayURL(url);
|
url = validateRelayURL(url);
|
||||||
const key = url.toString();
|
const key = url.toString();
|
||||||
if (!this.relays.has(key)) {
|
if (!this.relays.has(key)) {
|
||||||
const newRelay = new AbstractRelay(key, { verifyEvent });
|
const newRelay = new AbstractRelay(key, { verifyEvent: verifyEventMethod });
|
||||||
this.relays.set(key, newRelay);
|
this.relays.set(key, newRelay);
|
||||||
this.onRelayCreated.next(newRelay);
|
this.onRelayCreated.next(newRelay);
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,7 @@ import { logger } from "../helpers/debug";
|
|||||||
import { safeRelayUrl } from "../helpers/relay";
|
import { safeRelayUrl } from "../helpers/relay";
|
||||||
import WasmRelay from "./wasm-relay";
|
import WasmRelay from "./wasm-relay";
|
||||||
import MemoryRelay from "../classes/memory-relay";
|
import MemoryRelay from "../classes/memory-relay";
|
||||||
|
import { fakeVerifyEvent } from "./verify-event";
|
||||||
function fakeVerify(event: NostrEvent): event is VerifiedEvent {
|
|
||||||
return (event[verifiedSymbol] = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the local relay from query params to localStorage
|
// save the local relay from query params to localStorage
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
@@ -22,7 +19,10 @@ if (paramRelay) {
|
|||||||
export const NOSTR_RELAY_TRAY_URL = "ws://localhost:4869/";
|
export const NOSTR_RELAY_TRAY_URL = "ws://localhost:4869/";
|
||||||
export async function checkNostrRelayTray() {
|
export async function checkNostrRelayTray() {
|
||||||
return new Promise((res) => {
|
return new Promise((res) => {
|
||||||
const test = new AbstractRelay(NOSTR_RELAY_TRAY_URL, { verifyEvent: fakeVerify });
|
const test = new AbstractRelay(NOSTR_RELAY_TRAY_URL, {
|
||||||
|
// presume events from the cache are already verified
|
||||||
|
verifyEvent: fakeVerifyEvent,
|
||||||
|
});
|
||||||
test
|
test
|
||||||
.connect()
|
.connect()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -54,14 +54,14 @@ async function createRelay() {
|
|||||||
} else if (localRelayURL.startsWith("nostr-idb://")) {
|
} else if (localRelayURL.startsWith("nostr-idb://")) {
|
||||||
return createInternalRelay();
|
return createInternalRelay();
|
||||||
} else if (safeRelayUrl(localRelayURL)) {
|
} else if (safeRelayUrl(localRelayURL)) {
|
||||||
return new AbstractRelay(safeRelayUrl(localRelayURL)!, { verifyEvent: fakeVerify });
|
return new AbstractRelay(safeRelayUrl(localRelayURL)!, { verifyEvent: fakeVerifyEvent });
|
||||||
}
|
}
|
||||||
} else if (window.satellite) {
|
} else if (window.satellite) {
|
||||||
return new AbstractRelay(await window.satellite.getLocalRelay(), { verifyEvent: fakeVerify });
|
return new AbstractRelay(await window.satellite.getLocalRelay(), { verifyEvent: fakeVerifyEvent });
|
||||||
} else if (window.CACHE_RELAY_ENABLED) {
|
} else if (window.CACHE_RELAY_ENABLED) {
|
||||||
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
return new AbstractRelay(new URL(protocol + location.host + "/local-relay").toString(), {
|
return new AbstractRelay(new URL(protocol + location.host + "/local-relay").toString(), {
|
||||||
verifyEvent: fakeVerify,
|
verifyEvent: fakeVerifyEvent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return createInternalRelay();
|
return createInternalRelay();
|
||||||
|
@@ -11,6 +11,7 @@ import createDefer, { Deferred } from "../classes/deferred";
|
|||||||
import { truncatedId } from "../helpers/nostr/event";
|
import { truncatedId } from "../helpers/nostr/event";
|
||||||
import { NostrConnectAccount } from "./account";
|
import { NostrConnectAccount } from "./account";
|
||||||
import { safeRelayUrl } from "../helpers/relay";
|
import { safeRelayUrl } from "../helpers/relay";
|
||||||
|
import { alwaysVerify } from "./verify-event";
|
||||||
|
|
||||||
export function isErrorResponse(response: any): response is NostrConnectErrorResponse {
|
export function isErrorResponse(response: any): response is NostrConnectErrorResponse {
|
||||||
return !!response.error;
|
return !!response.error;
|
||||||
@@ -112,6 +113,7 @@ export class NostrConnectClient {
|
|||||||
private requests = new Map<string, Deferred<any>>();
|
private requests = new Map<string, Deferred<any>>();
|
||||||
private auths = new Set<string>();
|
private auths = new Set<string>();
|
||||||
async handleEvent(event: NostrEvent) {
|
async handleEvent(event: NostrEvent) {
|
||||||
|
if (!alwaysVerify(event)) return;
|
||||||
if (this.provider && event.pubkey !== this.provider) return;
|
if (this.provider && event.pubkey !== this.provider) return;
|
||||||
|
|
||||||
const to = event.tags.find(isPTag)?.[1];
|
const to = event.tags.find(isPTag)?.[1];
|
||||||
|
@@ -8,6 +8,7 @@ import { localRelay } from "./local-relay";
|
|||||||
import { MONITOR_STATS_KIND, SELF_REPORTED_KIND, getRelayURL } from "../helpers/nostr/relay-stats";
|
import { MONITOR_STATS_KIND, SELF_REPORTED_KIND, getRelayURL } from "../helpers/nostr/relay-stats";
|
||||||
import relayPoolService from "./relay-pool";
|
import relayPoolService from "./relay-pool";
|
||||||
import { Filter } from "nostr-tools";
|
import { Filter } from "nostr-tools";
|
||||||
|
import { alwaysVerify } from "./verify-event";
|
||||||
|
|
||||||
const MONITOR_PUBKEY = "151c17c9d234320cf0f189af7b761f63419fd6c38c6041587a008b7682e4640f";
|
const MONITOR_PUBKEY = "151c17c9d234320cf0f189af7b761f63419fd6c38c6041587a008b7682e4640f";
|
||||||
const MONITOR_RELAY = "wss://history.nostr.watch";
|
const MONITOR_RELAY = "wss://history.nostr.watch";
|
||||||
@@ -24,6 +25,8 @@ class RelayStatsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleEvent(event: NostrEvent, cache = true) {
|
handleEvent(event: NostrEvent, cache = true) {
|
||||||
|
if (!alwaysVerify(event)) return;
|
||||||
|
|
||||||
// ignore all events before NIP-66 start date
|
// ignore all events before NIP-66 start date
|
||||||
if (event.created_at < 1704196800) return;
|
if (event.created_at < 1704196800) return;
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@ import EventStore from "../classes/event-store";
|
|||||||
import Subject from "../classes/subject";
|
import Subject from "../classes/subject";
|
||||||
import BatchKindLoader, { createCoordinate } from "../classes/batch-kind-loader";
|
import BatchKindLoader, { createCoordinate } from "../classes/batch-kind-loader";
|
||||||
import relayPoolService from "./relay-pool";
|
import relayPoolService from "./relay-pool";
|
||||||
|
import { alwaysVerify } from "./verify-event";
|
||||||
|
|
||||||
export type RequestOptions = {
|
export type RequestOptions = {
|
||||||
/** Always request the event from the relays */
|
/** Always request the event from the relays */
|
||||||
@@ -43,6 +44,7 @@ class ReplaceableEventsService {
|
|||||||
dbLog = this.log.extend("database");
|
dbLog = this.log.extend("database");
|
||||||
|
|
||||||
handleEvent(event: NostrEvent, saveToCache = true) {
|
handleEvent(event: NostrEvent, saveToCache = true) {
|
||||||
|
if (!alwaysVerify(event)) return;
|
||||||
const cord = getEventCoordinate(event);
|
const cord = getEventCoordinate(event);
|
||||||
|
|
||||||
const subject = this.subjects.get(cord);
|
const subject = this.subjects.get(cord);
|
||||||
|
@@ -10,6 +10,7 @@ export type AppSettingsV0 = {
|
|||||||
autoShowMedia: boolean;
|
autoShowMedia: boolean;
|
||||||
proxyUserMedia: boolean;
|
proxyUserMedia: boolean;
|
||||||
showReactions: boolean;
|
showReactions: boolean;
|
||||||
|
/** @deprecated */
|
||||||
showSignatureVerification: boolean;
|
showSignatureVerification: boolean;
|
||||||
|
|
||||||
autoPayWithWebLN: boolean;
|
autoPayWithWebLN: boolean;
|
||||||
@@ -53,6 +54,7 @@ export const defaultSettings: AppSettings = {
|
|||||||
proxyUserMedia: false,
|
proxyUserMedia: false,
|
||||||
loadOpenGraphData: true,
|
loadOpenGraphData: true,
|
||||||
showReactions: true,
|
showReactions: true,
|
||||||
|
/** @deprecated */
|
||||||
showSignatureVerification: false,
|
showSignatureVerification: false,
|
||||||
noteDifficulty: null,
|
noteDifficulty: null,
|
||||||
|
|
||||||
|
44
src/services/verify-event/index.ts
Normal file
44
src/services/verify-event/index.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { NostrEvent, VerifiedEvent, verifiedSymbol, verifyEvent } from "nostr-tools";
|
||||||
|
import { logger } from "../../helpers/debug";
|
||||||
|
|
||||||
|
const localStorageKey = "verify-event-method";
|
||||||
|
|
||||||
|
const log = logger.extend("VerifyEvent");
|
||||||
|
let selectedMethod = "default";
|
||||||
|
let verifyEventMethod: typeof verifyEvent;
|
||||||
|
let alwaysVerify: typeof verifyEvent;
|
||||||
|
|
||||||
|
export function fakeVerifyEvent(event: NostrEvent): event is VerifiedEvent {
|
||||||
|
return (event[verifiedSymbol] = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
selectedMethod = localStorage.getItem(localStorageKey) ?? "default";
|
||||||
|
|
||||||
|
switch (selectedMethod) {
|
||||||
|
case "wasm":
|
||||||
|
if (!("WebAssembly" in window)) throw new Error("WebAssembly not supported");
|
||||||
|
log("Loading WebAssembly module");
|
||||||
|
verifyEventMethod = alwaysVerify = (await import("./wasm")).default;
|
||||||
|
log("Loaded");
|
||||||
|
break;
|
||||||
|
case "none":
|
||||||
|
log("Using fake verify event method");
|
||||||
|
verifyEventMethod = fakeVerifyEvent;
|
||||||
|
alwaysVerify = verifyEvent;
|
||||||
|
break;
|
||||||
|
case "default":
|
||||||
|
default:
|
||||||
|
log("Using nostr-tools default");
|
||||||
|
verifyEventMethod = alwaysVerify = verifyEvent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to initialize event verification method, falling back to default");
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
verifyEventMethod = alwaysVerify = verifyEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { alwaysVerify, selectedMethod };
|
||||||
|
export default verifyEventMethod;
|
7
src/services/verify-event/wasm.ts
Normal file
7
src/services/verify-event/wasm.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { setNostrWasm, verifyEvent } from "nostr-tools/wasm";
|
||||||
|
import { initNostrWasm } from "nostr-wasm";
|
||||||
|
|
||||||
|
const wasm = await initNostrWasm();
|
||||||
|
setNostrWasm(wasm);
|
||||||
|
|
||||||
|
export default verifyEvent;
|
3
src/types/nostr-tools-wasm.d.ts
vendored
Normal file
3
src/types/nostr-tools-wasm.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
declare module "nostr-tools/wasm" {
|
||||||
|
export * from "nostr-tools/lib/types/wasm.d.ts";
|
||||||
|
}
|
@@ -40,7 +40,7 @@ export default function DisplaySettings() {
|
|||||||
<FormLabel htmlFor="theme" mb="0">
|
<FormLabel htmlFor="theme" mb="0">
|
||||||
Theme
|
Theme
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Select id="theme" {...register("theme")}>
|
<Select id="theme" {...register("theme")} maxW="sm">
|
||||||
<option value="default">Default</option>
|
<option value="default">Default</option>
|
||||||
<option value="chakraui">ChakraUI</option>
|
<option value="chakraui">ChakraUI</option>
|
||||||
</Select>
|
</Select>
|
||||||
@@ -49,7 +49,7 @@ export default function DisplaySettings() {
|
|||||||
<FormLabel htmlFor="colorMode" mb="0">
|
<FormLabel htmlFor="colorMode" mb="0">
|
||||||
Color Mode
|
Color Mode
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Select id="colorMode" {...register("colorMode")}>
|
<Select id="colorMode" {...register("colorMode")} maxW="sm">
|
||||||
<option value="system">System Default</option>
|
<option value="system">System Default</option>
|
||||||
<option value="light">Light</option>
|
<option value="light">Light</option>
|
||||||
<option value="dark">Dark</option>
|
<option value="dark">Dark</option>
|
||||||
@@ -67,7 +67,7 @@ export default function DisplaySettings() {
|
|||||||
<FormLabel htmlFor="maxPageWidth" mb="0">
|
<FormLabel htmlFor="maxPageWidth" mb="0">
|
||||||
Max Page width
|
Max Page width
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Select id="maxPageWidth" {...register("maxPageWidth")}>
|
<Select id="maxPageWidth" {...register("maxPageWidth")} maxW="sm">
|
||||||
<option value="none">None</option>
|
<option value="none">None</option>
|
||||||
<option value="md">Medium (~768px)</option>
|
<option value="md">Medium (~768px)</option>
|
||||||
<option value="lg">Large (~992px)</option>
|
<option value="lg">Large (~992px)</option>
|
||||||
@@ -123,7 +123,12 @@ export default function DisplaySettings() {
|
|||||||
<FormLabel htmlFor="muted-words" mb="0">
|
<FormLabel htmlFor="muted-words" mb="0">
|
||||||
Muted words
|
Muted words
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<Textarea id="muted-words" {...register("mutedWords")} placeholder="Broccoli, Spinach, Artichoke..." />
|
<Textarea
|
||||||
|
id="muted-words"
|
||||||
|
{...register("mutedWords")}
|
||||||
|
placeholder="Broccoli, Spinach, Artichoke..."
|
||||||
|
maxW="2xl"
|
||||||
|
/>
|
||||||
<FormHelperText>
|
<FormHelperText>
|
||||||
<span>
|
<span>
|
||||||
Comma separated list of words, phrases or hashtags you never want to see in notes. (case insensitive)
|
Comma separated list of words, phrases or hashtags you never want to see in notes. (case insensitive)
|
||||||
|
@@ -13,10 +13,53 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Link,
|
Link,
|
||||||
FormErrorMessage,
|
FormErrorMessage,
|
||||||
|
Select,
|
||||||
|
Button,
|
||||||
|
Text,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
|
import { useLocalStorage } from "react-use";
|
||||||
|
|
||||||
import { safeUrl } from "../../helpers/parse";
|
import { safeUrl } from "../../helpers/parse";
|
||||||
import { AppSettings } from "../../services/settings/migrations";
|
import { AppSettings } from "../../services/settings/migrations";
|
||||||
import { PerformanceIcon } from "../../components/icons";
|
import { PerformanceIcon } from "../../components/icons";
|
||||||
|
import { selectedMethod } from "../../services/verify-event";
|
||||||
|
|
||||||
|
function VerifyEventSettings() {
|
||||||
|
const [verifyEventMethod, setVerifyEventMethod] = useLocalStorage<string>("verify-event-method", "default", {
|
||||||
|
raw: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(selectedMethod, verifyEventMethod);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel htmlFor="verifyEventMethod" mb="0">
|
||||||
|
Verify event method
|
||||||
|
</FormLabel>
|
||||||
|
<Select value={verifyEventMethod} onChange={(e) => setVerifyEventMethod(e.target.value)} maxW="sm">
|
||||||
|
<option value="default">Default</option>
|
||||||
|
<option value="wasm">WebAssembly</option>
|
||||||
|
<option value="none">None</option>
|
||||||
|
</Select>
|
||||||
|
<FormHelperText>Default: All events signatures are checked</FormHelperText>
|
||||||
|
<FormHelperText>WebAssembly: Events signatures are checked in a separate thread</FormHelperText>
|
||||||
|
<FormHelperText>None: Only Profiles, Follows, and replaceable event signatures are checked</FormHelperText>
|
||||||
|
|
||||||
|
{selectedMethod !== verifyEventMethod && (
|
||||||
|
<>
|
||||||
|
<Text color="blue.500" mt="2">
|
||||||
|
NOTE: You must reload the app for this setting to take effect
|
||||||
|
</Text>
|
||||||
|
<Button colorScheme="primary" size="sm" onClick={() => location.reload()}>
|
||||||
|
Reload App
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function PerformanceSettings() {
|
export default function PerformanceSettings() {
|
||||||
const { register, formState } = useFormContext<AppSettings>();
|
const { register, formState } = useFormContext<AppSettings>();
|
||||||
@@ -86,15 +129,6 @@ export default function PerformanceSettings() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<FormHelperText>Enabled: Show reactions on notes</FormHelperText>
|
<FormHelperText>Enabled: Show reactions on notes</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl>
|
|
||||||
<Flex alignItems="center">
|
|
||||||
<FormLabel htmlFor="showSignatureVerification" mb="0">
|
|
||||||
Show signature verification
|
|
||||||
</FormLabel>
|
|
||||||
<Switch id="showSignatureVerification" {...register("showSignatureVerification")} />
|
|
||||||
</Flex>
|
|
||||||
<FormHelperText>Enabled: show signature verification on notes</FormHelperText>
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Flex alignItems="center">
|
<Flex alignItems="center">
|
||||||
<FormLabel htmlFor="autoDecryptDMs" mb="0">
|
<FormLabel htmlFor="autoDecryptDMs" mb="0">
|
||||||
@@ -104,6 +138,7 @@ export default function PerformanceSettings() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<FormHelperText>Enabled: automatically decrypt direct messages</FormHelperText>
|
<FormHelperText>Enabled: automatically decrypt direct messages</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<VerifyEventSettings />
|
||||||
</Flex>
|
</Flex>
|
||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
@@ -16,12 +16,13 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
|
import { EventTemplate, NostrEvent, UnsignedEvent, getEventHash, verifyEvent } from "nostr-tools";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
import VerticalPageLayout from "../../../components/vertical-page-layout";
|
||||||
import BackButton from "../../../components/router/back-button";
|
import BackButton from "../../../components/router/back-button";
|
||||||
import Play from "../../../components/icons/play";
|
import Play from "../../../components/icons/play";
|
||||||
import EventEditor from "./event-editor";
|
import EventEditor from "./event-editor";
|
||||||
import { EventTemplate, NostrEvent, UnsignedEvent, getEventHash, verifyEvent } from "nostr-tools";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { processEvent } from "./process";
|
import { processEvent } from "./process";
|
||||||
import { WritingIcon } from "../../../components/icons";
|
import { WritingIcon } from "../../../components/icons";
|
||||||
import { useSigningContext } from "../../../providers/global/signing-provider";
|
import { useSigningContext } from "../../../providers/global/signing-provider";
|
||||||
|
10
yarn.lock
10
yarn.lock
@@ -5473,10 +5473,10 @@ nostr-tools@^2.3.2:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
nostr-wasm v0.1.0
|
nostr-wasm v0.1.0
|
||||||
|
|
||||||
nostr-tools@^2.4.0:
|
nostr-tools@^2.5.0:
|
||||||
version "2.4.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-2.4.0.tgz#bc2140a95ce0be8d4900bd852f652d811562753e"
|
resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-2.5.0.tgz#083c8a22eb88c65f30d88a25e200ea2274348663"
|
||||||
integrity sha512-xQC7XdGeh0gLyprcKhvx5lwr7OQ+ZOiQ9C6GpzlVAj+EBv+AiN8kySb57t3uJoG1HK15oT9jf++MmQLwhp1xNQ==
|
integrity sha512-G02O3JYNCfhx9NDjd3NOCw/5ck8PX5hiOIhHKpsXyu49ZtZbxGH3OLP9tf0fpUZ+EVWdjIYFR689sV0i7+TOng==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@noble/ciphers" "^0.5.1"
|
"@noble/ciphers" "^0.5.1"
|
||||||
"@noble/curves" "1.2.0"
|
"@noble/curves" "1.2.0"
|
||||||
@@ -5487,7 +5487,7 @@ nostr-tools@^2.4.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
nostr-wasm v0.1.0
|
nostr-wasm v0.1.0
|
||||||
|
|
||||||
nostr-wasm@v0.1.0:
|
nostr-wasm@^0.1.0, nostr-wasm@v0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/nostr-wasm/-/nostr-wasm-0.1.0.tgz#17af486745feb2b7dd29503fdd81613a24058d94"
|
resolved "https://registry.yarnpkg.com/nostr-wasm/-/nostr-wasm-0.1.0.tgz#17af486745feb2b7dd29503fdd81613a24058d94"
|
||||||
integrity sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==
|
integrity sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==
|
||||||
|
Reference in New Issue
Block a user