The goal of this tool is to behave as a public relay; think of the chosen topic as a public relay, where you can send and receive notes from your peers!
npm install -g hyper-nostr
hyper-nostr [port [...starting topics]]
(default 3000)
hyper-nostr 3000 nostr
ws://localhost:[port]/[topic]
in your Nostr client (I am using nostr
as a topic to make some kind of generic swarm) (topic is now optional; if you left it blank, it goes to nostr
)The best way is to setup a reverse proxy. I use caddy, so then all I need to do is to run caddy reverse-proxy --to localhost:[port]
.
Then I can add wss://localhost
as a relay.
Browsers have the tendency to refuse self signed certificates. A workaround is to go to the reverse-proxy link https://localhost
and "accept the risk". There is no page in that path, so you will see a blank page, but after that your browser client probably will accept it.
Hyper-Nostr is a distributed nostr relay that syncs your relay storage and real time events through the Hyperswarm, linearizes the databases with Autobase, and uses a Hyperbeedee database (loosely based on MongoDB).
The hyperswarm and cores management was highly abstracted thanks to Hyper SDK.
import * as SDK from 'hyper-sdk'
/** (sdk: SDK.SDK, topic: string) => swarm object */
import createSwarm from 'hyper-nostr'
import goodbye from 'graceful-goodbye'
const yourStorageFolder = '.hyper-nostr-relay' // set to false to not persist
const theTopic = 'nostr'
const sdk = SDK.create({
storage: yourStorageFolder
})
goodbye(_ => sdk.close())
const {
subscriptions, // a Map<subscriptionId: string, { filters: Filter[], socket: WebSocket, receivedEvents: Set<id: Number> }> object
sendEvent, // (event: Event) => document: Object | Error | void; to send an Nostr Event to the peers and the local database.
queryEvents, // (filters: Filter[]) => Promise<Event[]>; to query the database for the events that match the list of filters
sendQueryToSubscription, // (sub: Subscription, key: subscriptionId, opts: { hasLimit: Boolean }) => Promise<void> // Write the events to the socket; internally includes each id on receivedEvents and dont send duplicated events
update // () => Promise<void>; manually sync the databases in the background
} = await createSwarm(sdk, theTopic)
The client can send the following events through the websocket:
["REQ", <subscription id>, <filters JSON>...]
subs
map["EOSE", <subscription id>]
event, signalling that all events from now on will be on real time["EVENT", <event JSON>]
sendEvent
to broadcast the event, and received events through this broadcast are internally validated and sent through the subs
Map["OK", <event id>, true, ""]
(NIP-20)["CLOSE", <subscription id>]
subs
map["COUNT", <subscription id>, <filters JSON>...]
The server sends the following events:
["EVENT", <subscription id>, <event JSON>]
["NOTICE", <message>]
"Unrecognized event"
, for when there is no match for the event kind sent.
MIT