nostr-wot-sdk 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +13 -67
- package/dist/index.cjs +230 -251
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +230 -251
- package/dist/react/index.cjs +23 -269
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +17 -60
- package/dist/react/index.d.ts +17 -60
- package/dist/react/index.js +24 -270
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.0] - 2025-02-05
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Simplified extension connection** - Removed event-based connection flow
|
|
13
|
+
- SDK now simply checks `window.nostr.wot` directly
|
|
14
|
+
- Extension auto-injects when enabled, no handshake needed
|
|
15
|
+
- Faster and more reliable connection
|
|
16
|
+
|
|
17
|
+
- **React context simplified**
|
|
18
|
+
- Removed `ExtensionConnector` usage
|
|
19
|
+
- `useExtension()` hook now returns simpler state: `isConnected`, `isChecking`, `isChecked`, `refresh`
|
|
20
|
+
- Removed `extensionOptions` prop from `WoTProvider`
|
|
21
|
+
- State is now `'checking' | 'connected' | 'not-available'`
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
|
|
25
|
+
- Removed event-based connection (`nostr-wot-check`, `nostr-wot-connect` events)
|
|
26
|
+
- Removed `ExtensionConnectionOptions` from React exports
|
|
27
|
+
- Extension connection utilities (`checkExtension`, `connectExtension`, `checkAndConnect`, `ExtensionConnector`) are still exported but deprecated
|
|
28
|
+
|
|
8
29
|
## [0.4.2] - 2025-02-05
|
|
9
30
|
|
|
10
31
|
### Fixed
|
|
@@ -180,6 +201,7 @@ function Profile({ pubkey }) {
|
|
|
180
201
|
- TypeScript support with full type definitions
|
|
181
202
|
- Error classes: `WoTError`, `NetworkError`, `NotFoundError`, `TimeoutError`, `ValidationError`
|
|
182
203
|
|
|
204
|
+
[0.5.0]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.4.2...v0.5.0
|
|
183
205
|
[0.4.2]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.4.1...v0.4.2
|
|
184
206
|
[0.4.1]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.4.0...v0.4.1
|
|
185
207
|
[0.4.0]: https://github.com/nostr-wot/nostr-wot-sdk/compare/v0.3.2...v0.4.0
|
package/README.md
CHANGED
|
@@ -251,7 +251,7 @@ Install the [Nostr WoT Extension](https://github.com/nostr-wot/nostr-wot-extensi
|
|
|
251
251
|
- **Privacy** — Queries never leave your browser
|
|
252
252
|
- **Offline** — Works without internet once synced
|
|
253
253
|
|
|
254
|
-
The SDK automatically detects
|
|
254
|
+
The SDK automatically detects the extension via `window.nostr.wot`. When the extension is present (with auto-inject enabled), it **always takes priority** over oracle settings.
|
|
255
255
|
|
|
256
256
|
```javascript
|
|
257
257
|
const wot = new WoT({
|
|
@@ -269,60 +269,16 @@ if (await wot.isUsingExtension()) {
|
|
|
269
269
|
}
|
|
270
270
|
```
|
|
271
271
|
|
|
272
|
-
### Extension Connection Utilities
|
|
273
|
-
|
|
274
|
-
For advanced use cases, the SDK exports low-level extension connection functions:
|
|
275
|
-
|
|
276
|
-
```javascript
|
|
277
|
-
import {
|
|
278
|
-
checkExtension, // Check if extension is installed
|
|
279
|
-
connectExtension, // Connect to the extension
|
|
280
|
-
checkAndConnect, // Check and connect in one call
|
|
281
|
-
ExtensionConnector // Stateful connector class
|
|
282
|
-
} from 'nostr-wot-sdk';
|
|
283
|
-
|
|
284
|
-
// Check if extension is installed (100ms timeout)
|
|
285
|
-
const isInstalled = await checkExtension();
|
|
286
|
-
|
|
287
|
-
// Connect to extension (5s timeout)
|
|
288
|
-
const extension = await connectExtension();
|
|
289
|
-
|
|
290
|
-
// Or do both in one call
|
|
291
|
-
const result = await checkAndConnect();
|
|
292
|
-
if (result.state === 'connected') {
|
|
293
|
-
const distance = await result.extension.getDistance('target...');
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// For stateful connection management
|
|
297
|
-
const connector = new ExtensionConnector();
|
|
298
|
-
connector.subscribe((result) => {
|
|
299
|
-
console.log('State changed:', result.state);
|
|
300
|
-
});
|
|
301
|
-
await connector.connect();
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
#### Extension Events
|
|
305
|
-
|
|
306
|
-
The SDK uses a standard event-based protocol to communicate with the extension:
|
|
307
|
-
|
|
308
|
-
| Event | Direction | Purpose |
|
|
309
|
-
|-------|-----------|---------|
|
|
310
|
-
| `nostr-wot-check` | Page → Extension | Check if extension installed |
|
|
311
|
-
| `nostr-wot-present` | Extension → Page | Response confirming presence |
|
|
312
|
-
| `nostr-wot-connect` | Page → Extension | Request API injection |
|
|
313
|
-
| `nostr-wot-ready` | Extension → Page | API is ready at `window.nostr.wot` |
|
|
314
|
-
| `nostr-wot-error` | Extension → Page | Injection failed with error |
|
|
315
|
-
|
|
316
272
|
## Framework Integration
|
|
317
273
|
|
|
318
274
|
### React
|
|
319
275
|
|
|
320
|
-
The SDK provides first-class React support with automatic extension detection
|
|
276
|
+
The SDK provides first-class React support with automatic extension detection. Just wrap your app with `WoTProvider` and you're ready to go — no additional configuration needed.
|
|
321
277
|
|
|
322
278
|
```javascript
|
|
323
279
|
import { WoTProvider, useWoT, useExtension } from 'nostr-wot-sdk/react';
|
|
324
280
|
|
|
325
|
-
// Wrap your app - automatically
|
|
281
|
+
// Wrap your app - automatically detects extension
|
|
326
282
|
function App() {
|
|
327
283
|
return (
|
|
328
284
|
<WoTProvider>
|
|
@@ -333,13 +289,11 @@ function App() {
|
|
|
333
289
|
|
|
334
290
|
// Check extension status anywhere
|
|
335
291
|
function ExtensionStatus() {
|
|
336
|
-
const { isConnected,
|
|
292
|
+
const { isConnected, isChecking } = useExtension();
|
|
337
293
|
|
|
338
|
-
if (
|
|
339
|
-
if (
|
|
340
|
-
|
|
341
|
-
if (isConnected) return <span>Connected to extension!</span>;
|
|
342
|
-
return null;
|
|
294
|
+
if (isChecking) return <span>Checking for extension...</span>;
|
|
295
|
+
if (isConnected) return <span>Extension connected!</span>;
|
|
296
|
+
return <span>Extension not available</span>;
|
|
343
297
|
}
|
|
344
298
|
|
|
345
299
|
// Use WoT data in components
|
|
@@ -363,16 +317,10 @@ function Profile({ pubkey }) {
|
|
|
363
317
|
#### Provider Options
|
|
364
318
|
|
|
365
319
|
```javascript
|
|
366
|
-
// With fallback for when extension is not
|
|
320
|
+
// With fallback for when extension is not available
|
|
367
321
|
<WoTProvider options={{
|
|
368
322
|
fallback: { myPubkey: 'abc123...' }
|
|
369
323
|
}}>
|
|
370
|
-
|
|
371
|
-
// Custom extension connection timeouts
|
|
372
|
-
<WoTProvider extensionOptions={{
|
|
373
|
-
checkTimeout: 100, // Extension detection timeout (ms)
|
|
374
|
-
connectTimeout: 5000 // Connection timeout (ms)
|
|
375
|
-
}}>
|
|
376
324
|
```
|
|
377
325
|
|
|
378
326
|
#### Available Hooks
|
|
@@ -388,17 +336,15 @@ function Profile({ pubkey }) {
|
|
|
388
336
|
|
|
389
337
|
#### Extension State
|
|
390
338
|
|
|
391
|
-
The `useExtension()` hook provides
|
|
339
|
+
The `useExtension()` hook provides extension status:
|
|
392
340
|
|
|
393
341
|
```javascript
|
|
394
342
|
const {
|
|
395
|
-
state, // '
|
|
343
|
+
state, // 'checking' | 'connected' | 'not-available'
|
|
396
344
|
isConnected, // Extension is connected and ready
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
error, // Error message if connection failed
|
|
401
|
-
connect, // Function to manually retry connection
|
|
345
|
+
isChecking, // Currently checking
|
|
346
|
+
isChecked, // Check complete
|
|
347
|
+
refresh, // Function to re-check extension availability
|
|
402
348
|
} = useExtension();
|
|
403
349
|
```
|
|
404
350
|
|
package/dist/index.cjs
CHANGED
|
@@ -85,236 +85,10 @@ function chunk(array, size) {
|
|
|
85
85
|
return chunks;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
// src/extension.ts
|
|
89
|
-
function checkExtension(timeout = 100) {
|
|
90
|
-
return new Promise((resolve) => {
|
|
91
|
-
var _a;
|
|
92
|
-
if (typeof window === "undefined") {
|
|
93
|
-
resolve(false);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const win = window;
|
|
97
|
-
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
98
|
-
resolve(true);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const handler = () => {
|
|
102
|
-
window.removeEventListener("nostr-wot-present", handler);
|
|
103
|
-
clearTimeout(timer);
|
|
104
|
-
resolve(true);
|
|
105
|
-
};
|
|
106
|
-
window.addEventListener("nostr-wot-present", handler);
|
|
107
|
-
const timer = setTimeout(() => {
|
|
108
|
-
window.removeEventListener("nostr-wot-present", handler);
|
|
109
|
-
resolve(false);
|
|
110
|
-
}, timeout);
|
|
111
|
-
window.dispatchEvent(new CustomEvent("nostr-wot-check"));
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
function connectExtension(timeout = 5e3) {
|
|
115
|
-
return new Promise((resolve, reject) => {
|
|
116
|
-
var _a;
|
|
117
|
-
if (typeof window === "undefined") {
|
|
118
|
-
reject(new Error("Not in browser environment"));
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
const win = window;
|
|
122
|
-
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
123
|
-
resolve(win.nostr.wot);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
let timer;
|
|
127
|
-
const onReady = () => {
|
|
128
|
-
var _a2;
|
|
129
|
-
cleanup();
|
|
130
|
-
const ext = (_a2 = window.nostr) == null ? void 0 : _a2.wot;
|
|
131
|
-
if (ext) {
|
|
132
|
-
resolve(ext);
|
|
133
|
-
} else {
|
|
134
|
-
reject(new Error("Extension ready event fired but API not found"));
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
const onError = (e) => {
|
|
138
|
-
cleanup();
|
|
139
|
-
const detail = e.detail;
|
|
140
|
-
reject(new Error((detail == null ? void 0 : detail.error) || "Connection failed"));
|
|
141
|
-
};
|
|
142
|
-
const cleanup = () => {
|
|
143
|
-
clearTimeout(timer);
|
|
144
|
-
window.removeEventListener("nostr-wot-ready", onReady);
|
|
145
|
-
window.removeEventListener("nostr-wot-error", onError);
|
|
146
|
-
};
|
|
147
|
-
window.addEventListener("nostr-wot-ready", onReady);
|
|
148
|
-
window.addEventListener("nostr-wot-error", onError);
|
|
149
|
-
window.dispatchEvent(new CustomEvent("nostr-wot-connect"));
|
|
150
|
-
timer = setTimeout(() => {
|
|
151
|
-
cleanup();
|
|
152
|
-
reject(new Error("Connection timeout"));
|
|
153
|
-
}, timeout);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
async function checkAndConnect(options = {}) {
|
|
157
|
-
var _a;
|
|
158
|
-
const { checkTimeout = 100, connectTimeout = 5e3, autoConnect = true } = options;
|
|
159
|
-
if (typeof window === "undefined") {
|
|
160
|
-
return { state: "not-installed", extension: null };
|
|
161
|
-
}
|
|
162
|
-
const win = window;
|
|
163
|
-
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
164
|
-
return { state: "connected", extension: win.nostr.wot };
|
|
165
|
-
}
|
|
166
|
-
const isInstalled = await checkExtension(checkTimeout);
|
|
167
|
-
if (!isInstalled) {
|
|
168
|
-
return { state: "not-installed", extension: null };
|
|
169
|
-
}
|
|
170
|
-
if (!autoConnect) {
|
|
171
|
-
return { state: "idle", extension: null };
|
|
172
|
-
}
|
|
173
|
-
try {
|
|
174
|
-
const extension = await connectExtension(connectTimeout);
|
|
175
|
-
return { state: "connected", extension };
|
|
176
|
-
} catch (error) {
|
|
177
|
-
return {
|
|
178
|
-
state: "error",
|
|
179
|
-
extension: null,
|
|
180
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
var ExtensionConnector = class {
|
|
185
|
-
constructor(options = {}) {
|
|
186
|
-
this.options = options;
|
|
187
|
-
this.state = "idle";
|
|
188
|
-
this.extension = null;
|
|
189
|
-
this.connectionPromise = null;
|
|
190
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Get current state
|
|
194
|
-
*/
|
|
195
|
-
getState() {
|
|
196
|
-
return this.state;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Get current extension instance
|
|
200
|
-
*/
|
|
201
|
-
getExtension() {
|
|
202
|
-
return this.extension;
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Get current error
|
|
206
|
-
*/
|
|
207
|
-
getError() {
|
|
208
|
-
return this.error;
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Get current result
|
|
212
|
-
*/
|
|
213
|
-
getResult() {
|
|
214
|
-
return {
|
|
215
|
-
state: this.state,
|
|
216
|
-
extension: this.extension,
|
|
217
|
-
error: this.error
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Subscribe to state changes
|
|
222
|
-
*/
|
|
223
|
-
subscribe(listener) {
|
|
224
|
-
this.listeners.add(listener);
|
|
225
|
-
return () => {
|
|
226
|
-
this.listeners.delete(listener);
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
notify() {
|
|
230
|
-
const result = this.getResult();
|
|
231
|
-
for (const listener of this.listeners) {
|
|
232
|
-
listener(result);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
setState(state, extension = null, error) {
|
|
236
|
-
this.state = state;
|
|
237
|
-
this.extension = extension;
|
|
238
|
-
this.error = error;
|
|
239
|
-
this.notify();
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Connect to the extension
|
|
243
|
-
* Returns existing promise if already connecting
|
|
244
|
-
*/
|
|
245
|
-
async connect() {
|
|
246
|
-
if (this.state === "connected" && this.extension) {
|
|
247
|
-
return this.getResult();
|
|
248
|
-
}
|
|
249
|
-
if (this.connectionPromise) {
|
|
250
|
-
return this.connectionPromise;
|
|
251
|
-
}
|
|
252
|
-
this.connectionPromise = this.doConnect();
|
|
253
|
-
const result = await this.connectionPromise;
|
|
254
|
-
this.connectionPromise = null;
|
|
255
|
-
return result;
|
|
256
|
-
}
|
|
257
|
-
async doConnect() {
|
|
258
|
-
var _a;
|
|
259
|
-
const { checkTimeout = 100, connectTimeout = 5e3 } = this.options;
|
|
260
|
-
if (typeof window === "undefined") {
|
|
261
|
-
this.setState("not-installed");
|
|
262
|
-
return this.getResult();
|
|
263
|
-
}
|
|
264
|
-
const win = window;
|
|
265
|
-
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
266
|
-
this.setState("connected", win.nostr.wot);
|
|
267
|
-
return this.getResult();
|
|
268
|
-
}
|
|
269
|
-
this.setState("checking");
|
|
270
|
-
const isInstalled = await checkExtension(checkTimeout);
|
|
271
|
-
if (!isInstalled) {
|
|
272
|
-
this.setState("not-installed");
|
|
273
|
-
return this.getResult();
|
|
274
|
-
}
|
|
275
|
-
this.setState("connecting");
|
|
276
|
-
try {
|
|
277
|
-
const extension = await connectExtension(connectTimeout);
|
|
278
|
-
this.setState("connected", extension);
|
|
279
|
-
} catch (error) {
|
|
280
|
-
this.setState(
|
|
281
|
-
"error",
|
|
282
|
-
null,
|
|
283
|
-
error instanceof Error ? error.message : "Unknown error"
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
return this.getResult();
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Reset state and disconnect
|
|
290
|
-
*/
|
|
291
|
-
reset() {
|
|
292
|
-
this.state = "idle";
|
|
293
|
-
this.extension = null;
|
|
294
|
-
this.error = void 0;
|
|
295
|
-
this.connectionPromise = null;
|
|
296
|
-
this.notify();
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
var defaultConnector = null;
|
|
300
|
-
function getDefaultConnector(options) {
|
|
301
|
-
if (!defaultConnector) {
|
|
302
|
-
defaultConnector = new ExtensionConnector(options);
|
|
303
|
-
}
|
|
304
|
-
return defaultConnector;
|
|
305
|
-
}
|
|
306
|
-
function resetDefaultConnector() {
|
|
307
|
-
if (defaultConnector) {
|
|
308
|
-
defaultConnector.reset();
|
|
309
|
-
defaultConnector = null;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
88
|
// src/wot.ts
|
|
314
89
|
var WoT = class {
|
|
315
90
|
constructor(options = {}) {
|
|
316
91
|
this.extension = null;
|
|
317
|
-
this.extensionChecked = false;
|
|
318
92
|
this.extensionPubkey = null;
|
|
319
93
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
320
94
|
this.fallbackOptions = (_a = options.fallback) != null ? _a : null;
|
|
@@ -335,16 +109,15 @@ var WoT = class {
|
|
|
335
109
|
}
|
|
336
110
|
/**
|
|
337
111
|
* Checks if browser extension is available and returns it
|
|
338
|
-
*
|
|
339
|
-
* Always returns fresh reference
|
|
112
|
+
* Simply checks window.nostr.wot - extension auto-injects when enabled
|
|
113
|
+
* Always returns fresh reference to handle extension reloads
|
|
340
114
|
*/
|
|
341
115
|
async getExtension() {
|
|
342
|
-
var _a, _b
|
|
116
|
+
var _a, _b;
|
|
343
117
|
if (typeof window === "undefined") return null;
|
|
344
118
|
const win = window;
|
|
345
119
|
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
346
120
|
this.extension = win.nostr.wot;
|
|
347
|
-
this.extensionChecked = true;
|
|
348
121
|
if (!this.extensionPubkey) {
|
|
349
122
|
try {
|
|
350
123
|
this.extensionPubkey = await this.extension.getMyPubkey();
|
|
@@ -359,27 +132,8 @@ var WoT = class {
|
|
|
359
132
|
}
|
|
360
133
|
return this.extension;
|
|
361
134
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const result = await checkAndConnect({
|
|
365
|
-
checkTimeout: 100,
|
|
366
|
-
connectTimeout: 5e3,
|
|
367
|
-
autoConnect: true
|
|
368
|
-
});
|
|
369
|
-
if (result.state === "connected" && result.extension) {
|
|
370
|
-
this.extension = result.extension;
|
|
371
|
-
try {
|
|
372
|
-
this.extensionPubkey = await this.extension.getMyPubkey();
|
|
373
|
-
} catch (e) {
|
|
374
|
-
if ((_c = win.nostr) == null ? void 0 : _c.getPublicKey) {
|
|
375
|
-
try {
|
|
376
|
-
this.extensionPubkey = await win.nostr.getPublicKey();
|
|
377
|
-
} catch (e2) {
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
return this.extension;
|
|
135
|
+
this.extension = null;
|
|
136
|
+
return null;
|
|
383
137
|
}
|
|
384
138
|
/**
|
|
385
139
|
* Gets the effective pubkey (from extension or fallback)
|
|
@@ -823,6 +577,231 @@ var WoT = class {
|
|
|
823
577
|
}
|
|
824
578
|
};
|
|
825
579
|
|
|
580
|
+
// src/extension.ts
|
|
581
|
+
function checkExtension(timeout = 100) {
|
|
582
|
+
return new Promise((resolve) => {
|
|
583
|
+
var _a;
|
|
584
|
+
if (typeof window === "undefined") {
|
|
585
|
+
resolve(false);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
const win = window;
|
|
589
|
+
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
590
|
+
resolve(true);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const handler = () => {
|
|
594
|
+
window.removeEventListener("nostr-wot-present", handler);
|
|
595
|
+
clearTimeout(timer);
|
|
596
|
+
resolve(true);
|
|
597
|
+
};
|
|
598
|
+
window.addEventListener("nostr-wot-present", handler);
|
|
599
|
+
const timer = setTimeout(() => {
|
|
600
|
+
window.removeEventListener("nostr-wot-present", handler);
|
|
601
|
+
resolve(false);
|
|
602
|
+
}, timeout);
|
|
603
|
+
window.dispatchEvent(new CustomEvent("nostr-wot-check"));
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
function connectExtension(timeout = 5e3) {
|
|
607
|
+
return new Promise((resolve, reject) => {
|
|
608
|
+
var _a;
|
|
609
|
+
if (typeof window === "undefined") {
|
|
610
|
+
reject(new Error("Not in browser environment"));
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const win = window;
|
|
614
|
+
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
615
|
+
resolve(win.nostr.wot);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
let timer;
|
|
619
|
+
const onReady = () => {
|
|
620
|
+
var _a2;
|
|
621
|
+
cleanup();
|
|
622
|
+
const ext = (_a2 = window.nostr) == null ? void 0 : _a2.wot;
|
|
623
|
+
if (ext) {
|
|
624
|
+
resolve(ext);
|
|
625
|
+
} else {
|
|
626
|
+
reject(new Error("Extension ready event fired but API not found"));
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
const onError = (e) => {
|
|
630
|
+
cleanup();
|
|
631
|
+
const detail = e.detail;
|
|
632
|
+
reject(new Error((detail == null ? void 0 : detail.error) || "Connection failed"));
|
|
633
|
+
};
|
|
634
|
+
const cleanup = () => {
|
|
635
|
+
clearTimeout(timer);
|
|
636
|
+
window.removeEventListener("nostr-wot-ready", onReady);
|
|
637
|
+
window.removeEventListener("nostr-wot-error", onError);
|
|
638
|
+
};
|
|
639
|
+
window.addEventListener("nostr-wot-ready", onReady);
|
|
640
|
+
window.addEventListener("nostr-wot-error", onError);
|
|
641
|
+
window.dispatchEvent(new CustomEvent("nostr-wot-connect"));
|
|
642
|
+
timer = setTimeout(() => {
|
|
643
|
+
cleanup();
|
|
644
|
+
reject(new Error("Connection timeout"));
|
|
645
|
+
}, timeout);
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
async function checkAndConnect(options = {}) {
|
|
649
|
+
var _a;
|
|
650
|
+
const { checkTimeout = 100, connectTimeout = 5e3, autoConnect = true } = options;
|
|
651
|
+
if (typeof window === "undefined") {
|
|
652
|
+
return { state: "not-installed", extension: null };
|
|
653
|
+
}
|
|
654
|
+
const win = window;
|
|
655
|
+
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
656
|
+
return { state: "connected", extension: win.nostr.wot };
|
|
657
|
+
}
|
|
658
|
+
const isInstalled = await checkExtension(checkTimeout);
|
|
659
|
+
if (!isInstalled) {
|
|
660
|
+
return { state: "not-installed", extension: null };
|
|
661
|
+
}
|
|
662
|
+
if (!autoConnect) {
|
|
663
|
+
return { state: "idle", extension: null };
|
|
664
|
+
}
|
|
665
|
+
try {
|
|
666
|
+
const extension = await connectExtension(connectTimeout);
|
|
667
|
+
return { state: "connected", extension };
|
|
668
|
+
} catch (error) {
|
|
669
|
+
return {
|
|
670
|
+
state: "error",
|
|
671
|
+
extension: null,
|
|
672
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
var ExtensionConnector = class {
|
|
677
|
+
constructor(options = {}) {
|
|
678
|
+
this.options = options;
|
|
679
|
+
this.state = "idle";
|
|
680
|
+
this.extension = null;
|
|
681
|
+
this.connectionPromise = null;
|
|
682
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Get current state
|
|
686
|
+
*/
|
|
687
|
+
getState() {
|
|
688
|
+
return this.state;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Get current extension instance
|
|
692
|
+
*/
|
|
693
|
+
getExtension() {
|
|
694
|
+
return this.extension;
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Get current error
|
|
698
|
+
*/
|
|
699
|
+
getError() {
|
|
700
|
+
return this.error;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Get current result
|
|
704
|
+
*/
|
|
705
|
+
getResult() {
|
|
706
|
+
return {
|
|
707
|
+
state: this.state,
|
|
708
|
+
extension: this.extension,
|
|
709
|
+
error: this.error
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Subscribe to state changes
|
|
714
|
+
*/
|
|
715
|
+
subscribe(listener) {
|
|
716
|
+
this.listeners.add(listener);
|
|
717
|
+
return () => {
|
|
718
|
+
this.listeners.delete(listener);
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
notify() {
|
|
722
|
+
const result = this.getResult();
|
|
723
|
+
for (const listener of this.listeners) {
|
|
724
|
+
listener(result);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
setState(state, extension = null, error) {
|
|
728
|
+
this.state = state;
|
|
729
|
+
this.extension = extension;
|
|
730
|
+
this.error = error;
|
|
731
|
+
this.notify();
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Connect to the extension
|
|
735
|
+
* Returns existing promise if already connecting
|
|
736
|
+
*/
|
|
737
|
+
async connect() {
|
|
738
|
+
if (this.state === "connected" && this.extension) {
|
|
739
|
+
return this.getResult();
|
|
740
|
+
}
|
|
741
|
+
if (this.connectionPromise) {
|
|
742
|
+
return this.connectionPromise;
|
|
743
|
+
}
|
|
744
|
+
this.connectionPromise = this.doConnect();
|
|
745
|
+
const result = await this.connectionPromise;
|
|
746
|
+
this.connectionPromise = null;
|
|
747
|
+
return result;
|
|
748
|
+
}
|
|
749
|
+
async doConnect() {
|
|
750
|
+
var _a;
|
|
751
|
+
const { checkTimeout = 100, connectTimeout = 5e3 } = this.options;
|
|
752
|
+
if (typeof window === "undefined") {
|
|
753
|
+
this.setState("not-installed");
|
|
754
|
+
return this.getResult();
|
|
755
|
+
}
|
|
756
|
+
const win = window;
|
|
757
|
+
if ((_a = win.nostr) == null ? void 0 : _a.wot) {
|
|
758
|
+
this.setState("connected", win.nostr.wot);
|
|
759
|
+
return this.getResult();
|
|
760
|
+
}
|
|
761
|
+
this.setState("checking");
|
|
762
|
+
const isInstalled = await checkExtension(checkTimeout);
|
|
763
|
+
if (!isInstalled) {
|
|
764
|
+
this.setState("not-installed");
|
|
765
|
+
return this.getResult();
|
|
766
|
+
}
|
|
767
|
+
this.setState("connecting");
|
|
768
|
+
try {
|
|
769
|
+
const extension = await connectExtension(connectTimeout);
|
|
770
|
+
this.setState("connected", extension);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
this.setState(
|
|
773
|
+
"error",
|
|
774
|
+
null,
|
|
775
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
return this.getResult();
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Reset state and disconnect
|
|
782
|
+
*/
|
|
783
|
+
reset() {
|
|
784
|
+
this.state = "idle";
|
|
785
|
+
this.extension = null;
|
|
786
|
+
this.error = void 0;
|
|
787
|
+
this.connectionPromise = null;
|
|
788
|
+
this.notify();
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
var defaultConnector = null;
|
|
792
|
+
function getDefaultConnector(options) {
|
|
793
|
+
if (!defaultConnector) {
|
|
794
|
+
defaultConnector = new ExtensionConnector(options);
|
|
795
|
+
}
|
|
796
|
+
return defaultConnector;
|
|
797
|
+
}
|
|
798
|
+
function resetDefaultConnector() {
|
|
799
|
+
if (defaultConnector) {
|
|
800
|
+
defaultConnector.reset();
|
|
801
|
+
defaultConnector = null;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
826
805
|
exports.DEFAULT_MAX_HOPS = DEFAULT_MAX_HOPS;
|
|
827
806
|
exports.DEFAULT_ORACLE = DEFAULT_ORACLE;
|
|
828
807
|
exports.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
|
package/dist/index.d.cts
CHANGED
|
@@ -365,13 +365,12 @@ declare class WoT {
|
|
|
365
365
|
private readonly timeout;
|
|
366
366
|
private readonly fallbackOptions;
|
|
367
367
|
private extension;
|
|
368
|
-
private extensionChecked;
|
|
369
368
|
private extensionPubkey;
|
|
370
369
|
constructor(options?: WoTOptions);
|
|
371
370
|
/**
|
|
372
371
|
* Checks if browser extension is available and returns it
|
|
373
|
-
*
|
|
374
|
-
* Always returns fresh reference
|
|
372
|
+
* Simply checks window.nostr.wot - extension auto-injects when enabled
|
|
373
|
+
* Always returns fresh reference to handle extension reloads
|
|
375
374
|
*/
|
|
376
375
|
private getExtension;
|
|
377
376
|
/**
|