@candypoets/nipworker 1.0.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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/dist/hooks.d.ts +6 -0
  4. package/dist/hooks.d.ts.map +1 -0
  5. package/dist/hooks.js +33 -0
  6. package/dist/hooks.js.map +1 -0
  7. package/dist/index.d.ts +81 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +13 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index2.js +8 -0
  12. package/dist/index2.js.map +1 -0
  13. package/dist/index3.js +270 -0
  14. package/dist/index3.js.map +1 -0
  15. package/dist/lib/sharedBuffer.d.ts +50 -0
  16. package/dist/lib/sharedBuffer.d.ts.map +1 -0
  17. package/dist/nostr_worker.js +1001 -0
  18. package/dist/nostr_worker.js.map +1 -0
  19. package/dist/types/index.d.ts +53 -0
  20. package/dist/types/index.d.ts.map +1 -0
  21. package/dist/types/kind0.d.ts +24 -0
  22. package/dist/types/kind0.d.ts.map +1 -0
  23. package/dist/types/kind1.d.ts +17 -0
  24. package/dist/types/kind1.d.ts.map +1 -0
  25. package/dist/types/kind10002.d.ts +7 -0
  26. package/dist/types/kind10002.d.ts.map +1 -0
  27. package/dist/types/kind10019.d.ts +9 -0
  28. package/dist/types/kind10019.d.ts.map +1 -0
  29. package/dist/types/kind17.d.ts +4 -0
  30. package/dist/types/kind17.d.ts.map +1 -0
  31. package/dist/types/kind17375.d.ts +7 -0
  32. package/dist/types/kind17375.d.ts.map +1 -0
  33. package/dist/types/kind3.d.ts +7 -0
  34. package/dist/types/kind3.d.ts.map +1 -0
  35. package/dist/types/kind39089.d.ts +11 -0
  36. package/dist/types/kind39089.d.ts.map +1 -0
  37. package/dist/types/kind4.d.ts +9 -0
  38. package/dist/types/kind4.d.ts.map +1 -0
  39. package/dist/types/kind6.d.ts +6 -0
  40. package/dist/types/kind6.d.ts.map +1 -0
  41. package/dist/types/kind7.d.ts +18 -0
  42. package/dist/types/kind7.d.ts.map +1 -0
  43. package/dist/types/kind7374.d.ts +6 -0
  44. package/dist/types/kind7374.d.ts.map +1 -0
  45. package/dist/types/kind7375.d.ts +9 -0
  46. package/dist/types/kind7375.d.ts.map +1 -0
  47. package/dist/types/kind7376.d.ts +16 -0
  48. package/dist/types/kind7376.d.ts.map +1 -0
  49. package/dist/types/kind9321.d.ts +11 -0
  50. package/dist/types/kind9321.d.ts.map +1 -0
  51. package/dist/types/kind9735.d.ts +15 -0
  52. package/dist/types/kind9735.d.ts.map +1 -0
  53. package/dist/types/proofs.d.ts +21 -0
  54. package/dist/types/proofs.d.ts.map +1 -0
  55. package/dist/utils.d.ts +23 -0
  56. package/dist/utils.d.ts.map +1 -0
  57. package/dist/utils.js +56 -0
  58. package/dist/utils.js.map +1 -0
  59. package/dist/wasm/main/nostr_main.d.ts +74 -0
  60. package/dist/wasm/main/nostr_main_bg.wasm.d.ts +20 -0
  61. package/dist/wasm/worker/nostr_worker.d.ts +45 -0
  62. package/dist/wasm/worker/nostr_worker_bg.wasm.d.ts +41 -0
  63. package/dist/worker.d.ts +3 -0
  64. package/dist/worker.d.ts.map +1 -0
  65. package/dist/worker.js +13 -0
  66. package/dist/worker.js.map +1 -0
  67. package/package.json +71 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Thibaut Duchene
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # @candypoets/nipworker
2
+
3
+ A high-performance Nostr client library with worker-based architecture using Rust WebAssembly for optimal performance and non-blocking operations.
4
+
5
+ [![npm version](https://badge.fury.io/js/@candypoets%2Fnipworker.svg)](https://badge.fury.io/js/@candypoets%2Fnipworker)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## 🚀 Features
9
+
10
+ - **High Performance**: Rust WASM core for cryptographic operations and message processing
11
+ - **Worker-Based Architecture**: Non-blocking operations using Web Workers
12
+ - **TypeScript Support**: Full TypeScript definitions included
13
+ - **Dual Module Support**: Both ES modules and UMD builds
14
+ - **Efficient Serialization**: Uses MessagePack for optimal data transfer
15
+ - **Comprehensive NIP Support**: Implements 12+ standard Nostr Implementation Possibilities (NIPs)
16
+
17
+
18
+ ## 📋 Supported NIPs
19
+
20
+ | NIP | Name | Description | Event Kinds | Status |
21
+ |-----|------|-------------|-------------|---------|
22
+ | [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) | Basic Protocol | Core protocol flow description | 0, 1 | ✅ Full |
23
+ | [NIP-02](https://github.com/nostr-protocol/nips/blob/master/02.md) | Contact List | Contact lists and petnames | 3 | ✅ Full |
24
+ | [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) | Encrypted DMs | Encrypted direct messages | 4 | ✅ Full |
25
+ | [NIP-05](https://github.com/nostr-protocol/nips/blob/master/05.md) | DNS Identifiers | Mapping keys to DNS identifiers | - | 🔄 Partial |
26
+ | [NIP-10](https://github.com/nostr-protocol/nips/blob/master/10.md) | Text Note References | Threading and replies | - | ✅ Full |
27
+ | [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md) | Reposts | Event reposts | 6 | ✅ Full |
28
+ | [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) | bech32 Entities | npub, note, nevent, nprofile encoding | - | ✅ Full |
29
+ | [NIP-25](https://github.com/nostr-protocol/nips/blob/master/25.md) | Reactions | Event reactions and emoji | 7 | ✅ Full |
30
+ | [NIP-27](https://github.com/nostr-protocol/nips/blob/master/27.md) | Text References | Mentions and references in content | - | ✅ Full |
31
+ | [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md) | Versioned Encryption | Advanced encryption for private events | - | ✅ Full |
32
+ | [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md) | Lists | Categorized lists (people, bookmarks) | 39089 | ✅ Full |
33
+ | [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) | Lightning Zaps | Bitcoin Lightning Network integration | 9735 | ✅ Full |
34
+ | [NIP-60](https://github.com/nostr-protocol/nips/blob/master/60.md) | Cashu Wallet | Cashu ecash wallet functionality | 7374, 7375, 7376, 10019, 17375 | ✅ Full |
35
+ | [NIP-61](https://github.com/nostr-protocol/nips/blob/master/61.md) | Nutzaps | Cashu token zaps | 9321 | ✅ Full |
36
+ | [NIP-65](https://github.com/nostr-protocol/nips/blob/master/65.md) | Relay Lists | User relay preferences | 10002 | ✅ Full |
37
+
38
+ ### NIP-60 Cashu Wallet Events
39
+
40
+ The library provides complete support for **NIP-60 Cashu wallet functionality**:
41
+
42
+ | Event Kind | Description | Encryption | Purpose |
43
+ |------------|-------------|------------|---------|
44
+ | 7374 | Quote events | NIP-44 | Token redemption quotes |
45
+ | 7375 | Token events | NIP-44 | Cashu proofs and tokens |
46
+ | 7376 | Spending history | NIP-44 | Transaction history |
47
+ | 9321 | Nutzaps | - | Cashu token zaps |
48
+ | 10019 | Wallet settings | - | User wallet preferences |
49
+ | 17375 | Encrypted wallets | NIP-44 | Private wallet data |
50
+
51
+
52
+ ### Legend
53
+ - ✅ **Full**: Complete implementation with all features
54
+ - 🔄 **Partial**: Basic support, some features may be limited
55
+ - ❌ **Not Supported**: NIP is not implemented
56
+
57
+ ## 📦 Installation
58
+
59
+ ```bash
60
+ npm install @candypoets/nipworker
61
+ ```
62
+
63
+ That's it! No additional dependencies needed.
64
+
65
+ ## 🔧 Usage
66
+
67
+ ### Import Structure
68
+
69
+ The library is organized into logical modules for better tree-shaking:
70
+
71
+ ```javascript
72
+ // Core API - main functionality
73
+ import { nostrManager, createNostrManager } from '@candypoets/nipworker';
74
+
75
+ // Hooks - React-style subscription hooks
76
+ import { useSubscription } from '@candypoets/nipworker/hooks';
77
+
78
+ // Types - TypeScript type definitions
79
+ import type {
80
+ ParsedEvent,
81
+ Kind1Parsed,
82
+ NostrManagerConfig,
83
+ Request
84
+ } from '@candypoets/nipworker/types';
85
+
86
+ // Utils - type guards and helper functions
87
+ import { isKind1, isKind0, SignerTypes } from '@candypoets/nipworker/utils';
88
+ ```
89
+
90
+ ### Basic Usage
91
+
92
+ ```javascript
93
+ import { nostrManager } from '@candypoets/nipworker';
94
+ import { useSubscription } from '@candypoets/nipworker/hooks';
95
+
96
+ // Login by setting up a signer (private key)
97
+ nostrManager.setSigner('privkey', 'your-private-key-hex');
98
+
99
+ // Subscribe to events using the hook
100
+ const unsubscribe = useSubscription(
101
+ 'my-subscription',
102
+ [{
103
+ kinds: [1], // Text notes
104
+ limit: 10
105
+ }],
106
+ (events, eventType) => {
107
+ if (eventType === 'EVENTS') {
108
+ console.log('Received events:', events);
109
+ } else if (eventType === 'EOSE') {
110
+ console.log('End of stored events');
111
+ }
112
+ },
113
+ { closeOnEose: false }
114
+ );
115
+
116
+ // Publish an event
117
+ const event = {
118
+ kind: 1,
119
+ content: 'Hello Nostr!',
120
+ tags: [],
121
+ created_at: Math.floor(Date.now() / 1000)
122
+ };
123
+
124
+ nostrManager.publish('publish-id-123', event, (status, type) => {
125
+ console.log('Publish status:', status);
126
+ });
127
+
128
+ // Clean up subscription when done
129
+ // unsubscribe();
130
+ ```
131
+
132
+ ### Advanced Usage
133
+
134
+ ```javascript
135
+ import { createNostrManager } from '@candypoets/nipworker';
136
+ import { useSubscription } from '@candypoets/nipworker/hooks';
137
+
138
+ // Create a custom manager instance with configuration
139
+ const customManager = createNostrManager();
140
+
141
+ // Set up multiple signers
142
+ customManager.setSigner('privkey', 'main-private-key-hex');
143
+
144
+ // Subscribe to specific authors with multiple filters
145
+ const unsubscribe = useSubscription(
146
+ 'author-feed',
147
+ [
148
+ {
149
+ kinds: [1, 6, 7],
150
+ authors: ['pubkey1', 'pubkey2'],
151
+ since: Math.floor(Date.now() / 1000) - 3600, // Last hour
152
+ limit: 50
153
+ },
154
+ {
155
+ kinds: [30023], // Long-form content
156
+ authors: ['pubkey1'],
157
+ limit: 10
158
+ }
159
+ ],
160
+ (events, eventType) => {
161
+ if (eventType === 'EVENTS') {
162
+ events.forEach(event => {
163
+ switch (event.kind) {
164
+ case 1:
165
+ console.log('Text note:', event.content);
166
+ break;
167
+ case 6:
168
+ console.log('Repost:', event);
169
+ break;
170
+ case 7:
171
+ console.log('Reaction:', event);
172
+ break;
173
+ case 30023:
174
+ console.log('Long-form content:', event);
175
+ break;
176
+ }
177
+ });
178
+ } else if (eventType === 'EOSE') {
179
+ console.log('End of stored events for author feed');
180
+ }
181
+ },
182
+ { closeOnEose: false }
183
+ );
184
+
185
+ // Global publish status monitoring
186
+ customManager.addPublishCallbackAll((status, eventId) => {
187
+ console.log(`Event ${eventId} status:`, status);
188
+ });
189
+
190
+ // Clean up when done
191
+ setTimeout(() => {
192
+ unsubscribe();
193
+ customManager.cleanup();
194
+ }, 60000);
195
+ ```
196
+
197
+ ## 🏗️ Architecture
198
+
199
+ NipWorker uses a multi-layered architecture:
200
+
201
+ 1. **Main Thread**: Your application code
202
+ 2. **Web Worker**: Handles network operations and message routing
203
+ 3. **Rust WASM Core**: Performs cryptographic operations and message validation
204
+
205
+ This architecture ensures that heavy operations don't block your main thread, providing a smooth user experience.
206
+
207
+ ## 📚 API Reference
208
+
209
+ ### NostrManager
210
+
211
+ #### Factory Function
212
+
213
+ ```typescript
214
+ createNostrManager(config?: NostrManagerConfig): NostrManager
215
+ ```
216
+
217
+ #### Methods
218
+
219
+ - `setSigner(name: string, secretKeyHex: string): void` - Set up a signer for publishing
220
+ - `subscribe(subscriptionId: string, requests: Request[], options?: SubscriptionOptions): SharedArrayBuffer` - Subscribe to events
221
+ - `publish(publishId: string, event: NostrEvent, callback?: PublishCallback): void` - Publish an event
222
+ - `signEvent(event: NostrEvent): void` - Sign an event without publishing
223
+ - `getPublicKey(): void` - Get the public key of the current signer
224
+ - `unsubscribe(subscriptionId: string): void` - Unsubscribe from events
225
+ - `cleanup(): void` - Clean up unused subscriptions
226
+ - `addPublishCallbackAll(callback: Function): void` - Monitor all publish statuses
227
+
228
+ ### useSubscription Hook
229
+
230
+ ```typescript
231
+ useSubscription(
232
+ subId: string,
233
+ requests: Request[],
234
+ callback: SubscriptionCallback,
235
+ options?: SubscriptionOptions
236
+ ): () => void
237
+ ```
238
+
239
+ #### Parameters
240
+
241
+ - `subId` - Unique subscription identifier
242
+ - `requests` - Array of Nostr filter objects
243
+ - `callback` - Function called when events are received
244
+ - `options` - Subscription options (closeOnEose, skipCache, force)
245
+
246
+ #### Returns
247
+
248
+ - Function to unsubscribe and clean up resources
249
+
250
+ ### Event Types
251
+
252
+ - `EVENTS` - New events received
253
+ - `EOSE` - End of stored events
254
+ - `EOCE` - End of cached events
255
+ - `PUBLISH_STATUS` - Status update for published events
256
+
257
+ ## 🛠️ Development
258
+
259
+ ### Prerequisites
260
+
261
+ - Node.js 18+
262
+ - Rust 1.70+
263
+ - wasm-pack
264
+
265
+ ### Building from Source
266
+
267
+ ```bash
268
+ # Clone the repository
269
+ git clone https://github.com/candypoets/nipworker.git
270
+ cd nipworker
271
+
272
+ # Install dependencies
273
+ npm install
274
+
275
+ # Build WASM modules
276
+ npm run build:wasm
277
+
278
+ # Build the library
279
+ npm run build
280
+ ```
281
+
282
+ ### Scripts
283
+
284
+ - `npm run dev` - Start development server
285
+ - `npm run build` - Build for production
286
+ - `npm run build:wasm` - Build WASM modules only
287
+ - `npm run build:types` - Generate TypeScript declarations
288
+ - `npm run clean` - Clean build artifacts
289
+
290
+ ## 🤝 Contributing
291
+
292
+ We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.
293
+
294
+ ### Development Workflow
295
+
296
+ 1. Fork the repository
297
+ 2. Create a feature branch: `git checkout -b feature/amazing-feature`
298
+ 3. Make your changes
299
+ 4. Add tests if applicable
300
+ 5. Commit your changes: `git commit -m 'Add amazing feature'`
301
+ 6. Push to the branch: `git push origin feature/amazing-feature`
302
+ 7. Open a Pull Request
303
+
304
+ ## 📄 License
305
+
306
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
307
+
308
+ ## 🔗 Links
309
+
310
+ - [GitHub Repository](https://github.com/candypoets/nipworker)
311
+ - [Issue Tracker](https://github.com/candypoets/nipworker/issues)
312
+ - [Nostr Protocol](https://github.com/nostr-protocol/nostr)
313
+ - [NIPs Repository](https://github.com/nostr-protocol/nips)
314
+
315
+ ## 🙏 Acknowledgments
316
+
317
+ - [Nostr Protocol](https://nostr.com/) - The decentralized social protocol
318
+ - [nostr-tools](https://github.com/nbd-wtf/nostr-tools) - Essential Nostr utilities
319
+ - [wasm-pack](https://rustwasm.github.io/wasm-pack/) - Rust to WebAssembly workflow
320
+
321
+ ## 📊 Performance
322
+
323
+ NipWorker is designed for high performance:
324
+
325
+ - **Fast Event Processing**: Rust WASM core processes events up to 10x faster than pure JavaScript
326
+ - **Non-blocking Operations**: Web Worker architecture prevents UI freezing
327
+ - **Efficient Serialization**: MessagePack reduces bandwidth usage by ~30%
328
+ - **Connection Pooling**: Intelligent relay connection management
329
+
330
+
331
+
332
+ ## 🔒 Security
333
+
334
+ - All cryptographic operations are handled by the Rust WASM core
335
+ - Private keys never leave the worker thread
336
+ - Event validation is performed at the WASM level
337
+ - Secure random number generation for key operations
338
+
339
+ ---
340
+
341
+ Made with ❤️ by [So Tachi](mailto:sotachi@proton.me)
@@ -0,0 +1,6 @@
1
+ import { Request } from './types';
2
+
3
+ export declare function useSubscription(subId: string, requests: Request[], callback?: any, options?: {
4
+ closeOnEose: boolean;
5
+ }): () => void;
6
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAuB,OAAO,EAAE,MAAM,WAAW,CAAC;AAE9D,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,EAAE,EACnB,QAAQ,GAAE,GAAc,EACxB,OAAO;;CAAyB,cAwEjC"}
package/dist/hooks.js ADDED
@@ -0,0 +1,33 @@
1
+ import { n as E, S as v } from "./index3.js";
2
+ function b(i, u, o = () => {
3
+ }, a = { closeOnEose: !1 }) {
4
+ if (!i)
5
+ return console.warn("useSharedSubscription: No subscription ID provided"), () => {
6
+ };
7
+ let r = null, f = 4, e = null, t = 15;
8
+ const d = 4e3;
9
+ let s = !0;
10
+ if (u.length > 0) {
11
+ r = E.subscribe(i, u, a);
12
+ const c = () => {
13
+ if (!s || !r) {
14
+ e !== null && clearTimeout(e);
15
+ return;
16
+ }
17
+ const l = v.readMessages(r, f);
18
+ l.hasNewData ? (t = 5, l.messages.forEach((n) => {
19
+ "SubscriptionEvent" in n ? n.SubscriptionEvent.event_data.forEach((p) => {
20
+ o(p, n.SubscriptionEvent.event_type);
21
+ }) : "Eose" in n ? (a.closeOnEose && (console.log("close"), s = !1, e && clearTimeout(e)), o(n.Eose.data, "EOSE")) : "Eoce" in n && o([], "EOCE");
22
+ }), f = l.newReadPosition) : t = Math.min(t * 2, d), e !== null && clearTimeout(e), e = window.setTimeout(c, t);
23
+ };
24
+ e = window.setTimeout(c, 0);
25
+ }
26
+ return () => {
27
+ s = !1, e !== null && clearTimeout(e), E.unsubscribe(i);
28
+ };
29
+ }
30
+ export {
31
+ b as useSubscription
32
+ };
33
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sources":["../src/hooks.ts"],"sourcesContent":["import { nostrManager } from \".\";\nimport { SharedBufferReader } from \"src/lib/sharedBuffer\";\nimport type { WorkerToMainMessage, Request } from \"src/types\";\n\nexport function useSubscription(\n subId: string,\n requests: Request[],\n callback: any = () => {},\n options = { closeOnEose: false },\n) {\n if (!subId) {\n console.warn(\"useSharedSubscription: No subscription ID provided\");\n return () => {};\n }\n let buffer: SharedArrayBuffer | null = null;\n let lastReadPos: number = 4;\n let timeoutId: number | null = null;\n let pollInterval: number = 15; // Start at 5ms - very aggressive\n const maxInterval: number = 4000; // Max 4 seconds\n let running: boolean = true;\n\n if (requests.length > 0) {\n buffer = nostrManager.subscribe(subId, requests, options);\n\n const processEvents = (): void => {\n if (!running || !buffer) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n return;\n }\n\n const result = SharedBufferReader.readMessages(buffer, lastReadPos);\n\n if (result.hasNewData) {\n // Found new data - reset to aggressive polling\n pollInterval = 5;\n\n result.messages.forEach((message: WorkerToMainMessage) => {\n if (\"SubscriptionEvent\" in message) {\n message.SubscriptionEvent.event_data.forEach((event) => {\n callback(event, message.SubscriptionEvent.event_type);\n });\n } else if (\"Eose\" in message) {\n if (options.closeOnEose) {\n console.log(\"close\");\n running = false;\n timeoutId && clearTimeout(timeoutId);\n }\n callback(message.Eose.data, \"EOSE\");\n } else if (\"Eoce\" in message) {\n callback([], \"EOCE\");\n }\n });\n lastReadPos = result.newReadPosition;\n } else {\n // No new data - back off exponentially (faster backoff)\n pollInterval = Math.min(pollInterval * 2, maxInterval);\n }\n\n // Clear any existing timeout before scheduling a new one\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n // Schedule next poll\n timeoutId = window.setTimeout(processEvents, pollInterval);\n };\n\n // Start after a minimal delay to ensure the return function is available\n timeoutId = window.setTimeout(processEvents, 0);\n }\n\n return (): void => {\n running = false;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n nostrManager.unsubscribe(subId);\n };\n}\n"],"names":["useSubscription","subId","requests","callback","options","buffer","lastReadPos","timeoutId","pollInterval","maxInterval","running","nostrManager","processEvents","result","SharedBufferReader","message","event"],"mappings":";AAIO,SAASA,EACdC,GACAC,GACAC,IAAgB,MAAM;AAAC,GACvBC,IAAU,EAAE,aAAa,MACzB;AACA,MAAI,CAACH;AACH,mBAAQ,KAAK,oDAAoD,GAC1D,MAAM;AAAA,IAAC;AAEhB,MAAII,IAAmC,MACnCC,IAAsB,GACtBC,IAA2B,MAC3BC,IAAuB;AAC3B,QAAMC,IAAsB;AAC5B,MAAIC,IAAmB;AAEvB,MAAIR,EAAS,SAAS,GAAG;AACvB,IAAAG,IAASM,EAAa,UAAUV,GAAOC,GAAUE,CAAO;AAExD,UAAMQ,IAAgB,MAAY;AAChC,UAAI,CAACF,KAAW,CAACL,GAAQ;AACvB,QAAIE,MAAc,QAChB,aAAaA,CAAS;AAExB;AAAA,MACF;AAEA,YAAMM,IAASC,EAAmB,aAAaT,GAAQC,CAAW;AAElE,MAAIO,EAAO,cAETL,IAAe,GAEfK,EAAO,SAAS,QAAQ,CAACE,MAAiC;AACxD,QAAI,uBAAuBA,IACzBA,EAAQ,kBAAkB,WAAW,QAAQ,CAACC,MAAU;AACtD,UAAAb,EAASa,GAAOD,EAAQ,kBAAkB,UAAU;AAAA,QACtD,CAAC,IACQ,UAAUA,KACfX,EAAQ,gBACV,QAAQ,IAAI,OAAO,GACnBM,IAAU,IACVH,KAAa,aAAaA,CAAS,IAErCJ,EAASY,EAAQ,KAAK,MAAM,MAAM,KACzB,UAAUA,KACnBZ,EAAS,CAAA,GAAI,MAAM;AAAA,MAEvB,CAAC,GACDG,IAAcO,EAAO,mBAGrBL,IAAe,KAAK,IAAIA,IAAe,GAAGC,CAAW,GAInDF,MAAc,QAChB,aAAaA,CAAS,GAIxBA,IAAY,OAAO,WAAWK,GAAeJ,CAAY;AAAA,IAC3D;AAGA,IAAAD,IAAY,OAAO,WAAWK,GAAe,CAAC;AAAA,EAChD;AAEA,SAAO,MAAY;AACjB,IAAAF,IAAU,IACNH,MAAc,QAChB,aAAaA,CAAS,GAExBI,EAAa,YAAYV,CAAK;AAAA,EAChC;AACF;"}
@@ -0,0 +1,81 @@
1
+ import { RelayStatusUpdate, Request } from './wasm/main/nostr_main.js';
2
+ import { AnyKind, ParsedEvent, SubscribeKind, PublishKind } from './types';
3
+ import { NostrEvent } from 'nostr-tools';
4
+
5
+ export type { Request };
6
+ export type SubscriptionCallback = (data: ParsedEvent<AnyKind>[] | number, type: SubscribeKind) => void;
7
+ type PublishCallback = (data: RelayStatusUpdate, type: PublishKind) => void;
8
+ export declare enum PublishStatus {
9
+ StatusPending = "pending",
10
+ StatusSent = "sent",
11
+ StatusSuccess = "success",
12
+ StatusFailed = "failed",
13
+ StatusRejected = "rejected",
14
+ StatusConnError = "connection_error"
15
+ }
16
+ export type RelayStatus = {
17
+ relay: string;
18
+ status: PublishStatus;
19
+ message: string;
20
+ timestamp: number;
21
+ };
22
+ export interface SubscriptionOptions {
23
+ closeOnEose?: boolean;
24
+ skipCache?: boolean;
25
+ force?: boolean;
26
+ }
27
+ /**
28
+ * Configuration for the Nostr Manager
29
+ */
30
+ export interface NostrManagerConfig {
31
+ /**
32
+ * Custom worker URL. If not provided, uses the bundled worker.
33
+ */
34
+ workerUrl?: string;
35
+ /**
36
+ * Custom worker instance. If provided, workerUrl is ignored.
37
+ */
38
+ worker?: Worker;
39
+ }
40
+ /**
41
+ * Pure TypeScript NostrClient that manages worker communication and state.
42
+ * Uses WASM utilities for heavy lifting (encoding, decoding, crypto).
43
+ */
44
+ declare class NostrManager {
45
+ private worker;
46
+ private subscriptions;
47
+ private publishes;
48
+ private signers;
49
+ PERPETUAL_SUBSCRIPTIONS: string[];
50
+ constructor(config?: NostrManagerConfig);
51
+ private createWorker;
52
+ private setupWorkerListener;
53
+ private handleWorkerMessage;
54
+ private handlePublishStatus;
55
+ private handleSignedEvent;
56
+ private handlePublicKey;
57
+ private createShortId;
58
+ subscribe(subscriptionId: string, requests: Request[], options?: SubscriptionOptions): SharedArrayBuffer;
59
+ getBuffer(subId: string): SharedArrayBuffer | undefined;
60
+ unsubscribe(subscriptionId: string): void;
61
+ publish(publish_id: string, event: NostrEvent, callback?: PublishCallback): void;
62
+ setSigner(name: string, secretKeyHex: string): void;
63
+ signEvent(event: NostrEvent): void;
64
+ getPublicKey(): void;
65
+ addPublishCallbackAll(callback: (status: RelayStatusUpdate, eventId: string) => void): void;
66
+ cleanup(): void;
67
+ }
68
+ /**
69
+ * Factory function to create a new NostrManager instance.
70
+ * @param config - Configuration for the NostrManager.
71
+ * @returns A new instance of NostrManager.
72
+ */
73
+ export declare function createNostrManager(config?: NostrManagerConfig): NostrManager;
74
+ /**
75
+ * Default singleton instance of the NostrManager.
76
+ * Useful for applications that only need one instance.
77
+ */
78
+ export declare const nostrManager: NostrManager;
79
+ export declare function cleanup(): void;
80
+ export * from './types';
81
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,OAAO,EAEb,MAAM,6BAA6B,CAAC;AAGrC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAG5D,YAAY,EAAE,OAAO,EAAE,CAAC;AAGxB,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,MAAM,EACrC,IAAI,EAAE,aAAa,KAChB,IAAI,CAAC;AACV,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;AAE5E,oBAAY,aAAa;IACvB,aAAa,YAAY;IACzB,UAAU,SAAS;IACnB,aAAa,YAAY;IACzB,YAAY,WAAW;IACvB,cAAc,aAAa;IAC3B,eAAe,qBAAqB;CACrC;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID;;;GAGG;AACH,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAOjB;IACJ,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,OAAO,CAA6B;IAErC,uBAAuB,WAAoC;gBAEtD,MAAM,GAAE,kBAAuB;IAK3C,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,aAAa;IAWrB,SAAS,CACP,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,GAAE,mBAAwB,GAChC,iBAAiB;IAuDpB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IASvD,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAWzC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,eAAe;IA2BzE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAanD,SAAS,CAAC,KAAK,EAAE,UAAU;IAgB3B,YAAY;IAQZ,qBAAqB,CACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI;IAKhE,OAAO,IAAI,IAAI;CA0BhB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,GAAE,kBAAuB,GAC9B,YAAY,CAEd;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,cAAqB,CAAC;AAE/C,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import { P as r, R as t, a as n, c as o, i, n as p } from "./index3.js";
2
+ import "@msgpack/msgpack";
3
+ import { S as g } from "./index2.js";
4
+ export {
5
+ r as PublishStatus,
6
+ t as ReactionType,
7
+ g as SignerTypes,
8
+ n as cleanup,
9
+ o as createNostrManager,
10
+ i as isKind39089,
11
+ p as nostrManager
12
+ };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
package/dist/index2.js ADDED
@@ -0,0 +1,8 @@
1
+ const e = {
2
+ PK: "privkey"
3
+ // SignerTypeNone: "none" as SignerType
4
+ };
5
+ export {
6
+ e as S
7
+ };
8
+ //# sourceMappingURL=index2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index2.js","sources":["../src/types/index.ts"],"sourcesContent":["export {\n type MainToWorkerMessage,\n type RelayStatusUpdate,\n type Request,\n type WorkerToMainMessage,\n} from \"nostr-main/pkg/nostr_main.js\";\n\nimport type { NostrEvent } from \"nostr-tools\";\n\nimport { type Kind0Parsed } from \"./kind0\";\nimport { type Kind1Parsed } from \"./kind1\";\nimport { type Kind10002Parsed } from \"./kind10002\";\nimport { type Kind10019Parsed } from \"./kind10019\";\nimport { type Kind17Parsed } from \"./kind17\";\nimport { type Kind17375Parsed } from \"./kind17375\";\nimport { type Kind3Parsed } from \"./kind3\";\nimport { type Kind39089Parsed } from \"./kind39089\";\nimport { type Kind4Parsed } from \"./kind4\";\nimport { type Kind6Parsed } from \"./kind6\";\nimport { type Kind7Parsed } from \"./kind7\";\nimport { type Kind7374Parsed } from \"./kind7374\";\nimport { type Kind7375Parsed } from \"./kind7375\";\nimport type { Kind7376Parsed } from \"./kind7376\";\nimport { type Kind9321Parsed } from \"./kind9321\";\nimport { type Kind9735Parsed } from \"./kind9735\";\n\nexport * from \"./proofs\";\n\nexport * from \"./kind0\";\nexport * from \"./kind1\";\nexport * from \"./kind10002\";\nexport * from \"./kind10019\";\nexport * from \"./kind17\";\nexport * from \"./kind17375\";\nexport * from \"./kind3\";\nexport * from \"./kind39089\";\nexport * from \"./kind4\";\nexport * from \"./kind6\";\nexport * from \"./kind7\";\nexport * from \"./kind7374\";\nexport * from \"./kind7375\";\nexport * from \"./kind7376\";\nexport * from \"./kind9321\";\nexport * from \"./kind9735\";\n\nexport type ParsedEvent<T> = NostrEvent & {\n parsed?: T | null;\n requests?: Request[];\n relays?: string[];\n};\n\nexport type ContentBlock = {\n type:\n | \"text\"\n | \"image\"\n | \"video\"\n | \"mediaGrid\"\n | \"code\"\n | \"link\"\n | \"npub\"\n | \"nprofile\"\n | \"note\"\n | \"nevent\"\n | \"naddr\"\n | \"hashtag\"\n | \"cashu\";\n text: string;\n data?: Record<string, any>;\n};\n\nexport type AnyKind =\n | Kind0Parsed\n | Kind1Parsed\n | Kind3Parsed\n | Kind4Parsed\n | Kind6Parsed\n | Kind7Parsed\n | Kind17Parsed\n | Kind9735Parsed\n | Kind9321Parsed // For Kind9321 which seems to use Kind1Parsed\n | Kind10002Parsed\n | Kind10019Parsed\n | Kind17375Parsed\n | Kind7374Parsed\n | Kind7375Parsed\n | Kind7376Parsed\n | Kind39089Parsed;\n\nexport type SubscribeKind =\n | \"CACHED_EVENT\"\n | \"FETCHED_EVENT\"\n | \"COUNT\"\n | \"EOSE\"\n | \"EOCE\";\n\nexport type PublishKind = \"PUBLISH_STATUS\";\n\nexport type SignerType = string;\n\n// Enum-like object for SignerType\nexport const SignerTypes = {\n PK: \"privkey\" as SignerType,\n // SignerTypeNone: \"none\" as SignerType\n} as const;\n"],"names":["SignerTypes"],"mappings":"AAoGO,MAAMA,IAAc;AAAA,EACzB,IAAI;AAAA;AAEN;"}