Skip to content

Code Snippets ​

This section contains a growing collection of code snippets demonstrating how to perform specific tasks with NDK. Each snippet is focused on a single, targeted use case to help you find solutions for common implementation needs.

Snippets are grouped by category. Some of them are listed in more than one category.

Events ​

Creating an event ​

ts
import NDK, { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";

const ndk = new NDK(/* initialization options for the ndk singleton */);

const event = new NDKEvent(ndk, {
    kind: NDKKind.Text,
    content: "Hello world",
});

Tagging users ​

ts
import NDK, { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";

const ndk = new NDK();
const event = new NDKEvent(ndk, {
    kind: NDKKind.Text,
    content:
        "Hello, nostr:npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft this is a test from an NDK snippet.",
});
await event.sign();

Signing events ​

ts
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";

const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.sign();

Interest (kind 10015) Event ​

Interest events are used to tell the network about your interest in a particular topic. Those events and are making use of the NIP-51 specification kind:10015 events.

ts
import NDK, { NDKInterestList, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://relay.primal.net"],
});

// Create a signer (in production, use proper key management)
const signer = NDKPrivateKeySigner.generate();
ndk.signer = signer;

await ndk.connect();

// Create a new interest list
const interestList = new NDKInterestList(ndk);

// Add individual interests
interestList.addInterest("nostr");
interestList.addInterest("bitcoin");
interestList.addInterest("technology");
interestList.addInterest("privacy");

// Set a title for the list (optional)
interestList.title = "My Interests";
interestList.description = "Topics I'm passionate about";

console.log("Has 'nostr'?", interestList.hasInterest("nostr"));
console.log("Has 'ethereum'?", interestList.hasInterest("ethereum"));

// Publish the list (which also signs)
await interestList.publish();

Connecting ​

Specific Relays ​

ts
// 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();

Adding Relays ​

ts
// 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();

NIP-07 Relays ​

ts
// 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 });

Dev Relays ​

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    devWriteRelayUrls: ["wss://staging.relay", "wss://another.test.relay"],
});

await ndk.connect();

Relay Pools ​

ts
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; // 2

Connection Events ​

ts
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}`);
});

Subscribing ​

Simple Subscribe ​

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();

ndk.subscribe(
    { kinds: [1] }, // Filters
    { closeOnEose: true }, // Options (no explicit relays specified)
);

Subscribe on relays ​

ts
import NDK, {NDKRelaySet} from "@nostr-dev-kit/ndk";

const ndk = new NDK();
const explicitRelaySet = NDKRelaySet.fromRelayUrls(["wss://explicit.relay"], ndk);
ndk.subscribe(
    {kinds: [7]}, // Filters
    {
        // Options object now includes relaySet
        closeOnEose: true,
        relaySet: explicitRelaySet,
    },
);

Event Handler ​

ts
import NDK, { type NDKEvent, type NDKRelay, type NDKSubscription } from "@nostr-dev-kit/ndk";

const ndk = new NDK();

ndk.subscribe(
    { kinds: [1] }, // Filters
    { closeOnEose: true }, // Options (no explicit relays specified)
    {
        // Direct handlers via autoStart parameter (now the 3rd argument)
        onEvent: (event: NDKEvent, relay?: NDKRelay) => {
            // Called for events received from relays after the initial cache load (if onEvents is used)
            console.log("Received event from relay (id):", event.id);
        },
        onEvents: (events: NDKEvent[]) => {
            // Parameter renamed to 'events'
            console.log(`Received ${events.length} events from cache initially.`);
        },
        onEose: (subscription: NDKSubscription) => {
            console.log("Subscription reached EOSE:", subscription.internalId);
        },
    },
);

Attaching Handlers ​

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();

const subscription = ndk.subscribe(
    { kinds: [1] }, // Filters
    { closeOnEose: true }, // Options (no explicit relays specified)
);

// Attach handlers later
subscription.on("event", (event) => {
    console.log("Received event:", event.id);
});
subscription.on("eose", () => {
    console.log("Initial events loaded");
});

// Remember to stop the subscription when it's no longer needed
// setTimeout(() => subscription.stop(), 5000);

Exclusive Relays ​

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();

// Subscription that ONLY accepts events from relay-a.com
const exclusiveSub = ndk.subscribe(
    {kinds: [7]},
    {
        relayUrls: ["wss://relay-a.com"],
        exclusiveRelay: true, // 🔑 Key option
    },
);

exclusiveSub.on("event", (event) => {
    console.log("Event from relay-a.com:", event.content);
    // This will ONLY fire for events from relay-a.com
    // Events from relay-b.com or relay-c.com are rejected
});

Signers ​

Signing events ​

ts
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";

const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.sign();

Sign with NSec ​

ts
import NDK, { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const privateKeySigner = NDKPrivateKeySigner.generate();
const ndk = new NDK({ signer: privateKeySigner });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.sign();

Different signers ​

ts
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const signer1 = NDKPrivateKeySigner.generate();
const pubkey1 = signer1.pubkey;

const event1 = new NDKEvent();
event1.kind = 1;
event1.content = "Hello world";
await event1.sign(signer1);

event1.pubkey === pubkey1; // true

const signer2 = NDKPrivateKeySigner.generate();
const pubkey2 = signer2.pubkey;

const event2 = new NDKEvent();
event2.kind = 1;
event2.content = "Hello world";
await event2.sign(signer2);

event2.pubkey === pubkey2; // true

Sign using bunker ​

ts
// provided by the user
import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const signerConnectionString = "bunker://....";
const ndk = new NDK();

// local keypair generated when signer if first initialised
const clientKeypair = NDKPrivateKeySigner.generate(); //
const clientNsec = clientKeypair.nsec;

// initiate NIP-46 signer
const signer = NDKNip46Signer.bunker(ndk, signerConnectionString, clientNsec);

// promise will resolve once the `kind:24133` event is received
const user = await signer.blockUntilReady();

console.log("Welcome", user.npub);

Generate Keypair ​

ts
import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

// Generate a new private key
const signer = NDKPrivateKeySigner.generate();
const privateKey = signer.privateKey; // Get the hex private key
const publicKey = signer.pubkey; // Get the hex public key
const nsec = signer.nsec; // Get the private key in nsec format
const npub = signer.userSync.npub; // Get the public key in npub format

Encrypt/Decrypt Keypair ​

ts
import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const signer = NDKPrivateKeySigner.generate();

// Encrypt with a password
const password = "user-chosen-password";
const ncryptsec = signer.encryptToNcryptsec(password);

// Store securely (e.g., localStorage)
localStorage.setItem("encrypted_key", ncryptsec);

const restoredButEncrypted = localStorage.getItem("encrypted_key");

if (restoredButEncrypted) {
    // Later, restore the signer
    const restoredSigner = NDKPrivateKeySigner.fromNcryptsec(restoredButEncrypted, password);

    console.log("Original pubkey:", signer.pubkey);
    console.log("Restored pubkey:", restoredSigner.pubkey);
}

NIP-49 encryption ​

ts
import {bytesToHex, hexToBytes} from "@noble/hashes/utils";
import {nip49} from "@nostr-dev-kit/ndk";

// Encrypt raw private key bytes
const privateKeyHex = "14c226dbdd865d5e1645e72c7470fd0a17feb42cc87b750bab6538171b3a3f8a";
const privateKeyBytes = hexToBytes(privateKeyHex);
const password = "my-password";

const ncryptsec = nip49.encrypt(privateKeyBytes, password, 16, 0x02);
console.log("Encrypted:", ncryptsec);

// Decrypt to raw bytes
const decryptedBytes = nip49.decrypt(ncryptsec, password);
const decryptedHex = bytesToHex(decryptedBytes);
console.log("Decrypted:", decryptedHex);

Publishing ​

Publish Event ​

ts
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";

const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.publish(); 

Replaceable Event ​

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();
const existingEvent = await ndk.fetchEvent("574033c986bea1d7493738b46fec1bb98dd6a826391d6aa893137e89790027ec"); // fetch the event to replace

if (existingEvent) {
    existingEvent.tags.push(
        ["p", "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52"], // follow a new user
    );
    existingEvent.publish(); // this will NOT work
    existingEvent.publishReplaceable(); // this WILL work
}

Specify Relays ​

ts
import NDK, { NDKEvent, NDKRelaySet } from "@nostr-dev-kit/ndk";

const ndk = new NDK();

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";

const customRelaySet = NDKRelaySet.fromRelayUrls(["wss://relay.snort.social", "wss://relay.primal.net"], ndk);
await event.publish(customRelaySet);

Track Publication Status ​

ts
import NDK, { NDKEvent, type NDKRelay, type NDKRelaySet } from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"],
});

await ndk.connect();

const event = new NDKEvent(ndk, {
    kind: 1,
    content: "Hello Nostr!",
});

event.on("published", (data: { relaySet: NDKRelaySet; publishedToRelays: Set<NDKRelay> }) => {
    // Get all relays where the event was successfully published
    console.log("Published to:", data.publishedToRelays);
});

Handling Failures ​

ts
import NDK, { NDKEvent, type NDKPublishError } from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"],
});

await ndk.connect();

const event = new NDKEvent(ndk, {
    kind: 1,
    content: "Hello Nostr!",
});

ndk.on(`event:publish-failed`, (event: NDKEvent, error: NDKPublishError, relays: WebSocket["url"][]) => {
    console.log("Event failed to publish on", relays, error);
});

Not migrated yet ​