@candypoets/nipworker 0.96.3 → 0.96.5

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 (180) hide show
  1. package/README.md +206 -73
  2. package/crates/native-ffi/README.md +14 -151
  3. package/crates/native-ffi/ios/README.md +4 -50
  4. package/crates/native-ffi/react-native/README.md +8 -7
  5. package/crates/native-ffi/react-native/android/build.gradle +1 -0
  6. package/crates/native-ffi/react-native/android/src/main/cpp/NipworkerByteRuntime.cpp +348 -0
  7. package/crates/native-ffi/react-native/android/src/main/java/com/candypoets/nipworker/reactnative/NipworkerHooks.kt +292 -0
  8. package/crates/native-ffi/react-native/android/src/main/java/com/candypoets/nipworker/reactnative/NipworkerReactNativeModule.kt +283 -89
  9. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/AddressPointer.java +75 -0
  10. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ArticleBlock.java +102 -0
  11. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ArticleBlockType.java +23 -0
  12. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ArticleEntity.java +80 -0
  13. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ArticleInline.java +85 -0
  14. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ArticleInlineType.java +24 -0
  15. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/BadgeAwardRecipient.java +61 -0
  16. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/BufferFull.java +52 -0
  17. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CacheInput.java +16 -0
  18. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CacheInputMessage.java +57 -0
  19. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CacheRequest.java +84 -0
  20. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CacheResponse.java +67 -0
  21. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CashuData.java +55 -0
  22. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ChatLimiterPipeConfig.java +74 -0
  23. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CodeData.java +61 -0
  24. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ConnectionStatus.java +68 -0
  25. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Contact.java +70 -0
  26. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ContentBlock.java +70 -0
  27. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ContentData.java +23 -0
  28. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Coordinate.java +75 -0
  29. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CountResponse.java +60 -0
  30. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/CounterPipeConfig.java +67 -0
  31. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/DLEQProof.java +69 -0
  32. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Emoji.java +62 -0
  33. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/EmojiData.java +68 -0
  34. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Eoce.java +55 -0
  35. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/EventPointer.java +74 -0
  36. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/GetPublicKey.java +43 -0
  37. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/HTLCWitness.java +64 -0
  38. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/HashtagData.java +55 -0
  39. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/HistoryTag.java +74 -0
  40. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ImageData.java +67 -0
  41. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ImetaTag.java +100 -0
  42. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind0Parsed.java +168 -0
  43. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind10002Parsed.java +59 -0
  44. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind10019Parsed.java +73 -0
  45. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind1018Parsed.java +79 -0
  46. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind1068Parsed.java +107 -0
  47. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind1111Parsed.java +159 -0
  48. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind1311Parsed.java +91 -0
  49. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind17375Parsed.java +74 -0
  50. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind17Parsed.java +81 -0
  51. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind1Parsed.java +109 -0
  52. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind20Parsed.java +107 -0
  53. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind22Parsed.java +111 -0
  54. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind30023Parsed.java +113 -0
  55. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind3Parsed.java +59 -0
  56. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind4Parsed.java +78 -0
  57. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind6Parsed.java +53 -0
  58. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind7374Parsed.java +66 -0
  59. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind7375Parsed.java +79 -0
  60. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind7376Parsed.java +100 -0
  61. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind7Parsed.java +81 -0
  62. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind8Parsed.java +78 -0
  63. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind9321Parsed.java +117 -0
  64. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Kind9735Parsed.java +119 -0
  65. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/KindFilterPipeConfig.java +60 -0
  66. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/LinkPreviewData.java +73 -0
  67. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ListParsed.java +123 -0
  68. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/LiveActivityRef.java +72 -0
  69. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/LiveChatParticipant.java +61 -0
  70. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/LiveChatThreadRef.java +61 -0
  71. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MainContent.java +20 -0
  72. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MainMessage.java +57 -0
  73. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MediaGroupData.java +58 -0
  74. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MediaItem.java +58 -0
  75. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Message.java +24 -0
  76. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MessageType.java +19 -0
  77. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MintInfo.java +65 -0
  78. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MintProofs.java +66 -0
  79. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/MuteFilterPipeConfig.java +84 -0
  80. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Nip07.java +43 -0
  81. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Nip46Bunker.java +61 -0
  82. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Nip46QR.java +61 -0
  83. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/NostrData.java +81 -0
  84. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/NostrEvent.java +95 -0
  85. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/NpubLimiterKey.java +15 -0
  86. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/NpubLimiterPipeConfig.java +64 -0
  87. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/P2PKWitness.java +57 -0
  88. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ParsePipeConfig.java +43 -0
  89. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ParsedData.java +39 -0
  90. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ParsedDataUnion.java +35 -0
  91. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ParsedEvent.java +108 -0
  92. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Pipe.java +57 -0
  93. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PipeConfig.java +23 -0
  94. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PipelineConfig.java +59 -0
  95. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PollOption.java +62 -0
  96. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PollType.java +15 -0
  97. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PreGenericParsed.java +213 -0
  98. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PreParticipant.java +73 -0
  99. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PreRefEvent.java +67 -0
  100. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/PrivateKey.java +55 -0
  101. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ProfilePointer.java +64 -0
  102. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Proof.java +90 -0
  103. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ProofVerificationPipeConfig.java +52 -0
  104. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Pubkey.java +55 -0
  105. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Publish.java +80 -0
  106. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Raw.java +55 -0
  107. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ReactionType.java +17 -0
  108. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/RelayInfo.java +63 -0
  109. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Request.java +134 -0
  110. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SaveToDbPipeConfig.java +43 -0
  111. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SerializeEventsPipeConfig.java +55 -0
  112. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SetSigner.java +57 -0
  113. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SignEvent.java +54 -0
  114. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SignedEvent.java +54 -0
  115. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SignerOp.java +19 -0
  116. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SignerRequest.java +80 -0
  117. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SignerResponse.java +64 -0
  118. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SignerType.java +18 -0
  119. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/StringVec.java +57 -0
  120. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Subscribe.java +72 -0
  121. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SubscribeKind.java +19 -0
  122. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/SubscriptionConfig.java +95 -0
  123. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Tag.java +64 -0
  124. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Template.java +74 -0
  125. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Unsubscribe.java +55 -0
  126. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ValidProofs.java +59 -0
  127. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/VideoData.java +67 -0
  128. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/VideoVariant.java +102 -0
  129. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/Witness.java +17 -0
  130. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/WitnessString.java +54 -0
  131. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/WorkerMessage.java +74 -0
  132. package/crates/native-ffi/react-native/android/src/main/java/nostr/fb/ZapRequest.java +83 -0
  133. package/crates/native-ffi/react-native/ios/NipworkerReactNativeModule.h +18 -0
  134. package/crates/native-ffi/react-native/ios/NipworkerReactNativeModule.mm +263 -8
  135. package/dist/EngineManager.d.ts +1 -0
  136. package/dist/EngineManager.d.ts.map +1 -1
  137. package/dist/EngineManager.js +143 -137
  138. package/dist/NostrManager.d.ts +1 -0
  139. package/dist/NostrManager.d.ts.map +1 -1
  140. package/dist/NostrManager.js +49 -44
  141. package/dist/connections/index.js +87 -87
  142. package/dist/engine/index.js +119 -119
  143. package/dist/engine.d.ts.map +1 -1
  144. package/dist/hooks.d.ts +1 -1
  145. package/dist/hooks.d.ts.map +1 -1
  146. package/dist/hooks.js +27 -26
  147. package/dist/index.d.ts +1 -1
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/legacy.d.ts.map +1 -1
  150. package/dist/lib/ArrayBufferReader.d.ts +2 -1
  151. package/dist/lib/ArrayBufferReader.d.ts.map +1 -1
  152. package/dist/lib/BaseBackend.d.ts +5 -3
  153. package/dist/lib/BaseBackend.d.ts.map +1 -1
  154. package/dist/manager.d.ts +2 -6
  155. package/dist/manager.d.ts.map +1 -1
  156. package/dist/manager.js +10 -28
  157. package/dist/react-native.d.ts +33 -4
  158. package/dist/react-native.d.ts.map +1 -1
  159. package/dist/react-native.js +400 -122
  160. package/dist/scheduleMicrotask.js +58 -50
  161. package/package.json +13 -11
  162. package/swift/Package.swift +36 -0
  163. package/swift/README.md +438 -0
  164. package/swift/Sources/NipworkerSwift/ArrayBufferReader.swift +136 -0
  165. package/swift/Sources/NipworkerSwift/AuthSession.swift +24 -0
  166. package/swift/Sources/NipworkerSwift/FFI.swift +94 -0
  167. package/swift/Sources/NipworkerSwift/FlatBufferHelpers.swift +273 -0
  168. package/swift/Sources/NipworkerSwift/Generated/message_generated.swift +6530 -0
  169. package/swift/Sources/NipworkerSwift/Hooks.swift +300 -0
  170. package/swift/Sources/NipworkerSwift/Models.swift +156 -0
  171. package/swift/Sources/NipworkerSwift/NostrManager.swift +594 -0
  172. package/swift/Sources/NipworkerSwift/PublishTracker.swift +40 -0
  173. package/swift/Sources/NipworkerSwift/Subscription.swift +44 -0
  174. package/swift/Sources/NipworkerSwift/WorkerMessageView.swift +145 -0
  175. package/dist/NativeBackend.d.ts +0 -53
  176. package/dist/NativeBackend.d.ts.map +0 -1
  177. package/dist/NativeBackend.js +0 -464
  178. package/dist/native.d.ts +0 -29
  179. package/dist/native.d.ts.map +0 -1
  180. package/dist/native.js +0 -273
package/README.md CHANGED
@@ -1,118 +1,251 @@
1
1
  # @candypoets/nipworker
2
2
 
3
- A high-performance Nostr client library that moves everything off the main thread and becomes your entire application state layer.
3
+ NIPWorker is one Nostr SDK across platforms: web, React Native, native integrations, and relay proxy
4
+ tooling. It gives applications the same core model for subscribing, publishing, caching, parsing,
5
+ signing, and tracking relay state without making every app rebuild the protocol layer.
6
+
7
+ It is highly optimized and opinionated, but still lightweight at the API surface. NIPWorker pushes
8
+ relay I/O, parsing, cache work, and signing into Rust-backed workers or native engines, then exposes
9
+ small TypeScript entry points, framework-agnostic callback helpers, generated FlatBuffers views, and
10
+ signer integration.
11
+
12
+ It is built for Nostr clients with real feeds and long-lived sessions: social apps, wallets,
13
+ messaging clients, media browsers, dashboards, and any interface that has to keep many relay
14
+ connections active while rendering quickly. If your app only needs to fetch a handful of events,
15
+ `nostr-tools` may be enough. If your app needs a fast reusable Nostr runtime across platforms,
16
+ NIPWorker is meant for that layer.
4
17
 
5
18
  [![npm version](https://badge.fury.io/js/@candypoets%2Fnipworker.svg)](https://badge.fury.io/js/@candypoets%2Fnipworker)
6
19
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
20
 
8
- ## What is NIPWorker?
21
+ ## Platforms
22
+
23
+ | Platform | Support | Entry point |
24
+ | --- | --- | --- |
25
+ | Web apps | Supported with Web Workers and Rust WASM. | `@candypoets/nipworker` |
26
+ | Vite apps | Supported; proxy helpers are available for local or server-side relay routing. | `@candypoets/nipworker`, `@candypoets/nipworker/proxy/vite` |
27
+ | React Native | Supported through the native backend. | `@candypoets/nipworker/react-native` |
28
+ | Node.js servers | Supported for relay proxy server utilities; the main client runtime targets app environments. | `@candypoets/nipworker/proxy/server` |
29
+ | Swift/native integrations | Native artifacts and Swift package sources are included in this repository. | `swift/` package sources |
9
30
 
10
- Big, opinionated, and built for speed. FlatBuffers and Web Workers at its core, compiled from Rust to WASM.
31
+ The browser API is framework-agnostic. It can be used from React, Svelte, Vue, Solid, vanilla
32
+ TypeScript, or any environment that can run module workers and WASM.
11
33
 
12
- ## Framework Agnostic
34
+ ## Install
13
35
 
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.
36
+ ```bash
37
+ npm install @candypoets/nipworker flatbuffers
38
+ ```
15
39
 
16
- ## 4 Dedicated Workers
40
+ Optional peer dependencies:
17
41
 
18
- **Connections** Relay connections, WebSocket lifecycle, reconnection backoff. Owns all network I/O.
42
+ - `vite` for browser builds and the Vite relay proxy plugin.
43
+ - `ws` for the relay proxy server.
44
+ - `react-native` for the React Native native backend.
19
45
 
20
- **Cache** — Stores FlatBuffers in ring buffers in real time and IndexedDB in timeout chunks. No refetching what you already have.
46
+ ## Quick Start
21
47
 
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.
48
+ ```ts
49
+ import { createNostrManager, setManager } from '@candypoets/nipworker';
50
+ import { useSubscription, usePublish, isKind1 } from '@candypoets/nipworker/hooks';
51
+ import { fbArray } from '@candypoets/nipworker/utils';
23
52
 
24
- **Crypto** Signing, NIP:04/44 encryption, NIP:46 remote signer sessions, Cashu proof verification.
53
+ const manager = createNostrManager({
54
+ defaultRelays: ['wss://relay.damus.io', 'wss://nos.lol'],
55
+ indexerRelays: ['wss://purplepag.es']
56
+ });
25
57
 
26
- Each worker runs in its own Web Worker. The main thread just orchestrates. Heavy work happens in parallel.
58
+ setManager(manager);
27
59
 
28
- ## FlatBuffers Instead of JSON
60
+ const stop = useSubscription(
61
+ 'home-feed',
62
+ [{ kinds: [1], limit: 50, relays: ['wss://relay.damus.io'] }],
63
+ (message) => {
64
+ const note = isKind1(message);
65
+ if (!note) return;
66
+
67
+ const blocks = fbArray(note, 'contentBlocks');
68
+ renderNote(note, blocks);
69
+ },
70
+ { cacheFirst: true, closeOnEose: false }
71
+ );
29
72
 
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.
73
+ const stopPublish = usePublish(
74
+ 'publish-1',
75
+ { kind: 1, content: 'hello nostr', tags: [] },
76
+ (message) => {
77
+ console.log(message);
78
+ },
79
+ { defaultRelays: ['wss://relay.damus.io'] }
80
+ );
81
+ ```
31
82
 
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.
83
+ The `use*` functions are framework-agnostic callback helpers. They do not depend on React and can be
84
+ adapted to React, Svelte, Vue, Solid, or plain TypeScript state.
33
85
 
34
- ## Apollo-Inspired State Management
86
+ ## Backends
35
87
 
36
- Like Apollo Client, NIPWorker IS your store. You do not need Redux, Zustand, or custom state libraries.
88
+ ### Browser, Multi-Worker
37
89
 
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.
90
+ `createNostrManager()` creates the default browser backend, `NostrManager`. It starts dedicated
91
+ workers for:
39
92
 
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.
93
+ - `connections`: WebSocket relay connections and relay lifecycle.
94
+ - `cache`: cached event storage and cache lookups.
95
+ - `parser`: validation, filtering, pipelines, and FlatBuffers output.
96
+ - `crypto`: signing, NIP-04/NIP-44 operations, NIP-46, and proof verification.
41
97
 
42
- ## Pipeline Architecture
98
+ Workers communicate with `MessageChannel` ports and FlatBuffers messages.
43
99
 
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.
100
+ ### Browser, Single-Worker Engine
45
101
 
46
- ## Opinionated by Design
102
+ Pass `engine: true` to use `EngineManager`, which runs the newer engine inside one WASM worker:
47
103
 
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.
104
+ ```ts
105
+ const manager = createNostrManager({ engine: true });
106
+ setManager(manager);
107
+ ```
49
108
 
50
- Built for clients that need to render thousands of events without dropping frames.
109
+ This keeps the same public manager and hook surface while reducing worker topology.
51
110
 
52
- ## Installation
111
+ ### React Native
53
112
 
54
- ```bash
55
- npm install @candypoets/nipworker
56
- ```
113
+ React Native must import from the native entry point. This path avoids browser WASM worker imports
114
+ and talks to the native module instead.
57
115
 
58
- Install the skill for AI assistance:
116
+ ```ts
117
+ import { createNostrManager, setManager } from '@candypoets/nipworker/react-native';
59
118
 
60
- ```bash
61
- npx skills add candypoets/skills@nipworker
119
+ setManager(
120
+ createNostrManager({
121
+ defaultRelays: ['wss://relay.damus.io'],
122
+ indexerRelays: ['wss://purplepag.es']
123
+ })
124
+ );
62
125
  ```
63
126
 
64
- ## Quick Start
127
+ ## Public Entry Points
128
+
129
+ | Export | Purpose |
130
+ | --- | --- |
131
+ | `@candypoets/nipworker` | Manager factories, manager classes, types, generated FlatBuffers exports. |
132
+ | `@candypoets/nipworker/hooks` | Callback helpers for subscriptions, publishing, signing, and relay status. |
133
+ | `@candypoets/nipworker/utils` | FlatBuffers helpers, type guards, content parsing, NIP-46 QR helper. |
134
+ | `@candypoets/nipworker/proxy` | Browser proxy client. |
135
+ | `@candypoets/nipworker/proxy/server` | Node relay proxy server. |
136
+ | `@candypoets/nipworker/proxy/vite` | Vite plugin for relay proxy integration. |
137
+ | `@candypoets/nipworker/react-native` | React Native native backend. |
138
+ | `@candypoets/nipworker/engine` | Engine entry point. |
139
+ | `@candypoets/nipworker/legacy` | Legacy compatibility entry point. |
140
+
141
+ ## Signers
142
+
143
+ The manager supports several signer modes:
144
+
145
+ ```ts
146
+ manager.setSigner('privkey', '<hex-secret-key>');
147
+ manager.setNip07();
148
+ manager.setNip46Bunker('<bunker-url>');
149
+ manager.setNip46QR('<nostrconnect-url>');
150
+ manager.setPubkey('<readonly-pubkey>');
151
+ ```
65
152
 
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';
153
+ `useSignEvent(template, callback)` signs through the active signer.
70
154
 
71
- // Create and set the global manager
72
- const manager = createNostrManager();
73
- setManager(manager);
155
+ ## Subscription Options
156
+
157
+ Subscriptions accept relay requests plus options for cache behavior, lifecycle, and pipeline control:
74
158
 
75
- // Subscribe to events
76
- const unsubscribe = useSubscription(
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);
85
- }
86
- }
159
+ ```ts
160
+ useSubscription(
161
+ 'profile',
162
+ [{ kinds: [0], authors: [pubkey], relays: ['wss://purplepag.es'], limit: 1 }],
163
+ onMessage,
164
+ {
165
+ cacheFirst: true,
166
+ cacheOnly: false,
167
+ closeOnEose: true,
168
+ timeoutMs: 5000,
169
+ bytesPerEvent: 4096
170
+ }
87
171
  );
88
172
  ```
89
173
 
174
+ Useful request flags include `cacheFirst`, `noCache`, `closeOnEOSE`, `count`, `maxRelays`, and
175
+ `noOptimize`.
176
+
177
+ ## FlatBuffers and Data Movement
178
+
179
+ NIPWorker uses FlatBuffers for worker messages and parsed event data. Components can read directly
180
+ from generated FlatBuffers views and use helpers such as `fbArray()` and `fbIterable()` for vector
181
+ fields.
182
+
183
+ Within JavaScript worker-to-worker paths, buffers are transferred with `postMessage(data,
184
+ [transferable])`. Across the JS/WASM boundary, bytes still have to be copied into or out of WASM
185
+ linear memory. FlatBuffers parsing itself avoids object deserialization and allocation-heavy JSON
186
+ work, but this is not strict end-to-end zero-copy across WASM.
187
+
188
+ ## Development
189
+
190
+ Prerequisites:
191
+
192
+ - Node.js 18+
193
+ - Rust 1.70+
194
+ - `wasm-pack`
195
+ - `flatc` for schema generation
196
+
197
+ Common commands:
198
+
199
+ ```bash
200
+ npm run build # Build WASM crates, native artifacts, and TypeScript bundle
201
+ npm run build:crates # Build browser WASM crates only
202
+ npm run build:engine # Build the single-worker engine WASM
203
+ npm run build:native # Build Android and iOS native artifacts
204
+ npm run build:types # Emit TypeScript declarations
205
+ npm test # Run unit tests
206
+ npm run test:e2e # Run Playwright tests
207
+ ```
208
+
209
+ Schema generation:
210
+
211
+ ```bash
212
+ npm run flatc # Rust, TypeScript, and Java generated files
213
+ npm run flatc:rust
214
+ npm run flatc:ts
215
+ npm run flatc:java
216
+ npm run flatc:swift
217
+ ```
218
+
219
+ When editing files in `schemas/`, regenerate the affected FlatBuffers outputs before committing.
220
+
221
+ ## Repository Layout
222
+
223
+ | Path | Purpose |
224
+ | --- | --- |
225
+ | `src/NostrManager.ts` | Default browser multi-worker manager. |
226
+ | `src/EngineManager.ts` | Browser single-worker engine manager. |
227
+ | `src/react-native.ts` | React Native manager and native bridge. |
228
+ | `src/hooks.ts` | Framework-agnostic callback helpers. |
229
+ | `src/types/index.ts` | Public TypeScript types. |
230
+ | `src/lib/` | Shared TypeScript helpers. |
231
+ | `src/generated/` | Generated TypeScript FlatBuffers code. |
232
+ | `src/engine/` | Single-worker Rust WASM engine. |
233
+ | `crates/connections/` | Browser relay connection WASM crate. |
234
+ | `crates/cache/` | Browser cache WASM crate. |
235
+ | `crates/parser/` | Browser parser WASM crate. |
236
+ | `crates/crypto/` | Browser crypto WASM crate. |
237
+ | `crates/core/` | Shared Rust core/generated code. |
238
+ | `crates/native-ffi/` | Native FFI and React Native platform bindings. |
239
+ | `schemas/` | FlatBuffers schemas. |
240
+ | `swift/` | Swift package for native integration. |
241
+
90
242
  ## Supported NIPs
91
243
 
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 |
107
-
108
- ## Documentation
109
-
110
- See [AGENTS.md](AGENTS.md) for detailed architecture documentation.
244
+ The generated schema and parser currently include support for common Nostr event kinds across
245
+ NIP-01, NIP-02, NIP-04, NIP-18, NIP-19, NIP-25, NIP-44, NIP-46, NIP-51, NIP-57, NIP-60, NIP-61, and
246
+ NIP-65, plus newer parsed kinds such as long-form articles, media, polls, live activities, and
247
+ community/group-related events.
111
248
 
112
249
  ## License
113
250
 
114
251
  MIT License - see [LICENSE](LICENSE) for details.
115
-
116
- ---
117
-
118
- Made with ❤️ by [So Tachi](mailto:sotachi@proton.me)
@@ -1,158 +1,21 @@
1
1
  # NIPWorker Native FFI
2
2
 
3
- > **Status: Android and iOS builds verified. HarmonyOS is a skeleton.**
4
- > The TypeScript `createNostrManager()` auto-detects LynxJS and returns `NativeBackend` automatically.
3
+ This crate exposes the Rust `NostrEngine` through a C ABI used by the React Native
4
+ and Swift integrations.
5
5
 
6
- ## Overview
6
+ ## Build Artifacts
7
7
 
8
- `crates/native-ffi` exposes a C API over the Rust `NostrEngine` so that native mobile applications can reuse the same core logic as the WASM/TypeScript builds.
8
+ - Android: `android/build-android-aar.sh` builds `libnipworker_native_ffi.so`
9
+ for supported ABIs and places them under `android/src/main/jniLibs`.
10
+ - iOS/macOS: `ios/build-ios.sh` builds `NipworkerNativeFFI.xcframework`.
9
11
 
10
- ```c
11
- void* nipworker_init(void (*callback)(void* userdata, const uint8_t* ptr, size_t len), void* userdata);
12
- void nipworker_handle_message(void* handle, const uint8_t* ptr, size_t len);
13
- void nipworker_set_private_key(void* handle, const char* ptr);
14
- void nipworker_deinit(void* handle);
15
- void nipworker_free_bytes(uint8_t* ptr, size_t len);
16
- ```
12
+ The React Native package consumes these artifacts from
13
+ `crates/native-ffi/react-native`. The Swift package consumes the iOS
14
+ XCFramework through `swift/Package.swift`.
17
15
 
18
- The TypeScript side provides `NativeBackend` (`src/NativeBackend.ts`) which implements the same public interface as `EngineManager` / `NostrManager` and communicates with the native code through a Lynx module named `NipworkerLynxModule`.
16
+ ## API Ownership
19
17
 
20
- ## Quick Start for LynxJS Developers
21
-
22
- ```typescript
23
- import { createNostrManager, setManager } from '@candypoets/nipworker';
24
-
25
- // Auto-detects Lynx native module, WASM engine, or legacy 4-worker
26
- const backend = createNostrManager();
27
- setManager(backend);
28
- ```
29
-
30
- `createNostrManager()` detects the runtime in this order:
31
- 1. `globalThis.lynx.getNativeModules().NipworkerLynxModule` exists → `NativeBackend`
32
- 2. `config.engine === true` → `EngineManager` (single WASM worker)
33
- 3. Otherwise → `NostrManager` (legacy 4-worker WASM)
34
-
35
- ## Pre-built Binaries
36
-
37
- Every git tag `v*` triggers a [GitHub Actions workflow](../../.github/workflows/native-build.yml) that builds and attaches native libraries to the release:
38
-
39
- | Platform | Artifact | Download |
40
- |----------|----------|----------|
41
- | **Android** | `nipworker-native-ffi-android-release.aar` | GitHub Release attachments |
42
- | **iOS** | `nipworker-native-ios.zip` (XCFramework) | GitHub Release attachments |
43
- | **Linux** | `nipworker-native-linux.zip` | GitHub Release attachments |
44
-
45
- ## Platform Integration
46
-
47
- ### Android
48
-
49
- The Android artifact is a first-class AAR that contains:
50
- - `com.candypoets.nipworker.lynx.NipworkerLynxModule`
51
- - `libnipworker_native_ffi.so` for `arm64-v8a`, `armeabi-v7a`, `x86`, and `x86_64`
52
- - consumer ProGuard/R8 keep rules for the native module and JNI methods
53
-
54
- **Maven integration:**
55
- ```kotlin
56
- implementation("com.candypoets:nipworker-native-ffi-android:0.96.0")
57
- ```
58
-
59
- Register the module in your Sparkling/Lynx setup:
60
- ```kotlin
61
- "NipworkerLynxModule" to SparklingLynxModuleWrapper(
62
- NipworkerLynxModule::class.java,
63
- null
64
- )
65
- ```
66
-
67
- The AAR declares Lynx/Sparkling APIs as compile-only. The host app is expected to provide the real Lynx runtime.
68
-
69
- **Local monorepo / `node_modules` fallback:**
70
- ```kotlin
71
- include(":nipworker-native-ffi-android")
72
- project(":nipworker-native-ffi-android").projectDir =
73
- file("../node_modules/@candypoets/nipworker/crates/native-ffi/android")
74
- ```
75
-
76
- Then depend on it from the app:
77
- ```kotlin
78
- implementation(project(":nipworker-native-ffi-android"))
79
- ```
80
-
81
- **Local build (requires Android NDK):**
82
- ```bash
83
- cd crates/native-ffi/android
84
- ./build-android-aar.sh
85
- ./validate-aar.sh
86
- ```
87
-
88
- `build-android-aar.sh` builds Rust with `cargo-ndk --release`, copies all four ABI outputs into `src/main/jniLibs`, strips release symbols when `llvm-strip` is available, and runs `assembleRelease`.
89
-
90
- ### iOS
91
-
92
- **Files you need:**
93
- - `ios/LynxNipworkerModule.mm` — Objective-C++ Lynx module
94
- - `NipworkerNativeFFI.xcframework` — built from this crate
95
-
96
- **Integration steps:**
97
- 1. Download `nipworker-native-ios.zip` from the GitHub Release (or build locally on macOS).
98
- 2. Drag `NipworkerNativeFFI.xcframework` into your Xcode project.
99
- 3. In **Frameworks, Libraries, and Embedded Content**, set it to **Embed & Sign**.
100
- 4. Copy `crates/native-ffi/ios/LynxNipworkerModule.mm` into your Xcode project.
101
- 5. Register the module:
102
- ```objc
103
- [globalConfig registerModule:NipworkerLynxModule.class];
104
- ```
105
-
106
- **Local build (requires macOS + Xcode + Rust):**
107
- ```bash
108
- cd crates/native-ffi/ios
109
- ./build-ios.sh
110
- ```
111
-
112
- This produces:
113
- - `ios/libnipworker_native_ffi.a` — universal static library for CocoaPods
114
- - `ios/NipworkerNativeFFI.xcframework` — modern XCFramework for manual Xcode integration
115
-
116
- ### HarmonyOS
117
-
118
- * **Language:** ArkTS
119
- * **Registration:** `this.modules.set('NipworkerLynxModule', { moduleClass: NipworkerLynxModule })`
120
- * **Linking:** Not yet implemented. ArkTS cannot call C directly without a NAPI/FFI bridge.
121
- * **Build steps (future):**
122
- 1. Write a NAPI C++ addon that wraps the 5 C functions above.
123
- 2. Build the addon into an `.so` shipped with the HarmonyOS app.
124
- 3. Replace the `TODO` stubs in `LynxNipworkerModule.ets` with actual NAPI calls.
125
-
126
- ## Architecture
127
-
128
- ```
129
- ┌─────────────────────────────────────────────────────────────┐
130
- │ TypeScript App (LynxJS) │
131
- │ createNostrManager() → NativeBackend │
132
- │ │ │
133
- │ ▼ │
134
- │ ┌─────────────────────────────────────┐ │
135
- │ │ NativeBackend.ts │ │
136
- │ │ calls lynx.getNativeModules()... │ │
137
- │ └─────────────────────────────────────┘ │
138
- │ │ │
139
- │ ▼ │
140
- │ ┌─────────────────────────────────────┐ │
141
- │ │ Platform wrapper │ │
142
- │ │ Android: Kotlin + JNI C bridge │ │
143
- │ │ iOS: Objective-C++ │ │
144
- │ └─────────────────────────────────────┘ │
145
- │ │ │
146
- │ ▼ │
147
- │ ┌─────────────────────────────────────┐ │
148
- │ │ Rust: libnipworker_native_ffi.so/.a │ │
149
- │ │ C ABI → NostrEngine orchestrator │ │
150
- │ └─────────────────────────────────────┘ │
151
- └─────────────────────────────────────────────────────────────┘
152
- ```
153
-
154
- ## Known limitations
155
-
156
- * NIP-07 (browser extension) is not applicable in native mobile contexts and will warn at runtime.
157
- * NIP-46 (remote signer) is declared as a skeleton; full proxy-signer callbacks from the Rust engine are not yet wired through the C FFI.
158
- * Wake/visibility messages are not yet forwarded to the native engine.
18
+ Subscription and publish buffers are owned by Rust. Native hosts should create
19
+ subscriptions and publishes through `nipworker_subscribe_message` and
20
+ `nipworker_publish_message`, then read buffer pointers with
21
+ `nipworker_subscription_buffer_ptr` / `nipworker_subscription_buffer_len`.
@@ -1,56 +1,10 @@
1
- # Nipworker iOS Native Module
1
+ # NIPWorker iOS Native FFI
2
2
 
3
- ## Prerequisites
4
-
5
- - macOS with Xcode 15+
6
- - Rust toolchain with Apple targets:
7
- ```bash
8
- rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
9
- rustup target add aarch64-apple-darwin x86_64-apple-darwin
10
- ```
11
-
12
- ## Build
13
-
14
- From this directory, run the build script:
3
+ Run:
15
4
 
16
5
  ```bash
17
6
  ./build-ios.sh
18
7
  ```
19
8
 
20
- This script:
21
- 1. Builds `libnipworker_native_ffi.a` for iOS device, iOS simulator, and macOS
22
- 2. Creates universal simulator and macOS binaries with `lipo`
23
- 3. Creates `NipworkerNativeFFI.xcframework`
24
-
25
- By default, the script builds with `IPHONEOS_DEPLOYMENT_TARGET=14.0` and
26
- `MACOSX_DEPLOYMENT_TARGET=11.0`. Override either environment variable before
27
- running the script if the consuming package raises its minimum supported OS.
28
-
29
- ## CocoaPods integration
30
-
31
- The `Nipworker.podspec` in this directory references `libnipworker_native_ffi.a`.
32
- Make sure you ran `./build-ios.sh` first so the static library exists.
33
-
34
- In your app's `Podfile`:
35
- ```ruby
36
- pod 'Nipworker', :path => '../node_modules/@candypoets/nipworker/crates/native-ffi/ios'
37
- ```
38
-
39
- Then run:
40
- ```bash
41
- cd ios && pod install
42
- ```
43
-
44
- ## Manual Xcode integration (no CocoaPods)
45
-
46
- Drag `NipworkerNativeFFI.xcframework` into your Xcode project.
47
- In **Frameworks, Libraries, and Embedded Content**, set it to **Embed & Sign**.
48
- Also add `LynxNipworkerModule.h` and `LynxNipworkerModule.mm` to your build target.
49
-
50
- ## Registration
51
-
52
- The module is automatically registered by CocoaPods via the `LynxModule` protocol. No manual `[LynxEnv registerModule:]` call is required unless you prefer to do it in your `AppDelegate`.
53
-
54
- ```objc
55
- [globalConfig registerModule:NipworkerLynxModule.class];
56
- ```
9
+ This builds `NipworkerNativeFFI.xcframework` for iOS device, iOS simulator, and
10
+ macOS. React Native iOS and the Swift package both link this XCFramework.
@@ -14,7 +14,11 @@ setManager(manager);
14
14
 
15
15
  ## Event Transport
16
16
 
17
- The current legacy React Native bridge receives native events as:
17
+ The React Native entry point installs a JSI byte runtime when possible. Rust owns
18
+ subscription and publish buffers; JS receives a small wake event and drains
19
+ callback packets from native memory.
20
+
21
+ Fallback bridge events use:
18
22
 
19
23
  ```ts
20
24
  {
@@ -24,11 +28,7 @@ The current legacy React Native bridge receives native events as:
24
28
  }
25
29
  ```
26
30
 
27
- The JS entry point decodes those events and routes them through the shared
28
- `NativeBackend`. Outgoing `handleMessage` calls pass `number[]` payloads for the
29
- same reason: this legacy React Native native module does not expose a direct
30
- `ArrayBuffer` transport. A future JSI/TurboModule backend should replace the
31
- array bridge with direct `ArrayBuffer`/native-buffer access.
31
+ The fallback path decodes those events in `ReactNativeManager`.
32
32
 
33
33
  ## TurboModule Experiment
34
34
 
@@ -42,7 +42,8 @@ JSI runtime object:
42
42
 
43
43
  ```ts
44
44
  installByteRuntime(): boolean
45
- globalThis.__nipworkerReactNativeByteRuntime.handleMessage(bytes: ArrayBuffer): void
45
+ globalThis.__nipworkerReactNativeByteRuntime.subscribe(bytes: ArrayBuffer, subId: string): ArrayBuffer
46
+ globalThis.__nipworkerReactNativeByteRuntime.publish(bytes: ArrayBuffer, publishId: string): ArrayBuffer
46
47
  ```
47
48
 
48
49
  The installer keeps the codegen surface on officially supported types while the
@@ -70,4 +70,5 @@ android {
70
70
 
71
71
  dependencies {
72
72
  implementation 'com.facebook.react:react-android'
73
+ api 'com.google.flatbuffers:flatbuffers-java:25.2.10'
73
74
  }