@candypoets/nipworker 0.92.0 → 0.93.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 +68 -293
- package/dist/cache/index.js +52 -52
- package/dist/cache/pkg/cache.d.ts +2 -2
- package/dist/cache/pkg/cache_bg.wasm.d.ts +2 -2
- package/dist/connections/index.js +21 -21
- package/dist/connections/pkg/connections.d.ts +5 -5
- package/dist/connections/pkg/connections_bg.wasm.d.ts +5 -5
- package/dist/connections/proxy.js +1 -1
- package/dist/connections/proxy.js.map +3 -3
- package/dist/crypto/index.js +34 -34
- package/dist/generated/nostr/fb/video-data.d.ts +6 -2
- package/dist/generated/nostr/fb/video-data.d.ts.map +1 -1
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +55 -55
- package/dist/parser/index.js +305 -305
- package/dist/worker-message.js +83 -74
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,342 +1,117 @@
|
|
|
1
1
|
# @candypoets/nipworker
|
|
2
2
|
|
|
3
|
-
A high-performance Nostr client library
|
|
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
|
[](https://badge.fury.io/js/@candypoets%2Fnipworker)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## What is NIPWorker?
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Big, opinionated, and built for speed. FlatBuffers and Web Workers at its core, compiled from Rust to WASM.
|
|
11
11
|
|
|
12
|
-
|
|
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
|
-
##
|
|
16
|
+
## 4 Dedicated Workers
|
|
21
17
|
|
|
22
|
-
|
|
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
|
-
|
|
20
|
+
• **Cache** — Stores FlatBuffers in ring buffers in real time and IndexedDB in timeout chunks. No refetching what you already have.
|
|
41
21
|
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
34
|
+
## Apollo-Inspired State Management
|
|
68
35
|
|
|
69
|
-
|
|
36
|
+
Like Apollo Client, NIPWorker IS your store. You do not need Redux, Zustand, or custom state libraries.
|
|
70
37
|
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
import { useSubscription } from '@candypoets/nipworker/hooks';
|
|
42
|
+
## Pipeline Architecture
|
|
79
43
|
|
|
80
|
-
|
|
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
|
-
|
|
89
|
-
import { isKind1, isKind0, SignerTypes } from '@candypoets/nipworker/utils';
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Basic Usage
|
|
46
|
+
## Opinionated by Design
|
|
93
47
|
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
127
|
-
console.log('Publish status:', status);
|
|
128
|
-
});
|
|
58
|
+
Install the skill for AI assistance:
|
|
129
59
|
|
|
130
|
-
|
|
131
|
-
|
|
60
|
+
```bash
|
|
61
|
+
npx skills add candypoets/skills@nipworker
|
|
132
62
|
```
|
|
133
63
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```javascript
|
|
137
|
-
import { createNostrManager } from '@candypoets/nipworker';
|
|
138
|
-
import { useSubscription } from '@candypoets/nipworker/hooks';
|
|
64
|
+
## Quick Start
|
|
139
65
|
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
//
|
|
144
|
-
|
|
71
|
+
// Create and set the global manager
|
|
72
|
+
const manager = createNostrManager();
|
|
73
|
+
setManager(manager);
|
|
145
74
|
|
|
146
|
-
// Subscribe to
|
|
75
|
+
// Subscribe to events
|
|
147
76
|
const unsubscribe = useSubscription(
|
|
148
|
-
'
|
|
149
|
-
[
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
-
|
|
330
|
-
-
|
|
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
|
-
##
|
|
112
|
+
## License
|
|
335
113
|
|
|
336
|
-
|
|
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
|
|