mirror of
https://github.com/smolgrrr/TAO.git
synced 2024-09-20 09:21:25 +00:00
messy global feed
This commit is contained in:
parent
e968c13939
commit
d31771aa11
@ -3,9 +3,7 @@ import './App.css';
|
|||||||
import Home from './components/Home';
|
import Home from './components/Home';
|
||||||
import Settings from './components/Settings';
|
import Settings from './components/Settings';
|
||||||
import SwipeableViews from 'react-swipeable-views';
|
import SwipeableViews from 'react-swipeable-views';
|
||||||
import { NostrProvider } from './utils/relays';
|
|
||||||
|
|
||||||
const relayUrls = ['wss://relay.damus.io'];
|
|
||||||
function App() {
|
function App() {
|
||||||
const [index, setIndex] = React.useState(1);
|
const [index, setIndex] = React.useState(1);
|
||||||
|
|
||||||
@ -15,7 +13,6 @@ function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NostrProvider relayUrls={relayUrls} debug={true}>
|
|
||||||
<SwipeableViews index={index} onChangeIndex={handleChangeIndex}>
|
<SwipeableViews index={index} onChangeIndex={handleChangeIndex}>
|
||||||
<div>
|
<div>
|
||||||
<Settings />
|
<Settings />
|
||||||
@ -24,7 +21,6 @@ function App() {
|
|||||||
<Home />
|
<Home />
|
||||||
</div>
|
</div>
|
||||||
</SwipeableViews>
|
</SwipeableViews>
|
||||||
</NostrProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,48 +1,48 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { relayInit } from 'nostr-tools';
|
|
||||||
import PostCard from './PostCard/PostCard';
|
import PostCard from './PostCard/PostCard';
|
||||||
import Header from './Header/Header';
|
|
||||||
import NewThreadCard from './PostCard/NewThreadCard';
|
import NewThreadCard from './PostCard/NewThreadCard';
|
||||||
import { getPow } from '../utils/mine';
|
import { getPow } from '../utils/mine';
|
||||||
import { Event } from 'nostr-tools';
|
import { relayInit, Event } from 'nostr-tools';
|
||||||
|
import { subGlobalFeed, simpleSub24hFeed } from '../utils/subscriptions';
|
||||||
|
import { uniqBy } from '../utils/utils';
|
||||||
|
|
||||||
const relay = relayInit('wss://nostr.lu.ke');
|
const relay = relayInit('wss://nostr.lu.ke');
|
||||||
|
|
||||||
|
type EventRelayMap = {
|
||||||
|
[eventId: string]: string[];
|
||||||
|
};
|
||||||
|
const eventRelayMap: EventRelayMap = {}; // eventId: [relay1, relay2]
|
||||||
|
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
// Define the type of the state variable
|
const [events, setEvents] = useState<Event[]>([]); // Initialize state
|
||||||
const [events, setEvents] = useState<Event[]>([]);
|
|
||||||
|
// Define your callback function for subGlobalFeed
|
||||||
|
const onEvent = (event: Event, relay: string) => {
|
||||||
|
setEvents((prevEvents) => [...prevEvents, event]);
|
||||||
|
console.log(event.id);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
relay.on('connect', async () => {
|
// Subscribe to global feed when the component mounts
|
||||||
console.log(`connected to ${relay.url}`);
|
subGlobalFeed(onEvent);
|
||||||
|
|
||||||
const eventList = await relay.list([
|
// Optionally, return a cleanup function to unsubscribe when the component unmounts
|
||||||
{
|
return () => {
|
||||||
kinds: [1],
|
// Your cleanup code here
|
||||||
limit: 200,
|
};
|
||||||
},
|
}, []); // Empty dependency array means this useEffect runs once when the component mounts
|
||||||
]);
|
|
||||||
|
|
||||||
// Filter events with a difficulty greater than 10
|
const uniqEvents = events.length > 0 ? uniqBy(events, "id") : [];
|
||||||
const filteredEvents = eventList.filter(event => getPow(event.id) > 2);
|
// const filteredEvents = uniqEvents.filter(event => getPow(event.id) > 5);
|
||||||
|
const sortedEvents = uniqEvents.sort((a, b) => (b.created_at as any) - (a.created_at as any));
|
||||||
// Assuming eventList is of type Event[]
|
|
||||||
setEvents(filteredEvents);
|
|
||||||
});
|
|
||||||
|
|
||||||
relay.on('error', () => {
|
|
||||||
console.log(`failed to connect to ${relay.url}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
relay.connect();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<main className="bg-black text-white min-h-screen">
|
<main className="bg-black text-white min-h-screen">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4">
|
||||||
<NewThreadCard />
|
<NewThreadCard />
|
||||||
{events.sort((a, b) => b.created_at - a.created_at).map((event, index) => (
|
{sortedEvents.sort((a, b) => b.created_at - a.created_at).map((event, index) => (
|
||||||
<PostCard key={index} event={event}/>
|
<PostCard key={index} event={event}/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,47 +1,34 @@
|
|||||||
import CardContainer from './CardContainer';
|
import CardContainer from './CardContainer';
|
||||||
import { ArrowUpTrayIcon } from '@heroicons/react/24/outline';
|
import { ArrowUpTrayIcon, CpuChipIcon } from '@heroicons/react/24/outline';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { generatePrivateKey, getPublicKey, finishEvent, relayInit} from 'nostr-tools';
|
import { Event, generatePrivateKey, getPublicKey, finishEvent, relayInit} from 'nostr-tools';
|
||||||
import { minePow } from '../../utils/mine';
|
import { minePow } from '../../utils/mine';
|
||||||
|
|
||||||
const difficulty = 10
|
const difficulty = 10
|
||||||
|
|
||||||
export const relay = relayInit('wss://nostr.lu.ke')
|
const NewThreadCard: React.FC = () => {
|
||||||
|
|
||||||
const NewThreadCard = () => {
|
|
||||||
const [comment, setComment] = useState("");
|
const [comment, setComment] = useState("");
|
||||||
|
|
||||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let sk = generatePrivateKey()
|
let sk = generatePrivateKey();
|
||||||
let pk = getPublicKey(sk)
|
|
||||||
|
|
||||||
relay.on('connect', () => {
|
|
||||||
console.log(`connected to ${relay.url}`)
|
|
||||||
})
|
|
||||||
relay.on('error', () => {
|
|
||||||
console.log(`failed to connect to ${relay.url}`)
|
|
||||||
})
|
|
||||||
|
|
||||||
await relay.connect()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const event = minePow({
|
const event = minePow({
|
||||||
kind: 1,
|
kind: 1,
|
||||||
tags: [],
|
tags: [],
|
||||||
content: 'Hello, world!',
|
content: comment,
|
||||||
created_at: Math.floor(Date.now() / 1000), //needs to be date To Unix
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
pubkey: pk,
|
pubkey: getPublicKey(sk),
|
||||||
}, difficulty)
|
}, difficulty);
|
||||||
|
|
||||||
const signedEvent = finishEvent(event, sk)
|
const signedEvent = finishEvent(event, sk);
|
||||||
await relay.publish(signedEvent)
|
// await publish(signedEvent);
|
||||||
console.log(signedEvent.id)
|
console.log(signedEvent.id);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setComment(comment + " " + error);
|
setComment(comment + " " + error);
|
||||||
}
|
}
|
||||||
relay.close()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// async function attachFile(file_input: File | null) {
|
// async function attachFile(file_input: File | null) {
|
||||||
@ -80,6 +67,8 @@ const NewThreadCard = () => {
|
|||||||
name="com"
|
name="com"
|
||||||
wrap="soft"
|
wrap="soft"
|
||||||
className="w-full p-2 rounded bg-gradient-to-r from-blue-900 to-cyan-500 text-white border-none"
|
className="w-full p-2 rounded bg-gradient-to-r from-blue-900 to-cyan-500 text-white border-none"
|
||||||
|
value={comment}
|
||||||
|
onChange={(e) => setComment(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
@ -87,6 +76,7 @@ const NewThreadCard = () => {
|
|||||||
<ArrowUpTrayIcon className="h-6 w-6 text-white" />
|
<ArrowUpTrayIcon className="h-6 w-6 text-white" />
|
||||||
<input type="file" className="hidden" />
|
<input type="file" className="hidden" />
|
||||||
</div>
|
</div>
|
||||||
|
<span className="flex items-center"><CpuChipIcon className="h-6 w-6 text-white" />: {difficulty}</span>
|
||||||
<button type="submit" className="px-4 py-2 bg-gradient-to-r from-cyan-900 to-blue-500 rounded text-white font-semibold">
|
<button type="submit" className="px-4 py-2 bg-gradient-to-r from-cyan-900 to-blue-500 rounded text-white font-semibold">
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
@ -98,5 +88,4 @@ const NewThreadCard = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default NewThreadCard;
|
export default NewThreadCard;
|
@ -21,11 +21,6 @@ const colorCombos = [
|
|||||||
'from-sky-400 to-cyan-500'
|
'from-sky-400 to-cyan-500'
|
||||||
];
|
];
|
||||||
|
|
||||||
function getRandomElement(array: string[]): string {
|
|
||||||
const index = Math.floor(Math.random() * array.length);
|
|
||||||
return array[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const getColorFromHash = (id: string, colors: string[]): string => {
|
const getColorFromHash = (id: string, colors: string[]): string => {
|
||||||
// Create a simple hash from the event.id
|
// Create a simple hash from the event.id
|
||||||
let hash = 0;
|
let hash = 0;
|
||||||
|
@ -1,152 +1,108 @@
|
|||||||
import {
|
import {Event, Filter, relayInit, Relay, Sub} from 'nostr-tools';
|
||||||
createContext,
|
|
||||||
ReactNode,
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from "react"
|
|
||||||
import { Relay, Filter, Event, relayInit, Sub } from "nostr-tools"
|
|
||||||
import { uniqBy } from "./utils"
|
|
||||||
|
|
||||||
type OnConnectFunc = (relay: Relay) => void
|
type SubCallback = (
|
||||||
type OnDisconnectFunc = (relay: Relay) => void
|
event: Readonly<Event>,
|
||||||
type OnEventFunc = (event: Event) => void
|
relay: Readonly<string>,
|
||||||
type OnDoneFunc = () => void
|
) => void;
|
||||||
type OnSubscribeFunc = (sub: Sub, relay: Relay) => void
|
|
||||||
|
|
||||||
interface NostrContextType {
|
type Subscribe = {
|
||||||
isLoading: boolean
|
cb: SubCallback;
|
||||||
debug?: boolean
|
filter: Filter;
|
||||||
connectedRelays: Relay[]
|
unsub?: boolean;
|
||||||
onConnect: (_onConnectCallback?: OnConnectFunc) => void
|
};
|
||||||
onDisconnect: (_onDisconnectCallback?: OnDisconnectFunc) => void
|
|
||||||
publish: (event: Event) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const NostrContext = createContext<NostrContextType>({
|
const subList: Array<Sub> = [];
|
||||||
isLoading: true,
|
const currentSubList: Array<Subscribe> = [];
|
||||||
connectedRelays: [],
|
const relayMap = new Map<string, Relay>();
|
||||||
onConnect: () => null,
|
|
||||||
onDisconnect: () => null,
|
|
||||||
publish: () => null,
|
|
||||||
})
|
|
||||||
|
|
||||||
const log = (
|
export const addRelay = async (url: string) => {
|
||||||
isOn: boolean | undefined,
|
const relay = relayInit(url);
|
||||||
type: "info" | "error" | "warn",
|
relay.on('connect', () => {
|
||||||
...args: unknown[]
|
console.info(`connected to ${relay.url}`);
|
||||||
|
});
|
||||||
|
relay.on('error', () => {
|
||||||
|
console.warn(`failed to connect to ${relay.url}`);
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await relay.connect();
|
||||||
|
currentSubList.forEach(({cb, filter}) => subscribe(cb, filter, relay));
|
||||||
|
relayMap.set(url, relay);
|
||||||
|
} catch {
|
||||||
|
console.warn(`could not connect to ${url}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const unsubscribe = (sub: Sub) => {
|
||||||
|
sub.unsub();
|
||||||
|
subList.splice(subList.indexOf(sub), 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const subscribe = (
|
||||||
|
cb: SubCallback,
|
||||||
|
filter: Filter,
|
||||||
|
relay: Relay,
|
||||||
|
unsub?: boolean
|
||||||
) => {
|
) => {
|
||||||
if (!isOn) return
|
const sub = relay.sub([filter]);
|
||||||
console[type](...args)
|
subList.push(sub);
|
||||||
}
|
sub.on('event', (event: Event) => {
|
||||||
|
cb(event, relay.url);
|
||||||
export function NostrProvider({
|
});
|
||||||
children,
|
if (unsub) {
|
||||||
relayUrls,
|
sub.on('eose', () => {
|
||||||
debug,
|
// console.log('eose', relay.url);
|
||||||
}: {
|
unsubscribe(sub);
|
||||||
children: ReactNode
|
});
|
||||||
relayUrls: string[]
|
|
||||||
debug?: boolean
|
|
||||||
}) {
|
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
|
||||||
const [connectedRelays, setConnectedRelays] = useState<Relay[]>([])
|
|
||||||
const [relays, setRelays] = useState<Relay[]>([])
|
|
||||||
const relayUrlsRef = useRef<string[]>([])
|
|
||||||
|
|
||||||
let onConnectCallback: null | OnConnectFunc = null
|
|
||||||
let onDisconnectCallback: null | OnDisconnectFunc = null
|
|
||||||
|
|
||||||
const disconnectToRelays = useCallback(
|
|
||||||
(relayUrls: string[]) => {
|
|
||||||
relayUrls.forEach(async (relayUrl) => {
|
|
||||||
await relays.find((relay) => relay.url === relayUrl)?.close()
|
|
||||||
setRelays((prev) => prev.filter((r) => r.url !== relayUrl))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[relays],
|
|
||||||
)
|
|
||||||
|
|
||||||
const connectToRelays = useCallback(
|
|
||||||
(relayUrls: string[]) => {
|
|
||||||
relayUrls.forEach(async (relayUrl) => {
|
|
||||||
const relay = relayInit(relayUrl)
|
|
||||||
|
|
||||||
if (connectedRelays.findIndex((r) => r.url === relayUrl) >= 0) {
|
|
||||||
// already connected, skip
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return sub;
|
||||||
|
};
|
||||||
|
|
||||||
setRelays((prev) => uniqBy([...prev, relay], "url"))
|
export const sub = (obj: Subscribe) => {
|
||||||
relay.connect()
|
currentSubList.push(obj);
|
||||||
|
relayMap.forEach((relay) => subscribe(obj.cb, obj.filter, relay, obj.unsub));
|
||||||
|
};
|
||||||
|
|
||||||
relay.on("connect", () => {
|
export const subOnce = (
|
||||||
log(debug, "info", `✅ nostr (${relayUrl}): Connected!`)
|
obj: Subscribe & {relay: string}
|
||||||
setIsLoading(false)
|
) => {
|
||||||
onConnectCallback?.(relay)
|
const relay = relayMap.get(obj.relay);
|
||||||
setConnectedRelays((prev) => uniqBy([...prev, relay], "url"))
|
if (relay) {
|
||||||
})
|
const sub = subscribe(obj.cb, obj.filter, relay);
|
||||||
|
sub.on('eose', () => {
|
||||||
relay.on("disconnect", () => {
|
// console.log('eose', obj.relay);
|
||||||
log(debug, "warn", `🚪 nostr (${relayUrl}): Connection closed.`)
|
unsubscribe(sub);
|
||||||
onDisconnectCallback?.(relay)
|
});
|
||||||
setConnectedRelays((prev) => prev.filter((r) => r.url !== relayUrl))
|
|
||||||
})
|
|
||||||
|
|
||||||
relay.on("error", () => {
|
|
||||||
log(debug, "error", `❌ nostr (${relayUrl}): Connection error!`)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[connectedRelays, debug, onConnectCallback, onDisconnectCallback],
|
|
||||||
)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (relayUrlsRef.current === relayUrls) {
|
|
||||||
// relayUrls isn't updated, skip
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const relayUrlsToDisconnect = relayUrlsRef.current.filter(
|
export const unsubAll = () => {
|
||||||
(relayUrl) => !relayUrls.includes(relayUrl),
|
subList.forEach(unsubscribe);
|
||||||
)
|
currentSubList.length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
disconnectToRelays(relayUrlsToDisconnect)
|
type PublishCallback = (
|
||||||
connectToRelays(relayUrls)
|
relay: string,
|
||||||
|
errorMessage?: string,
|
||||||
|
) => void;
|
||||||
|
|
||||||
relayUrlsRef.current = relayUrls
|
|
||||||
}, [relayUrls, connectToRelays, disconnectToRelays])
|
|
||||||
|
|
||||||
const publish = (event: Event) => {
|
export const publish = (event: Event, cb: PublishCallback) => {
|
||||||
return connectedRelays.map((relay) => {
|
relayMap.forEach(async (relay, url) => {
|
||||||
log(debug, "info", `⬆️ nostr (${relay.url}): Sending event:`, event)
|
try {
|
||||||
|
await relay.publish(event);
|
||||||
return relay.publish(event)
|
console.info(`${relay.url} has accepted our event`);
|
||||||
})
|
cb(relay.url);
|
||||||
|
} catch (reason) {
|
||||||
|
console.error(`failed to publish to ${relay.url}: ${reason}`);
|
||||||
|
cb(relay.url, reason as string);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const value: NostrContextType = {
|
|
||||||
debug,
|
|
||||||
isLoading,
|
|
||||||
connectedRelays,
|
|
||||||
publish,
|
|
||||||
onConnect: (_onConnectCallback?: OnConnectFunc) => {
|
|
||||||
if (_onConnectCallback) {
|
|
||||||
onConnectCallback = _onConnectCallback
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDisconnect: (_onDisconnectCallback?: OnDisconnectFunc) => {
|
|
||||||
if (_onDisconnectCallback) {
|
|
||||||
onDisconnectCallback = _onDisconnectCallback
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return <NostrContext.Provider value={value}>{children}</NostrContext.Provider>
|
addRelay('wss://relay.snort.social');
|
||||||
}
|
addRelay('wss://nostr.bitcoiner.social');
|
||||||
|
addRelay('wss://nostr.mom');
|
||||||
export function useNostr() {
|
addRelay('wss://relay.nostr.bg');
|
||||||
return useContext(NostrContext)
|
addRelay('wss://nos.lol');
|
||||||
}
|
// addRelay('wss://relay.nostr.ch');
|
86
client/src/utils/subscriptions.ts
Normal file
86
client/src/utils/subscriptions.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import {sub, subOnce, unsubAll} from './relays';
|
||||||
|
import { Event } from 'nostr-tools';
|
||||||
|
|
||||||
|
type SubCallback = (
|
||||||
|
event: Event,
|
||||||
|
relay: string,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
/** subscribe to global feed */
|
||||||
|
export const subGlobalFeed = (onEvent: SubCallback) => {
|
||||||
|
console.info('subscribe to global feed');
|
||||||
|
unsubAll();
|
||||||
|
const now = Math.floor(Date.now() * 0.001);
|
||||||
|
const pubkeys = new Set<string>();
|
||||||
|
const notes = new Set<string>();
|
||||||
|
const prefix = Math.floor(10 / 4); // 4 bits in each '0' character
|
||||||
|
|
||||||
|
sub({ // get past events
|
||||||
|
cb: (evt, relay) => {
|
||||||
|
pubkeys.add(evt.pubkey);
|
||||||
|
notes.add(evt.id);
|
||||||
|
onEvent(evt, relay);
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
kinds: [1],
|
||||||
|
since: Math.floor((Date.now() * 0.001) - (24 * 60 * 60)),
|
||||||
|
limit: 10,
|
||||||
|
},
|
||||||
|
unsub: true
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// get profile info
|
||||||
|
sub({
|
||||||
|
cb: onEvent,
|
||||||
|
filter: {
|
||||||
|
authors: Array.from(pubkeys),
|
||||||
|
kinds: [0],
|
||||||
|
limit: pubkeys.size,
|
||||||
|
},
|
||||||
|
unsub: true,
|
||||||
|
});
|
||||||
|
pubkeys.clear();
|
||||||
|
notes.clear();
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
// subscribe to future notes, reactions and profile updates
|
||||||
|
sub({
|
||||||
|
cb: (evt, relay) => {
|
||||||
|
onEvent(evt, relay);
|
||||||
|
if (
|
||||||
|
evt.kind !== 1
|
||||||
|
|| pubkeys.has(evt.pubkey)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
subOnce({ // get profil data
|
||||||
|
relay,
|
||||||
|
cb: onEvent,
|
||||||
|
filter: {
|
||||||
|
authors: [evt.pubkey],
|
||||||
|
kinds: [0],
|
||||||
|
limit: 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
kinds: [0, 1],
|
||||||
|
since: now,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** subscribe to global feed */
|
||||||
|
export const simpleSub24hFeed = (onEvent: SubCallback) => {
|
||||||
|
unsubAll();
|
||||||
|
sub({
|
||||||
|
cb: onEvent,
|
||||||
|
filter: {
|
||||||
|
kinds: [1],
|
||||||
|
//until: Math.floor(Date.now() * 0.001),
|
||||||
|
since: Math.floor((Date.now() * 0.001) - (24 * 60 * 60)),
|
||||||
|
limit: 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user