@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.
- package/LICENSE +21 -0
- package/README.md +341 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +33 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/index2.js +8 -0
- package/dist/index2.js.map +1 -0
- package/dist/index3.js +270 -0
- package/dist/index3.js.map +1 -0
- package/dist/lib/sharedBuffer.d.ts +50 -0
- package/dist/lib/sharedBuffer.d.ts.map +1 -0
- package/dist/nostr_worker.js +1001 -0
- package/dist/nostr_worker.js.map +1 -0
- package/dist/types/index.d.ts +53 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/kind0.d.ts +24 -0
- package/dist/types/kind0.d.ts.map +1 -0
- package/dist/types/kind1.d.ts +17 -0
- package/dist/types/kind1.d.ts.map +1 -0
- package/dist/types/kind10002.d.ts +7 -0
- package/dist/types/kind10002.d.ts.map +1 -0
- package/dist/types/kind10019.d.ts +9 -0
- package/dist/types/kind10019.d.ts.map +1 -0
- package/dist/types/kind17.d.ts +4 -0
- package/dist/types/kind17.d.ts.map +1 -0
- package/dist/types/kind17375.d.ts +7 -0
- package/dist/types/kind17375.d.ts.map +1 -0
- package/dist/types/kind3.d.ts +7 -0
- package/dist/types/kind3.d.ts.map +1 -0
- package/dist/types/kind39089.d.ts +11 -0
- package/dist/types/kind39089.d.ts.map +1 -0
- package/dist/types/kind4.d.ts +9 -0
- package/dist/types/kind4.d.ts.map +1 -0
- package/dist/types/kind6.d.ts +6 -0
- package/dist/types/kind6.d.ts.map +1 -0
- package/dist/types/kind7.d.ts +18 -0
- package/dist/types/kind7.d.ts.map +1 -0
- package/dist/types/kind7374.d.ts +6 -0
- package/dist/types/kind7374.d.ts.map +1 -0
- package/dist/types/kind7375.d.ts +9 -0
- package/dist/types/kind7375.d.ts.map +1 -0
- package/dist/types/kind7376.d.ts +16 -0
- package/dist/types/kind7376.d.ts.map +1 -0
- package/dist/types/kind9321.d.ts +11 -0
- package/dist/types/kind9321.d.ts.map +1 -0
- package/dist/types/kind9735.d.ts +15 -0
- package/dist/types/kind9735.d.ts.map +1 -0
- package/dist/types/proofs.d.ts +21 -0
- package/dist/types/proofs.d.ts.map +1 -0
- package/dist/utils.d.ts +23 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +56 -0
- package/dist/utils.js.map +1 -0
- package/dist/wasm/main/nostr_main.d.ts +74 -0
- package/dist/wasm/main/nostr_main_bg.wasm.d.ts +20 -0
- package/dist/wasm/worker/nostr_worker.d.ts +45 -0
- package/dist/wasm/worker/nostr_worker_bg.wasm.d.ts +41 -0
- package/dist/worker.d.ts +3 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +13 -0
- package/dist/worker.js.map +1 -0
- 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
|
+
[](https://badge.fury.io/js/@candypoets%2Fnipworker)
|
|
6
|
+
[](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)
|
package/dist/hooks.d.ts
ADDED
|
@@ -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;"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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;"}
|