@unicitylabs/nostr-js-sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +290 -0
- package/dist/browser/index.js +8444 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/index.min.js +12 -0
- package/dist/browser/index.min.js.map +1 -0
- package/dist/browser/index.umd.js +8524 -0
- package/dist/browser/index.umd.js.map +1 -0
- package/dist/browser/index.umd.min.js +12 -0
- package/dist/browser/index.umd.min.js.map +1 -0
- package/dist/cjs/NostrKeyManager.js +265 -0
- package/dist/cjs/NostrKeyManager.js.map +1 -0
- package/dist/cjs/client/NostrClient.js +518 -0
- package/dist/cjs/client/NostrClient.js.map +1 -0
- package/dist/cjs/client/NostrEventListener.js +31 -0
- package/dist/cjs/client/NostrEventListener.js.map +1 -0
- package/dist/cjs/client/WebSocketAdapter.js +90 -0
- package/dist/cjs/client/WebSocketAdapter.js.map +1 -0
- package/dist/cjs/client/index.js +18 -0
- package/dist/cjs/client/index.js.map +1 -0
- package/dist/cjs/crypto/bech32.js +201 -0
- package/dist/cjs/crypto/bech32.js.map +1 -0
- package/dist/cjs/crypto/index.js +49 -0
- package/dist/cjs/crypto/index.js.map +1 -0
- package/dist/cjs/crypto/nip04.js +327 -0
- package/dist/cjs/crypto/nip04.js.map +1 -0
- package/dist/cjs/crypto/schnorr.js +101 -0
- package/dist/cjs/crypto/schnorr.js.map +1 -0
- package/dist/cjs/index.js +57 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/nametag/NametagBinding.js +196 -0
- package/dist/cjs/nametag/NametagBinding.js.map +1 -0
- package/dist/cjs/nametag/NametagUtils.js +156 -0
- package/dist/cjs/nametag/NametagUtils.js.map +1 -0
- package/dist/cjs/nametag/index.js +47 -0
- package/dist/cjs/nametag/index.js.map +1 -0
- package/dist/cjs/protocol/Event.js +209 -0
- package/dist/cjs/protocol/Event.js.map +1 -0
- package/dist/cjs/protocol/EventKinds.js +126 -0
- package/dist/cjs/protocol/EventKinds.js.map +1 -0
- package/dist/cjs/protocol/Filter.js +202 -0
- package/dist/cjs/protocol/Filter.js.map +1 -0
- package/dist/cjs/protocol/index.js +50 -0
- package/dist/cjs/protocol/index.js.map +1 -0
- package/dist/cjs/token/TokenTransferProtocol.js +196 -0
- package/dist/cjs/token/TokenTransferProtocol.js.map +1 -0
- package/dist/cjs/token/index.js +45 -0
- package/dist/cjs/token/index.js.map +1 -0
- package/dist/esm/NostrKeyManager.js +228 -0
- package/dist/esm/NostrKeyManager.js.map +1 -0
- package/dist/esm/client/NostrClient.js +481 -0
- package/dist/esm/client/NostrClient.js.map +1 -0
- package/dist/esm/client/NostrEventListener.js +27 -0
- package/dist/esm/client/NostrEventListener.js.map +1 -0
- package/dist/esm/client/WebSocketAdapter.js +52 -0
- package/dist/esm/client/WebSocketAdapter.js.map +1 -0
- package/dist/esm/client/index.js +7 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/crypto/bech32.js +193 -0
- package/dist/esm/crypto/bech32.js.map +1 -0
- package/dist/esm/crypto/index.js +10 -0
- package/dist/esm/crypto/index.js.map +1 -0
- package/dist/esm/crypto/nip04.js +286 -0
- package/dist/esm/crypto/nip04.js.map +1 -0
- package/dist/esm/crypto/schnorr.js +93 -0
- package/dist/esm/crypto/schnorr.js.map +1 -0
- package/dist/esm/index.js +32 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/nametag/NametagBinding.js +155 -0
- package/dist/esm/nametag/NametagBinding.js.map +1 -0
- package/dist/esm/nametag/NametagUtils.js +149 -0
- package/dist/esm/nametag/NametagUtils.js.map +1 -0
- package/dist/esm/nametag/index.js +8 -0
- package/dist/esm/nametag/index.js.map +1 -0
- package/dist/esm/protocol/Event.js +172 -0
- package/dist/esm/protocol/Event.js.map +1 -0
- package/dist/esm/protocol/EventKinds.js +119 -0
- package/dist/esm/protocol/EventKinds.js.map +1 -0
- package/dist/esm/protocol/Filter.js +197 -0
- package/dist/esm/protocol/Filter.js.map +1 -0
- package/dist/esm/protocol/index.js +8 -0
- package/dist/esm/protocol/index.js.map +1 -0
- package/dist/esm/token/TokenTransferProtocol.js +154 -0
- package/dist/esm/token/TokenTransferProtocol.js.map +1 -0
- package/dist/esm/token/index.js +6 -0
- package/dist/esm/token/index.js.map +1 -0
- package/dist/types/NostrKeyManager.d.ts +150 -0
- package/dist/types/NostrKeyManager.d.ts.map +1 -0
- package/dist/types/client/NostrClient.d.ts +154 -0
- package/dist/types/client/NostrClient.d.ts.map +1 -0
- package/dist/types/client/NostrEventListener.d.ts +40 -0
- package/dist/types/client/NostrEventListener.d.ts.map +1 -0
- package/dist/types/client/WebSocketAdapter.d.ts +55 -0
- package/dist/types/client/WebSocketAdapter.d.ts.map +1 -0
- package/dist/types/client/index.d.ts +9 -0
- package/dist/types/client/index.d.ts.map +1 -0
- package/dist/types/crypto/bech32.d.ts +51 -0
- package/dist/types/crypto/bech32.d.ts.map +1 -0
- package/dist/types/crypto/index.d.ts +10 -0
- package/dist/types/crypto/index.d.ts.map +1 -0
- package/dist/types/crypto/nip04.d.ts +56 -0
- package/dist/types/crypto/nip04.d.ts.map +1 -0
- package/dist/types/crypto/schnorr.d.ts +47 -0
- package/dist/types/crypto/schnorr.d.ts.map +1 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/nametag/NametagBinding.d.ts +68 -0
- package/dist/types/nametag/NametagBinding.d.ts.map +1 -0
- package/dist/types/nametag/NametagUtils.d.ts +44 -0
- package/dist/types/nametag/NametagUtils.d.ts.map +1 -0
- package/dist/types/nametag/index.d.ts +8 -0
- package/dist/types/nametag/index.d.ts.map +1 -0
- package/dist/types/protocol/Event.d.ts +112 -0
- package/dist/types/protocol/Event.d.ts.map +1 -0
- package/dist/types/protocol/EventKinds.d.ts +62 -0
- package/dist/types/protocol/EventKinds.d.ts.map +1 -0
- package/dist/types/protocol/Filter.d.ts +146 -0
- package/dist/types/protocol/Filter.d.ts.map +1 -0
- package/dist/types/protocol/index.d.ts +10 -0
- package/dist/types/protocol/index.d.ts.map +1 -0
- package/dist/types/token/TokenTransferProtocol.d.ts +67 -0
- package/dist/types/token/TokenTransferProtocol.d.ts.map +1 -0
- package/dist/types/token/index.d.ts +6 -0
- package/dist/types/token/index.d.ts.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NostrClient - Main entry point for Nostr protocol operations.
|
|
3
|
+
* Handles relay connections, event publishing, and subscriptions.
|
|
4
|
+
*/
|
|
5
|
+
import { Event } from '../protocol/Event.js';
|
|
6
|
+
import * as EventKinds from '../protocol/EventKinds.js';
|
|
7
|
+
import { createWebSocket, extractMessageData, OPEN, CLOSED, } from './WebSocketAdapter.js';
|
|
8
|
+
/** Connection timeout in milliseconds */
|
|
9
|
+
const CONNECTION_TIMEOUT_MS = 30000;
|
|
10
|
+
/** Reconnection delay in milliseconds */
|
|
11
|
+
const RECONNECT_DELAY_MS = 5000;
|
|
12
|
+
/** Query timeout in milliseconds */
|
|
13
|
+
const QUERY_TIMEOUT_MS = 5000;
|
|
14
|
+
/**
|
|
15
|
+
* NostrClient provides the main interface for Nostr protocol operations.
|
|
16
|
+
*/
|
|
17
|
+
export class NostrClient {
|
|
18
|
+
keyManager;
|
|
19
|
+
relays = new Map();
|
|
20
|
+
subscriptions = new Map();
|
|
21
|
+
eventQueue = [];
|
|
22
|
+
pendingOks = new Map();
|
|
23
|
+
subscriptionCounter = 0;
|
|
24
|
+
closed = false;
|
|
25
|
+
/**
|
|
26
|
+
* Create a NostrClient instance.
|
|
27
|
+
* @param keyManager Key manager with signing keys
|
|
28
|
+
*/
|
|
29
|
+
constructor(keyManager) {
|
|
30
|
+
this.keyManager = keyManager;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the key manager.
|
|
34
|
+
* @returns The key manager instance
|
|
35
|
+
*/
|
|
36
|
+
getKeyManager() {
|
|
37
|
+
return this.keyManager;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Connect to one or more relay WebSocket URLs.
|
|
41
|
+
* @param relayUrls Relay URLs to connect to
|
|
42
|
+
* @returns Promise that resolves when all connections are established
|
|
43
|
+
*/
|
|
44
|
+
async connect(...relayUrls) {
|
|
45
|
+
if (this.closed) {
|
|
46
|
+
throw new Error('Client has been disconnected');
|
|
47
|
+
}
|
|
48
|
+
const connectionPromises = relayUrls.map((url) => this.connectToRelay(url));
|
|
49
|
+
await Promise.all(connectionPromises);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Connect to a single relay.
|
|
53
|
+
*/
|
|
54
|
+
async connectToRelay(url) {
|
|
55
|
+
if (this.relays.has(url)) {
|
|
56
|
+
const relay = this.relays.get(url);
|
|
57
|
+
if (relay.connected) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const timeoutId = setTimeout(() => {
|
|
63
|
+
reject(new Error(`Connection to ${url} timed out`));
|
|
64
|
+
}, CONNECTION_TIMEOUT_MS);
|
|
65
|
+
createWebSocket(url)
|
|
66
|
+
.then((socket) => {
|
|
67
|
+
const relay = {
|
|
68
|
+
url,
|
|
69
|
+
socket,
|
|
70
|
+
connected: false,
|
|
71
|
+
reconnecting: false,
|
|
72
|
+
};
|
|
73
|
+
socket.onopen = () => {
|
|
74
|
+
clearTimeout(timeoutId);
|
|
75
|
+
relay.connected = true;
|
|
76
|
+
this.relays.set(url, relay);
|
|
77
|
+
// Re-establish subscriptions
|
|
78
|
+
this.resubscribeAll(url);
|
|
79
|
+
// Flush queued events
|
|
80
|
+
this.flushEventQueue();
|
|
81
|
+
resolve();
|
|
82
|
+
};
|
|
83
|
+
socket.onmessage = (event) => {
|
|
84
|
+
try {
|
|
85
|
+
const data = extractMessageData(event);
|
|
86
|
+
this.handleRelayMessage(url, data);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.error(`Error handling message from ${url}:`, error);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
socket.onclose = () => {
|
|
93
|
+
relay.connected = false;
|
|
94
|
+
if (!this.closed && !relay.reconnecting) {
|
|
95
|
+
this.scheduleReconnect(url);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
socket.onerror = (error) => {
|
|
99
|
+
if (!relay.connected) {
|
|
100
|
+
clearTimeout(timeoutId);
|
|
101
|
+
reject(new Error(`Failed to connect to ${url}: ${error.message || 'Unknown error'}`));
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
this.relays.set(url, relay);
|
|
105
|
+
})
|
|
106
|
+
.catch((error) => {
|
|
107
|
+
clearTimeout(timeoutId);
|
|
108
|
+
reject(error);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Schedule a reconnection attempt for a relay.
|
|
114
|
+
*/
|
|
115
|
+
scheduleReconnect(url) {
|
|
116
|
+
const relay = this.relays.get(url);
|
|
117
|
+
if (!relay || this.closed)
|
|
118
|
+
return;
|
|
119
|
+
relay.reconnecting = true;
|
|
120
|
+
setTimeout(async () => {
|
|
121
|
+
if (this.closed)
|
|
122
|
+
return;
|
|
123
|
+
try {
|
|
124
|
+
relay.reconnecting = false;
|
|
125
|
+
await this.connectToRelay(url);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Will trigger another reconnect via onclose
|
|
129
|
+
}
|
|
130
|
+
}, RECONNECT_DELAY_MS);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Re-establish all subscriptions for a relay.
|
|
134
|
+
*/
|
|
135
|
+
resubscribeAll(url) {
|
|
136
|
+
const relay = this.relays.get(url);
|
|
137
|
+
if (!relay?.socket || !relay.connected)
|
|
138
|
+
return;
|
|
139
|
+
for (const [subId, info] of this.subscriptions) {
|
|
140
|
+
const message = JSON.stringify(['REQ', subId, info.filter.toJSON()]);
|
|
141
|
+
relay.socket.send(message);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Flush queued events to connected relays.
|
|
146
|
+
*/
|
|
147
|
+
flushEventQueue() {
|
|
148
|
+
const queue = [...this.eventQueue];
|
|
149
|
+
this.eventQueue = [];
|
|
150
|
+
for (const item of queue) {
|
|
151
|
+
this.broadcastEvent(item.event)
|
|
152
|
+
.then(() => item.resolve(item.event.id))
|
|
153
|
+
.catch(item.reject);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Handle a message from a relay.
|
|
158
|
+
*/
|
|
159
|
+
handleRelayMessage(_url, message) {
|
|
160
|
+
try {
|
|
161
|
+
const json = JSON.parse(message);
|
|
162
|
+
if (!Array.isArray(json) || json.length < 2)
|
|
163
|
+
return;
|
|
164
|
+
const messageType = json[0];
|
|
165
|
+
switch (messageType) {
|
|
166
|
+
case 'EVENT':
|
|
167
|
+
this.handleEventMessage(json);
|
|
168
|
+
break;
|
|
169
|
+
case 'OK':
|
|
170
|
+
this.handleOkMessage(json);
|
|
171
|
+
break;
|
|
172
|
+
case 'EOSE':
|
|
173
|
+
this.handleEOSEMessage(json);
|
|
174
|
+
break;
|
|
175
|
+
case 'NOTICE':
|
|
176
|
+
this.handleNoticeMessage(json);
|
|
177
|
+
break;
|
|
178
|
+
case 'CLOSED':
|
|
179
|
+
this.handleClosedMessage(json);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Ignore malformed messages
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Handle EVENT message from relay.
|
|
189
|
+
*/
|
|
190
|
+
handleEventMessage(json) {
|
|
191
|
+
if (json.length < 3)
|
|
192
|
+
return;
|
|
193
|
+
const subscriptionId = json[1];
|
|
194
|
+
const eventData = json[2];
|
|
195
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
196
|
+
if (!subscription)
|
|
197
|
+
return;
|
|
198
|
+
try {
|
|
199
|
+
const event = Event.fromJSON(eventData);
|
|
200
|
+
subscription.listener.onEvent(event);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Ignore invalid events
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Handle OK message from relay.
|
|
208
|
+
*/
|
|
209
|
+
handleOkMessage(json) {
|
|
210
|
+
if (json.length < 4)
|
|
211
|
+
return;
|
|
212
|
+
const eventId = json[1];
|
|
213
|
+
const accepted = json[2];
|
|
214
|
+
const message = json[3];
|
|
215
|
+
const pending = this.pendingOks.get(eventId);
|
|
216
|
+
if (!pending)
|
|
217
|
+
return;
|
|
218
|
+
clearTimeout(pending.timer);
|
|
219
|
+
this.pendingOks.delete(eventId);
|
|
220
|
+
if (accepted) {
|
|
221
|
+
pending.resolve(eventId);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
pending.reject(new Error(`Event rejected: ${message}`));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Handle EOSE (End of Stored Events) message from relay.
|
|
229
|
+
*/
|
|
230
|
+
handleEOSEMessage(json) {
|
|
231
|
+
if (json.length < 2)
|
|
232
|
+
return;
|
|
233
|
+
const subscriptionId = json[1];
|
|
234
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
235
|
+
if (subscription?.listener.onEndOfStoredEvents) {
|
|
236
|
+
subscription.listener.onEndOfStoredEvents(subscriptionId);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Handle NOTICE message from relay.
|
|
241
|
+
*/
|
|
242
|
+
handleNoticeMessage(json) {
|
|
243
|
+
if (json.length < 2)
|
|
244
|
+
return;
|
|
245
|
+
const message = json[1];
|
|
246
|
+
console.warn('Relay notice:', message);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Handle CLOSED message from relay (subscription closed by relay).
|
|
250
|
+
*/
|
|
251
|
+
handleClosedMessage(json) {
|
|
252
|
+
if (json.length < 3)
|
|
253
|
+
return;
|
|
254
|
+
const subscriptionId = json[1];
|
|
255
|
+
const message = json[2];
|
|
256
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
257
|
+
if (subscription?.listener.onError) {
|
|
258
|
+
subscription.listener.onError(subscriptionId, `Subscription closed: ${message}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Disconnect from all relays.
|
|
263
|
+
*/
|
|
264
|
+
disconnect() {
|
|
265
|
+
this.closed = true;
|
|
266
|
+
// Clear pending OKs
|
|
267
|
+
for (const [, pending] of this.pendingOks) {
|
|
268
|
+
clearTimeout(pending.timer);
|
|
269
|
+
pending.reject(new Error('Client disconnected'));
|
|
270
|
+
}
|
|
271
|
+
this.pendingOks.clear();
|
|
272
|
+
// Clear queued events
|
|
273
|
+
for (const item of this.eventQueue) {
|
|
274
|
+
item.reject(new Error('Client disconnected'));
|
|
275
|
+
}
|
|
276
|
+
this.eventQueue = [];
|
|
277
|
+
// Close all relay connections
|
|
278
|
+
for (const [, relay] of this.relays) {
|
|
279
|
+
if (relay.socket && relay.socket.readyState !== CLOSED) {
|
|
280
|
+
relay.socket.close(1000, 'Client disconnected');
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
this.relays.clear();
|
|
284
|
+
this.subscriptions.clear();
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Check if connected to at least one relay.
|
|
288
|
+
* @returns true if connected to at least one relay
|
|
289
|
+
*/
|
|
290
|
+
isConnected() {
|
|
291
|
+
for (const [, relay] of this.relays) {
|
|
292
|
+
if (relay.connected)
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Get the set of connected relay URLs.
|
|
299
|
+
* @returns Set of connected relay URLs
|
|
300
|
+
*/
|
|
301
|
+
getConnectedRelays() {
|
|
302
|
+
const connected = new Set();
|
|
303
|
+
for (const [url, relay] of this.relays) {
|
|
304
|
+
if (relay.connected) {
|
|
305
|
+
connected.add(url);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return connected;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Publish an event to all connected relays.
|
|
312
|
+
* @param event Event to publish
|
|
313
|
+
* @returns Promise that resolves with the event ID
|
|
314
|
+
*/
|
|
315
|
+
async publishEvent(event) {
|
|
316
|
+
if (this.closed) {
|
|
317
|
+
throw new Error('Client has been disconnected');
|
|
318
|
+
}
|
|
319
|
+
if (!this.isConnected()) {
|
|
320
|
+
// Queue the event for later
|
|
321
|
+
return new Promise((resolve, reject) => {
|
|
322
|
+
this.eventQueue.push({
|
|
323
|
+
event,
|
|
324
|
+
timestamp: Date.now(),
|
|
325
|
+
resolve,
|
|
326
|
+
reject,
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return this.broadcastEvent(event);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Broadcast an event to all connected relays.
|
|
334
|
+
*/
|
|
335
|
+
async broadcastEvent(event) {
|
|
336
|
+
const message = JSON.stringify(['EVENT', event.toJSON()]);
|
|
337
|
+
let sent = false;
|
|
338
|
+
for (const [, relay] of this.relays) {
|
|
339
|
+
if (relay.connected && relay.socket?.readyState === OPEN) {
|
|
340
|
+
relay.socket.send(message);
|
|
341
|
+
sent = true;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (!sent) {
|
|
345
|
+
throw new Error('No connected relays');
|
|
346
|
+
}
|
|
347
|
+
// Wait for at least one OK response
|
|
348
|
+
return new Promise((resolve, reject) => {
|
|
349
|
+
const timer = setTimeout(() => {
|
|
350
|
+
this.pendingOks.delete(event.id);
|
|
351
|
+
// Consider it successful if we sent it (some relays don't send OK)
|
|
352
|
+
resolve(event.id);
|
|
353
|
+
}, 5000);
|
|
354
|
+
this.pendingOks.set(event.id, { resolve, reject, timer });
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Publish an encrypted direct message (NIP-04).
|
|
359
|
+
* @param recipientPubkeyHex Recipient's public key (hex)
|
|
360
|
+
* @param message Message to send
|
|
361
|
+
* @returns Promise that resolves with the event ID
|
|
362
|
+
*/
|
|
363
|
+
async publishEncryptedMessage(recipientPubkeyHex, message) {
|
|
364
|
+
const encryptedContent = await this.keyManager.encryptHex(message, recipientPubkeyHex);
|
|
365
|
+
const event = Event.create(this.keyManager, {
|
|
366
|
+
kind: EventKinds.ENCRYPTED_DM,
|
|
367
|
+
tags: [['p', recipientPubkeyHex]],
|
|
368
|
+
content: encryptedContent,
|
|
369
|
+
});
|
|
370
|
+
return this.publishEvent(event);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Send a token transfer (encrypted).
|
|
374
|
+
* @param recipientPubkeyHex Recipient's public key (hex)
|
|
375
|
+
* @param tokenJson Token JSON string
|
|
376
|
+
* @returns Promise that resolves with the event ID
|
|
377
|
+
*/
|
|
378
|
+
async sendTokenTransfer(recipientPubkeyHex, tokenJson) {
|
|
379
|
+
const TokenTransferProtocol = await import('../token/TokenTransferProtocol.js');
|
|
380
|
+
const event = await TokenTransferProtocol.createTokenTransferEvent(this.keyManager, recipientPubkeyHex, tokenJson);
|
|
381
|
+
return this.publishEvent(event);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Publish a nametag binding.
|
|
385
|
+
* @param nametagId Nametag identifier
|
|
386
|
+
* @param unicityAddress Unicity address
|
|
387
|
+
* @returns Promise that resolves with success status
|
|
388
|
+
*/
|
|
389
|
+
async publishNametagBinding(nametagId, unicityAddress) {
|
|
390
|
+
const NametagBinding = await import('../nametag/NametagBinding.js');
|
|
391
|
+
const event = await NametagBinding.createBindingEvent(this.keyManager, nametagId, unicityAddress);
|
|
392
|
+
try {
|
|
393
|
+
await this.publishEvent(event);
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
subscribe(filterOrSubId, listenerOrFilter, maybeListener) {
|
|
401
|
+
let subscriptionId;
|
|
402
|
+
let filter;
|
|
403
|
+
let listener;
|
|
404
|
+
if (typeof filterOrSubId === 'string') {
|
|
405
|
+
subscriptionId = filterOrSubId;
|
|
406
|
+
filter = listenerOrFilter;
|
|
407
|
+
listener = maybeListener;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
subscriptionId = `sub_${++this.subscriptionCounter}`;
|
|
411
|
+
filter = filterOrSubId;
|
|
412
|
+
listener = listenerOrFilter;
|
|
413
|
+
}
|
|
414
|
+
this.subscriptions.set(subscriptionId, { filter, listener });
|
|
415
|
+
// Send subscription request to all connected relays
|
|
416
|
+
const message = JSON.stringify(['REQ', subscriptionId, filter.toJSON()]);
|
|
417
|
+
for (const [, relay] of this.relays) {
|
|
418
|
+
if (relay.connected && relay.socket?.readyState === OPEN) {
|
|
419
|
+
relay.socket.send(message);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return subscriptionId;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Unsubscribe from a subscription.
|
|
426
|
+
* @param subscriptionId Subscription ID to unsubscribe
|
|
427
|
+
*/
|
|
428
|
+
unsubscribe(subscriptionId) {
|
|
429
|
+
if (!this.subscriptions.has(subscriptionId))
|
|
430
|
+
return;
|
|
431
|
+
this.subscriptions.delete(subscriptionId);
|
|
432
|
+
// Send CLOSE to all connected relays
|
|
433
|
+
const message = JSON.stringify(['CLOSE', subscriptionId]);
|
|
434
|
+
for (const [, relay] of this.relays) {
|
|
435
|
+
if (relay.connected && relay.socket?.readyState === OPEN) {
|
|
436
|
+
relay.socket.send(message);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Query for a public key by nametag.
|
|
442
|
+
* @param nametagId Nametag identifier
|
|
443
|
+
* @returns Promise that resolves with the public key hex, or null if not found
|
|
444
|
+
*/
|
|
445
|
+
async queryPubkeyByNametag(nametagId) {
|
|
446
|
+
const NametagBinding = await import('../nametag/NametagBinding.js');
|
|
447
|
+
const filter = NametagBinding.createNametagToPubkeyFilter(nametagId);
|
|
448
|
+
return new Promise((resolve) => {
|
|
449
|
+
const timeoutId = setTimeout(() => {
|
|
450
|
+
this.unsubscribe(subscriptionId);
|
|
451
|
+
resolve(null);
|
|
452
|
+
}, QUERY_TIMEOUT_MS);
|
|
453
|
+
let result = null;
|
|
454
|
+
let latestCreatedAt = 0;
|
|
455
|
+
const subscriptionId = this.subscribe(filter, {
|
|
456
|
+
onEvent: (event) => {
|
|
457
|
+
// Keep the most recent binding
|
|
458
|
+
if (event.created_at > latestCreatedAt) {
|
|
459
|
+
latestCreatedAt = event.created_at;
|
|
460
|
+
result = event.pubkey;
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
onEndOfStoredEvents: () => {
|
|
464
|
+
clearTimeout(timeoutId);
|
|
465
|
+
this.unsubscribe(subscriptionId);
|
|
466
|
+
resolve(result);
|
|
467
|
+
},
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Create and publish a signed event.
|
|
473
|
+
* @param data Unsigned event data
|
|
474
|
+
* @returns Promise that resolves with the event ID
|
|
475
|
+
*/
|
|
476
|
+
async createAndPublishEvent(data) {
|
|
477
|
+
const event = Event.create(this.keyManager, data);
|
|
478
|
+
return this.publishEvent(event);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
//# sourceMappingURL=NostrClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NostrClient.js","sourceRoot":"","sources":["../../../src/client/NostrClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NostrEventListener - Callback interface for receiving events and subscription status.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Simple callback-based event listener.
|
|
6
|
+
* Useful for creating listeners from callback functions.
|
|
7
|
+
*/
|
|
8
|
+
export class CallbackEventListener {
|
|
9
|
+
eventCallback;
|
|
10
|
+
eoseCallback;
|
|
11
|
+
errorCallback;
|
|
12
|
+
constructor(onEvent, onEndOfStoredEvents, onError) {
|
|
13
|
+
this.eventCallback = onEvent;
|
|
14
|
+
this.eoseCallback = onEndOfStoredEvents;
|
|
15
|
+
this.errorCallback = onError;
|
|
16
|
+
}
|
|
17
|
+
onEvent(event) {
|
|
18
|
+
this.eventCallback(event);
|
|
19
|
+
}
|
|
20
|
+
onEndOfStoredEvents(subscriptionId) {
|
|
21
|
+
this.eoseCallback?.(subscriptionId);
|
|
22
|
+
}
|
|
23
|
+
onError(subscriptionId, error) {
|
|
24
|
+
this.errorCallback?.(subscriptionId, error);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=NostrEventListener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NostrEventListener.js","sourceRoot":"","sources":["../../../src/client/NostrEventListener.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6BH;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IACxB,aAAa,CAAyB;IACtC,YAAY,CAAoC;IAChD,aAAa,CAAmD;IAExE,YACE,OAA+B,EAC/B,mBAAsD,EACtD,OAAyD;QAEzD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,KAAY;QAClB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,mBAAmB,CAAC,cAAsB;QACxC,IAAI,CAAC,YAAY,EAAE,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,CAAC,cAAsB,EAAE,KAAa;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;CACF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocketAdapter - Cross-platform WebSocket implementation.
|
|
3
|
+
* Provides a unified interface for WebSocket connections in Node.js and browsers.
|
|
4
|
+
*/
|
|
5
|
+
/** WebSocket ready state constants */
|
|
6
|
+
export const CONNECTING = 0;
|
|
7
|
+
export const OPEN = 1;
|
|
8
|
+
export const CLOSING = 2;
|
|
9
|
+
export const CLOSED = 3;
|
|
10
|
+
/**
|
|
11
|
+
* Create a WebSocket connection that works in both Node.js and browsers.
|
|
12
|
+
* @param url WebSocket URL (ws:// or wss://)
|
|
13
|
+
* @returns WebSocket instance
|
|
14
|
+
*/
|
|
15
|
+
export async function createWebSocket(url) {
|
|
16
|
+
// Check if we're in a browser environment
|
|
17
|
+
if (typeof WebSocket !== 'undefined') {
|
|
18
|
+
return new WebSocket(url);
|
|
19
|
+
}
|
|
20
|
+
// Node.js environment - dynamically import ws
|
|
21
|
+
try {
|
|
22
|
+
const { default: WS } = await import('ws');
|
|
23
|
+
return new WS(url);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new Error('WebSocket not available. In Node.js, install the "ws" package: npm install ws');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Extract string data from WebSocket message event.
|
|
31
|
+
* Handles different message types across platforms.
|
|
32
|
+
* @param event WebSocket message event
|
|
33
|
+
* @returns String message data
|
|
34
|
+
*/
|
|
35
|
+
export function extractMessageData(event) {
|
|
36
|
+
if (typeof event.data === 'string') {
|
|
37
|
+
return event.data;
|
|
38
|
+
}
|
|
39
|
+
if (event.data instanceof ArrayBuffer) {
|
|
40
|
+
return new TextDecoder().decode(event.data);
|
|
41
|
+
}
|
|
42
|
+
if (typeof Blob !== 'undefined' && event.data instanceof Blob) {
|
|
43
|
+
// This shouldn't happen in normal Nostr relay communication
|
|
44
|
+
throw new Error('Blob messages are not supported');
|
|
45
|
+
}
|
|
46
|
+
// Node.js Buffer case
|
|
47
|
+
if (Buffer && Buffer.isBuffer(event.data)) {
|
|
48
|
+
return event.data.toString('utf-8');
|
|
49
|
+
}
|
|
50
|
+
return String(event.data);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=WebSocketAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketAdapter.js","sourceRoot":"","sources":["../../../src/client/WebSocketAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsCH,sCAAsC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;AACtB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,0CAA0C;IAC1C,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE,CAAC;QACrC,OAAO,IAAI,SAAS,CAAC,GAAG,CAA0B,CAAC;IACrD,CAAC;IAED,8CAA8C;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3C,OAAO,IAAI,EAAE,CAAC,GAAG,CAA0B,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA4B;IAC7D,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,YAAY,WAAW,EAAE,CAAC;QACtC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,YAAY,IAAI,EAAE,CAAC;QAC9D,4DAA4D;QAC5D,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,sBAAsB;IACtB,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAQ,KAAK,CAAC,IAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client module - Nostr relay client
|
|
3
|
+
*/
|
|
4
|
+
export { NostrClient } from './NostrClient.js';
|
|
5
|
+
export { CallbackEventListener } from './NostrEventListener.js';
|
|
6
|
+
export { createWebSocket, extractMessageData, CONNECTING, OPEN, CLOSING, CLOSED, } from './WebSocketAdapter.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,IAAI,EACJ,OAAO,EACP,MAAM,GACP,MAAM,uBAAuB,CAAC"}
|