@scom/nostr
v0.1.1
Published
A comprehensive TypeScript library for working with the Nostr protocol, providing cryptographic utilities, event management, client APIs, and interfaces for building Nostr-based applications.
Readme
@scom/nostr
A comprehensive TypeScript library for working with the Nostr protocol, providing cryptographic utilities, event management, client APIs, and interfaces for building Nostr-based applications.
Overview
This package provides a complete toolkit for interacting with the Nostr protocol, including:
- Unified Client API:
NostrClientfor seamless HTTP and WebSocket relay interactions - Cryptographic Functions: Key generation, signing, encryption, and verification
- Event Management: Create, serialize, validate, and submit Nostr events
- NIP-19 Support: Encode and decode bech32-formatted Nostr entities (npub, nsec, note, etc.)
- Connection Plugins: Extensible architecture supporting HTTP and WebSocket protocols
- High-level APIs: Social features, communities, channels, marketplace, and more
- Type Definitions: Comprehensive TypeScript interfaces for Nostr data structures
Installation
npm install @scom/nostrQuick Start
Using NostrClient (Recommended)
The NostrClient provides a unified interface for interacting with Nostr relays via HTTP or WebSocket protocols:
import { NostrClient } from '@scom/nostr';
// Create an HTTP client
const client = NostrClient.create('https://relay.decom.app/api/v1', privateKey);
// Or create a WebSocket client
const wsClient = NostrClient.create('wss://relay.damus.io', privateKey);
// Connect to the relay
await client.connect();
// Fetch events
const response = await client.fetchEvents({
kinds: [1],
limit: 10
});
// Send a note
await client.sendNote('Hello Nostr!');
// Update your profile
await client.updateProfile({
name: 'Alice',
about: 'Nostr enthusiast',
picture: 'https://example.com/avatar.jpg'
});
// Disconnect when done
await client.disconnect();Core Cryptography
Low-level cryptographic utilities:
import { Keys } from '@scom/nostr';
// Generate a new private key
const privateKey = Keys.generatePrivateKey();
// Get the public key from a private key
const publicKey = Keys.getPublicKey(privateKey);
// Get shared secret for encryption (NIP-04)
const sharedSecret = Keys.getSharedSecret(privateKey, recipientPubkey);Event Creation and Validation
Create and manage Nostr events:
import { Event } from '@scom/nostr';
// Create a blank event template
const eventTemplate = Event.getBlankEvent(Event.Kind.Text);
// Finish and sign an event
const signedEvent = Event.finishEvent(
{
kind: 1,
content: 'Hello Nostr!',
tags: [],
created_at: Math.floor(Date.now() / 1000)
},
privateKey
);
// Validate an event
const isValid = Event.validateEvent(signedEvent);
// Verify event signature
const isVerified = Event.verifySignature(signedEvent);Features
NostrClient API
The NostrClient class provides a high-level API for common Nostr operations:
Client Creation
import { NostrClient } from '@scom/nostr';
// Create with protocol auto-detection
const client = NostrClient.create('https://relay.example.com', privateKey);
// Create with specific plugin
import { NostrHttpConnectionPlugin } from '@scom/nostr';
const httpPlugin = new NostrHttpConnectionPlugin('https://relay.example.com');
const client = new NostrClient(httpPlugin, privateKey);Connection Management
// Connect to relay
await client.connect();
// Check connection status
const connected = client.isConnected();
// Disconnect
await client.disconnect();Fetching Events
// Fetch events with filters
const response = await client.fetchEvents({
kinds: [1],
authors: [pubkey],
limit: 20
});
// Fetch cached events (HTTP only)
const cachedResponse = await client.fetchCachedEvents('user_profile', {
pubKeys: [pubkey]
});
// Fetch user profile
const profile = await client.fetchUserProfileDetail(pubkey);
// Fetch events by IDs
const events = await client.fetchEventsByIds([eventId1, eventId2]);Publishing Events
// Send a text note
await client.sendNote('Hello Nostr!');
// Send a note with hashtags
await client.sendNote('Building on #nostr', [['t', 'nostr']]);
// Send a reply
await client.sendReply('Great post!', originalEventId, originalAuthorPubkey);
// Update profile
await client.updateProfile({
name: 'Alice',
display_name: 'Alice in Nostrland',
about: 'Building on Nostr',
picture: 'https://example.com/avatar.jpg',
banner: 'https://example.com/banner.jpg',
website: 'https://example.com',
lud16: '[email protected]',
nip05: '[email protected]'
});
// Merge with existing profile
await client.updateProfile(
{ name: 'Alice' },
undefined,
true // mergeWithExisting
);
// Send a reaction
await client.sendReaction('+', eventId, eventAuthorPubkey);
// Repost an event
await client.repostEvent(originalEvent);Encryption (NIP-04)
// Encrypt a message
const encrypted = await client.encryptMessage(
'Secret message',
recipientPubkey
);
// Decrypt a message
const decrypted = await client.decryptMessage(
encryptedContent,
senderPubkey
);Private Key Management
// Get public key from stored private key
const pubkey = client.getPublicKey();
// Set/update private key (supports nsec and hex formats)
client.setPrivateKey('nsec1...');
client.setPrivateKey('hexadecimal...');WebSocket Subscriptions
// Subscribe to events (WebSocket only)
const subscriptionId = await client.subscribe(
[{ kinds: [1], authors: [pubkey] }],
(event) => {
console.log('New event:', event);
},
() => {
console.log('End of stored events (EOSE)');
}
);
// Unsubscribe
await client.unsubscribe(subscriptionId);NIP-19 Encoding/Decoding
Work with bech32-formatted Nostr identifiers:
import { Nip19 } from '@scom/nostr';
// Encode entities
const npub = Nip19.npubEncode(publicKey);
const nsec = Nip19.nsecEncode(privateKey);
const note = Nip19.noteEncode(eventId);
// Encode with relay hints
const nprofile = Nip19.nprofileEncode({
pubkey: publicKey,
relays: ['wss://relay.damus.io', 'wss://nos.lol']
});
const nevent = Nip19.neventEncode({
id: eventId,
relays: ['wss://relay.damus.io'],
author: authorPubkey
});
// Decode entities
const decoded = Nip19.decode(npub);
console.log(decoded.type); // 'npub'
console.log(decoded.data); // public key hexConnection Plugins
Extend NostrClient with custom connection plugins:
import {
NostrClient,
NostrHttpConnectionPlugin,
NostrWebSocketConnectionPlugin
} from '@scom/nostr';
// HTTP Plugin
const httpPlugin = new NostrHttpConnectionPlugin('https://relay.example.com');
const httpClient = new NostrClient(httpPlugin, privateKey);
// WebSocket Plugin
const wsPlugin = new NostrWebSocketConnectionPlugin('wss://relay.example.com');
const wsClient = new NostrClient(wsPlugin, privateKey);
// Or use the factory method with auto-detection
const client = NostrClient.create('https://relay.example.com', privateKey);Event Kinds
The library supports standard Nostr event kinds (NIP-01 and extensions):
0- Metadata (user profile)1- Text Note2- Recommend Relay3- Contacts4- Encrypted Direct Message (NIP-04)5- Event Deletion6- Repost7- Reaction40- Channel Creation41- Channel Metadata42- Channel Message43- Channel Hide Message44- Channel Mute User1984- Report9734- Zap Request9735- Zap Receipt10000- Mute List10002- Relay List Metadata30000- Categorized People List30008- Profile Badges30009- Badge Definition30023- Long-form Content (Article)30078- Application-specific Data- And more...
Manager Classes
Advanced manager classes for specialized operations:
import {
NostrEventManagerRead,
NostrEventManagerWrite,
SocialUtilsManager,
SocialDataManager,
NostrRestAPIManager,
NostrWebSocketManager
} from '@scom/nostr';
// REST API Manager for HTTP relay communication
const restManager = new NostrRestAPIManager('https://relay.example.com');
// WebSocket Manager for real-time communication
const wsManager = new NostrWebSocketManager(['wss://relay.example.com']);
// Event read operations
const eventReader = new NostrEventManagerRead(relayUrls);
// Event write operations
const eventWriter = new NostrEventManagerWrite(relayUrls, privateKey);
// Social utilities
const socialUtils = new SocialUtilsManager();
// Social data management
const socialData = new SocialDataManager();TypeScript Interfaces
The package provides comprehensive TypeScript interfaces for type-safe Nostr development:
import {
INostrEvent,
INostrMetadataContent,
INostrFetchEventsResponse,
INostrSubmitResponse
} from '@scom/nostr';
// Nostr event structure
interface INostrEvent {
id: string;
pubkey: string;
created_at: number;
kind: number;
tags: string[][];
content: string;
sig: string;
}
// User profile metadata
interface INostrMetadataContent {
name?: string;
display_name?: string;
username?: string;
website?: string;
picture?: string;
about?: string;
banner?: string;
lud16?: string; // Lightning address
nip05?: string; // Nostr verification
}
// Fetch response
interface INostrFetchEventsResponse {
error?: string;
events?: INostrEvent[];
data?: any;
}
// Submit response
interface INostrSubmitResponse {
success: boolean;
message?: string;
relay?: string;
eventId?: string;
}Advanced Features
Custom Connection Plugins
Implement your own connection plugin by implementing the INostrConnectionPlugin interface:
import { INostrConnectionPlugin, NostrConnectionProtocol } from '@scom/nostr';
class MyCustomPlugin implements INostrConnectionPlugin {
protocol = NostrConnectionProtocol.CUSTOM;
async connect(): Promise<void> { /* ... */ }
async disconnect(): Promise<void> { /* ... */ }
isConnected(): boolean { /* ... */ }
async subscribe(/* ... */): Promise<string> { /* ... */ }
async unsubscribe(id: string): Promise<void> { /* ... */ }
}Communities and Channels
The library includes interfaces and utilities for:
- Communities: Community creation, management, and moderation
- Channels: Public and private channel operations
- Marketplace: Product listings and transactions
- Social Features: Following, contacts, reactions, reposts
- Data Management: Event fetching, caching, and aggregation
Testing
The package includes a comprehensive test suite. See tests/README.md for details.
# Run all tests
npm test
# Run specific test file
npx @scom/test tests/client-api.test.tsBuilding
To build the package from source:
# Build library and bundle
npm run build
# Build library only
npm run build:lib
# Build browser bundle only
npm run build:bundleThis will compile the TypeScript source files and generate:
- CommonJS/ES modules in the
libdirectory - Browser bundle in the
distdirectory
API Reference
NostrClient
Main client class for Nostr relay interactions:
Static Methods:
NostrClient.create(url, privateKey?, options?): Create client with auto-detected protocol
Instance Methods:
connect(): Connect to relaydisconnect(): Disconnect from relayisConnected(): Check connection statusfetchEvents(...requests): Fetch events with filtersfetchCachedEvents(eventType, msg): Fetch cached events (HTTP only)submitEvent(event, authHeader?): Submit a signed eventsubscribe(requests, onEvent, onEose): Subscribe to events (WebSocket)unsubscribe(subscriptionId): Unsubscribe from eventssendNote(content, tags?, privateKey?): Send a text notesendReply(content, originalEventId, originalAuthorPubkey, privateKey?): Send a replyupdateProfile(metadata, privateKey?, mergeWithExisting?): Update user profilesendReaction(content, eventId, eventAuthorPubkey, privateKey?): Send a reactionrepostEvent(event, privateKey?): Repost an eventfetchUserProfileDetail(pubkey): Fetch user profilefetchEventsByIds(ids): Fetch events by IDsencryptMessage(content, recipientPubkey): Encrypt message (NIP-04)decryptMessage(encryptedContent, senderPubkey): Decrypt message (NIP-04)getPublicKey(): Get public key from stored private keysetPrivateKey(privateKey): Set/update private key
Keys Module
Cryptographic key operations:
Keys.generatePrivateKey(): Generate a new random private keyKeys.getPublicKey(privateKey): Derive public key from private keyKeys.getPublicKeyY(privateKey): Get the Y coordinate of the public keyKeys.getSharedSecret(privateKey, publicKey): Calculate shared secret (ECDH)Keys.decompressPublicKey(publicKey): Decompress a compressed public key
Event Module
Event creation and validation:
Event.getBlankEvent(kind?): Create a blank event templateEvent.finishEvent(template, privateKey): Sign and finalize an eventEvent.serializeEvent(event): Serialize event for hashingEvent.getEventHash(event): Calculate event IDEvent.validateEvent(event): Validate event structureEvent.verifySignature(event): Verify event signature
Nip19 Module
Bech32 encoding/decoding (NIP-19):
Nip19.npubEncode(publicKey): Encode public key to npubNip19.nsecEncode(privateKey): Encode private key to nsecNip19.noteEncode(eventId): Encode event ID to noteNip19.nprofileEncode(profile): Encode profile with relaysNip19.neventEncode(event): Encode event with metadataNip19.naddrEncode(addr): Encode parameterized replaceable eventNip19.decode(encoded): Decode any NIP-19 entity
Bech32 Module
Low-level bech32 encoding/decoding utilities as defined in NIP-19.
Documentation
- NostrClient API Reference - Complete API documentation with examples
- Test Suite - Comprehensive test examples
