@nostrify/nostrify 0.46.4

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 (182) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/BunkerURI.test.ts +28 -0
  3. package/BunkerURI.ts +58 -0
  4. package/CHANGELOG.md +562 -0
  5. package/LICENSE +21 -0
  6. package/NBrowserSigner.test.ts +170 -0
  7. package/NBrowserSigner.ts +100 -0
  8. package/NCache.bench.ts +81 -0
  9. package/NCache.test.ts +22 -0
  10. package/NCache.ts +73 -0
  11. package/NConnectSigner.test.ts +102 -0
  12. package/NConnectSigner.ts +189 -0
  13. package/NIP05.test.ts +67 -0
  14. package/NIP05.ts +52 -0
  15. package/NIP50.test.ts +58 -0
  16. package/NIP50.ts +24 -0
  17. package/NIP98.test.ts +181 -0
  18. package/NIP98.ts +97 -0
  19. package/NKinds.test.ts +42 -0
  20. package/NKinds.ts +26 -0
  21. package/NPool.test.ts +117 -0
  22. package/NPool.ts +224 -0
  23. package/NRelay1.test.ts +174 -0
  24. package/NRelay1.ts +440 -0
  25. package/NSchema.test.ts +94 -0
  26. package/NSchema.ts +255 -0
  27. package/NSecSigner.bench.ts +55 -0
  28. package/NSecSigner.test.ts +26 -0
  29. package/NSecSigner.ts +60 -0
  30. package/NSet.bench.ts +10 -0
  31. package/NSet.test.ts +92 -0
  32. package/NSet.ts +203 -0
  33. package/README.md +314 -0
  34. package/RelayError.test.ts +23 -0
  35. package/RelayError.ts +22 -0
  36. package/dist/BunkerURI.d.ts +23 -0
  37. package/dist/BunkerURI.d.ts.map +1 -0
  38. package/dist/BunkerURI.js +52 -0
  39. package/dist/BunkerURI.js.map +1 -0
  40. package/dist/NBrowserSigner.d.ts +27 -0
  41. package/dist/NBrowserSigner.d.ts.map +1 -0
  42. package/dist/NBrowserSigner.js +96 -0
  43. package/dist/NBrowserSigner.js.map +1 -0
  44. package/dist/NCache.d.ts +34 -0
  45. package/dist/NCache.d.ts.map +1 -0
  46. package/dist/NCache.js +63 -0
  47. package/dist/NCache.js.map +1 -0
  48. package/dist/NConnectSigner.d.ts +50 -0
  49. package/dist/NConnectSigner.d.ts.map +1 -0
  50. package/dist/NConnectSigner.js +130 -0
  51. package/dist/NConnectSigner.js.map +1 -0
  52. package/dist/NIP05.d.ts +15 -0
  53. package/dist/NIP05.d.ts.map +1 -0
  54. package/dist/NIP05.js +40 -0
  55. package/dist/NIP05.js.map +1 -0
  56. package/dist/NIP50.d.ts +10 -0
  57. package/dist/NIP50.d.ts.map +1 -0
  58. package/dist/NIP50.js +26 -0
  59. package/dist/NIP50.js.map +1 -0
  60. package/dist/NIP98.d.ts +15 -0
  61. package/dist/NIP98.d.ts.map +1 -0
  62. package/dist/NIP98.js +71 -0
  63. package/dist/NIP98.js.map +1 -0
  64. package/dist/NKinds.d.ts +13 -0
  65. package/dist/NKinds.d.ts.map +1 -0
  66. package/dist/NKinds.js +27 -0
  67. package/dist/NKinds.js.map +1 -0
  68. package/dist/NPool.d.ts +91 -0
  69. package/dist/NPool.d.ts.map +1 -0
  70. package/dist/NPool.js +185 -0
  71. package/dist/NPool.js.map +1 -0
  72. package/dist/NRelay1.d.ts +80 -0
  73. package/dist/NRelay1.d.ts.map +1 -0
  74. package/dist/NRelay1.js +336 -0
  75. package/dist/NRelay1.js.map +1 -0
  76. package/dist/NSchema.d.ts +73 -0
  77. package/dist/NSchema.d.ts.map +1 -0
  78. package/dist/NSchema.js +215 -0
  79. package/dist/NSchema.js.map +1 -0
  80. package/dist/NSecSigner.d.ts +29 -0
  81. package/dist/NSecSigner.d.ts.map +1 -0
  82. package/dist/NSecSigner.js +52 -0
  83. package/dist/NSecSigner.js.map +1 -0
  84. package/dist/NSet.d.ts +76 -0
  85. package/dist/NSet.d.ts.map +1 -0
  86. package/dist/NSet.js +174 -0
  87. package/dist/NSet.js.map +1 -0
  88. package/dist/RelayError.d.ts +10 -0
  89. package/dist/RelayError.d.ts.map +1 -0
  90. package/dist/RelayError.js +23 -0
  91. package/dist/RelayError.js.map +1 -0
  92. package/dist/ln/LNURL.d.ts +55 -0
  93. package/dist/ln/LNURL.d.ts.map +1 -0
  94. package/dist/ln/LNURL.js +105 -0
  95. package/dist/ln/LNURL.js.map +1 -0
  96. package/dist/ln/mod.d.ts +4 -0
  97. package/dist/ln/mod.d.ts.map +1 -0
  98. package/dist/ln/mod.js +6 -0
  99. package/dist/ln/mod.js.map +1 -0
  100. package/dist/ln/types/LNURLCallback.d.ts +8 -0
  101. package/dist/ln/types/LNURLCallback.d.ts.map +1 -0
  102. package/dist/ln/types/LNURLCallback.js +3 -0
  103. package/dist/ln/types/LNURLCallback.js.map +1 -0
  104. package/dist/ln/types/LNURLDetails.d.ts +20 -0
  105. package/dist/ln/types/LNURLDetails.d.ts.map +1 -0
  106. package/dist/ln/types/LNURLDetails.js +3 -0
  107. package/dist/ln/types/LNURLDetails.js.map +1 -0
  108. package/dist/mod.d.ts +16 -0
  109. package/dist/mod.d.ts.map +1 -0
  110. package/dist/mod.js +32 -0
  111. package/dist/mod.js.map +1 -0
  112. package/dist/test/ErrorRelay.d.ts +21 -0
  113. package/dist/test/ErrorRelay.d.ts.map +1 -0
  114. package/dist/test/ErrorRelay.js +26 -0
  115. package/dist/test/ErrorRelay.js.map +1 -0
  116. package/dist/test/MockRelay.d.ts +20 -0
  117. package/dist/test/MockRelay.d.ts.map +1 -0
  118. package/dist/test/MockRelay.js +66 -0
  119. package/dist/test/MockRelay.js.map +1 -0
  120. package/dist/test/TestRelayServer.d.ts +25 -0
  121. package/dist/test/TestRelayServer.d.ts.map +1 -0
  122. package/dist/test/TestRelayServer.js +134 -0
  123. package/dist/test/TestRelayServer.js.map +1 -0
  124. package/dist/test/mod.d.ts +8 -0
  125. package/dist/test/mod.d.ts.map +1 -0
  126. package/dist/test/mod.js +28 -0
  127. package/dist/test/mod.js.map +1 -0
  128. package/dist/tsconfig.tsbuildinfo +1 -0
  129. package/dist/uploaders/BlossomUploader.d.ts +26 -0
  130. package/dist/uploaders/BlossomUploader.d.ts.map +1 -0
  131. package/dist/uploaders/BlossomUploader.js +71 -0
  132. package/dist/uploaders/BlossomUploader.js.map +1 -0
  133. package/dist/uploaders/NostrBuildUploader.d.ts +24 -0
  134. package/dist/uploaders/NostrBuildUploader.d.ts.map +1 -0
  135. package/dist/uploaders/NostrBuildUploader.js +67 -0
  136. package/dist/uploaders/NostrBuildUploader.js.map +1 -0
  137. package/dist/uploaders/mod.d.ts +3 -0
  138. package/dist/uploaders/mod.d.ts.map +1 -0
  139. package/dist/uploaders/mod.js +8 -0
  140. package/dist/uploaders/mod.js.map +1 -0
  141. package/dist/utils/CircularSet.d.ts +13 -0
  142. package/dist/utils/CircularSet.d.ts.map +1 -0
  143. package/dist/utils/CircularSet.js +35 -0
  144. package/dist/utils/CircularSet.js.map +1 -0
  145. package/dist/utils/Machina.d.ts +36 -0
  146. package/dist/utils/Machina.d.ts.map +1 -0
  147. package/dist/utils/Machina.js +66 -0
  148. package/dist/utils/Machina.js.map +1 -0
  149. package/dist/utils/N64.d.ts +9 -0
  150. package/dist/utils/N64.d.ts.map +1 -0
  151. package/dist/utils/N64.js +23 -0
  152. package/dist/utils/N64.js.map +1 -0
  153. package/dist/utils/mod.d.ts +3 -0
  154. package/dist/utils/mod.d.ts.map +1 -0
  155. package/dist/utils/mod.js +8 -0
  156. package/dist/utils/mod.js.map +1 -0
  157. package/ln/LNURL.test.ts +87 -0
  158. package/ln/LNURL.ts +146 -0
  159. package/ln/mod.ts +4 -0
  160. package/ln/types/LNURLCallback.ts +7 -0
  161. package/ln/types/LNURLDetails.ts +19 -0
  162. package/mod.ts +16 -0
  163. package/package.json +23 -0
  164. package/test/ErrorRelay.test.ts +19 -0
  165. package/test/ErrorRelay.ts +40 -0
  166. package/test/MockRelay.test.ts +20 -0
  167. package/test/MockRelay.ts +92 -0
  168. package/test/TestRelayServer.ts +156 -0
  169. package/test/mod.ts +28 -0
  170. package/tsconfig.json +14 -0
  171. package/uploaders/BlossomUploader.test.ts +26 -0
  172. package/uploaders/BlossomUploader.ts +98 -0
  173. package/uploaders/NostrBuildUploader.test.ts +22 -0
  174. package/uploaders/NostrBuildUploader.ts +89 -0
  175. package/uploaders/mod.ts +2 -0
  176. package/utils/CircularSet.test.ts +15 -0
  177. package/utils/CircularSet.ts +34 -0
  178. package/utils/Machina.test.ts +91 -0
  179. package/utils/Machina.ts +66 -0
  180. package/utils/N64.test.ts +27 -0
  181. package/utils/N64.ts +23 -0
  182. package/utils/mod.ts +2 -0
package/README.md ADDED
@@ -0,0 +1,314 @@
1
+ # Nostrify
2
+
3
+ Bring your projects to life on Nostr. 🌱
4
+
5
+ Nostrify is a Nostr framework for web browsers and Deno. It's made up of of simple modules that can be used independently, or swapped out with your own implementations.
6
+
7
+ Use it alongside nostr-tools, NDK, or your existing application. Nostrify can be gradually adopted and plays nice with others.
8
+
9
+ ## Schema
10
+
11
+ A suite of [zod](https://github.com/colinhacks/zod) schemas for Nostr are available in the `NSchema` module.
12
+
13
+ ```ts
14
+ import { NSchema as n } from '@nostrify/nostrify';
15
+
16
+ const event: NostrEvent = n.event().parse(eventData);
17
+ const metadata: NostrMetadata = n.json().pipe(n.metadata()).parse(event.content);
18
+ const msg: NostrRelayMsg = n.relayMsg().parse(e.data);
19
+ const nsec: `nsec1${string}` = n.bech32('nsec').parse(token);
20
+ ```
21
+
22
+ ## Storages
23
+
24
+ Storages (implementing the `NStore` interface) allow interacting with Nostr events.
25
+ A database is a Storage. A relay is a Storage. A cache is a Storage.
26
+ It should be possible to use Nostr storages interchangeably to get the best performance.
27
+
28
+ ### `NStore` interface
29
+
30
+ `NStore` is the interface that all Nostr Storages implement.
31
+
32
+ ```ts
33
+ /** Nostr event store. */
34
+ interface NStore {
35
+ /** Add an event to the store (equivalent of `EVENT` verb). */
36
+ event(event: NostrEvent, opts?: NStoreOpts): Promise<void>;
37
+ /** Get an array of events matching filters. */
38
+ query(filters: NostrFilter[], opts?: NStoreOpts): Promise<NostrEvent[]>;
39
+ /** Get the number of events matching filters (equivalent of `COUNT` verb). */
40
+ count?(filters: NostrFilter[], opts?: NStoreOpts): Promise<NostrRelayCOUNT[2]>;
41
+ /** Remove events from the store. This action is temporary, unless a kind `5` deletion is issued. */
42
+ remove?(filters: NostrFilter[], opts?: NStoreOpts): Promise<void>;
43
+ }
44
+ ```
45
+
46
+ ### `NCache` class
47
+
48
+ Nostr LRU cache based on [`npm:lru-cache`](https://www.npmjs.com/package/lru-cache).
49
+ It implements both `NStore` and `NSet` interfaces.
50
+
51
+ ```ts
52
+ // Accepts the options of `npm:lru-cache`:
53
+ const cache = new NCache({ max: 1000 });
54
+
55
+ // Events can be added like a regular `Set`:
56
+ cache.add(event1);
57
+ cache.add(event2);
58
+
59
+ // Can be queried like `NStore`:
60
+ const events = await cache.query([{ kinds: [1] }]);
61
+
62
+ // Can be iterated like `NSet`:
63
+ for (const event of cache) {
64
+ console.log(event);
65
+ }
66
+ ```
67
+
68
+ ### `NDatabase` class
69
+
70
+ SQLite database storage adapter for Nostr events.
71
+ It uses [Kysely](https://kysely.dev/) to make queries, making it flexible for a variety of use-cases.
72
+
73
+ ```ts
74
+ // Create a Kysely instance.
75
+ const kysely = new Kysely({
76
+ dialect: new DenoSqliteDialect({
77
+ database: new Sqlite('./db.sqlite3'),
78
+ }),
79
+ });
80
+
81
+ // Pass Kysely into the constructor.
82
+ const db = new NDatabase(kysely);
83
+
84
+ // Migrate the database before use.
85
+ await db.migrate();
86
+
87
+ // Now it's just a regular storage.
88
+ await db.event(event1);
89
+ await db.event(event2);
90
+ const events = await db.query([{ kinds: [1] }]);
91
+ ```
92
+
93
+ ### `NSet` class (not really a storage)
94
+
95
+ Nostr event implementation of the `Set` interface.
96
+
97
+ NSet is an implementation of the theory that a Nostr Storage is actually just a Set.
98
+ Events are Nostr's only data type, and they are immutable, making the Set interface ideal.
99
+
100
+ ```ts
101
+ const events = new NSet();
102
+
103
+ // Events can be added like a regular `Set`:
104
+ events.add(event1);
105
+ events.add(event2);
106
+
107
+ // Can be iterated:
108
+ for (const event of events) {
109
+ if (matchFilters(filters, event)) {
110
+ console.log(event);
111
+ }
112
+ }
113
+ ```
114
+
115
+ `NSet` will handle kind `5` deletions, removing events from the set.
116
+ Replaceable (and parameterized) events will keep only the newest version.
117
+ However, verification of `id` and `sig` is NOT performed.
118
+
119
+ Any `Map` instance can be passed into `new NSet()`, making it compatible with
120
+ [lru-cache](https://www.npmjs.com/package/lru-cache), among others.
121
+
122
+ ## Relays
123
+
124
+ Relays are an extended form of Storage with real-time streaming capabilities.
125
+
126
+ ### `NRelay` interface
127
+
128
+ `NRelay` implements all the methods of `NStore`, including a `req` method for streaming events.
129
+
130
+ ```ts
131
+ interface NRelay extends NStore {
132
+ /** Subscribe to events matching the given filters. Returns an iterator of raw NIP-01 relay messages. */
133
+ req(filters: NostrFilter[], opts?: NReqOpts): AsyncIterable<NostrRelayEVENT | NostrRelayEOSE | NostrRelayCLOSED>;
134
+ }
135
+ ```
136
+
137
+ The `req` method returns raw NIP-01 relay messages, but only those pertaining to subscriptions: `EVENT`, `EOSE`, and `CLOSED`.
138
+
139
+ Other messages such as `COUNT` and `OK` are handled internally by `NStore` methods:
140
+
141
+ - `NRelay.event` - sends an `EVENT` and waits for an `OK`. If the `OK` is false, an error is thrown with the reason as its message.
142
+ - `NRelay.query` - calls `NRelay.req` internally, closing the subscription automatically on `EOSE`.
143
+ - `NRelay.count` - sends a `COUNT` and waits for the response `COUNT`.
144
+ - `NRelay.remove` - not applicable.
145
+
146
+ Other notes:
147
+
148
+ - `AUTH` is not part of the interface, and should be handled by the implementation using an option in the constructor (see the `NRelay` class below).
149
+ - Using a `break` statement in the `req` loop will close the subscription automatically, sending a `CLOSE` message to the relay. This works thanks to special treatment of `try...finally` blocks by AsyncIterables.
150
+ - Passing an `AbortSignal` into the `req` method will also close the subscription automatically when the signal aborts, sending a `CLOSE` message.
151
+
152
+ ### `NRelay1` class
153
+
154
+ The main `NRelay` implementation for connecting to one relay.
155
+ Instantiate it with a WebSocket URL, and then loop over the messages:
156
+
157
+ ```ts
158
+ const relay = new NRelay1('wss://relay.mostr.pub');
159
+
160
+ for await (const msg of relay.req([{ kinds: [1] }])) {
161
+ if (msg[0] === 'EVENT') console.log(msg[2]);
162
+ if (msg[0] === 'EOSE') break; // Sends a `CLOSE` message to the relay.
163
+ }
164
+ ```
165
+
166
+ If the WebSocket disconnects, it will reconnect automatically thanks to the wonderful [websocket-ts](https://github.com/jjxxs/websocket-ts) library.
167
+ Upon reconnection, it will automatically re-subscribe to all subscriptions.
168
+
169
+ #### `NRelay1Opts` interface
170
+
171
+ All options are optional.
172
+
173
+ - `auth` - A function like `(challenge: string) => Promise<NostrEvent>`. If provided, it will be called whenever the relay sends an `AUTH` message, and then it will send the resulting event back to the relay in an `AUTH` message. If not provided, auth is ignored.
174
+ - `backoff` - A [`Backoff`](https://github.com/jjxxs/websocket-ts/blob/v2.1.5/src/backoff/backoff.ts) object for reconnection attempts, or `false` to disable automatic reconnect. Default is `new ExponentialBackoff(1000)`.
175
+ - `verifyEvent` - Custom event verification function. Default is `nostrTools.verifyEvent`.
176
+
177
+ ### `NPool` class
178
+
179
+ The `NPool` class is a `NRelay` implementation for connecting to multiple relays.
180
+
181
+ ```ts
182
+ const pool = new NPool({
183
+ open: (url) => new NRelay1(url),
184
+ reqRelays: async (filters) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'],
185
+ eventRelays: async (event) => ['wss://relay1.mostr.pub', 'wss://relay2.mostr.pub'],
186
+ });
187
+
188
+ // Now you can use the pool like a regular relay.
189
+ for await (const msg of pool.req([{ kinds: [1] }])) {
190
+ if (msg[0] === 'EVENT') console.log(msg[2]);
191
+ if (msg[0] === 'EOSE') break;
192
+ }
193
+ ```
194
+
195
+ This class is designed with the Outbox model in mind.
196
+ Instead of passing relay URLs into each method, you pass functions into the contructor that statically-analyze filters and events to determine which relays to use for requesting and publishing events.
197
+ If a relay wasn't already connected, it will be opened automatically.
198
+ Defining `open` will also let you use any relay implementation, such as `NRelay1`.
199
+
200
+ Note that `pool.req` may stream duplicate events, while `pool.query` will correctly process replaceable events and deletions within the event set before returning them.
201
+
202
+ `pool.req` will only emit an `EOSE` when all relays in its set have emitted an `EOSE`, and likewise for `CLOSED`.
203
+
204
+ #### `NPoolOpts` interface
205
+
206
+ - `open` - A function like `(url: string) => NRelay`. This function should return a new instance of `NRelay` for the given URL.
207
+
208
+ - `reqRelays` - A function like `(filters: NostrFilter[]) => Promise<string[]>`. This function should return an array of relay URLs to use for making a REQ to the given filters. To support the Outbox model, it should analyze the `authors` field of the filters.
209
+
210
+ - `eventRelays` - A function like `(event: NostrEvent) => Promise<string[]>`. This function should return an array of relay URLs to use for publishing an EVENT. To support the Outbox model, it should analyze the `pubkey` field of the event.
211
+
212
+ Pro-tip: the `url` parameter is a unique relay identifier (string), and doesn't technically _have_ to be a URL, as long as you handle it correctly in your `open` function.
213
+
214
+ ## Signers
215
+
216
+ Signer, like storages, should be usable in an interoperable/composable way.
217
+ The foundation of this is NIP-07.
218
+
219
+ ### `NostrSigner` interface
220
+
221
+ The `NostrSigner` interface is pulled right out of NIP-07.
222
+ This means any signer implementing it can be used as a drop-in replacement for `window.nostr`.
223
+ Since NIP-07 functions don't accept many options, new Signers are created by abusing constructor props.
224
+
225
+ ```ts
226
+ /** NIP-07 Nostr signer. */
227
+ interface NostrSigner {
228
+ /** Returns a public key as hex. */
229
+ getPublicKey(): Promise<string>;
230
+ /** Takes an event template, adds `id`, `pubkey` and `sig` and returns it. */
231
+ signEvent(event: Omit<NostrEvent, 'id' | 'pubkey' | 'sig'>): Promise<NostrEvent>;
232
+ /** Returns a record of relay URLs to relay policies. */
233
+ getRelays?(): Promise<Record<string, { read: boolean; write: boolean }>>;
234
+ /** @deprecated NIP-04 crypto methods. Use `nip44` instead. */
235
+ nip04?: {
236
+ /** @deprecated Returns ciphertext and iv as specified in NIP-04. */
237
+ encrypt(pubkey: string, plaintext: string): Promise<string>;
238
+ /** @deprecated Takes ciphertext and iv as specified in NIP-04. */
239
+ decrypt(pubkey: string, ciphertext: string): Promise<string>;
240
+ };
241
+ /** NIP-44 crypto methods. */
242
+ nip44?: {
243
+ /** Returns ciphertext as specified in NIP-44. */
244
+ encrypt(pubkey: string, plaintext: string): Promise<string>;
245
+ /** Takes ciphertext as specified in NIP-44. */
246
+ decrypt(pubkey: string, ciphertext: string): Promise<string>;
247
+ };
248
+ }
249
+ ```
250
+
251
+ ### `NSecSigner` class
252
+
253
+ NIP-07-compatible signer with secret key. It is a drop-in replacement for `window.nostr`.
254
+
255
+ Usage:
256
+
257
+ ```ts
258
+ const signer = new NSecSigner(secretKey);
259
+ const pubkey = await signer.getPublicKey();
260
+ const event = await signer.signEvent({ kind: 1, content: 'Hello, world!', tags: [], created_at: 0 });
261
+ ```
262
+
263
+ ### `NSeedSigner` class
264
+
265
+ Accepts an HD seed which it uses to derive the secret key according to [NIP-06](https://github.com/nostr-protocol/nips/blob/master/06.md).
266
+ This method is useful for supporting multiple accounts for the same user, or for sharing a Nostr account with a Bitcoin wallet.
267
+
268
+ ```ts
269
+ const signer = new NSeedSigner(seed, 0);
270
+
271
+ signer.getPublicKey();
272
+ signer.signEvent(t);
273
+ ```
274
+
275
+ ### `NPhraseSigner` class
276
+
277
+ Similar to `NSeedSigner`, but accepts a BIP-39 mnemonic phrase which it converts into a seed before usage.
278
+
279
+ ```ts
280
+ const signer = new NPhraseSigner('abandon baby cabbage dad ...', {
281
+ account: 0, // Optional account number. Default is 0.
282
+ passphrase: 'very special mother', // Optional passphrase. Default is no passphrase.
283
+ });
284
+
285
+ signer.getPublicKey();
286
+ signer.signEvent(t);
287
+ ```
288
+
289
+ ### `NCustodial` class
290
+
291
+ Signer manager for multiple users.
292
+ Pass a shared secret into it, then it will generate keys for your users determinstically.
293
+ Useful for custodial auth where you only want to manage one secret for the entire application.
294
+
295
+ ```ts
296
+ const SECRET_KEY = Deno.env.get('SECRET_KEY'); // generate with `openssl rand -base64 48`
297
+ const seed = new TextEncoder().encode(SECRET_KEY);
298
+
299
+ const signers = new NCustodial(seed);
300
+
301
+ const alex = await signers.get('alex');
302
+ const fiatjaf = await signers.get('fiatjaf');
303
+
304
+ alex.getPublicKey();
305
+ fiatjaf.signEvent(t);
306
+ ```
307
+
308
+ ### `NConnectSigner` class
309
+
310
+ TODO
311
+
312
+ ## License
313
+
314
+ MIT
@@ -0,0 +1,23 @@
1
+ import { assertThrows } from '@std/assert';
2
+
3
+ import { RelayError } from './RelayError.ts';
4
+
5
+ Deno.test('Construct a RelayError from the reason message', () => {
6
+ assertThrows(
7
+ () => {
8
+ throw RelayError.fromReason('duplicate: already exists');
9
+ },
10
+ RelayError,
11
+ 'duplicate: already exists',
12
+ );
13
+ });
14
+
15
+ Deno.test('Throw a new RelayError if the OK message is false', () => {
16
+ assertThrows(
17
+ () => {
18
+ RelayError.assert(['OK', 'yolo', false, 'error: bla bla bla']);
19
+ },
20
+ RelayError,
21
+ 'error: bla bla bla',
22
+ );
23
+ });
package/RelayError.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { NostrRelayOK } from '@nostrify/nostrify';
2
+
3
+ /** NIP-01 command line result. */
4
+ export class RelayError extends Error {
5
+ constructor(prefix: string, message: string) {
6
+ super(`${prefix}: ${message}`);
7
+ }
8
+
9
+ /** Construct a RelayError from the reason message. */
10
+ static fromReason(reason: string): RelayError {
11
+ const [prefix, ...rest] = reason.split(': ');
12
+ return new RelayError(prefix, rest.join(': '));
13
+ }
14
+
15
+ /** Throw a new RelayError if the OK message is false. */
16
+ static assert(msg: NostrRelayOK): void {
17
+ const [, , ok, reason] = msg;
18
+ if (!ok) {
19
+ throw RelayError.fromReason(reason);
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,23 @@
1
+ /** Construct a [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md) bunker URI. */
2
+ export declare class BunkerURI {
3
+ /** Remote signer pubkey. */
4
+ pubkey: string;
5
+ /** Relay URLs on which the client is listening for responses from the remote-signer. */
6
+ relays: string[];
7
+ /** A short random string that the remote-signer should return as the `result` field of its response. */
8
+ secret?: string;
9
+ constructor(uri: string);
10
+ /** Convert into a `bunker://` URI string. */
11
+ get href(): string;
12
+ /** Convert into a `bunker://` URI string. */
13
+ toString(): string;
14
+ /** Convert a bunker data object into a `BunkerURI` instance. */
15
+ static fromJSON(data: {
16
+ pubkey: string;
17
+ relays: string[];
18
+ secret?: string;
19
+ }): BunkerURI;
20
+ /** Convert a bunker data object into a bunker URI string. */
21
+ private static toString;
22
+ }
23
+ //# sourceMappingURL=BunkerURI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BunkerURI.d.ts","sourceRoot":"","sources":["../BunkerURI.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,qBAAa,SAAS;IACpB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEJ,GAAG,EAAE,MAAM;IAkBvB,6CAA6C;IAC7C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,6CAA6C;IAC7C,QAAQ,IAAI,MAAM;IAIlB,gEAAgE;IAChE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAKvF,6DAA6D;IAC7D,OAAO,CAAC,MAAM,CAAC,QAAQ;CAaxB"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BunkerURI = void 0;
4
+ /** Construct a [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md) bunker URI. */
5
+ class BunkerURI {
6
+ /** Remote signer pubkey. */
7
+ pubkey;
8
+ /** Relay URLs on which the client is listening for responses from the remote-signer. */
9
+ relays;
10
+ /** A short random string that the remote-signer should return as the `result` field of its response. */
11
+ secret;
12
+ constructor(uri) {
13
+ const url = new URL(uri);
14
+ const params = new URLSearchParams(url.search);
15
+ // https://github.com/denoland/deno/issues/26440
16
+ const pubkey = url.hostname || url.pathname.slice(2);
17
+ const relays = params.getAll('relay');
18
+ const secret = params.get('secret') ?? undefined;
19
+ if (!pubkey) {
20
+ throw new Error('Invalid bunker URI');
21
+ }
22
+ this.pubkey = pubkey;
23
+ this.relays = relays;
24
+ this.secret = secret;
25
+ }
26
+ /** Convert into a `bunker://` URI string. */
27
+ get href() {
28
+ return this.toString();
29
+ }
30
+ /** Convert into a `bunker://` URI string. */
31
+ toString() {
32
+ return BunkerURI.toString(this);
33
+ }
34
+ /** Convert a bunker data object into a `BunkerURI` instance. */
35
+ static fromJSON(data) {
36
+ const uri = BunkerURI.toString(data);
37
+ return new BunkerURI(uri);
38
+ }
39
+ /** Convert a bunker data object into a bunker URI string. */
40
+ static toString(data) {
41
+ const search = new URLSearchParams();
42
+ for (const relay of data.relays) {
43
+ search.append('relay', relay);
44
+ }
45
+ if (data.secret) {
46
+ search.set('secret', data.secret);
47
+ }
48
+ return `bunker://${data.pubkey}?${search.toString()}`;
49
+ }
50
+ }
51
+ exports.BunkerURI = BunkerURI;
52
+ //# sourceMappingURL=BunkerURI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BunkerURI.js","sourceRoot":"","sources":["../BunkerURI.ts"],"names":[],"mappings":";;;AAAA,iGAAiG;AACjG,MAAa,SAAS;IACpB,4BAA4B;IAC5B,MAAM,CAAS;IACf,wFAAwF;IACxF,MAAM,CAAW;IACjB,wGAAwG;IACxG,MAAM,CAAU;IAEhB,YAAY,GAAW;QACrB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE/C,gDAAgD;QAChD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC;QAEjD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,6CAA6C;IAC7C,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAED,6CAA6C;IAC7C,QAAQ;QACN,OAAO,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,QAAQ,CAAC,IAA2D;QACzE,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,6DAA6D;IACrD,MAAM,CAAC,QAAQ,CAAC,IAA2D;QACjF,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,YAAY,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IACxD,CAAC;CACF;AAxDD,8BAwDC"}
@@ -0,0 +1,27 @@
1
+ import type { NostrEvent, NostrSigner } from '@nostrify/types';
2
+ /**
3
+ * NIP-07-compatible signer that proxies to browser extension, normalizing behavior across different implementations.
4
+ *
5
+ * This signer delegates all operations to the browser's `window.nostr` object,
6
+ * which is typically provided by browser extensions like Alby, nos2x, etc.
7
+ *
8
+ * Usage:
9
+ *
10
+ * ```ts
11
+ * const signer = new NBrowserSigner();
12
+ * const pubkey = await signer.getPublicKey();
13
+ * const event = await signer.signEvent({ kind: 1, content: 'Hello, world!', tags: [], created_at: 0 });
14
+ * ```
15
+ */
16
+ export declare class NBrowserSigner implements NostrSigner {
17
+ private get nostr();
18
+ getPublicKey(): Promise<string>;
19
+ signEvent(event: Omit<NostrEvent, 'id' | 'pubkey' | 'sig'>): Promise<NostrEvent>;
20
+ getRelays(): Promise<Record<string, {
21
+ read: boolean;
22
+ write: boolean;
23
+ }>>;
24
+ get nip04(): NostrSigner['nip04'];
25
+ get nip44(): NostrSigner['nip44'];
26
+ }
27
+ //# sourceMappingURL=NBrowserSigner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NBrowserSigner.d.ts","sourceRoot":"","sources":["../NBrowserSigner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,KAAK,KAAK,GAMhB;IAEK,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ/B,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,QAAQ,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAUhF,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAW7E,IAAI,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAqBhC;IAED,IAAI,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,CAqBhC;CACF"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NBrowserSigner = void 0;
4
+ /**
5
+ * NIP-07-compatible signer that proxies to browser extension, normalizing behavior across different implementations.
6
+ *
7
+ * This signer delegates all operations to the browser's `window.nostr` object,
8
+ * which is typically provided by browser extensions like Alby, nos2x, etc.
9
+ *
10
+ * Usage:
11
+ *
12
+ * ```ts
13
+ * const signer = new NBrowserSigner();
14
+ * const pubkey = await signer.getPublicKey();
15
+ * const event = await signer.signEvent({ kind: 1, content: 'Hello, world!', tags: [], created_at: 0 });
16
+ * ```
17
+ */
18
+ class NBrowserSigner {
19
+ get nostr() {
20
+ const nostr = globalThis.nostr;
21
+ if (!nostr) {
22
+ throw new Error('Browser extension not available');
23
+ }
24
+ return nostr;
25
+ }
26
+ async getPublicKey() {
27
+ const pubkey = await this.nostr.getPublicKey();
28
+ if (typeof pubkey !== 'string') {
29
+ throw new Error(`Nostr public key retrieval failed: expected string, got ${JSON.stringify(pubkey)}`);
30
+ }
31
+ return pubkey;
32
+ }
33
+ async signEvent(event) {
34
+ const signed = await this.nostr.signEvent(event);
35
+ if (typeof signed !== 'object' || !signed.id || !signed.pubkey || !signed.sig) {
36
+ throw new Error(`Nostr event signing failed: expected object with id, pubkey, and sig, got ${JSON.stringify(signed)}`);
37
+ }
38
+ return signed;
39
+ }
40
+ async getRelays() {
41
+ if (!this.nostr.getRelays) {
42
+ return {};
43
+ }
44
+ const relays = await this.nostr.getRelays();
45
+ if (typeof relays !== 'object' || relays === null) {
46
+ throw new Error(`Nostr getRelays failed: expected object, got ${JSON.stringify(relays)}`);
47
+ }
48
+ return this.nostr.getRelays();
49
+ }
50
+ get nip04() {
51
+ const nostr = this.nostr;
52
+ if (!nostr.nip04) {
53
+ return undefined;
54
+ }
55
+ return {
56
+ encrypt: async (pubkey, plaintext) => {
57
+ const encrypted = await nostr.nip04.encrypt(pubkey, plaintext);
58
+ if (typeof encrypted !== 'string') {
59
+ throw new Error(`NIP-04 encryption failed: expected string result, got ${JSON.stringify(encrypted)}`);
60
+ }
61
+ return encrypted;
62
+ },
63
+ decrypt: async (pubkey, ciphertext) => {
64
+ const decrypted = await nostr.nip04.decrypt(pubkey, ciphertext);
65
+ if (typeof decrypted !== 'string') {
66
+ throw new Error(`NIP-04 decryption failed: expected string result, got ${JSON.stringify(decrypted)}`);
67
+ }
68
+ return decrypted;
69
+ },
70
+ };
71
+ }
72
+ get nip44() {
73
+ const nostr = this.nostr;
74
+ if (!nostr.nip44) {
75
+ return undefined;
76
+ }
77
+ return {
78
+ encrypt: async (pubkey, plaintext) => {
79
+ const encrypted = await nostr.nip44.encrypt(pubkey, plaintext);
80
+ if (typeof encrypted !== 'string') {
81
+ throw new Error(`NIP-44 encryption failed: expected string result, got ${JSON.stringify(encrypted)}`);
82
+ }
83
+ return encrypted;
84
+ },
85
+ decrypt: async (pubkey, ciphertext) => {
86
+ const decrypted = await nostr.nip44.decrypt(pubkey, ciphertext);
87
+ if (typeof decrypted !== 'string') {
88
+ throw new Error(`NIP-44 decryption failed: expected string result, got ${JSON.stringify(decrypted)}`);
89
+ }
90
+ return decrypted;
91
+ },
92
+ };
93
+ }
94
+ }
95
+ exports.NBrowserSigner = NBrowserSigner;
96
+ //# sourceMappingURL=NBrowserSigner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NBrowserSigner.js","sourceRoot":"","sources":["../NBrowserSigner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { NostrEvent, NostrFilter, NostrRelayCOUNT, NStore } from '@nostrify/types';
2
+ import { LRUCache } from 'lru-cache';
3
+ import { NSet } from './NSet';
4
+ /**
5
+ * Nostr LRU cache based on [`npm:lru-cache`](https://www.npmjs.com/package/lru-cache).
6
+ * It implements both `NStore` and `NSet` interfaces.
7
+ *
8
+ * ```ts
9
+ * // Accepts the options of `npm:lru-cache`:
10
+ * const cache = new NCache({ max: 1000 });
11
+ *
12
+ * // Events can be added like a regular `Set`:
13
+ * cache.add(event1);
14
+ * cache.add(event2);
15
+ *
16
+ * // Can be queried like `NStore`:
17
+ * const events = await cache.query([{ kinds: [1] }]);
18
+ *
19
+ * // Can be iterated like `NSet`:
20
+ * for (const event of cache) {
21
+ * console.log(event);
22
+ * }
23
+ * ```
24
+ */
25
+ declare class NCache extends NSet implements NStore {
26
+ constructor(...args: ConstructorParameters<typeof LRUCache<string, NostrEvent>>);
27
+ event(event: NostrEvent): Promise<void>;
28
+ query(filters: NostrFilter[]): Promise<NostrEvent[]>;
29
+ remove(filters: NostrFilter[]): Promise<void>;
30
+ count(filters: NostrFilter[]): Promise<NostrRelayCOUNT[2]>;
31
+ [Symbol.toStringTag]: string;
32
+ }
33
+ export { NCache };
34
+ //# sourceMappingURL=NCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NCache.d.ts","sourceRoot":"","sources":["../NCache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,cAAM,MAAO,SAAQ,IAAK,YAAW,MAAM;gBAEvC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAK/D,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAapD,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ7C,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAQvD,CAAC,MAAM,CAAC,WAAW,CAAC,SAAY;CAC1C;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}