diff --git a/.env b/.env index dc5f3f5a..004c7e8a 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ VITE_DARK_THEME="accent:#FC560E,neutral-100:#F5F5F5,neutral-200:#E5E5E5,neutral- VITE_LIGHT_THEME="accent:#FC560E,neutral-950:#FAFAFA,neutral-900:#FAFAFA,neutral-800:#F5F5F5,neutral-700:#D4D4D4,neutral-600:#A3A3A3,neutral-500:#737373,neutral-400:#525252,neutral-300:#404040,neutral-200:#262626,neutral-100:#171717,neutral-50:#0A0A0A,success:#12D2B0,tinted-800:#FFFFFF,tinted-700:#FAFAFA,tinted-600:#F5F5F5,tinted-500:#D4D4D4,tinted-400:#A3A3A3,tinted-200:#737373,tinted-100:#525252,warning:#FCAB0E" VITE_DVM_RELAYS=wss://relay.damus.io,wss://offchain.pub,wss://relay.f7z.io,wss://nos.lol,wss://relay.nostr.net,wss://relay.nostr.band,wss://bucket.coracle.social VITE_SEARCH_RELAYS=wss://relay.nostr.band,wss://nostr.wine,wss://search.nos.today -VITE_DEFAULT_RELAYS=wss://purplepag.es,wss://relay.damus.io,wss://relay.nostr.band,wss://relayable.org,wss://nostr.wine +VITE_DEFAULT_RELAYS=wss://purplepag.es,wss://relay.damus.io,wss://relay.nostr.band VITE_DEFAULT_FOLLOWS=fe7f6bc6f7338b76bbf80db402ade65953e20b2f23e66e898204b63cc42539a3,f4db5270bd991b17bea1e6d035f45dee392919c29474bbac10342d223c74e0d0,180a6d42c7d64f8c3958d9d10dd5a4117eaaacea8e7f980781e9a53136cf5693,7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805,676ffea2ec31426a906d7795d7ebae2ba5e61f0b9fa815995b4a299dd085d510,1577e4599dd10c863498fe3c20bd82aafaf829a595ce83c5cf8ac3463531b09b,4d5ce768123563bc583697db5e84841fb528f7b708d966f2e546286ce3c72077,eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f,04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9,85080d3bad70ccdcd7f74c29a44f55bb85cbcd3dd0cbb957da1d215bdb931204,74ffc51cc30150cf79b6cb316d3a15cf332ab29a38fec9eb484ab1551d6d1856,93518f91dfa51d8acf39217cdcd3d2ccd178433cb9e72368544aacd7412cb50c,f728d9e6e7048358e70930f5ca64b097770d989ccd86854fe618eda9c8a38106,91c9a5e1a9744114c6fe2d61ae4de82629eaaa0fb52f48288093c7e7e036f832,83e818dfbeccea56b0f551576b3fd39a7a50e1d8159343500368fa085ccd964b,090254801a7e8e5085b02e711622f0dfa1a85503493af246aa42af08f5e4d2df,472f440f29ef996e92a186b8d320ff180c855903882e59d50de1b8bd5669301e,7b3f7803750746f455413a221f80965eecb69ef308f2ead1da89cc2c8912e968,330fb1431ff9d8c250706bbcdc016d5495a3f744e047a408173e92ae7ee42dac,c4eabae1be3cf657bc1855ee05e69de9f059cb7a059227168b80b89761cbc4e0,a4cb51f4618cfcd16b2d3171c466179bed8e197c43b8598823b04de266cef110,f9acb0b034c4c1177e985f14639f317ef0fedee7657c060b146ee790024317ec,6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93,e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411,6389be6491e7b693e9f368ece88fcd145f07c068d2c1bbae4247b9b5ef439d32,e1ff3bfdd4e40315959b08b4fcc8245eaa514637e1d4ec2ae166b743341be1af,38dbb9b07d93861d40620ad62d44b1a8e8785df0997eeb4454f12d217048cd5c,064de2497ce621aee2a5b4b926a08b1ca01bce9da85b0c714e883e119375140c,aa5e6ccfc7cb7c3431d12b0ea4b83e5b35427602522080a6a8618950527f811b,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,676ffea2ec31426a906d7795d7ebae2ba5e61f0b9fa815995b4a299dd085d510,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,ffca54e078fd9884a745d70eb0159c0b8a9e7d383a4906a7484b83ebf6101dd5,9a4acdeb978565e27490dca65c83e9f65745eaec1d9a0405a52d198c1489913b,e5177ebf513530c2d0924083b64b7eadd7fb85efcc3e4dfb55c73a924c901ca7,5b0183ab6c3e322bf4d41c6b3aef98562a144847b7499543727c5539a114563e,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,26bd32c67232bdf16d05e763ec67d883015eb99fd1269025224c20c6cfdb0158,d307643547703537dfdef811c3dea96f1f9e84c8249e200353425924a9908cf8,604e96e099936a104883958b040b47672e0f048c98ac793f37ffe4c720279eb2,90b9bec74789688e515125596ab6350bfe646176ac75742275063922c5fea010,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,c43bbb58e2e6bc2f9455758257f6ba5329107bd4e8274068c2936c69d9980b7d,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,66bd8fed3590f2299ef0128f58d67879289e6a99a660e83ead94feab7606fd17,eeb11961b25442b16389fe6c7ebea9adf0ac36dd596816ea7119e521b8821b9e,61066504617ee79387021e18c89fb79d1ddbc3e7bff19cf2298f40466f8715e9,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,a9434ee165ed01b286becfc2771ef1705d3537d051b387288898cc00d5c885be,ee6ea13ab9fe5c4a68eaf9b1a34fe014a66b40117c50ee2a614f4cda959b6e74,7bdef7be22dd8e59f4600e044aa53a1cf975a9dc7d27df5833bc77db784a5805,1577e4599dd10c863498fe3c20bd82aafaf829a595ce83c5cf8ac3463531b09b,1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,b83a28b7e4e5d20bd960c5faeb6625f95529166b8bdb045d42634a2f35919450,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,a4cb51f4618cfcd16b2d3171c466179bed8e197c43b8598823b04de266cef110,e56e7b4326618f3d626c0e398f5082c3b16732e469e0a048b7ddb544c2be294a,011c1b374c12fbd3633e98957d3c46bed67983abecef50706c73a77c171d0d2c,b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc,b708f7392f588406212c3882e7b3bc0d9b08d62f95fa170d099127ece2770e5e,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,0fecf65daa26faf3f668e8143325a4c199a040b6345ed40a08614d7dd85b1823,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49,eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f,58c741aa630c2da35a56a77c1d05381908bd10504fdd2d8b43f725efa6d23196,84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240,33bd77e5394520747faae1394a4af5fa47f404389676375b6dc7be865ed81452,21335073401a310cc9179fe3a77e9666710cfdf630dfd840f972c183a244b1ad,36732cc35fe56185af1b11160a393d6c73a1fe41ddf1184c10394c28ca5d627b,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245,63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,00000000827ffaa94bfea288c3dfce4422c794fbb96625b6b31e9049f729d700,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,e8ed3798c6ffebffa08501ac39e271662bfd160f688f94c45d692d8767dd345a,c5fb6ecc876e0458e3eca9918e370cbcd376901c58460512fe537a46e58c38bb,40b9c85fffeafc1cadf8c30a4e5c88660ff6e4971a0dc723d5ab674b5e61b451,a3eb29554bd27fca7f53f66272e4bb59d066f2f31708cf341540cb4729fbd841,460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c,b154080cb49639bb079a6a53c1d98e7130eeab3c61aa95dd9e38f9e400027cc7,0000005f87f64341c212cc93d6c266c03ae752c02660e78a6da1424f7b05c470,d61f3bc5b3eb4400efdae6169a5c17cabf3246b514361de939ce4a1a0da6ef4a,1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,7adb520c3ac7cb6dc8253508df0ce1d975da49fefda9b5c956744a049d230ace,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5,17717ad4d20e2a425cda0a2195624a0a4a73c4f6975f16b1593fc87fa46f2d58,af9d70407464247d19fd243cf1bee81e6df1e639217dc66366bf37aa42d05d35,ddf03aca85ade039e6742d5bef3df352df199d0d31e22b9858e7eda85cb3bbbe,d36e8083fa7b36daee646cb8b3f99feaa3d89e5a396508741f003e21ac0b6bec,7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3d842afecd5e293f28b6627933704a3fb8ce153aa91d790ab11f6a752d44a42d,79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6,17538dc2a62769d09443f18c37cbe358fab5bbf981173542aa7c5ff171ed77c4,ff27d01cb1e56fb58580306c7ba76bb037bf211c5b573c56e4e70ca858755af0,8fb140b4e8ddef97ce4b821d247278a1a4353362623f64021484b372f948000c,27797bd4e5ee52db0a197668c92b9a3e7e237e1f9fa73a10c38d731c294cfc9a,7cc328a08ddb2afdf9f9be77beff4c83489ff979721827d628a542f32a247c0e,c35ff8c340449f0d68af1aec4844bb44a9c0b8c1dd4f4d4efbc65e12039a348a,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,eab0e756d32b80bcd464f3d844b8040303075a13eabc3599a762c9ac7ab91f4f,dace63b00c42e6e017d00dd190a9328386002ff597b841eb5ef91de4f1ce8491,76c71aae3a491f1d9eec47cba17e229cda4113a0bbb6e6ae1776d7643e29cafa,266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075 VITE_ONBOARDING_LISTS="30003:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:5263247253161571,30003:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:2706265821742835,30003:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:42382467334209006,30003:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:16207364281277292,30003:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:8382789831817543,30003:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:Nostr Devs" VITE_NIP96_URLS=https://nostr.build,https://nostrcheck.me,https://sove.rent,https://void.cat diff --git a/src/app/router.ts b/src/app/router.ts index 37d5f59c..af4f1017 100644 --- a/src/app/router.ts +++ b/src/app/router.ts @@ -56,7 +56,7 @@ export const decodeEntity = entity => { // pass } - return {type, data, relays: hints.FetchFromHints(data?.relays || []).getUrls()} + return {type, data, relays: hints.scenario([data?.relays || []]).getUrls()} } // Serializers @@ -143,7 +143,12 @@ router.extend("notes", (id, {relays = []} = {}) => { router.extend("people", (pubkey, {relays = []} = {}) => { if (relays.length < 3) { - relays = relays.concat(hints.FetchFromPubkey(pubkey).getUrls(3 - relays.length)) + relays = relays.concat( + hints + .FromPubkeys([pubkey]) + .limit(3 - relays.length) + .getUrls(), + ) } return nip19.nprofileEncode({pubkey, relays}) diff --git a/src/app/shared/Compose.svelte b/src/app/shared/Compose.svelte index 18482920..8f0eaefa 100644 --- a/src/app/shared/Compose.svelte +++ b/src/app/shared/Compose.svelte @@ -30,7 +30,7 @@ const pubkeyEncoder = { encode: pubkey => { - const relays = hints.FetchFromPubkey(pubkey).getUrls(3) + const relays = hints.FromPubkeys([pubkey]).limit(3).getUrls() const nprofile = nip19.nprofileEncode({pubkey, relays}) return "nostr:" + nprofile diff --git a/src/app/shared/Feed.svelte b/src/app/shared/Feed.svelte index d6b6dcd9..47520896 100644 --- a/src/app/shared/Feed.svelte +++ b/src/app/shared/Feed.svelte @@ -47,7 +47,7 @@ selection = getRelaysFromFilters(compileFilters([filter])) } - return hints.FetchFromHints(selection).getUrls().concat(LOCAL_RELAY_URL) + return hints.scenario([selection]).getUrls().concat(LOCAL_RELAY_URL) } const loadMore = () => feed.load(5) diff --git a/src/app/shared/Note.svelte b/src/app/shared/Note.svelte index 02b2c75a..3a62efce 100644 --- a/src/app/shared/Note.svelte +++ b/src/app/shared/Note.svelte @@ -69,7 +69,7 @@ if (interactive && !["I"].includes(target.tagName) && !target.closest("a")) { router .at("notes") - .of(getIdOrAddress(event), {relays: hints.FetchEvent(event).getUrls(3)}) + .of(getIdOrAddress(event), {relays: hints.Event(event).limit(3).getUrls()}) .cx({context: ctx.concat(event)}) .open() } @@ -80,21 +80,21 @@ const goToDetail = () => router .at("notes") - .of(getIdOrAddress(event), {relays: hints.FetchEvent(event).getUrls(3)}) + .of(getIdOrAddress(event), {relays: hints.Event(event).limit(3).getUrls()}) .cx({context: ctx.concat(event)}) .push() const goToParent = () => router .at("notes") - .of(reply.value(), {relays: hints.FetchEventParent(event).getUrls(3)}) + .of(reply.value(), {relays: hints.EventParent(event).limit(3).getUrls()}) .cx({context: ctx.concat(event)}) .open() const goToThread = () => router .at("notes") - .of(getIdOrAddress(event), {relays: hints.FetchEvent(event).getUrls(3)}) + .of(getIdOrAddress(event), {relays: hints.Event(event).limit(3).getUrls()}) .at("thread") .cx({context: ctx.concat(event)}) .open() @@ -180,7 +180,7 @@ if (!event.pubkey) { event = await loadOne({ - relays: hints.FetchFromHints(relays).getUrls(), + relays: hints.scenario([relays]).getUrls(), filters: getIdFilters([event.id]), }) } @@ -205,7 +205,7 @@ } load({ - relays: hints.FetchEventChildren(event).getUrls(), + relays: hints.EventChildren(event).getUrls(), filters: getReplyFilters([event], {kinds}), onEvent: batch(200, events => { ctx = uniqBy(prop("id"), ctx.concat(events)) diff --git a/src/app/shared/NoteActions.svelte b/src/app/shared/NoteActions.svelte index c4c84d77..6429de35 100644 --- a/src/app/shared/NoteActions.svelte +++ b/src/app/shared/NoteActions.svelte @@ -55,8 +55,8 @@ export let zapper const tags = Tags.fromEvent(note) - const relays = hints.FetchEvent(note).getUrls(3) const address = tags.context().values().first() + const relays = hints.Event(note).limit(3).getUrls() const nevent = nip19.neventEncode({id: note.id, relays}) const muted = isEventMuted.derived($isEventMuted => $isEventMuted(note, true)) const kindHandlers = deriveHandlers(note.kind).derived(filter((h: any) => h.recs.length > 1)) @@ -66,7 +66,7 @@ const repliesCount = tweened(0, {interpolate}) const handler = handlers.key(tags.get("client")?.mark()) - //const report = () => router.at("notes").of(note.id, {relays: hints.FetchEvent(note).getUrls(3)}).at('report').qp({pubkey: note.pubkey}).open() + //const report = () => router.at("notes").of(note.id, {relays: hints.Event(note).getUrls(3)}).at('report').qp({pubkey: note.pubkey}).open() const setView = v => { view = v @@ -139,7 +139,7 @@ const broadcast = () => { Publisher.publish({ event: asNostrEvent(note), - relays: hints.Broadcast().getUrls(), + relays: hints.Outbox().getUrls(), }) toast.show("info", "Note has been re-published!") diff --git a/src/app/shared/NoteContentKind0.svelte b/src/app/shared/NoteContentKind0.svelte index 332399ce..dbb4e5ec 100644 --- a/src/app/shared/NoteContentKind0.svelte +++ b/src/app/shared/NoteContentKind0.svelte @@ -19,7 +19,7 @@ router .at("people") .of(pubkey) - .cx({relays: hints.FetchEvent(note).getUrls(3)}) + .cx({relays: hints.Event(note).limit(3).getUrls()}) .open() diff --git a/src/app/shared/NoteContentQuote.svelte b/src/app/shared/NoteContentQuote.svelte index a12bdec5..41a9985f 100644 --- a/src/app/shared/NoteContentQuote.svelte +++ b/src/app/shared/NoteContentQuote.svelte @@ -1,6 +1,5 @@ diff --git a/src/app/shared/PersonCollections.svelte b/src/app/shared/PersonCollections.svelte index 5f549cfd..3ed73a4d 100644 --- a/src/app/shared/PersonCollections.svelte +++ b/src/app/shared/PersonCollections.svelte @@ -37,7 +37,7 @@ } load({ - relays: hints.FetchFromPubkey(pubkey).getUrls(), + relays: hints.FromPubkeys([pubkey]).getUrls(), filters: [{kinds: [1985], authors: [pubkey], "#L": ["#t"]}], onEvent: batch(300, chunk => { events = [...events, ...chunk] diff --git a/src/app/shared/PersonFollowers.svelte b/src/app/shared/PersonFollowers.svelte index 1b11a145..d4ba638e 100644 --- a/src/app/shared/PersonFollowers.svelte +++ b/src/app/shared/PersonFollowers.svelte @@ -20,7 +20,7 @@ onMount(() => { const scroller = createScroller(loadMore, {element: getModal()}) const sub = subscribe({ - relays: hints.FetchFromPubkey(pubkey).getUrls(), + relays: hints.FromPubkeys([pubkey]).getUrls(), filters: [{kinds: [3], "#p": [pubkey]}], onEvent: batch(500, (events: Event[]) => { const newPubkeys = pluck("pubkey", events) diff --git a/src/app/shared/RelaySearch.svelte b/src/app/shared/RelaySearch.svelte index 5774e878..7d3e359d 100644 --- a/src/app/shared/RelaySearch.svelte +++ b/src/app/shared/RelaySearch.svelte @@ -42,7 +42,7 @@ ) load({ - relays: hints.Aggregate().getUrls(), + relays: hints.Inbox().getUrls(), filters: [{limit: 1000, kinds: [1986], "#l": ["review/relay"]}], onEvent: event => { reviews = reviews.concat(event) diff --git a/src/app/state.ts b/src/app/state.ts index b0514336..86486f3b 100644 --- a/src/app/state.ts +++ b/src/app/state.ts @@ -1,6 +1,6 @@ import Bugsnag from "@bugsnag/js" import {hash, union} from "hurdak" -import {now} from "paravel" +import {ConnectionStatus} from "paravel" import {warn} from "src/util/logger" import {userKinds} from "src/util/nostr" import {toast} from "src/partials/state" @@ -88,11 +88,15 @@ setInterval(() => { // Prune connections we haven't used in a while, clear errors periodically, // and keep track of slow connections for (const [url, connection] of pool.data.entries()) { - if (connection.meta.last_activity < now() - 60) { - connection.socket.disconnect() - } else if (connection.lastError < Date.now() - 10_000) { - connection.clearError() - } else if (userRelays.has(url) && connection.meta.quality < 0.3) { + const {lastPublish, lastRequest, lastFault} = connection.meta + const lastActivity = Math.max(lastPublish, lastRequest) + const status = connection.meta.getStatus() + + if (lastActivity < Date.now() - 60_000) { + connection.disconnect() + } else if (lastFault < Date.now() - 10_000) { + connection.disconnect() + } else if (userRelays.has(url) && status === ConnectionStatus.Slow) { $slowConnections.push(url) } } diff --git a/src/app/views/GroupList.svelte b/src/app/views/GroupList.svelte index defd052b..8d0a7333 100644 --- a/src/app/views/GroupList.svelte +++ b/src/app/views/GroupList.svelte @@ -50,7 +50,7 @@ }) load({ - relays: hints.Aggregate().getUrls(), + relays: hints.User().getUrls(), filters: [ {kinds: [35834, 34550], authors: admins}, {kinds: [35834, 34550], limit: 500}, diff --git a/src/app/views/InviteCreate.svelte b/src/app/views/InviteCreate.svelte index cea5b71c..0d3b364f 100644 --- a/src/app/views/InviteCreate.svelte +++ b/src/app/views/InviteCreate.svelte @@ -79,7 +79,7 @@ const addGroup = e => { const newGroup = { address: groupSelection.address, - relay: hints.FetchFromContext(groupSelection.address).getUrl(), + relay: hints.WithinContext(groupSelection.address).getUrl(), claim: groupClaim, } diff --git a/src/app/views/Login.svelte b/src/app/views/Login.svelte index e0944bf2..1c132778 100644 --- a/src/app/views/Login.svelte +++ b/src/app/views/Login.svelte @@ -88,7 +88,7 @@ onMount(() => { load({ - relays: hints.Aggregate().getUrls(), + relays: hints.Inbox().getUrls(), filters: [ { kinds: [Handlerinformation], diff --git a/src/app/views/NoteCreate.svelte b/src/app/views/NoteCreate.svelte index 269714a8..24b25f62 100644 --- a/src/app/views/NoteCreate.svelte +++ b/src/app/views/NoteCreate.svelte @@ -61,7 +61,7 @@ summary: "", price: "", currency: currencyOptions.find(whereEq({code: "SAT"})), - relays: hints.PublishToContexts(defaultGroups).getUrls(), + relays: hints.WithinMultipleContexts(defaultGroups).getUrls(), groups: defaultGroups, anonymous: false, location: null, @@ -197,7 +197,10 @@ } if (quote) { - const nevent = nip19.neventEncode({id: quote.id, relays: hints.FetchEvent(quote).getUrls(3)}) + const nevent = nip19.neventEncode({ + id: quote.id, + relays: hints.Event(quote).limit(3).getUrls(), + }) compose.nevent("nostr:" + nevent) } diff --git a/src/app/views/UserData.svelte b/src/app/views/UserData.svelte index f34275b7..a83aed06 100644 --- a/src/app/views/UserData.svelte +++ b/src/app/views/UserData.svelte @@ -70,7 +70,7 @@ diff --git a/src/app/views/Zap.svelte b/src/app/views/Zap.svelte index 49660ae6..4ecdb155 100644 --- a/src/app/views/Zap.svelte +++ b/src/app/views/Zap.svelte @@ -62,7 +62,7 @@ if (percent > 0 && totalWeight > 0) { zaps.push({ pubkey: $env.PLATFORM_PUBKEY, - relay: hints.FetchFromPubkey($env.PLATFORM_PUBKEY).getUrl(), + relay: hints.FromPubkeys([$env.PLATFORM_PUBKEY]).getUrl(), amount: Math.round(zaps.reduce((a, z) => a + z.amount, 0) * percent), status: "pending", isTip: true, @@ -86,7 +86,9 @@ return } - const relays = hints.PublishMessage([zap.pubkey]).getUrls(null, [zap.relay]) + const relays = hints + .merge([hints.PublishMessage(zap.pubkey), hints.scenario([[zap.relay]])]) + .getUrls() zaps[i].invoice = await requestZap(msg, zap.amount, { eid, diff --git a/src/engine/channels/commands.ts b/src/engine/channels/commands.ts index 47033158..23ae003c 100644 --- a/src/engine/channels/commands.ts +++ b/src/engine/channels/commands.ts @@ -23,7 +23,7 @@ export const sendLegacyMessage = async (channelId: string, content: string) => { return Publisher.publish({ event: await signer.get().signAsUser(template), - relays: hints.PublishMessage(recipients).getUrls(), + relays: hints.PublishMessage(pubkey).getUrls(), }) } @@ -46,7 +46,7 @@ export const sendMessage = async (channelId: string, content: string) => { Publisher.publish({ event: rumor.wrap, - relays: hints.PublishMessage(recipients).getUrls(), + relays: hints.merge(recipients.map(hints.PublishMessage)).getUrls(), }) } } diff --git a/src/engine/channels/requests.ts b/src/engine/channels/requests.ts index 2214128a..77f71903 100644 --- a/src/engine/channels/requests.ts +++ b/src/engine/channels/requests.ts @@ -19,7 +19,7 @@ export const loadAllMessages = ({reload = false} = {}) => { }) const cursor = new MultiCursor({ - relays: hints.FetchAllMessages().getUrls(), + relays: hints.AllMessages().getUrls(), filters: [ {kinds: [4], authors: [pubkey], since}, {kinds: [4, 1059], "#p": [pubkey], since}, @@ -53,7 +53,7 @@ export const listenForMessages = (pubkeys: string[]) => { return subscribe({ skipCache: true, - relays: hints.FetchMessages(pubkeys).getUrls(), + relays: hints.Messages(pubkeys).getUrls(), filters: [ {kinds: [4], authors: allPubkeys, "#p": allPubkeys}, {kinds: [1059], "#p": [pubkey]}, diff --git a/src/engine/events/commands.ts b/src/engine/events/commands.ts index 9322bee8..6a279bf8 100644 --- a/src/engine/events/commands.ts +++ b/src/engine/events/commands.ts @@ -21,7 +21,7 @@ export const markAsSeenPublicly = batch(5000, async idChunks => { const event = await signer.get().signAsUser(createReadReceipt(ids)) if (event) { - Publisher.publish({event, relays: hints.NoteToSelf().getUrls()}) + Publisher.publish({event, relays: hints.Outbox().getUrls()}) } } }) @@ -41,7 +41,7 @@ export const markAsSeenPrivately = batch(5000, async idChunks => { Publisher.publish({ event: rumor.wrap, - relays: hints.NoteToSelf().getUrls(), + relays: hints.Outbox().getUrls(), }) } }) diff --git a/src/engine/events/requests.ts b/src/engine/events/requests.ts index 0164dc45..8f30b502 100644 --- a/src/engine/events/requests.ts +++ b/src/engine/events/requests.ts @@ -8,7 +8,7 @@ export const loadDeletes = () => { const since = Math.max(0, deletes_last_synced - seconds(6, "hour")) return load({ - relays: hints.Aggregate().getUrls(), + relays: hints.User().getUrls(), filters: [{kinds: [5], authors: [pubkey], since}], }) } @@ -18,7 +18,7 @@ export const loadSeen = () => { const since = Math.max(0, deletes_last_synced - seconds(6, "hour")) return load({ - relays: hints.NoteToSelf().getUrls(), + relays: hints.Outbox().getUrls(), filters: [{kinds: [15], authors: [pubkey], since}], }) } @@ -39,7 +39,7 @@ export const loadGiftWrap = () => { const since = Math.max(0, nip59_messages_last_synced - seconds(6, "hour")) return load({ - relays: hints.FetchAllMessages().getUrls(), + relays: hints.AllMessages().getUrls(), filters: [{kinds: [1059, 1060], authors: [pubkey], since}], }) } diff --git a/src/engine/groups/commands.ts b/src/engine/groups/commands.ts index 4a3b0584..9bb45084 100644 --- a/src/engine/groups/commands.ts +++ b/src/engine/groups/commands.ts @@ -11,7 +11,12 @@ import {displayPubkey} from "src/engine/people/utils" import {hints} from "src/engine/relays/utils" import {GroupAccess} from "./model" import {groups, groupAdminKeys, groupSharedKeys} from "./state" -import {deriveGroup, deriveAdminKeyForGroup, deriveSharedKeyForGroup, deriveIsGroupMember} from "./utils" +import { + deriveGroup, + deriveAdminKeyForGroup, + deriveSharedKeyForGroup, + deriveIsGroupMember, +} from "./utils" // Key state management @@ -80,7 +85,7 @@ export const wrapWithFallback = async (template, {author = null, wrap}) => { export const publishToGroupAdmin = async (address, template) => { const addr = Address.fromRaw(address) - const relays = hints.PublishToContext(address).getUrls() + const relays = hints.WithinContext(address).getUrls() const pubkeys = [addr.pubkey, session.get().pubkey] const pubs = [] @@ -104,7 +109,7 @@ export const publishToGroupAdmin = async (address, template) => { } export const publishAsGroupAdminPublicly = async (address, template) => { - const relays = hints.PublishToContext(address).getUrls() + const relays = hints.WithinContext(address).getUrls() const adminKey = deriveAdminKeyForGroup(address).get() const event = await signer.get().signWithKey(template, adminKey.privkey) @@ -112,7 +117,7 @@ export const publishAsGroupAdminPublicly = async (address, template) => { } export const publishAsGroupAdminPrivately = async (address, template) => { - const relays = hints.PublishToContext(address).getUrls() + const relays = hints.WithinContext(address).getUrls() const adminKey = deriveAdminKeyForGroup(address).get() const sharedKey = deriveSharedKeyForGroup(address).get() @@ -160,7 +165,7 @@ export const publishToGroupsPrivately = async (addresses, template, {anonymous = const pubs = [] const events = [] for (const address of addresses) { - const relays = hints.PublishToContext(address).getUrls() + const relays = hints.WithinContext(address).getUrls() const thisTemplate = updateIn("tags", (tags: string[][]) => [...tags, ["a", address]], template) const sharedKey = deriveSharedKeyForGroup(address).get() @@ -229,7 +234,7 @@ export const publishToZeroOrMoreGroups = async (addresses, template, {anonymous // Admin functions export const publishKeyShares = async (address, pubkeys, template) => { - const relays = hints.PublishToContext(address).getUrls() + const relays = hints.WithinContext(address).getUrls() const adminKey = deriveAdminKeyForGroup(address).get() const pubs = [] diff --git a/src/engine/groups/projections.ts b/src/engine/groups/projections.ts index 634d9851..64f25015 100644 --- a/src/engine/groups/projections.ts +++ b/src/engine/groups/projections.ts @@ -53,7 +53,7 @@ projections.addHandler(24, (e: Event) => { // Load the group's metadata and posts load({ - relays: hints.FetchFromHints(relays).getUrls(), + relays: hints.scenario([relays]).getUrls(), filters: [ ...getIdFilters([address]), {kinds: [1059, 1060], "#p": [pubkey]}, @@ -160,7 +160,7 @@ projections.addHandler(10004, (e: Event) => { const addresses = Tags.fromEvent(e).communities().values().valueOf() - for (const address of uniq(Object.keys($session.groups.values || {}).concat(addresses))) { + for (const address of uniq(Object.keys($session.groups?.values || {}).concat(addresses))) { $session = modifyGroupStatus($session, address, e.created_at, { joined: addresses.includes(address), }) diff --git a/src/engine/groups/requests.ts b/src/engine/groups/requests.ts index ab1f829d..86ae1776 100644 --- a/src/engine/groups/requests.ts +++ b/src/engine/groups/requests.ts @@ -44,7 +44,7 @@ export const loadGroups = async (rawAddrs: string[], relays: string[] = []) => { if (addrs.length > 0) { load({ - relays: hints.FetchFromHints(relays).getUrls(), + relays: hints.scenario([relays]).getUrls(), filters: [{kinds: [34550, 35834], authors, "#d": identifiers}], }) } diff --git a/src/engine/groups/utils.ts b/src/engine/groups/utils.ts index 2cca55a0..cd305b84 100644 --- a/src/engine/groups/utils.ts +++ b/src/engine/groups/utils.ts @@ -1,6 +1,6 @@ import {prop, uniqBy, defaultTo, sortBy, last, whereEq} from "ramda" import {ellipsize, first, seconds} from "hurdak" -import {Tags, Address, useMaximalFallbacks, RelayMode} from "paravel" +import {Tags, Address} from "paravel" import {fuzzy} from "src/util/misc" import type {GroupStatus, Session} from "src/engine/session/model" import {pubkey} from "src/engine/session/state" @@ -70,12 +70,7 @@ export const getGroupReqInfo = (address = null) => { recipients.push(key.pubkey) } - const relays = hints - .merge({ - fallbackPolicy: useMaximalFallbacks(RelayMode.Inbox), - scenarios: addresses.map(a => hints.FetchFromContext(a)), - }) - .getUrls() + const relays = hints.merge(addresses.map(hints.WithinContext)).getUrls() return {admins, recipients, relays, since} } @@ -86,7 +81,7 @@ export const getCommunityReqInfo = (address = null) => { return { since: since - seconds(6, "hour"), - relays: hints.FetchFromContext(address).getUrls(), + relays: hints.WithinContext(address).getUrls(), } } diff --git a/src/engine/handlers/commands.ts b/src/engine/handlers/commands.ts index 44d71405..f22ae65e 100644 --- a/src/engine/handlers/commands.ts +++ b/src/engine/handlers/commands.ts @@ -13,7 +13,7 @@ export const deriveHandlers = cached({ const $follows = follows.get() load({ - relays: hints.Aggregate().getUrls(), + relays: hints.Inbox().getUrls(), filters: [ {kinds: [31989], "#d": [String(kind)], authors: Array.from($follows)}, {kinds: [31990], "#k": [String(kind)]}, diff --git a/src/engine/network/utils/dvms.ts b/src/engine/network/utils/dvms.ts index e72f8077..b3809fb5 100644 --- a/src/engine/network/utils/dvms.ts +++ b/src/engine/network/utils/dvms.ts @@ -27,7 +27,7 @@ export const dvmRequest = async ({ onProgress = null, }: DVMRequestOpts): Promise => { if (!relays) { - relays = hints.Broadcast().getUrls(null, env.get().DVM_RELAYS) + relays = hints.merge([hints.Outbox(), hints.scenario([env.get().DVM_RELAYS])]).getUrls() } if (typeof input !== "string") { diff --git a/src/engine/network/utils/filters.ts b/src/engine/network/utils/filters.ts index 5dcbec30..637a77d3 100644 --- a/src/engine/network/utils/filters.ts +++ b/src/engine/network/utils/filters.ts @@ -1,4 +1,4 @@ -import {Address, getAddress, isContextAddress, useMaximalFallbacks, RelayMode} from "paravel" +import {Address, getAddress, isContextAddress} from "paravel" import {omit, without, find, prop, groupBy, uniq} from "ramda" import {shuffle, randomId, seconds, avg} from "hurdak" import {isAddressable} from "src/util/nostr" @@ -166,18 +166,17 @@ export const compileFilters = (filters: DynamicFilter[], opts: CompileFiltersOpt export const getRelaysFromFilters = filters => hints - .merge({ - fallbackPolicy: useMaximalFallbacks(RelayMode.Inbox), - scenarios: filters.flatMap(filter => { + .merge( + filters.map(filter => { if (filter["#a"]?.some(isContextAddress)) { - return filter["#a"].filter(isContextAddress).map(hints.FetchFromContext) + return hints.WithinMultipleContexts(filter["#a"].filter(isContextAddress)) } if (filter.authors) { - return filter.authors.map(hints.FetchFromPubkey) + return hints.FromPubkeys(filter.authors) } - return [hints.Aggregate()] + return hints.Inbox() }), - }) + ) .getUrls() diff --git a/src/engine/network/utils/load.ts b/src/engine/network/utils/load.ts index 318cd616..34f752f8 100644 --- a/src/engine/network/utils/load.ts +++ b/src/engine/network/utils/load.ts @@ -90,11 +90,7 @@ export const execute = batch(500, (items: LoadItem[]) => { // If we're using multiplexer, let it do its thing if (getSetting("multiplextr_url")) { - loadChunk( - items, - hints.FetchFromHints(items.map(getPath(["request", "relays"]))).getUrls(), - tracker, - ) + loadChunk(items, hints.scenario(items.map(getPath(["request", "relays"]))).getUrls(), tracker) } else { const itemsByRelay = {} for (const item of items) { diff --git a/src/engine/network/utils/pubkeys.ts b/src/engine/network/utils/pubkeys.ts index 9fc91d43..9a8db661 100644 --- a/src/engine/network/utils/pubkeys.ts +++ b/src/engine/network/utils/pubkeys.ts @@ -68,6 +68,6 @@ export const loadPubkeys = async ( return load({ filters, - relays: hints.FetchFromPubkeys(pubkeys).getUrls(null, relays), + relays: hints.merge([hints.scenario([relays]), hints.FromPubkeys(pubkeys)]).getUrls(), }) } diff --git a/src/engine/network/utils/publish.ts b/src/engine/network/utils/publish.ts index 3b558dff..7c33c11d 100644 --- a/src/engine/network/utils/publish.ts +++ b/src/engine/network/utils/publish.ts @@ -150,7 +150,7 @@ export type PublishOpts = EventOpts & { export const publish = async (template, {sk, relays}: PublishOpts = {}) => { return Publisher.publish({ timeout: 5000, - relays: relays || hints.Broadcast().getUrls(), + relays: relays || hints.Outbox().getUrls(), event: sk ? await signer.get().signWithKey(template, sk) : await signer.get().signAsUser(template), diff --git a/src/engine/network/utils/subscribe.ts b/src/engine/network/utils/subscribe.ts index 8f726ba9..9c325ffe 100644 --- a/src/engine/network/utils/subscribe.ts +++ b/src/engine/network/utils/subscribe.ts @@ -11,12 +11,12 @@ import {Tracker} from "./tracker" export type SubscribeOpts = Omit & { relays?: string[] tracker?: Tracker + executor?: Executor skipCache?: boolean shouldProject?: boolean onEvent?: (e: Event) => void onEose?: (url: string) => void onClose?: (events: Event[]) => void - executor?: Executor } const getExecutorFromOpts = (opts: SubscribeOpts) => { diff --git a/src/engine/network/utils/thread.ts b/src/engine/network/utils/thread.ts index fe846ec2..90352091 100644 --- a/src/engine/network/utils/thread.ts +++ b/src/engine/network/utils/thread.ts @@ -41,7 +41,7 @@ export class ThreadLoader { if (filteredIds.length > 0) { load({ - relays: hints.FetchFromHints(this.relays).getUrls(), + relays: hints.scenario([this.relays]).getUrls(), filters: getIdFilters(filteredIds), onEvent: batch(300, (events: Event[]) => { this.addToThread(events) diff --git a/src/engine/notes/commands.ts b/src/engine/notes/commands.ts index 2ff67407..8303fc4e 100644 --- a/src/engine/notes/commands.ts +++ b/src/engine/notes/commands.ts @@ -7,7 +7,7 @@ export const publishNote = (content, tags = [], relays = null) => export const publishDeletion = ids => createAndPublish(5, { - relays: hints.Broadcast().getUrls(), + relays: hints.Outbox().getUrls(), tags: ids.map(id => [id.includes(":") ? "a" : "e", id]), }) diff --git a/src/engine/notes/requests.ts b/src/engine/notes/requests.ts index ad54bd8e..4a1f313b 100644 --- a/src/engine/notes/requests.ts +++ b/src/engine/notes/requests.ts @@ -21,7 +21,7 @@ export const dereferenceNote = async ({ } return loadOne({ - relays: hints.FetchFromHints(relays).getUrls(), + relays: hints.scenario([relays]).getUrls(), filters: getIdFilters([eid]), }) } @@ -45,7 +45,7 @@ export const dereferenceNote = async ({ subscribe({ timeout: 3000, closeOnEose: true, - relays: hints.FetchFromHints(relays).getUrls(), + relays: hints.scenario([relays]).getUrls(), filters: [{kinds: [kind], authors: [pubkey], "#d": [identifier]}], onClose: () => resolve(note), onEvent: event => { @@ -67,7 +67,7 @@ type LoadReactionsRequest = { const executeLoadReactions = batch(500, async (requests: LoadReactionsRequest[]) => { const ids = pluck("id", requests) - const relays = hints.FetchFromHints(...pluck("relays", requests)).getUrls() + const relays = hints.scenario(pluck("relays", requests)).getUrls() let data = {} diff --git a/src/engine/notifications/requests.ts b/src/engine/notifications/requests.ts index 48c5a8f0..ca77974d 100644 --- a/src/engine/notifications/requests.ts +++ b/src/engine/notifications/requests.ts @@ -1,4 +1,4 @@ -import {now, Tags, RelayMode, useMaximalFallbacks} from "paravel" +import {now, Tags} from "paravel" import {seconds, updateIn, batch, doPipe} from "hurdak" import {pluck, max, slice, filter, without, sortBy} from "ramda" import {noteKinds, repostKinds, reactionKinds} from "src/util/nostr" @@ -40,12 +40,7 @@ const onNotificationEvent = batch(300, (chunk: Event[]) => { loadPubkeys(pubkeys) load({ - relays: hints - .merge({ - fallbackPolicy: useMaximalFallbacks(RelayMode.Inbox), - scenarios: eventsWithParent.map(hints.FetchEventParent), - }) - .getUrls(), + relays: hints.merge(eventsWithParent.map(hints.EventParent)).getUrls(), filters: getIdFilters( eventsWithParent.flatMap(e => Tags.fromEvent(e).replies().values().valueOf()), ), @@ -90,7 +85,7 @@ export const loadNotifications = () => { timeout: 15000, skipCache: true, closeOnEose: true, - relays: hints.Aggregate().getUrls(), + relays: hints.Inbox().getUrls(), onEvent: onNotificationEvent, }) } @@ -121,7 +116,7 @@ export const listenForNotifications = async () => { filters, timeout: 30_000, skipCache: true, - relays: hints.Aggregate().getUrls(), + relays: hints.Inbox().getUrls(), onEvent: onNotificationEvent, }) } diff --git a/src/engine/people/utils.ts b/src/engine/people/utils.ts index ef4ae5c0..2f80e1e2 100644 --- a/src/engine/people/utils.ts +++ b/src/engine/people/utils.ts @@ -166,7 +166,7 @@ export const getWotScore = (pk, tpk) => { } const annotatePerson = pubkey => { - const relays = hints.FetchFromPubkey(pubkey).getUrls() + const relays = hints.FromPubkeys([pubkey]).getUrls() return { pubkey, diff --git a/src/engine/relays/utils.ts b/src/engine/relays/utils.ts index ed1876a4..f7b834d4 100644 --- a/src/engine/relays/utils.ts +++ b/src/engine/relays/utils.ts @@ -1,8 +1,8 @@ import {nip19} from "nostr-tools" import {Router} from "paravel" -import {normalizeRelayUrl as normalize, fromNostrURI} from "paravel" +import {normalizeRelayUrl as normalize, ConnectionStatus, fromNostrURI} from "paravel" import {sortBy, whereEq, pluck, uniq, prop, last} from "ramda" -import {displayList} from "hurdak" +import {displayList, switcher} from "hurdak" import {fuzzy} from "src/util/misc" import {LOCAL_RELAY_URL} from "src/util/nostr" import {env} from "src/engine/session/state" @@ -37,9 +37,6 @@ export const decodeRelay = entity => { } } -export const relayIsLowQuality = (url: string) => - pool.get(url, {autoConnect: false})?.meta?.quality < 0.6 - export const displayRelay = ({url}: Relay) => last(url.split("://")).replace(/\/$/, "") export const displayRelays = (relays: Relay[], max = 3) => @@ -90,9 +87,20 @@ export const hints = new Router({ getUserPubkey: () => stateKey.get(), getGroupRelays: getGroupRelayUrls, getCommunityRelays: getGroupRelayUrls, - getPubkeyInboxRelays: pubkey => getPubkeyRelayUrls(pubkey, "read"), - getPubkeyOutboxRelays: pubkey => getPubkeyRelayUrls(pubkey, "write"), - getFallbackInboxRelays: () => env.get().DEFAULT_RELAYS, - getFallbackOutboxRelays: () => env.get().DEFAULT_RELAYS, - getDefaultLimit: () => getSetting("relay_limit"), + getPubkeyRelays: getPubkeyRelayUrls, + getDefaultRelays: () => env.get().DEFAULT_RELAYS, + getDefaultLimit: () => parseInt(getSetting("relay_limit")), + getRelayQuality: (url: string) => { + const connection = pool.get(url, {autoConnect: false}) + + return switcher(connection?.meta.getStatus(), { + [ConnectionStatus.Unauthorized]: 0.5, + [ConnectionStatus.Forbidden]: 0, + [ConnectionStatus.Error]: 0, + [ConnectionStatus.Closed]: 0.6, + [ConnectionStatus.Slow]: 0.5, + [ConnectionStatus.Ok]: 1, + default: 0.5, + }) + }, }) diff --git a/src/engine/reports/commands.ts b/src/engine/reports/commands.ts index fe75d3d3..2ea7c9b9 100644 --- a/src/engine/reports/commands.ts +++ b/src/engine/reports/commands.ts @@ -7,6 +7,6 @@ import {Publisher} from "src/engine/network/utils" // Use an ephemeral private key for user privacy export const publishReport = async (content = "", tags = []) => Publisher.publish({ - relays: hints.Broadcast().getUrls(), + relays: hints.Outbox().getUrls(), event: await signer.get().signWithKey(createEvent(1984, {content, tags}), generatePrivateKey()), })