Connecting
This section will briefly explain the different mechanmisms through which NDK can connect to relays.
Connecting
Connecting to relays in itself is super easy.
// Import the package
import NDK from "@nostr-dev-kit/ndk";
// ... set up signer, specify relays, ...
await ndk.connect(); On connection changes NDK will emit a number of connection events.
Connection types
TIP
Because NOSTR is decentralized and comprised of thousands of relays, it's important to read up on the advised ways of connecting to relays. We advise you to use the "Outbox Model" in addition or as a replacement for specifying explicit relays.
Specific Relays
The simplest way to get NDK to connect to relays is to specify them:
// Import the package
import NDK from "@nostr-dev-kit/ndk";
// Create a new NDK instance with explicit relays
const ndk = new NDK({
explicitRelayUrls: ["wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band"],
});
// Now connect to specified relays
await ndk.connect();Make sure to wait for the connect() promise to resolve before using NDK after which you can start interacting with relays.
Explicit relays can also be added using the addExplicitRelay() method.
// Import the package
import NDK from "@nostr-dev-kit/ndk";
// Create a new NDK instance with explicit relays
const ndk = new NDK();
ndk.addExplicitRelay("wss://a.relay");
ndk.addExplicitRelay("wss://another.relay");
// Now connect to specified relays
await ndk.connect();User preferred relays
A signer is used to sign events and tells NDK about your pubkey and related settings. Once you link up a signer and you have autoConnectUserRelays enabled (on by default) NDK will fetch your kind:10002 event (NIP-65) and add discovered relays specified to a 2nd pool of connected relays.
// Import NDK + NIP07 signer
import NDK, { NDKNip07Signer } from "@nostr-dev-kit/ndk";
// Create a new NDK instance with signer
// (provided the signer implements the getRelays() method)
const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });Outbox Model
Outbox (previously known as the Gossip Model) is a more elaborate way of dynamically connecting to relays based on who you are interacting with. More about the outbox model.
The outbox model works similarly to the web/RSS model:
- Outbox Relays: You post your content to your own designated relays
- Inbox Relays: You designate relays where you want to receive messages
- Dynamic Discovery: Clients discover and connect to relays based on where users actually post
The protocol is formalized in (NIP-65), which defines:
kind:10002events: Relay list metadata containing read/write relay preferences- Relay tags: "r" tags with optional "read"/"write" markers
- Fallback to Kind 3: Contact list events can contain relay information in their content
By enabling enableOutboxModel (off by default) NDK will add an extra outboxPool to the ndk pool AND (@TODO Explain)
https://primal.net/e/nevent1qqs2txvkjpa6fdlhxdtqmyk2tzzchpaa4vrfgx7h20539u5k9lzgqwgfjnlen
Dev Write Relays
During local development you might want to specify a list of relays to write to. THis can be done by using devWriteRelayUrls which will
import NDK from "@nostr-dev-kit/ndk";
const ndk = new NDK({
devWriteRelayUrls: ["wss://staging.relay", "wss://another.test.relay"],
});
await ndk.connect();This will write new events to those relays only. Note that if you have provided relays in explicitRelayUrls these will also be used to write events to.
Relay Sets
Under the hood NDK uses different sets of relays to send and receive messages. You can tap into that pool logic by using the NDKPool class.
import NDK, { NDKPool, NDKRelay } from "@nostr-dev-kit/ndk";
const ndk = new NDK();
const largeRelays = new NDKPool([`wss://relay.damus.io`, "wss://premium.primal.net"], ndk);
largeRelays.addRelay(new NDKRelay("wss://nos.lol", undefined, ndk));
const nicheRelays = new NDKPool([`wss://asad`, "wss://premisadasdum.primal.net"], ndk);
nicheRelays.connect();
ndk.pools.length; // 2Note that if you have outbox enabled you will have an extra pool in the ndk.pools array reserved for user provided relays.
Authentication
(NIP-42) defines that relays can request authentication from clients. NDK uses an NDKAuthPolicy callback to provide a way to handle authentication requests.
- Relays can have specific
NDKAuthPolicyfunctions. - NDK can be configured with a default
relayAuthDefaultPolicyfunction. - NDK provides some generic policies:
NDKAuthPolicies.signIn: Authenticate to the relay (using thendk.signersigner).NDKAuthPolicies.disconnect: Immediately disconnect from the relay if asked to authenticate.
import NDK, { NDKRelayAuthPolicies } from "@nostr-dev-kit/ndk";
const ndk = new NDK();
ndk.addExplicitRelay("wss://relay.f7z.io", NDKRelayAuthPolicies.signIn({ ndk }));Clients should typically allow their users to choose where to authenticate. This can be accomplished by returning the decision the user made from the NDKAuthPolicy function.
import NDK, {NDKRelayAuthPolicies} from "@nostr-dev-kit/ndk";
const ndk = new NDK();
ndk.relayAuthDefaultPolicy = (relay: NDKRelay) => {
return confirm(`Authenticate to ${relay.url}?`);
};Connection Events
There are a number of events you can hook into to get information about relay connection status
import NDK, { type NDKRelay } from "@nostr-dev-kit/ndk";
// Create a new NDK instance with explicit relays
const ndk = new NDK({
explicitRelayUrls: ["wss://a.relay", "wss://another.relay"],
});
// Main pool events
ndk.pool.on("relay:connecting", (relay: NDKRelay) => {
console.log(`⟳ [Main Pool] Connecting to relay: ${relay.url}`);
});
ndk.pool.on("relay:connect", (relay: NDKRelay) => {
console.log(`✓ [Main Pool] Connected to relay: ${relay.url}`);
});
ndk.pool.on("relay:disconnect", (relay: NDKRelay) => {
console.log(`✗ [Main Pool] Disconnected from relay: ${relay.url}`);
});Code Snippets
More snippets and examples can be found in the snippets directory