JSPM

@nostr-dev-kit/messages

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 112
  • Score
    100M100P100Q75859F
  • License MIT

High-level messaging library for NDK supporting NIP-17 and NIP-EE

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 received
  • conversation-created - New conversation started
  • error - 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 conversation
  • state-change - Conversation state changed
  • error - 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 querying
  • conversations - Conversation metadata and participants
  • mlsGroups - (Future) MLS group state
  • dmRelays - 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

See Also