@konemono/nostr-login 1.7.27 → 1.7.29

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konemono/nostr-login",
3
- "version": "1.7.27",
3
+ "version": "1.7.29",
4
4
  "description": "",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,579 +1,173 @@
1
- import NDK, { NDKEvent, NDKFilter, NDKNip46Signer, NDKNostrRpc, NDKRpcRequest, NDKRpcResponse, NDKSubscription, NDKSubscriptionCacheUsage, NostrEvent } from '@nostr-dev-kit/ndk';
1
+ // Nip46.ts
2
+ import NDK, { NDKEvent, NDKFilter, NDKNip46Signer, NDKNostrRpc, NDKRpcRequest, NDKRpcResponse, NDKSubscription, NostrEvent } from '@nostr-dev-kit/ndk';
2
3
  import { validateEvent, verifySignature } from 'nostr-tools';
3
4
  import { PrivateKeySigner } from './Signer';
4
5
  import { NIP46_TIMEOUT } from '../const';
5
6
  import ProcessManager from './ProcessManager';
6
7
 
8
+ /* =========================
9
+ * NostrRpc
10
+ * ========================= */
7
11
  class NostrRpc extends NDKNostrRpc {
8
- protected processManager?: ProcessManager;
12
+ protected processManager: ProcessManager;
9
13
  protected _ndk: NDK;
10
14
  protected _signer: PrivateKeySigner;
11
15
  protected requests: Set<string> = new Set();
12
16
  protected requestTimeouts: Map<string, NodeJS.Timeout> = new Map();
13
17
  private sub?: NDKSubscription;
14
- protected _useNip44: boolean = false;
18
+ protected _useNip44 = false;
15
19
 
16
- public constructor(ndk: NDK, signer: PrivateKeySigner, processManager?: ProcessManager) {
20
+ constructor(ndk: NDK, signer: PrivateKeySigner, processManager: ProcessManager) {
17
21
  super(ndk, signer, ndk.debug.extend('nip46:signer:rpc'));
18
22
  this._ndk = ndk;
19
23
  this._signer = signer;
20
24
  this.processManager = processManager;
21
25
  }
22
26
 
23
- public async subscribe(filter: NDKFilter): Promise<NDKSubscription> {
27
+ async subscribe(filter: NDKFilter): Promise<NDKSubscription> {
24
28
  filter.kinds = filter.kinds?.filter(k => k === 24133);
25
29
  this.sub = await super.subscribe(filter);
26
30
  return this.sub;
27
31
  }
28
32
 
29
- public stop() {
30
- this.clearAllTimeouts();
33
+ stop() {
34
+ for (const t of this.requestTimeouts.values()) clearTimeout(t);
35
+ this.requestTimeouts.clear();
31
36
  if (this.sub) {
32
37
  this.sub.stop();
33
38
  this.sub = undefined;
34
39
  }
35
40
  }
36
41
 
37
- private clearAllTimeouts() {
38
- for (const timeout of this.requestTimeouts.values()) {
39
- clearTimeout(timeout);
40
- }
41
- this.requestTimeouts.clear();
42
- }
43
-
44
42
  protected clearTimeout(id: string) {
45
- const timeout = this.requestTimeouts.get(id);
46
- if (timeout) {
47
- clearTimeout(timeout);
48
- this.requestTimeouts.delete(id);
49
- }
43
+ const t = this.requestTimeouts.get(id);
44
+ if (t) clearTimeout(t);
45
+ this.requestTimeouts.delete(id);
50
46
  }
51
47
 
52
- public setUseNip44(useNip44: boolean) {
53
- this._useNip44 = useNip44;
48
+ setUseNip44(v: boolean) {
49
+ this._useNip44 = v;
54
50
  }
55
51
 
56
- private isNip04(ciphertext: string) {
57
- const l = ciphertext.length;
58
- if (l < 28) return false;
59
- return ciphertext[l - 28] === '?' && ciphertext[l - 27] === 'i' && ciphertext[l - 26] === 'v' && ciphertext[l - 25] === '=';
60
- }
61
-
62
- public async parseEvent(event: NDKEvent): Promise<NDKRpcRequest | NDKRpcResponse> {
52
+ async parseEvent(event: NDKEvent): Promise<NDKRpcRequest | NDKRpcResponse> {
63
53
  const remoteUser = this._ndk.getUser({ pubkey: event.pubkey });
64
54
  remoteUser.ndk = this._ndk;
65
- const decrypt = this.isNip04(event.content) ? this._signer.decrypt : this._signer.decryptNip44;
66
- const decryptedContent = await decrypt.call(this._signer, remoteUser, event.content);
67
- const parsedContent = JSON.parse(decryptedContent);
68
- const { id, method, params, result, error } = parsedContent;
69
-
70
- if (method) {
71
- return { id, pubkey: event.pubkey, method, params, event };
72
- } else {
73
- return { id, result, error, event };
74
- }
75
- }
76
55
 
77
- public async parseNostrConnectReply(reply: any, secret: string) {
78
- const event = new NDKEvent(this._ndk, reply);
79
- const parsedEvent = await this.parseEvent(event);
80
- console.log('nostr connect parsedEvent', parsedEvent);
81
- if (!(parsedEvent as NDKRpcRequest).method) {
82
- const response = parsedEvent as NDKRpcResponse;
83
- if (response.result !== secret) throw new Error(response.error);
84
- return event.pubkey;
85
- } else {
86
- throw new Error('Bad nostr connect reply');
87
- }
88
- }
56
+ const decrypted = await this._signer.decrypt.call(this._signer, remoteUser, event.content);
89
57
 
90
- public async listen(nostrConnectSecret: string): Promise<string> {
91
- const pubkey = this._signer.pubkey;
92
- console.log('nostr-login listening for conn to', pubkey);
93
- const sub = await this.subscribe({
94
- 'kinds': [24133],
95
- '#p': [pubkey],
96
- });
97
- return new Promise<string>((ok, err) => {
98
- const timeoutId = setTimeout(() => {
99
- this.stop();
100
- err(new Error('NIP46 listen timeout'));
101
- }, NIP46_TIMEOUT);
102
-
103
- sub.on('event', async (event: NDKEvent) => {
104
- try {
105
- const parsedEvent = await this.parseEvent(event);
106
- if (!(parsedEvent as NDKRpcRequest).method) {
107
- const response = parsedEvent as NDKRpcResponse;
108
-
109
- if (response.result === 'auth_url') return;
110
-
111
- if (response.result === 'ack' || response.result === nostrConnectSecret) {
112
- clearTimeout(timeoutId);
113
- ok(event.pubkey);
114
- } else {
115
- clearTimeout(timeoutId);
116
- err(response.error);
117
- }
118
- }
119
- } catch (e) {
120
- console.log('error parsing event', e, event.rawEvent());
121
- }
122
- this.stop();
123
- });
124
- });
125
- }
58
+ const { id, method, params, result, error } = JSON.parse(decrypted);
126
59
 
127
- public async connect(pubkey: string, token?: string, perms?: string) {
128
- return new Promise<void>((ok, err) => {
129
- const connectParams = [pubkey!, token || '', perms || ''];
130
-
131
- const timeoutId = setTimeout(() => {
132
- err(new Error('NIP46 connect timeout'));
133
- }, NIP46_TIMEOUT);
134
-
135
- this.sendRequest(pubkey!, 'connect', connectParams, 24133, (response: NDKRpcResponse) => {
136
- clearTimeout(timeoutId);
137
- if (response.result === 'ack') {
138
- ok();
139
- } else {
140
- err(response.error);
141
- }
142
- });
143
- });
60
+ return method ? { id, pubkey: event.pubkey, method, params, event } : { id, result, error, event };
144
61
  }
145
62
 
146
- protected getId(): string {
147
- return Math.random().toString(36).substring(7);
63
+ protected getId() {
64
+ return Math.random().toString(36).slice(2);
148
65
  }
149
66
 
150
- protected async ensureConnected(): Promise<void> {
67
+ protected async ensureConnected() {
151
68
  const relays = Array.from(this._ndk.pool.relays.values());
152
- console.log(
153
- 'Checking relay connections:',
154
- relays.map(r => ({ url: r.url, status: r.status })),
155
- );
156
-
157
- const connectedRelays = relays.filter(r => r.status === 1);
158
-
159
- if (connectedRelays.length === 0) {
160
- console.log('No connected relays, forcing reconnection...');
161
-
162
- // 既存の接続を全てクリーンアップ
163
- for (const relay of relays) {
164
- try {
165
- await relay.disconnect();
166
- } catch (e) {
167
- console.log('Error disconnecting relay:', relay.url, e);
168
- }
169
- }
69
+ if (relays.some(r => r.status === 1)) return;
170
70
 
171
- // 再接続
172
- await this._ndk.connect();
173
-
174
- // 接続確立を待つ
175
- await new Promise<void>((resolve, reject) => {
176
- const timeout = setTimeout(() => {
177
- const status = Array.from(this._ndk.pool.relays.values()).map(r => ({ url: r.url, status: r.status }));
178
- console.error('Failed to reconnect to relays within 10s. Status:', status);
179
- reject(new Error('Failed to reconnect to relays'));
180
- }, 10000);
181
-
182
- const checkConnection = () => {
183
- const connected = Array.from(this._ndk.pool.relays.values()).filter(r => r.status === 1);
184
- if (connected.length > 0) {
185
- clearTimeout(timeout);
186
- console.log(
187
- 'Successfully reconnected to',
188
- connected.length,
189
- 'relays:',
190
- connected.map(r => r.url),
191
- );
192
- resolve();
193
- } else {
194
- setTimeout(checkConnection, 200);
195
- }
196
- };
197
- checkConnection();
198
- });
199
- } else {
200
- console.log(
201
- 'Already connected to',
202
- connectedRelays.length,
203
- 'relays:',
204
- connectedRelays.map(r => r.url),
205
- );
71
+ for (const r of relays) {
72
+ try {
73
+ await r.disconnect();
74
+ } catch {}
206
75
  }
207
- }
208
76
 
209
- public async sendRequest(remotePubkey: string, method: string, params: string[] = [], kind = 24133, cb?: (res: NDKRpcResponse) => void): Promise<NDKRpcResponse> {
210
- console.log('sendRequest called:', method, 'to', remotePubkey);
77
+ await this._ndk.connect();
78
+ }
211
79
 
80
+ async sendRequest(remotePubkey: string, method: string, params: string[] = [], kind = 24133, cb?: (r: NDKRpcResponse) => void): Promise<NDKRpcResponse> {
81
+ this.processManager.pause();
212
82
  try {
213
- this.processManager?.pause();
214
83
  await this.ensureConnected();
215
- } catch (e) {
216
- console.error('Failed to ensure connection:', e);
217
- if (cb) {
218
- cb({
219
- id: '',
220
- result: '',
221
- error: 'Failed to connect to relays: ' + (e as Error).message,
222
- event: undefined as any,
223
- });
224
- }
225
- throw e;
226
84
  } finally {
227
- this.processManager?.resume();
85
+ this.processManager.resume();
228
86
  }
229
87
 
230
88
  const id = this.getId();
231
-
232
89
  this.setResponseHandler(id, cb);
233
90
 
234
91
  const event = await this.createRequestEvent(id, remotePubkey, method, params, kind);
235
- console.log('sendRequest event created', { event, method, remotePubkey, params });
236
-
237
- try {
238
- await event.publish();
239
- console.log('sendRequest event published successfully');
240
- } catch (e) {
241
- console.error('Failed to publish event:', e);
242
- this.clearTimeout(id);
243
- this.requests.delete(id);
244
- if (cb) {
245
- cb({
246
- id,
247
- result: '',
248
- error: 'Failed to publish event: ' + (e as Error).message,
249
- event: undefined as any,
250
- });
251
- }
252
- throw e;
253
- }
92
+ await event.publish();
254
93
 
255
94
  // @ts-ignore
256
- return undefined as NDKRpcResponse;
95
+ return undefined;
257
96
  }
258
97
 
259
- protected setResponseHandler(id: string, cb?: (res: NDKRpcResponse) => void) {
260
- let authUrlSent = false;
261
- const now = Date.now();
262
-
263
- const timeoutId = setTimeout(() => {
264
- if (this.requests.has(id)) {
265
- this.requests.delete(id);
266
- this.requestTimeouts.delete(id);
267
- console.log('NIP46 request timeout for', id);
268
- if (cb) {
269
- cb({
270
- id,
271
- result: '',
272
- error: 'NIP46 request timeout',
273
- event: undefined as any,
274
- });
275
- }
276
- }
98
+ protected setResponseHandler(id: string, cb?: (r: NDKRpcResponse) => void) {
99
+ const to = setTimeout(() => {
100
+ this.requests.delete(id);
101
+ cb?.({ id, result: '', error: 'timeout', event: undefined as any });
277
102
  }, NIP46_TIMEOUT);
278
103
 
279
- this.requestTimeouts.set(id, timeoutId);
280
-
281
- return new Promise<NDKRpcResponse>(() => {
282
- const responseHandler = (response: NDKRpcResponse) => {
283
- if (response.result === 'auth_url') {
284
- this.once(`response-${id}`, responseHandler);
285
- if (!authUrlSent) {
286
- authUrlSent = true;
287
- this.emit('authUrl', response.error);
288
- }
289
- } else if (cb) {
290
- if (this.requests.has(id)) {
291
- this.clearTimeout(id);
292
- this.requests.delete(id);
293
- console.log('nostr-login processed nip46 request in', Date.now() - now, 'ms');
294
- cb(response);
295
- }
296
- }
297
- };
298
-
299
- this.once(`response-${id}`, responseHandler);
104
+ this.requestTimeouts.set(id, to);
105
+
106
+ this.once(`response-${id}`, r => {
107
+ this.clearTimeout(id);
108
+ this.requests.delete(id);
109
+ cb?.(r);
300
110
  });
301
111
  }
302
112
 
303
- protected async createRequestEvent(id: string, remotePubkey: string, method: string, params: string[] = [], kind = 24133) {
113
+ protected async createRequestEvent(id: string, remotePubkey: string, method: string, params: string[], kind: number) {
304
114
  this.requests.add(id);
305
115
  const localUser = await this._signer.user();
306
116
  const remoteUser = this._ndk.getUser({ pubkey: remotePubkey });
307
- const request = { id, method, params };
308
117
 
309
118
  const event = new NDKEvent(this._ndk, {
310
119
  kind,
311
- content: JSON.stringify(request),
120
+ content: JSON.stringify({ id, method, params }),
312
121
  tags: [['p', remotePubkey]],
313
122
  pubkey: localUser.pubkey,
314
123
  } as NostrEvent);
315
124
 
316
- const useNip44 = this._useNip44 && method !== 'create_account';
317
- const encrypt = useNip44 ? this._signer.encryptNip44 : this._signer.encrypt;
318
- event.content = await encrypt.call(this._signer, remoteUser, event.content);
319
- await event.sign(this._signer);
125
+ event.content = await this._signer.encrypt.call(this._signer, remoteUser, event.content);
320
126
 
127
+ await event.sign(this._signer);
321
128
  return event;
322
129
  }
323
130
  }
324
131
 
132
+ /* =========================
133
+ * IframeNostrRpc
134
+ * ========================= */
325
135
  export class IframeNostrRpc extends NostrRpc {
326
- private peerOrigin?: string;
327
136
  private iframePort?: MessagePort;
328
- private iframeRequests = new Map<string, { id: string; pubkey: string }>();
329
-
330
- public constructor(ndk: NDK, localSigner: PrivateKeySigner, iframePeerOrigin?: string) {
331
- super(ndk, localSigner);
332
- this._ndk = ndk;
333
- this.peerOrigin = iframePeerOrigin;
334
- }
335
137
 
336
- public async subscribe(filter: NDKFilter): Promise<NDKSubscription> {
337
- if (!this.peerOrigin) return super.subscribe(filter);
338
- return new NDKSubscription(
339
- this._ndk,
340
- {},
341
- {
342
- closeOnEose: true,
343
- cacheUsage: NDKSubscriptionCacheUsage.ONLY_CACHE,
344
- },
345
- );
138
+ constructor(ndk: NDK, signer: PrivateKeySigner, processManager: ProcessManager) {
139
+ super(ndk, signer, processManager);
346
140
  }
347
141
 
348
- public setWorkerIframePort(port: MessagePort) {
349
- if (!this.peerOrigin) throw new Error('Unexpected iframe port');
350
-
142
+ setWorkerIframePort(port: MessagePort) {
351
143
  this.iframePort = port;
352
144
 
353
- setInterval(() => {
354
- console.log('iframe-nip46 ping');
355
- this.iframePort!.postMessage('ping');
356
- }, 5000);
357
-
358
145
  port.onmessage = async ev => {
359
- console.log('iframe-nip46 got response', ev.data);
360
- if (typeof ev.data === 'string' && ev.data.startsWith('errorNoKey')) {
361
- const event_id = ev.data.split(':')[1];
362
- const { id = '', pubkey = '' } = this.iframeRequests.get(event_id) || {};
363
- if (id && pubkey && this.requests.has(id)) this.emit(`iframeRestart-${pubkey}`);
364
- return;
365
- }
366
-
367
- try {
368
- const event = ev.data;
369
-
370
- if (!validateEvent(event)) throw new Error('Invalid event from iframe');
371
- if (!verifySignature(event)) throw new Error('Invalid event signature from iframe');
372
- const nevent = new NDKEvent(this._ndk, event);
373
- const parsedEvent = await this.parseEvent(nevent);
374
- if (!(parsedEvent as NDKRpcRequest).method) {
375
- console.log('parsed response', parsedEvent);
376
- this.emit(`response-${parsedEvent.id}`, parsedEvent);
377
- }
378
- } catch (e) {
379
- console.log('error parsing event', e, ev.data);
146
+ const event = ev.data;
147
+ if (!validateEvent(event) || !verifySignature(event)) return;
148
+ const parsed = await this.parseEvent(new NDKEvent(this._ndk, event));
149
+ if (!('method' in parsed)) {
150
+ this.emit(`response-${parsed.id}`, parsed);
380
151
  }
381
152
  };
382
153
  }
383
-
384
- public async sendRequest(remotePubkey: string, method: string, params: string[] = [], kind = 24133, cb?: (res: NDKRpcResponse) => void): Promise<NDKRpcResponse> {
385
- console.log('IframeNostrRpc.sendRequest called:', method, 'iframePort:', !!this.iframePort);
386
-
387
- if (!this.iframePort) {
388
- try {
389
- this.processManager?.pause();
390
- await this.ensureConnected();
391
- } catch (e) {
392
- console.error('Failed to ensure connection:', e);
393
- if (cb) {
394
- cb({
395
- id: '',
396
- result: '',
397
- error: 'Failed to connect to relays: ' + (e as Error).message,
398
- event: undefined as any,
399
- });
400
- }
401
- throw e;
402
- } finally {
403
- this.processManager?.resume();
404
- }
405
- }
406
-
407
- const id = this.getId();
408
-
409
- const event = await this.createRequestEvent(id, remotePubkey, method, params, kind);
410
-
411
- this.setResponseHandler(id, cb);
412
-
413
- if (this.iframePort) {
414
- this.iframeRequests.set(event.id, { id, pubkey: remotePubkey });
415
-
416
- console.log('iframe-nip46 sending request to', this.peerOrigin, event.rawEvent());
417
- this.iframePort.postMessage(event.rawEvent());
418
- } else {
419
- try {
420
- await event.publish();
421
- console.log('Request published to relays successfully');
422
- } catch (e) {
423
- console.error('Failed to publish event:', e);
424
- this.clearTimeout(id);
425
- this.requests.delete(id);
426
- if (cb) {
427
- cb({
428
- id,
429
- result: '',
430
- error: 'Failed to publish event: ' + (e as Error).message,
431
- event: undefined as any,
432
- });
433
- }
434
- throw e;
435
- }
436
- }
437
-
438
- // @ts-ignore
439
- return undefined as NDKRpcResponse;
440
- }
441
- }
442
-
443
- export class ReadyListener {
444
- origin: string;
445
- messages: string[];
446
- promise: Promise<any>;
447
-
448
- constructor(messages: string[], origin: string) {
449
- this.origin = origin;
450
- this.messages = messages;
451
- this.promise = new Promise<any>(ok => {
452
- console.log(new Date(), 'started listener for', this.messages);
453
-
454
- const onReady = async (e: MessageEvent) => {
455
- const originHostname = new URL(origin!).hostname;
456
- const messageHostname = new URL(e.origin).hostname;
457
- const validHost = messageHostname === originHostname || messageHostname.endsWith('.' + originHostname);
458
- if (!validHost || !Array.isArray(e.data) || !e.data.length || !this.messages.includes(e.data[0])) {
459
- return;
460
- }
461
-
462
- console.log(new Date(), 'got ready message from', e.origin, e.data);
463
- window.removeEventListener('message', onReady);
464
- ok(e.data);
465
- };
466
- window.addEventListener('message', onReady);
467
- });
468
- }
469
-
470
- async wait(): Promise<any> {
471
- console.log(new Date(), 'waiting for', this.messages);
472
- const r = await this.promise;
473
- console.log(new Date(), 'finished waiting for', this.messages, r);
474
- return r;
475
- }
476
154
  }
477
155
 
156
+ /* =========================
157
+ * Nip46Signer
158
+ * ========================= */
478
159
  export class Nip46Signer extends NDKNip46Signer {
479
- private _userPubkey: string = '';
480
160
  private _rpc: IframeNostrRpc;
481
161
 
482
- constructor(ndk: NDK, localSigner: PrivateKeySigner, signerPubkey: string, iframeOrigin?: string) {
162
+ constructor(ndk: NDK, localSigner: PrivateKeySigner, signerPubkey: string) {
163
+ const pm = new ProcessManager();
483
164
  super(ndk, signerPubkey, localSigner);
484
165
 
485
- this._rpc = new IframeNostrRpc(ndk, localSigner, iframeOrigin);
486
- this._rpc.setUseNip44(true);
487
- this._rpc.on('authUrl', (url: string) => {
488
- this.emit('authUrl', url);
489
- });
490
-
166
+ this._rpc = new IframeNostrRpc(ndk, localSigner, pm);
491
167
  this.rpc = this._rpc;
492
- }
493
-
494
- get userPubkey() {
495
- return this._userPubkey;
496
- }
497
-
498
- private async setSignerPubkey(signerPubkey: string, sameAsUser: boolean = false) {
499
- console.log('setSignerPubkey', signerPubkey);
500
168
 
501
- this.remotePubkey = signerPubkey;
502
-
503
- this._rpc.on(`iframeRestart-${signerPubkey}`, () => {
504
- this.emit('iframeRestart');
505
- });
506
-
507
- await this.initUserPubkey(sameAsUser ? signerPubkey : '');
508
- }
509
-
510
- public async initUserPubkey(hintPubkey?: string) {
511
- if (this._userPubkey) throw new Error('Already called initUserPubkey');
512
-
513
- if (hintPubkey) {
514
- this._userPubkey = hintPubkey;
515
- return;
516
- }
517
-
518
- this._userPubkey = await new Promise<string>((ok, err) => {
519
- if (!this.remotePubkey) throw new Error('Signer pubkey not set');
520
-
521
- console.log('get_public_key', this.remotePubkey);
522
-
523
- const timeoutId = setTimeout(() => {
524
- err(new Error('NIP46 get_public_key timeout'));
525
- }, NIP46_TIMEOUT);
526
-
527
- this._rpc.sendRequest(this.remotePubkey, 'get_public_key', [], 24133, (response: NDKRpcResponse) => {
528
- clearTimeout(timeoutId);
529
- if (response.error) {
530
- err(new Error(response.error));
531
- } else {
532
- ok(response.result);
533
- }
534
- });
535
- });
536
- }
537
-
538
- public async listen(nostrConnectSecret: string) {
539
- const signerPubkey = await (this.rpc as IframeNostrRpc).listen(nostrConnectSecret);
540
- await this.setSignerPubkey(signerPubkey);
541
- }
542
-
543
- public async connect(token?: string, perms?: string) {
544
- if (!this.remotePubkey) throw new Error('No signer pubkey');
545
- await this._rpc.connect(this.remotePubkey, token, perms);
546
- await this.setSignerPubkey(this.remotePubkey);
547
- }
548
-
549
- public async setListenReply(reply: any, nostrConnectSecret: string) {
550
- const signerPubkey = await this._rpc.parseNostrConnectReply(reply, nostrConnectSecret);
551
- await this.setSignerPubkey(signerPubkey, true);
552
- }
553
-
554
- public async createAccount2({ bunkerPubkey, name, domain, perms = '' }: { bunkerPubkey: string; name: string; domain: string; perms?: string }) {
555
- const params = [name, domain, '', perms];
556
-
557
- const r = await new Promise<NDKRpcResponse>((ok, err) => {
558
- const timeoutId = setTimeout(() => {
559
- err(new Error('NIP46 create_account timeout'));
560
- }, NIP46_TIMEOUT);
561
-
562
- this.rpc.sendRequest(bunkerPubkey, 'create_account', params, undefined, response => {
563
- clearTimeout(timeoutId);
564
- if (response.error) {
565
- err(new Error(response.error));
566
- } else {
567
- ok(response);
568
- }
569
- });
169
+ this._rpc.on('authUrl', url => {
170
+ this.emit('authUrl', url);
570
171
  });
571
-
572
- console.log('create_account pubkey', r);
573
- if (r.result === 'error') {
574
- throw new Error(r.error);
575
- }
576
-
577
- return r.result;
578
172
  }
579
173
  }
@@ -2,34 +2,45 @@ import { EventEmitter } from 'tseep';
2
2
  import { CALL_TIMEOUT } from '../const';
3
3
 
4
4
  class ProcessManager extends EventEmitter {
5
- private paused = false;
6
5
  private callCount = 0;
7
6
  private callTimer?: NodeJS.Timeout;
7
+ private paused = false;
8
8
 
9
- constructor() {
10
- super();
11
- }
12
-
9
+ /* 呼び出し元互換 */
13
10
  public onAuthUrl() {
14
11
  this.resetTimer();
15
12
  }
16
13
 
14
+ /* 呼び出し元互換 */
17
15
  public onIframeUrl() {
18
16
  this.resetTimer();
19
17
  }
20
18
 
21
- private startTimer() {
19
+ private resetTimer() {
22
20
  if (this.paused) return;
21
+
23
22
  if (this.callTimer) clearTimeout(this.callTimer);
24
23
 
24
+ if (this.callCount > 0) {
25
+ this.callTimer = setTimeout(() => {
26
+ this.emit('onCallTimeout');
27
+ }, CALL_TIMEOUT);
28
+ }
29
+ }
30
+
31
+ private startTimer() {
32
+ if (this.paused) return;
33
+ if (this.callTimer) return;
34
+
25
35
  this.callTimer = setTimeout(() => {
26
36
  this.emit('onCallTimeout');
27
37
  }, CALL_TIMEOUT);
28
38
  }
29
39
 
30
- private resetTimer() {
31
- if (this.callCount > 0) {
32
- this.startTimer();
40
+ private stopTimerIfIdle() {
41
+ if (this.callCount === 0 && this.callTimer) {
42
+ clearTimeout(this.callTimer);
43
+ this.callTimer = undefined;
33
44
  }
34
45
  }
35
46
 
@@ -39,23 +50,19 @@ class ProcessManager extends EventEmitter {
39
50
  }
40
51
 
41
52
  this.callCount++;
42
- this.startTimer();
43
53
 
44
54
  try {
45
- return await cb();
55
+ const p = Promise.resolve().then(cb);
56
+ this.startTimer();
57
+ return await p;
46
58
  } finally {
47
59
  this.callCount--;
48
-
49
- if (this.callCount === 0) {
50
- if (this.callTimer) {
51
- clearTimeout(this.callTimer);
52
- this.callTimer = undefined;
53
- }
54
- this.emit('onCallEnd');
55
- }
60
+ this.emit('onCallEnd');
61
+ this.stopTimerIfIdle();
56
62
  }
57
63
  }
58
64
 
65
+ /* 再接続などで timeout を止めるため */
59
66
  public pause() {
60
67
  this.paused = true;
61
68
  if (this.callTimer) {
@@ -64,9 +71,10 @@ class ProcessManager extends EventEmitter {
64
71
  }
65
72
  }
66
73
 
74
+ /* 再接続完了後に再開 */
67
75
  public resume() {
68
76
  this.paused = false;
69
- if (this.callCount > 0) {
77
+ if (this.callCount > 0 && !this.callTimer) {
70
78
  this.startTimer();
71
79
  }
72
80
  }