npm package: @scom/nostr
Description: A comprehensive TypeScript library for working with the Nostr protocol, providing cryptographic utilities, event management, client APIs, and interfaces for building Nostr-based applications.
Latest version: 0.1.1

# @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**: `NostrClient` for 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

```bash
npm install @scom/nostr
```

## Quick Start

### Using NostrClient (Recommended)

The `NostrClient` provides a unified interface for interacting with Nostr relays via HTTP or WebSocket protocols:

```typescript
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:

```typescript
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:

```typescript
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

```typescript
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

```typescript
// Connect to relay
await client.connect();

// Check connection status
const connected = client.isConnected();

// Disconnect
await client.disconnect();
```

#### Fetching Events

```typescript
// 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

```typescript
// 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: 'alice@getalby.com',
  nip05: 'alice@example.com'
});

// 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)

```typescript
// Encrypt a message
const encrypted = await client.encryptMessage(
  'Secret message',
  recipientPubkey
);

// Decrypt a message
const decrypted = await client.decryptMessage(
  encryptedContent,
  senderPubkey
);
```

#### Private Key Management

```typescript
// 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

```typescript
// 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:

```typescript
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 hex
```

### Connection Plugins

Extend NostrClient with custom connection plugins:

```typescript
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 Note
- `2` - Recommend Relay
- `3` - Contacts
- `4` - Encrypted Direct Message (NIP-04)
- `5` - Event Deletion
- `6` - Repost
- `7` - Reaction
- `40` - Channel Creation
- `41` - Channel Metadata
- `42` - Channel Message
- `43` - Channel Hide Message
- `44` - Channel Mute User
- `1984` - Report
- `9734` - Zap Request
- `9735` - Zap Receipt
- `10000` - Mute List
- `10002` - Relay List Metadata
- `30000` - Categorized People List
- `30008` - Profile Badges
- `30009` - Badge Definition
- `30023` - Long-form Content (Article)
- `30078` - Application-specific Data
- And more...

### Manager Classes

Advanced manager classes for specialized operations:

```typescript
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:

```typescript
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:

```typescript
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](./tests/README.md) for details.

```bash
# Run all tests
npm test

# Run specific test file
npx @scom/test tests/client-api.test.ts
```

## Building

To build the package from source:

```bash
# Build library and bundle
npm run build

# Build library only
npm run build:lib

# Build browser bundle only
npm run build:bundle
```

This will compile the TypeScript source files and generate:
- CommonJS/ES modules in the `lib` directory
- Browser bundle in the `dist` directory

## 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 relay
- `disconnect()`: Disconnect from relay
- `isConnected()`: Check connection status
- `fetchEvents(...requests)`: Fetch events with filters
- `fetchCachedEvents(eventType, msg)`: Fetch cached events (HTTP only)
- `submitEvent(event, authHeader?)`: Submit a signed event
- `subscribe(requests, onEvent, onEose)`: Subscribe to events (WebSocket)
- `unsubscribe(subscriptionId)`: Unsubscribe from events
- `sendNote(content, tags?, privateKey?)`: Send a text note
- `sendReply(content, originalEventId, originalAuthorPubkey, privateKey?)`: Send a reply
- `updateProfile(metadata, privateKey?, mergeWithExisting?)`: Update user profile
- `sendReaction(content, eventId, eventAuthorPubkey, privateKey?)`: Send a reaction
- `repostEvent(event, privateKey?)`: Repost an event
- `fetchUserProfileDetail(pubkey)`: Fetch user profile
- `fetchEventsByIds(ids)`: Fetch events by IDs
- `encryptMessage(content, recipientPubkey)`: Encrypt message (NIP-04)
- `decryptMessage(encryptedContent, senderPubkey)`: Decrypt message (NIP-04)
- `getPublicKey()`: Get public key from stored private key
- `setPrivateKey(privateKey)`: Set/update private key

### Keys Module

Cryptographic key operations:

- `Keys.generatePrivateKey()`: Generate a new random private key
- `Keys.getPublicKey(privateKey)`: Derive public key from private key
- `Keys.getPublicKeyY(privateKey)`: Get the Y coordinate of the public key
- `Keys.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 template
- `Event.finishEvent(template, privateKey)`: Sign and finalize an event
- `Event.serializeEvent(event)`: Serialize event for hashing
- `Event.getEventHash(event)`: Calculate event ID
- `Event.validateEvent(event)`: Validate event structure
- `Event.verifySignature(event)`: Verify event signature

### Nip19 Module

Bech32 encoding/decoding (NIP-19):

- `Nip19.npubEncode(publicKey)`: Encode public key to npub
- `Nip19.nsecEncode(privateKey)`: Encode private key to nsec
- `Nip19.noteEncode(eventId)`: Encode event ID to note
- `Nip19.nprofileEncode(profile)`: Encode profile with relays
- `Nip19.neventEncode(event)`: Encode event with metadata
- `Nip19.naddrEncode(addr)`: Encode parameterized replaceable event
- `Nip19.decode(encoded)`: Decode any NIP-19 entity

### Bech32 Module

Low-level bech32 encoding/decoding utilities as defined in NIP-19.

## Documentation

- [NostrClient API Reference](./docs/NostrClient-API.md) - Complete API documentation with examples
- [Test Suite](./tests/README.md) - Comprehensive test examples

## Resources

- [Nostr Protocol Documentation](https://github.com/nostr-protocol/nostr)
- [NIPs (Nostr Implementation Possibilities)](https://github.com/nostr-protocol/nips)