@candypoets/nipworker 0.92.0 → 0.94.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,342 +1,117 @@
1
1
  # @candypoets/nipworker
2
2
 
3
- A high-performance Nostr client library with worker-based architecture using Rust WebAssembly for optimal performance and non-blocking operations.
3
+ A high-performance Nostr client library that moves everything off the main thread and becomes your entire application state layer.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/@candypoets%2Fnipworker.svg)](https://badge.fury.io/js/@candypoets%2Fnipworker)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- ![NipWorker](static/nipworker.jpg)
8
+ ## What is NIPWorker?
9
9
 
10
- ## 🚀 Features
10
+ Big, opinionated, and built for speed. FlatBuffers and Web Workers at its core, compiled from Rust to WASM.
11
11
 
12
- - **High Performance**: Rust WASM core for cryptographic operations and message processing
13
- - **Worker-Based Architecture**: Non-blocking operations using Web Workers
14
- - **TypeScript Support**: Full TypeScript definitions included
15
- - **Dual Module Support**: Both ES modules and UMD builds
16
- - **Efficient Serialization**: Uses MessagePack for optimal data transfer
17
- - **Comprehensive NIP Support**: Implements 12+ standard Nostr Implementation Possibilities (NIPs)
12
+ ## Framework Agnostic
18
13
 
14
+ Works with any frontend. No React dependency, no Svelte stores to learn, no Vue composables. Just hook-like methods with callbacks that you wire to your framework's reactivity however you want.
19
15
 
20
- ## 📋 Supported NIPs
16
+ ## 4 Dedicated Workers
21
17
 
22
- | NIP | Name | Description | Event Kinds | Status |
23
- |-----|------|-------------|-------------|---------|
24
- | [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) | Basic Protocol | Core protocol flow description | 0, 1 | ✅ Full |
25
- | [NIP-02](https://github.com/nostr-protocol/nips/blob/master/02.md) | Contact List | Contact lists and petnames | 3 | ✅ Full |
26
- | [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) | Encrypted DMs | Encrypted direct messages | 4 | ✅ Full |
27
- | [NIP-05](https://github.com/nostr-protocol/nips/blob/master/05.md) | DNS Identifiers | Mapping keys to DNS identifiers | - | 🔄 Partial |
28
- | [NIP-10](https://github.com/nostr-protocol/nips/blob/master/10.md) | Text Note References | Threading and replies | - | ✅ Full |
29
- | [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md) | Reposts | Event reposts | 6 | ✅ Full |
30
- | [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) | bech32 Entities | npub, note, nevent, nprofile encoding | - | ✅ Full |
31
- | [NIP-25](https://github.com/nostr-protocol/nips/blob/master/25.md) | Reactions | Event reactions and emoji | 7 | ✅ Full |
32
- | [NIP-27](https://github.com/nostr-protocol/nips/blob/master/27.md) | Text References | Mentions and references in content | - | ✅ Full |
33
- | [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md) | Versioned Encryption | Advanced encryption for private events | - | ✅ Full |
34
- | [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md) | Lists | Categorized lists (people, bookmarks) | 39089 | ✅ Full |
35
- | [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) | Lightning Zaps | Bitcoin Lightning Network integration | 9735 | ✅ Full |
36
- | [NIP-60](https://github.com/nostr-protocol/nips/blob/master/60.md) | Cashu Wallet | Cashu ecash wallet functionality | 7374, 7375, 7376, 10019, 17375 | ✅ Full |
37
- | [NIP-61](https://github.com/nostr-protocol/nips/blob/master/61.md) | Nutzaps | Cashu token zaps | 9321 | ✅ Full |
38
- | [NIP-65](https://github.com/nostr-protocol/nips/blob/master/65.md) | Relay Lists | User relay preferences | 10002 | ✅ Full |
18
+ **Connections** Relay connections, WebSocket lifecycle, reconnection backoff. Owns all network I/O.
39
19
 
40
- ### NIP-60 Cashu Wallet Events
20
+ **Cache** Stores FlatBuffers in ring buffers in real time and IndexedDB in timeout chunks. No refetching what you already have.
41
21
 
42
- The library provides complete support for **NIP-60 Cashu wallet functionality**:
22
+ **Parser** Event validation, signature verification, content parsing. Receives raw JSON from relays, outputs FlatBuffers to your frontend. No JSON.parse on the main thread. Ever.
43
23
 
44
- | Event Kind | Description | Encryption | Purpose |
45
- |------------|-------------|------------|---------|
46
- | 7374 | Quote events | NIP-44 | Token redemption quotes |
47
- | 7375 | Token events | NIP-44 | Cashu proofs and tokens |
48
- | 7376 | Spending history | NIP-44 | Transaction history |
49
- | 9321 | Nutzaps | - | Cashu token zaps |
50
- | 10019 | Wallet settings | - | User wallet preferences |
51
- | 17375 | Encrypted wallets | NIP-44 | Private wallet data |
24
+ **Crypto** Signing, NIP:04/44 encryption, NIP:46 remote signer sessions, Cashu proof verification.
52
25
 
26
+ Each worker runs in its own Web Worker. The main thread just orchestrates. Heavy work happens in parallel.
53
27
 
54
- ### Legend
55
- - ✅ **Full**: Complete implementation with all features
56
- - 🔄 **Partial**: Basic support, some features may be limited
57
- - ❌ **Not Supported**: NIP is not implemented
28
+ ## FlatBuffers Instead of JSON
58
29
 
59
- ## 📦 Installation
30
+ NIPWorker speaks FlatBuffers end to end. Raw relay messages get parsed once in Rust, then flow through the system as zero-copy binary views. No JSON.parse. No object allocation. No GC pauses on infinite scroll.
60
31
 
61
- ```bash
62
- npm install @candypoets/nipworker
63
- ```
64
-
65
- That's it! No additional dependencies needed.
32
+ Your components read directly from FlatBuffers tables. A Kind1 note's content blocks (images, videos, hashtags) arrive pre-parsed. You iterate them with `fbArray()` and render straight from the binary buffer to the DOM. The schema lives from wire to HTML.
66
33
 
67
- ## 🔧 Usage
34
+ ## Apollo-Inspired State Management
68
35
 
69
- ### Import Structure
36
+ Like Apollo Client, NIPWorker IS your store. You do not need Redux, Zustand, or custom state libraries.
70
37
 
71
- The library is organized into logical modules for better tree-shaking:
38
+ `useSubscribe` pulls FlatBuffers from the worker pool and feeds your UI directly. Subscriptions accept fetch policies: `cacheFirst` serves from memory immediately if available, `noCache` always bypass the cache and hits the network. You control the speed versus freshness tradeoff per query.
72
39
 
73
- ```javascript
74
- // Core API - main functionality
75
- import { nostrManager, createNostrManager } from '@candypoets/nipworker';
40
+ `usePublish` sends events and tracks relay acknowledgments. Your entire app state flows through these two hooks. Subscriptions are deduped across components automatically. The library manages the cache, merge logic, and reactive updates.
76
41
 
77
- // Hooks - React-style subscription hooks
78
- import { useSubscription } from '@candypoets/nipworker/hooks';
42
+ ## Pipeline Architecture
79
43
 
80
- // Types - TypeScript type definitions
81
- import type {
82
- ParsedEvent,
83
- Kind1Parsed,
84
- NostrManagerConfig,
85
- Request
86
- } from '@candypoets/nipworker/types';
44
+ Events flow through a processing pipeline: verify → dedupe → filter → transform → store. Each subscription configures its own pipeline. The pipeline runs in the Parser worker before FlatBuffers reach your callback.
87
45
 
88
- // Utils - type guards and helper functions
89
- import { isKind1, isKind0, SignerTypes } from '@candypoets/nipworker/utils';
90
- ```
91
-
92
- ### Basic Usage
46
+ ## Opinionated by Design
93
47
 
94
- ```javascript
95
- import { nostrManager } from '@candypoets/nipworker';
96
- import { useSubscription } from '@candypoets/nipworker/hooks';
48
+ NIPWorker enforces outbox model by default. It reads every author's NIP:65 relay list to discover where they publish. The library manages relay discovery and publication strategy for you.
97
49
 
98
- // Login by setting up a signer (private key)
99
- nostrManager.setSigner('privkey', 'your-private-key-hex');
50
+ Built for clients that need to render thousands of events without dropping frames.
100
51
 
101
- // Subscribe to events using the hook
102
- const unsubscribe = useSubscription(
103
- 'my-subscription',
104
- [{
105
- kinds: [1], // Text notes
106
- limit: 10
107
- }],
108
- (events, eventType) => {
109
- if (eventType === 'EVENTS') {
110
- console.log('Received events:', events);
111
- } else if (eventType === 'EOSE') {
112
- console.log('End of stored events');
113
- }
114
- },
115
- { closeOnEose: false }
116
- );
52
+ ## Installation
117
53
 
118
- // Publish an event
119
- const event = {
120
- kind: 1,
121
- content: 'Hello Nostr!',
122
- tags: [],
123
- created_at: Math.floor(Date.now() / 1000)
124
- };
54
+ ```bash
55
+ npm install @candypoets/nipworker
56
+ ```
125
57
 
126
- nostrManager.publish('publish-id-123', event, (status, type) => {
127
- console.log('Publish status:', status);
128
- });
58
+ Install the skill for AI assistance:
129
59
 
130
- // Clean up subscription when done
131
- // unsubscribe();
60
+ ```bash
61
+ npx skills add candypoets/skills@nipworker
132
62
  ```
133
63
 
134
- ### Advanced Usage
135
-
136
- ```javascript
137
- import { createNostrManager } from '@candypoets/nipworker';
138
- import { useSubscription } from '@candypoets/nipworker/hooks';
64
+ ## Quick Start
139
65
 
140
- // Create a custom manager instance with configuration
141
- const customManager = createNostrManager();
66
+ ```typescript
67
+ import { createNostrManager, setManager } from '@candypoets/nipworker';
68
+ import { useSubscription, usePublish } from '@candypoets/nipworker/hooks';
69
+ import { isKind1, asKind1, fbArray } from '@candypoets/nipworker/utils';
142
70
 
143
- // Set up multiple signers
144
- customManager.setSigner('privkey', 'main-private-key-hex');
71
+ // Create and set the global manager
72
+ const manager = createNostrManager();
73
+ setManager(manager);
145
74
 
146
- // Subscribe to specific authors with multiple filters
75
+ // Subscribe to events
147
76
  const unsubscribe = useSubscription(
148
- 'author-feed',
149
- [
150
- {
151
- kinds: [1, 6, 7],
152
- authors: ['pubkey1', 'pubkey2'],
153
- since: Math.floor(Date.now() / 1000) - 3600, // Last hour
154
- limit: 50
155
- },
156
- {
157
- kinds: [30023], // Long-form content
158
- authors: ['pubkey1'],
159
- limit: 10
160
- }
161
- ],
162
- (events, eventType) => {
163
- if (eventType === 'EVENTS') {
164
- events.forEach(event => {
165
- switch (event.kind) {
166
- case 1:
167
- console.log('Text note:', event.content);
168
- break;
169
- case 6:
170
- console.log('Repost:', event);
171
- break;
172
- case 7:
173
- console.log('Reaction:', event);
174
- break;
175
- case 30023:
176
- console.log('Long-form content:', event);
177
- break;
178
- }
179
- });
180
- } else if (eventType === 'EOSE') {
181
- console.log('End of stored events for author feed');
77
+ 'feed_home',
78
+ [{ kinds: [1], limit: 50, relays: ['wss://relay.example.com'] }],
79
+ (msg) => {
80
+ const kind1 = isKind1(msg);
81
+ if (kind1) {
82
+ // Access content blocks directly from FlatBuffers view
83
+ const blocks = fbArray(kind1, 'contentBlocks');
84
+ renderNote(blocks);
182
85
  }
183
- },
184
- { closeOnEose: false }
86
+ }
185
87
  );
186
-
187
- // Global publish status monitoring
188
- customManager.addPublishCallbackAll((status, eventId) => {
189
- console.log(`Event ${eventId} status:`, status);
190
- });
191
-
192
- // Clean up when done
193
- setTimeout(() => {
194
- unsubscribe();
195
- customManager.cleanup();
196
- }, 60000);
197
- ```
198
-
199
- ## 🏗️ Architecture
200
-
201
- NipWorker uses a multi-layered architecture:
202
-
203
- 1. **Main Thread**: Your application code
204
- 2. **Web Worker**: Handles network operations and message routing
205
- 3. **Rust WASM Core**: Performs cryptographic operations and message validation
206
-
207
- This architecture ensures that heavy operations don't block your main thread, providing a smooth user experience.
208
-
209
- ## 📚 API Reference
210
-
211
- ### NostrManager
212
-
213
- #### Factory Function
214
-
215
- ```typescript
216
- createNostrManager(config?: NostrManagerConfig): NostrManager
217
88
  ```
218
89
 
219
- #### Methods
220
-
221
- - `setSigner(name: string, secretKeyHex: string): void` - Set up a signer for publishing
222
- - `subscribe(subscriptionId: string, requests: Request[], options?: SubscriptionOptions): SharedArrayBuffer` - Subscribe to events
223
- - `publish(publishId: string, event: NostrEvent, callback?: PublishCallback): void` - Publish an event
224
- - `signEvent(event: NostrEvent): void` - Sign an event without publishing
225
- - `getPublicKey(): void` - Get the public key of the current signer
226
- - `unsubscribe(subscriptionId: string): void` - Unsubscribe from events
227
- - `cleanup(): void` - Clean up unused subscriptions
228
- - `addPublishCallbackAll(callback: Function): void` - Monitor all publish statuses
229
-
230
- ### useSubscription Hook
231
-
232
- ```typescript
233
- useSubscription(
234
- subId: string,
235
- requests: Request[],
236
- callback: SubscriptionCallback,
237
- options?: SubscriptionOptions
238
- ): () => void
239
- ```
240
-
241
- #### Parameters
242
-
243
- - `subId` - Unique subscription identifier
244
- - `requests` - Array of Nostr filter objects
245
- - `callback` - Function called when events are received
246
- - `options` - Subscription options (closeOnEose, skipCache, force)
247
-
248
- #### Returns
249
-
250
- - Function to unsubscribe and clean up resources
251
-
252
- ### Event Types
253
-
254
- - `EVENTS` - New events received
255
- - `EOSE` - End of stored events
256
- - `EOCE` - End of cached events
257
- - `PUBLISH_STATUS` - Status update for published events
258
-
259
- ## 🛠️ Development
260
-
261
- ### Prerequisites
262
-
263
- - Node.js 18+
264
- - Rust 1.70+
265
- - wasm-pack
266
-
267
- ### Building from Source
268
-
269
- ```bash
270
- # Clone the repository
271
- git clone https://github.com/candypoets/nipworker.git
272
- cd nipworker
273
-
274
- # Install dependencies
275
- npm install
276
-
277
- # Build WASM modules
278
- npm run build:wasm
279
-
280
- # Build the library
281
- npm run build
282
- ```
283
-
284
- ### Scripts
285
-
286
- - `npm run dev` - Start development server
287
- - `npm run build` - Build for production
288
- - `npm run build:wasm` - Build WASM modules only
289
- - `npm run build:types` - Generate TypeScript declarations
290
- - `npm run clean` - Clean build artifacts
291
-
292
- ## 🤝 Contributing
293
-
294
- We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.
295
-
296
- ### Development Workflow
297
-
298
- 1. Fork the repository
299
- 2. Create a feature branch: `git checkout -b feature/amazing-feature`
300
- 3. Make your changes
301
- 4. Add tests if applicable
302
- 5. Commit your changes: `git commit -m 'Add amazing feature'`
303
- 6. Push to the branch: `git push origin feature/amazing-feature`
304
- 7. Open a Pull Request
305
-
306
- ## 📄 License
307
-
308
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
309
-
310
- ## 🔗 Links
311
-
312
- - [GitHub Repository](https://github.com/candypoets/nipworker)
313
- - [Issue Tracker](https://github.com/candypoets/nipworker/issues)
314
- - [Nostr Protocol](https://github.com/nostr-protocol/nostr)
315
- - [NIPs Repository](https://github.com/nostr-protocol/nips)
316
-
317
- ## 🙏 Acknowledgments
318
-
319
- - [Nostr Protocol](https://nostr.com/) - The decentralized social protocol
320
- - [nostr-tools](https://github.com/nbd-wtf/nostr-tools) - Essential Nostr utilities
321
- - [wasm-pack](https://rustwasm.github.io/wasm-pack/) - Rust to WebAssembly workflow
322
-
323
- ## 📊 Performance
324
-
325
- NipWorker is designed for high performance:
90
+ ## Supported NIPs
326
91
 
327
- - **Fast Event Processing**: Rust WASM core processes events up to 10x faster than pure JavaScript
328
- - **Non-blocking Operations**: Web Worker architecture prevents UI freezing
329
- - **Efficient Serialization**: MessagePack reduces bandwidth usage by ~30%
330
- - **Connection Pooling**: Intelligent relay connection management
92
+ | NIP | Description | Status |
93
+ |-----|-------------|--------|
94
+ | NIP-01 | Basic Protocol | Full |
95
+ | NIP-02 | Contact List | Full |
96
+ | NIP-04 | Encrypted DMs | ✅ Full |
97
+ | NIP-18 | Reposts | ✅ Full |
98
+ | NIP-19 | bech32 Entities | ✅ Full |
99
+ | NIP-25 | Reactions | ✅ Full |
100
+ | NIP-44 | Versioned Encryption | ✅ Full |
101
+ | NIP-46 | Nostr Connect | ✅ Full |
102
+ | NIP-51 | Lists | ✅ Full |
103
+ | NIP-57 | Lightning Zaps | ✅ Full |
104
+ | NIP-60 | Cashu Wallet | ✅ Full |
105
+ | NIP-61 | Nutzaps | ✅ Full |
106
+ | NIP-65 | Relay Lists | ✅ Full |
331
107
 
108
+ ## Documentation
332
109
 
110
+ See [AGENTS.md](AGENTS.md) for detailed architecture documentation.
333
111
 
334
- ## 🔒 Security
112
+ ## License
335
113
 
336
- - All cryptographic operations are handled by the Rust WASM core
337
- - Private keys never leave the worker thread
338
- - Event validation is performed at the WASM level
339
- - Secure random number generation for key operations
114
+ MIT License - see [LICENSE](LICENSE) for details.
340
115
 
341
116
  ---
342
117