Package Exports
- @nostr-dev-kit/messages
- @nostr-dev-kit/messages/storage
Readme
@nostr-dev-kit/messages
High-level messaging library for NDK that provides a unified API for private messaging protocols on Nostr.
Features
- 🎯 Simple API - One-line message sending with automatic protocol handling
- 🔐 NIP-17 Support - Gift-wrapped private messages with proper relay management
- 💬 Conversation Management - Automatic grouping, threading, and read status
- 📡 Event-Driven - Real-time updates via EventEmitter pattern
- 💾 Storage Abstraction - Pluggable storage adapters for persistence
- 🔄 Future-Proof - Ready for NIP-EE (MLS) when implemented
Installation
npm install @nostr-dev-kit/messages
# or
bun add @nostr-dev-kit/messages
Quick Start
import NDK from '@nostr-dev-kit/ndk';
import { NDKMessenger } from '@nostr-dev-kit/messages';
// Initialize NDK
const ndk = new NDK({
explicitRelayUrls: ['wss://relay.damus.io'],
signer: new NDKPrivateKeySigner(privateKey)
});
await ndk.connect();
// Create messenger
const messenger = new NDKMessenger(ndk);
await messenger.start();
// Send a message
const recipient = ndk.getUser({ npub: "npub1..." });
await messenger.sendMessage(recipient, "Hello!");
// Listen for messages
messenger.on('message', (message) => {
console.log(`New message from ${message.sender.npub}: ${message.content}`);
});
API Reference
NDKMessenger
Main orchestrator class for messaging functionality.
class NDKMessenger extends EventEmitter {
constructor(ndk: NDK, options?: MessengerOptions)
// Start/stop the messenger
async start(): Promise<void>
stop(): void
// Send messages
async sendMessage(recipient: NDKUser, content: string): Promise<NDKMessage>
// Manage conversations
async getConversation(user: NDKUser): Promise<NDKConversation>
async getConversations(): Promise<NDKConversation[]>
// Publish relay preferences
async publishDMRelays(relays: string[]): Promise<NDKEvent>
}
Events
message
- New message receivedconversation-created
- New conversation startederror
- Error occurred
NDKConversation
Represents a conversation between users with real-time updates.
class NDKConversation extends EventEmitter {
readonly id: string
readonly participants: NDKUser[]
readonly protocol: 'nip17' | 'mls'
// Send messages
async sendMessage(content: string): Promise<NDKMessage>
// Get messages
async getMessages(limit?: number): Promise<NDKMessage[]>
// Mark as read
async markAsRead(): Promise<void>
// Helpers
getUnreadCount(): number
getOtherParticipant(): NDKUser | undefined
getLastMessage(): NDKMessage | undefined
}
Events
message
- New message in conversationstate-change
- Conversation state changederror
- Error in conversation
Storage Adapters
The library uses a storage adapter pattern for flexibility:
interface StorageAdapter {
saveMessage(message: NDKMessage): Promise<void>
getMessages(conversationId: string, limit?: number): Promise<NDKMessage[]>
markAsRead(messageIds: string[]): Promise<void>
getConversations(userId: string): Promise<ConversationMeta[]>
saveConversation(conversation: ConversationMeta): Promise<void>
}
Built-in Adapters
MemoryAdapter
- In-memory storage (default)- More adapters coming soon (Dexie, SQLite)
Examples
Basic Messaging
// Initialize
const messenger = new NDKMessenger(ndk);
await messenger.start();
// Send message
const bob = ndk.getUser({ npub: "npub1bob..." });
await messenger.sendMessage(bob, "Hey Bob!");
// Get conversation
const conversation = await messenger.getConversation(bob);
const messages = await conversation.getMessages();
// Mark as read
await conversation.markAsRead();
Real-time Updates
// Listen to all messages
messenger.on('message', (message) => {
if (message.sender.pubkey !== messenger.myPubkey) {
showNotification(`New message from ${message.sender.displayName}`);
}
});
// Listen to specific conversation
conversation.on('message', (message) => {
updateChatUI(message);
});
conversation.on('error', (error) => {
console.error('Conversation error:', error);
});
Custom Storage
import { MemoryAdapter } from '@nostr-dev-kit/messages';
// Use custom storage
const messenger = new NDKMessenger(ndk, {
storage: new MemoryAdapter(),
autoStart: true
});
// Or implement your own
class MyStorageAdapter implements StorageAdapter {
// ... implement interface methods
}
Cache Module Integration
This package supports NDK's cache module system for persistent storage:
import NDKCacheAdapterDexie from '@nostr-dev-kit/cache-dexie';
import { CacheModuleStorage, messagesCacheModule } from '@nostr-dev-kit/messages';
// Use with cache adapter that supports modules
const cacheAdapter = new NDKCacheAdapterDexie({ dbName: 'my-app' });
const ndk = new NDK({
cacheAdapter,
// ... other options
});
// Messages will automatically use cache if available
const messenger = new NDKMessenger(ndk, {
storage: new CacheModuleStorage(cacheAdapter, userPubkey)
});
The messages cache module creates these collections:
messages
- Individual messages with indexes for efficient queryingconversations
- Conversation metadata and participantsmlsGroups
- (Future) MLS group statedmRelays
- Relay preferences for DMs
Benefits:
- Persistent Storage: Messages survive app restarts (IndexedDB in browser)
- Automatic Migrations: Schema upgrades handled automatically
- Type Safety: Fully typed collections and queries
- Performance: Indexed fields for fast lookups
Relay Management
// Publish your DM relay preferences (kind 10050)
await messenger.publishDMRelays([
'wss://relay.damus.io',
'wss://nos.lol'
]);
NIP-17 Implementation
This library implements NIP-17 (Private Direct Messages) with:
- Automatic rumor creation with proper pubkey setting
- Gift wrapping with ephemeral keys
- Relay discovery via kind 10050
- Automatic subscription to kind 1059 events
- Message deduplication
Future: NIP-EE Support
The library is designed to support NIP-EE (MLS-based messaging) when ready:
// Future API (same interface, different protocol)
const conversation = await messenger.createConversation([alice, bob, charlie]);
console.log(conversation.protocol); // 'mls' if all support it, 'nip17' otherwise
Development
# Install dependencies
bun install
# Build
bun run build
# Run tests
bun test
# Run example
cd examples/nip-17-chat
bunx tsx generate-keys.ts
bunx tsx src/index.ts
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
License
MIT