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; // 2Connection 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; // trueSign 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 formatEncrypt/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
- User
- Generate Keys - Generate a new key pair and obtain all formats (private key, public key, nsec, npub)
- Get Profile - Fetch and handle user profile information
- Mobile
- [Basics]
- Initialize NDK + SQLite cache - Set up NDK with SQLite caching for mobile apps
- User
- Loading User Profiles - Efficiently load and cache user profiles in mobile apps
- Events
- Rendering Event Content - Rich text rendering of Nostr event content with mentions, hashtags, and media
- Session
- Login - Handle user authentication with NDK Mobile using various methods (NIP-46, nsec)
- [Basics]
- Wallet
- Connect Nostr Wallet Connect - Connect to an NWC wallet and set it up for zapping
- Using Cashu Wallet - Create and use a Cashu wallet for managing e-cash tokens
- Nutzap Monitor - Track and process Cashu tokens sent via Nostr zaps
- Cashu Deposits - Fund your Cashu wallet using Lightning invoices
- Testing
- Mock Relays - Create and use mock relays for testing NDK applications
- Event Generation - Generate test events with different kinds and content
- Nutzap Testing - Test Cashu token and Nutzap functionality
- Relay Pool Testing - Test relay pool behavior and event handling