@konemono/nostr-login 1.7.36 → 1.7.37
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/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/modules/AuthNostrService.d.ts +3 -3
- package/dist/modules/BannerManager.d.ts +1 -1
- package/dist/modules/ModalManager.d.ts +1 -1
- package/dist/modules/Nip46.d.ts +0 -2
- package/dist/modules/Nostr.d.ts +1 -1
- package/dist/modules/NostrParams.d.ts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/unpkg.js +2 -2
- package/dist/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/const/index.ts +1 -2
- package/src/iife-module.ts +2 -7
- package/src/index.ts +2 -7
- package/src/modules/AuthNostrService.ts +170 -56
- package/src/modules/BannerManager.ts +1 -1
- package/src/modules/ModalManager.ts +58 -51
- package/src/modules/Nip46.ts +70 -249
- package/src/modules/Nostr.ts +1 -1
- package/src/modules/NostrParams.ts +1 -1
- package/src/modules/ProcessManager.ts +18 -57
- package/src/types.ts +31 -1
- package/src/utils/index.ts +1 -1
package/src/modules/Nip46.ts
CHANGED
|
@@ -1,59 +1,34 @@
|
|
|
1
1
|
import NDK, { NDKEvent, NDKFilter, NDKNip46Signer, NDKNostrRpc, NDKRpcRequest, NDKRpcResponse, NDKSubscription, NDKSubscriptionCacheUsage, NostrEvent } from '@nostr-dev-kit/ndk';
|
|
2
2
|
import { validateEvent, verifySignature } from 'nostr-tools';
|
|
3
3
|
import { PrivateKeySigner } from './Signer';
|
|
4
|
-
import { NIP46_TIMEOUT } from '../const';
|
|
5
|
-
import ProcessManager from './ProcessManager';
|
|
6
4
|
|
|
7
5
|
class NostrRpc extends NDKNostrRpc {
|
|
8
|
-
protected processManager?: ProcessManager;
|
|
9
6
|
protected _ndk: NDK;
|
|
10
7
|
protected _signer: PrivateKeySigner;
|
|
11
8
|
protected requests: Set<string> = new Set();
|
|
12
|
-
protected requestTimeouts: Map<string, NodeJS.Timeout> = new Map();
|
|
13
9
|
private sub?: NDKSubscription;
|
|
14
10
|
protected _useNip44: boolean = false;
|
|
15
11
|
|
|
16
|
-
public
|
|
17
|
-
this.clearAllTimeouts(); // private/protected なメソッドを呼び出す
|
|
18
|
-
this.requests.clear(); // requests Setをクリア
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public constructor(ndk: NDK, signer: PrivateKeySigner, processManager?: ProcessManager) {
|
|
12
|
+
public constructor(ndk: NDK, signer: PrivateKeySigner) {
|
|
22
13
|
super(ndk, signer, ndk.debug.extend('nip46:signer:rpc'));
|
|
23
14
|
this._ndk = ndk;
|
|
24
15
|
this._signer = signer;
|
|
25
|
-
this.processManager = processManager;
|
|
26
16
|
}
|
|
27
17
|
|
|
28
18
|
public async subscribe(filter: NDKFilter): Promise<NDKSubscription> {
|
|
19
|
+
// NOTE: fixing ndk
|
|
29
20
|
filter.kinds = filter.kinds?.filter(k => k === 24133);
|
|
30
21
|
this.sub = await super.subscribe(filter);
|
|
31
22
|
return this.sub;
|
|
32
23
|
}
|
|
33
24
|
|
|
34
25
|
public stop() {
|
|
35
|
-
this.clearAllTimeouts();
|
|
36
26
|
if (this.sub) {
|
|
37
27
|
this.sub.stop();
|
|
38
28
|
this.sub = undefined;
|
|
39
29
|
}
|
|
40
30
|
}
|
|
41
31
|
|
|
42
|
-
protected clearAllTimeouts() {
|
|
43
|
-
for (const timeout of this.requestTimeouts.values()) {
|
|
44
|
-
clearTimeout(timeout);
|
|
45
|
-
}
|
|
46
|
-
this.requestTimeouts.clear();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
protected clearTimeout(id: string) {
|
|
50
|
-
const timeout = this.requestTimeouts.get(id);
|
|
51
|
-
if (timeout) {
|
|
52
|
-
clearTimeout(timeout);
|
|
53
|
-
this.requestTimeouts.delete(id);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
32
|
public setUseNip44(useNip44: boolean) {
|
|
58
33
|
this._useNip44 = useNip44;
|
|
59
34
|
}
|
|
@@ -64,6 +39,7 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
64
39
|
return ciphertext[l - 28] === '?' && ciphertext[l - 27] === 'i' && ciphertext[l - 26] === 'v' && ciphertext[l - 25] === '=';
|
|
65
40
|
}
|
|
66
41
|
|
|
42
|
+
// override to auto-decrypt nip04/nip44
|
|
67
43
|
public async parseEvent(event: NDKEvent): Promise<NDKRpcRequest | NDKRpcResponse> {
|
|
68
44
|
const remoteUser = this._ndk.getUser({ pubkey: event.pubkey });
|
|
69
45
|
remoteUser.ndk = this._ndk;
|
|
@@ -92,6 +68,9 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
92
68
|
}
|
|
93
69
|
}
|
|
94
70
|
|
|
71
|
+
// ndk doesn't support nostrconnect:
|
|
72
|
+
// we just listed to an unsolicited reply to
|
|
73
|
+
// our pubkey and if it's ack/secret - we're fine
|
|
95
74
|
public async listen(nostrConnectSecret: string): Promise<string> {
|
|
96
75
|
const pubkey = this._signer.pubkey;
|
|
97
76
|
console.log('nostr-login listening for conn to', pubkey);
|
|
@@ -100,45 +79,40 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
100
79
|
'#p': [pubkey],
|
|
101
80
|
});
|
|
102
81
|
return new Promise<string>((ok, err) => {
|
|
103
|
-
const timeoutId = setTimeout(() => {
|
|
104
|
-
this.stop();
|
|
105
|
-
err(new Error('NIP46 listen timeout'));
|
|
106
|
-
}, NIP46_TIMEOUT);
|
|
107
|
-
|
|
108
82
|
sub.on('event', async (event: NDKEvent) => {
|
|
109
83
|
try {
|
|
110
84
|
const parsedEvent = await this.parseEvent(event);
|
|
85
|
+
// console.log('ack parsedEvent', parsedEvent);
|
|
111
86
|
if (!(parsedEvent as NDKRpcRequest).method) {
|
|
112
87
|
const response = parsedEvent as NDKRpcResponse;
|
|
113
88
|
|
|
89
|
+
// ignore
|
|
114
90
|
if (response.result === 'auth_url') return;
|
|
115
91
|
|
|
92
|
+
// FIXME for now accept 'ack' replies, later on only
|
|
93
|
+
// accept secrets
|
|
116
94
|
if (response.result === 'ack' || response.result === nostrConnectSecret) {
|
|
117
|
-
clearTimeout(timeoutId);
|
|
118
95
|
ok(event.pubkey);
|
|
119
96
|
} else {
|
|
120
|
-
clearTimeout(timeoutId);
|
|
121
97
|
err(response.error);
|
|
122
98
|
}
|
|
123
99
|
}
|
|
124
100
|
} catch (e) {
|
|
125
101
|
console.log('error parsing event', e, event.rawEvent());
|
|
126
102
|
}
|
|
103
|
+
// done
|
|
127
104
|
this.stop();
|
|
128
105
|
});
|
|
129
106
|
});
|
|
130
107
|
}
|
|
131
108
|
|
|
109
|
+
// since ndk doesn't yet support perms param
|
|
110
|
+
// we reimplement the 'connect' call here
|
|
111
|
+
// instead of await signer.blockUntilReady();
|
|
132
112
|
public async connect(pubkey: string, token?: string, perms?: string) {
|
|
133
113
|
return new Promise<void>((ok, err) => {
|
|
134
114
|
const connectParams = [pubkey!, token || '', perms || ''];
|
|
135
|
-
|
|
136
|
-
const timeoutId = setTimeout(() => {
|
|
137
|
-
err(new Error('NIP46 connect timeout'));
|
|
138
|
-
}, NIP46_TIMEOUT);
|
|
139
|
-
|
|
140
115
|
this.sendRequest(pubkey!, 'connect', connectParams, 24133, (response: NDKRpcResponse) => {
|
|
141
|
-
clearTimeout(timeoutId);
|
|
142
116
|
if (response.result === 'ack') {
|
|
143
117
|
ok();
|
|
144
118
|
} else {
|
|
@@ -152,113 +126,24 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
152
126
|
return Math.random().toString(36).substring(7);
|
|
153
127
|
}
|
|
154
128
|
|
|
155
|
-
protected async ensureConnected(): Promise<void> {
|
|
156
|
-
const relays = Array.from(this._ndk.pool.relays.values());
|
|
157
|
-
console.log(
|
|
158
|
-
'Checking relay connections:',
|
|
159
|
-
relays.map(r => ({ url: r.url, status: r.status })),
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
const connectedRelays = relays.filter(r => r.status === 1);
|
|
163
|
-
console.log('connected relays', connectedRelays);
|
|
164
|
-
|
|
165
|
-
if (connectedRelays.length === 0) {
|
|
166
|
-
console.log('No connected relays, forcing reconnection...');
|
|
167
|
-
|
|
168
|
-
// 既存の接続を全てクリーンアップ
|
|
169
|
-
for (const relay of relays) {
|
|
170
|
-
try {
|
|
171
|
-
await relay.disconnect();
|
|
172
|
-
} catch (e) {
|
|
173
|
-
console.log('Error disconnecting relay:', relay.url, e);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// 再接続
|
|
178
|
-
await this._ndk.connect();
|
|
179
|
-
|
|
180
|
-
// 接続確立を待つ
|
|
181
|
-
await new Promise<void>((resolve, reject) => {
|
|
182
|
-
const timeout = setTimeout(() => {
|
|
183
|
-
const status = Array.from(this._ndk.pool.relays.values()).map(r => ({ url: r.url, status: r.status }));
|
|
184
|
-
console.error('Failed to reconnect to relays within 10s. Status:', status);
|
|
185
|
-
reject(new Error('Failed to reconnect to relays'));
|
|
186
|
-
}, 10000);
|
|
187
|
-
|
|
188
|
-
const checkConnection = () => {
|
|
189
|
-
const connected = Array.from(this._ndk.pool.relays.values()).filter(r => r.status === 1);
|
|
190
|
-
if (connected.length > 0) {
|
|
191
|
-
clearTimeout(timeout);
|
|
192
|
-
console.log(
|
|
193
|
-
'Successfully reconnected to',
|
|
194
|
-
connected.length,
|
|
195
|
-
'relays:',
|
|
196
|
-
connected.map(r => r.url),
|
|
197
|
-
);
|
|
198
|
-
resolve();
|
|
199
|
-
} else {
|
|
200
|
-
setTimeout(checkConnection, 200);
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
checkConnection();
|
|
204
|
-
});
|
|
205
|
-
} else {
|
|
206
|
-
console.log(
|
|
207
|
-
'Already connected to',
|
|
208
|
-
connectedRelays.length,
|
|
209
|
-
'relays:',
|
|
210
|
-
connectedRelays.map(r => r.url),
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
129
|
public async sendRequest(remotePubkey: string, method: string, params: string[] = [], kind = 24133, cb?: (res: NDKRpcResponse) => void): Promise<NDKRpcResponse> {
|
|
216
|
-
console.log('sendRequest called:', method, 'to', remotePubkey);
|
|
217
|
-
|
|
218
|
-
try {
|
|
219
|
-
this.processManager?.pause();
|
|
220
|
-
await this.ensureConnected();
|
|
221
|
-
this.processManager?.resetTimer();
|
|
222
|
-
} catch (e) {
|
|
223
|
-
console.error('Failed to ensure connection:', e);
|
|
224
|
-
if (cb) {
|
|
225
|
-
cb({
|
|
226
|
-
id: '',
|
|
227
|
-
result: '',
|
|
228
|
-
error: 'Failed to connect to relays: ' + (e as Error).message,
|
|
229
|
-
event: undefined as any,
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
throw e;
|
|
233
|
-
} finally {
|
|
234
|
-
this.processManager?.resume();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
130
|
const id = this.getId();
|
|
238
131
|
|
|
132
|
+
// response handler will deduplicate auth urls and responses
|
|
239
133
|
this.setResponseHandler(id, cb);
|
|
240
134
|
|
|
135
|
+
// create and sign request
|
|
241
136
|
const event = await this.createRequestEvent(id, remotePubkey, method, params, kind);
|
|
242
|
-
console.log(
|
|
137
|
+
console.log("sendRequest", { event, method, remotePubkey, params });
|
|
243
138
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
console.log('sendRequest event published successfully');
|
|
247
|
-
} catch (e) {
|
|
248
|
-
console.error('Failed to publish event:', e);
|
|
249
|
-
this.clearTimeout(id);
|
|
250
|
-
this.requests.delete(id);
|
|
251
|
-
if (cb) {
|
|
252
|
-
cb({
|
|
253
|
-
id,
|
|
254
|
-
result: '',
|
|
255
|
-
error: 'Failed to publish event: ' + (e as Error).message,
|
|
256
|
-
event: undefined as any,
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
throw e;
|
|
260
|
-
}
|
|
139
|
+
// send to relays
|
|
140
|
+
await event.publish();
|
|
261
141
|
|
|
142
|
+
// NOTE: ndk returns a promise that never resolves and
|
|
143
|
+
// in fact REQUIRES cb to be provided (otherwise no way
|
|
144
|
+
// to consume the result), we've already stepped on the bug
|
|
145
|
+
// of waiting for this unresolvable result, so now we return
|
|
146
|
+
// undefined to make sure waiters fail, not hang.
|
|
262
147
|
// @ts-ignore
|
|
263
148
|
return undefined as NDKRpcResponse;
|
|
264
149
|
}
|
|
@@ -266,26 +151,6 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
266
151
|
protected setResponseHandler(id: string, cb?: (res: NDKRpcResponse) => void) {
|
|
267
152
|
let authUrlSent = false;
|
|
268
153
|
const now = Date.now();
|
|
269
|
-
|
|
270
|
-
const timeoutId = setTimeout(() => {
|
|
271
|
-
if (this.requests.has(id)) {
|
|
272
|
-
clearTimeout(timeoutId);
|
|
273
|
-
this.requests.delete(id);
|
|
274
|
-
this.requestTimeouts.delete(id);
|
|
275
|
-
console.log('NIP46 request timeout for', id);
|
|
276
|
-
if (cb) {
|
|
277
|
-
cb({
|
|
278
|
-
id,
|
|
279
|
-
result: '',
|
|
280
|
-
error: 'NIP46 request timeout',
|
|
281
|
-
event: undefined as any,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}, NIP46_TIMEOUT);
|
|
286
|
-
|
|
287
|
-
this.requestTimeouts.set(id, timeoutId);
|
|
288
|
-
|
|
289
154
|
return new Promise<NDKRpcResponse>(() => {
|
|
290
155
|
const responseHandler = (response: NDKRpcResponse) => {
|
|
291
156
|
if (response.result === 'auth_url') {
|
|
@@ -296,7 +161,6 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
296
161
|
}
|
|
297
162
|
} else if (cb) {
|
|
298
163
|
if (this.requests.has(id)) {
|
|
299
|
-
this.clearTimeout(id);
|
|
300
164
|
this.requests.delete(id);
|
|
301
165
|
console.log('nostr-login processed nip46 request in', Date.now() - now, 'ms');
|
|
302
166
|
cb(response);
|
|
@@ -311,14 +175,6 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
311
175
|
protected async createRequestEvent(id: string, remotePubkey: string, method: string, params: string[] = [], kind = 24133) {
|
|
312
176
|
this.requests.add(id);
|
|
313
177
|
const localUser = await this._signer.user();
|
|
314
|
-
|
|
315
|
-
if (!localUser.pubkey) {
|
|
316
|
-
throw new Error('CORRUPTION: Missing local pubkey. Signer state compromised.');
|
|
317
|
-
}
|
|
318
|
-
if (!remotePubkey) {
|
|
319
|
-
throw new Error('CORRUPTION: Missing remote pubkey. Signer state compromised.');
|
|
320
|
-
}
|
|
321
|
-
|
|
322
178
|
const remoteUser = this._ndk.getUser({ pubkey: remotePubkey });
|
|
323
179
|
const request = { id, method, params };
|
|
324
180
|
|
|
@@ -355,6 +211,7 @@ export class IframeNostrRpc extends NostrRpc {
|
|
|
355
211
|
this._ndk,
|
|
356
212
|
{},
|
|
357
213
|
{
|
|
214
|
+
// don't send to relay
|
|
358
215
|
closeOnEose: true,
|
|
359
216
|
cacheUsage: NDKSubscriptionCacheUsage.ONLY_CACHE,
|
|
360
217
|
},
|
|
@@ -366,6 +223,7 @@ export class IframeNostrRpc extends NostrRpc {
|
|
|
366
223
|
|
|
367
224
|
this.iframePort = port;
|
|
368
225
|
|
|
226
|
+
// to make sure Chrome doesn't terminate the channel
|
|
369
227
|
setInterval(() => {
|
|
370
228
|
console.log('iframe-nip46 ping');
|
|
371
229
|
this.iframePort!.postMessage('ping');
|
|
@@ -380,6 +238,7 @@ export class IframeNostrRpc extends NostrRpc {
|
|
|
380
238
|
return;
|
|
381
239
|
}
|
|
382
240
|
|
|
241
|
+
// a copy-paste from rpc.subscribe
|
|
383
242
|
try {
|
|
384
243
|
const event = ev.data;
|
|
385
244
|
|
|
@@ -387,6 +246,7 @@ export class IframeNostrRpc extends NostrRpc {
|
|
|
387
246
|
if (!verifySignature(event)) throw new Error('Invalid event signature from iframe');
|
|
388
247
|
const nevent = new NDKEvent(this._ndk, event);
|
|
389
248
|
const parsedEvent = await this.parseEvent(nevent);
|
|
249
|
+
// we're only implementing client-side rpc
|
|
390
250
|
if (!(parsedEvent as NDKRpcRequest).method) {
|
|
391
251
|
console.log('parsed response', parsedEvent);
|
|
392
252
|
this.emit(`response-${parsedEvent.id}`, parsedEvent);
|
|
@@ -398,60 +258,31 @@ export class IframeNostrRpc extends NostrRpc {
|
|
|
398
258
|
}
|
|
399
259
|
|
|
400
260
|
public async sendRequest(remotePubkey: string, method: string, params: string[] = [], kind = 24133, cb?: (res: NDKRpcResponse) => void): Promise<NDKRpcResponse> {
|
|
401
|
-
console.log('IframeNostrRpc.sendRequest called:', method, 'iframePort:', !!this.iframePort);
|
|
402
|
-
|
|
403
|
-
if (!this.iframePort) {
|
|
404
|
-
try {
|
|
405
|
-
console.log(this.processManager);
|
|
406
|
-
this.processManager?.pause();
|
|
407
|
-
await this.ensureConnected();
|
|
408
|
-
} catch (e) {
|
|
409
|
-
console.error('Failed to ensure connection:', e);
|
|
410
|
-
if (cb) {
|
|
411
|
-
cb({
|
|
412
|
-
id: '',
|
|
413
|
-
result: '',
|
|
414
|
-
error: 'Failed to connect to relays: ' + (e as Error).message,
|
|
415
|
-
event: undefined as any,
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
throw e;
|
|
419
|
-
} finally {
|
|
420
|
-
this.processManager?.resume();
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
|
|
424
261
|
const id = this.getId();
|
|
425
262
|
|
|
263
|
+
// create and sign request event
|
|
426
264
|
const event = await this.createRequestEvent(id, remotePubkey, method, params, kind);
|
|
427
265
|
|
|
266
|
+
// set response handler, it will dedup auth urls,
|
|
267
|
+
// and also dedup response handlers - we're sending
|
|
268
|
+
// to relays and to iframe
|
|
428
269
|
this.setResponseHandler(id, cb);
|
|
429
270
|
|
|
430
271
|
if (this.iframePort) {
|
|
272
|
+
// map request event id to request id, if iframe
|
|
273
|
+
// has no key it will reply with error:event_id (it can't
|
|
274
|
+
// decrypt the request id without keys)
|
|
431
275
|
this.iframeRequests.set(event.id, { id, pubkey: remotePubkey });
|
|
432
276
|
|
|
277
|
+
// send to iframe
|
|
433
278
|
console.log('iframe-nip46 sending request to', this.peerOrigin, event.rawEvent());
|
|
434
279
|
this.iframePort.postMessage(event.rawEvent());
|
|
435
280
|
} else {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
console.log('Request published to relays successfully');
|
|
439
|
-
} catch (e) {
|
|
440
|
-
console.error('Failed to publish event:', e);
|
|
441
|
-
this.clearTimeout(id);
|
|
442
|
-
this.requests.delete(id);
|
|
443
|
-
if (cb) {
|
|
444
|
-
cb({
|
|
445
|
-
id,
|
|
446
|
-
result: '',
|
|
447
|
-
error: 'Failed to publish event: ' + (e as Error).message,
|
|
448
|
-
event: undefined as any,
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
throw e;
|
|
452
|
-
}
|
|
281
|
+
// send to relays
|
|
282
|
+
await event.publish();
|
|
453
283
|
}
|
|
454
284
|
|
|
285
|
+
// see notes in 'super'
|
|
455
286
|
// @ts-ignore
|
|
456
287
|
return undefined as NDKRpcResponse;
|
|
457
288
|
}
|
|
@@ -468,11 +299,14 @@ export class ReadyListener {
|
|
|
468
299
|
this.promise = new Promise<any>(ok => {
|
|
469
300
|
console.log(new Date(), 'started listener for', this.messages);
|
|
470
301
|
|
|
302
|
+
// ready message handler
|
|
471
303
|
const onReady = async (e: MessageEvent) => {
|
|
472
304
|
const originHostname = new URL(origin!).hostname;
|
|
473
305
|
const messageHostname = new URL(e.origin).hostname;
|
|
306
|
+
// same host or subdomain
|
|
474
307
|
const validHost = messageHostname === originHostname || messageHostname.endsWith('.' + originHostname);
|
|
475
308
|
if (!validHost || !Array.isArray(e.data) || !e.data.length || !this.messages.includes(e.data[0])) {
|
|
309
|
+
// console.log(new Date(), 'got invalid ready message', e.origin, e.data);
|
|
476
310
|
return;
|
|
477
311
|
}
|
|
478
312
|
|
|
@@ -487,6 +321,17 @@ export class ReadyListener {
|
|
|
487
321
|
async wait(): Promise<any> {
|
|
488
322
|
console.log(new Date(), 'waiting for', this.messages);
|
|
489
323
|
const r = await this.promise;
|
|
324
|
+
// NOTE: timer here doesn't help bcs it must be activated when
|
|
325
|
+
// user "confirms", but that's happening on a different
|
|
326
|
+
// origin and we can't really know.
|
|
327
|
+
// await new Promise<any>((ok, err) => {
|
|
328
|
+
// // 10 sec should be more than enough
|
|
329
|
+
// setTimeout(() => err(new Date() + ' timeout for ' + this.message), 10000);
|
|
330
|
+
|
|
331
|
+
// // if promise already resolved or will resolve in the future
|
|
332
|
+
// this.promise.then(ok);
|
|
333
|
+
// });
|
|
334
|
+
|
|
490
335
|
console.log(new Date(), 'finished waiting for', this.messages, r);
|
|
491
336
|
return r;
|
|
492
337
|
}
|
|
@@ -499,8 +344,9 @@ export class Nip46Signer extends NDKNip46Signer {
|
|
|
499
344
|
constructor(ndk: NDK, localSigner: PrivateKeySigner, signerPubkey: string, iframeOrigin?: string) {
|
|
500
345
|
super(ndk, signerPubkey, localSigner);
|
|
501
346
|
|
|
347
|
+
// override with our own rpc implementation
|
|
502
348
|
this._rpc = new IframeNostrRpc(ndk, localSigner, iframeOrigin);
|
|
503
|
-
this._rpc.setUseNip44(true);
|
|
349
|
+
this._rpc.setUseNip44(true); // !!this.params.optionsModal.dev);
|
|
504
350
|
this._rpc.on('authUrl', (url: string) => {
|
|
505
351
|
this.emit('authUrl', url);
|
|
506
352
|
});
|
|
@@ -513,29 +359,20 @@ export class Nip46Signer extends NDKNip46Signer {
|
|
|
513
359
|
}
|
|
514
360
|
|
|
515
361
|
private async setSignerPubkey(signerPubkey: string, sameAsUser: boolean = false) {
|
|
516
|
-
console.log(
|
|
362
|
+
console.log("setSignerPubkey", signerPubkey);
|
|
517
363
|
|
|
364
|
+
// ensure it's set
|
|
518
365
|
this.remotePubkey = signerPubkey;
|
|
519
366
|
|
|
367
|
+
// when we're sure it's known
|
|
520
368
|
this._rpc.on(`iframeRestart-${signerPubkey}`, () => {
|
|
521
369
|
this.emit('iframeRestart');
|
|
522
370
|
});
|
|
523
371
|
|
|
372
|
+
// now call getPublicKey and swap remotePubkey w/ that
|
|
524
373
|
await this.initUserPubkey(sameAsUser ? signerPubkey : '');
|
|
525
374
|
}
|
|
526
375
|
|
|
527
|
-
public forceResetState() {
|
|
528
|
-
console.log('Nip46Signer state reset due to connection failure or timeout.');
|
|
529
|
-
|
|
530
|
-
// 1. ユーザー公開鍵をクリア
|
|
531
|
-
this._userPubkey = '';
|
|
532
|
-
|
|
533
|
-
// 2. リモート公開鍵をクリア
|
|
534
|
-
this.remotePubkey = ''; // 親クラスのプロパティをクリア
|
|
535
|
-
|
|
536
|
-
// 3. RPC側のタイマーとリクエストを、公開メソッド経由でクリア
|
|
537
|
-
(this._rpc as NostrRpc).cleanupTimersAndRequests();
|
|
538
|
-
}
|
|
539
376
|
public async initUserPubkey(hintPubkey?: string) {
|
|
540
377
|
if (this._userPubkey) throw new Error('Already called initUserPubkey');
|
|
541
378
|
|
|
@@ -547,19 +384,9 @@ export class Nip46Signer extends NDKNip46Signer {
|
|
|
547
384
|
this._userPubkey = await new Promise<string>((ok, err) => {
|
|
548
385
|
if (!this.remotePubkey) throw new Error('Signer pubkey not set');
|
|
549
386
|
|
|
550
|
-
console.log(
|
|
551
|
-
|
|
552
|
-
const timeoutId = setTimeout(() => {
|
|
553
|
-
err(new Error('NIP46 get_public_key timeout'));
|
|
554
|
-
}, NIP46_TIMEOUT);
|
|
555
|
-
|
|
387
|
+
console.log("get_public_key", this.remotePubkey);
|
|
556
388
|
this._rpc.sendRequest(this.remotePubkey, 'get_public_key', [], 24133, (response: NDKRpcResponse) => {
|
|
557
|
-
|
|
558
|
-
if (response.error) {
|
|
559
|
-
err(new Error(response.error));
|
|
560
|
-
} else {
|
|
561
|
-
ok(response.result);
|
|
562
|
-
}
|
|
389
|
+
ok(response.result);
|
|
563
390
|
});
|
|
564
391
|
});
|
|
565
392
|
}
|
|
@@ -581,21 +408,15 @@ export class Nip46Signer extends NDKNip46Signer {
|
|
|
581
408
|
}
|
|
582
409
|
|
|
583
410
|
public async createAccount2({ bunkerPubkey, name, domain, perms = '' }: { bunkerPubkey: string; name: string; domain: string; perms?: string }) {
|
|
584
|
-
const params = [
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
if (response.error) {
|
|
594
|
-
err(new Error(response.error));
|
|
595
|
-
} else {
|
|
596
|
-
ok(response);
|
|
597
|
-
}
|
|
598
|
-
});
|
|
411
|
+
const params = [
|
|
412
|
+
name,
|
|
413
|
+
domain,
|
|
414
|
+
'', // email
|
|
415
|
+
perms,
|
|
416
|
+
];
|
|
417
|
+
|
|
418
|
+
const r = await new Promise<NDKRpcResponse>(ok => {
|
|
419
|
+
this.rpc.sendRequest(bunkerPubkey, 'create_account', params, undefined, ok);
|
|
599
420
|
});
|
|
600
421
|
|
|
601
422
|
console.log('create_account pubkey', r);
|
package/src/modules/Nostr.ts
CHANGED
|
@@ -2,7 +2,6 @@ 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: number = 0;
|
|
7
6
|
private callTimer: NodeJS.Timeout | undefined;
|
|
8
7
|
|
|
@@ -11,41 +10,22 @@ class ProcessManager extends EventEmitter {
|
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
public onAuthUrl() {
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
if (Boolean(this.callTimer)) {
|
|
14
|
+
clearTimeout(this.callTimer);
|
|
15
|
+
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
public onIframeUrl() {
|
|
19
|
-
|
|
20
|
-
this.resetTimer();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public resetTimer() {
|
|
24
|
-
// 既存のタイマーがあればクリア
|
|
25
|
-
if (this.callTimer) {
|
|
19
|
+
if (Boolean(this.callTimer)) {
|
|
26
20
|
clearTimeout(this.callTimer);
|
|
27
|
-
this.callTimer = undefined; // IDをクリア
|
|
28
|
-
console.log('ProcessManager: timer reset');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 監視対象が残っていて、かつ一時停止中でなければ、新しいタイマーを設定
|
|
32
|
-
if (this.callCount > 0 && !this.paused) {
|
|
33
|
-
this.callTimer = setTimeout(() => {
|
|
34
|
-
console.log('ProcessManager: timeout reached, emitting onCallTimeout');
|
|
35
|
-
this.callTimer = undefined; // タイムアウト時にIDをクリア
|
|
36
|
-
this.emit('onCallTimeout');
|
|
37
|
-
}, CALL_TIMEOUT);
|
|
38
|
-
console.log(`ProcessManager: new timer set for ${CALL_TIMEOUT} ms`);
|
|
39
21
|
}
|
|
40
22
|
}
|
|
41
23
|
|
|
42
24
|
public async wait<T>(cb: () => Promise<T>): Promise<T> {
|
|
43
|
-
|
|
25
|
+
// FIXME only allow 1 parallel req
|
|
44
26
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// waitの最初の呼び出し時のみ、タイマーを初期設定
|
|
48
|
-
this.resetTimer();
|
|
27
|
+
if (!this.callTimer) {
|
|
28
|
+
this.callTimer = setTimeout(() => this.emit('onCallTimeout'), CALL_TIMEOUT);
|
|
49
29
|
}
|
|
50
30
|
|
|
51
31
|
if (!this.callCount) {
|
|
@@ -54,52 +34,33 @@ class ProcessManager extends EventEmitter {
|
|
|
54
34
|
|
|
55
35
|
this.callCount++;
|
|
56
36
|
|
|
57
|
-
let error
|
|
58
|
-
let result
|
|
37
|
+
let error;
|
|
38
|
+
let result;
|
|
59
39
|
|
|
60
|
-
// 非同期処理の実行
|
|
61
40
|
try {
|
|
62
41
|
result = await cb();
|
|
63
42
|
} catch (e) {
|
|
64
43
|
error = e;
|
|
65
44
|
}
|
|
66
45
|
|
|
67
|
-
// ★ 修正点: クリーンアップロジックを resetTimer に置き換え
|
|
68
|
-
// ProcessManagerの呼び出しカウントをデクリメント
|
|
69
46
|
this.callCount--;
|
|
70
|
-
this.emit('onCallEnd');
|
|
71
|
-
|
|
72
|
-
// リクエスト完了後、タイマーをリセットし、callCountに応じて再設定
|
|
73
|
-
this.resetTimer();
|
|
74
47
|
|
|
75
|
-
|
|
76
|
-
if (error) {
|
|
77
|
-
throw error;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// @ts-ignore
|
|
81
|
-
return result as T;
|
|
82
|
-
}
|
|
48
|
+
this.emit('onCallEnd');
|
|
83
49
|
|
|
84
|
-
public pause() {
|
|
85
|
-
console.log('ProcessManager: PAUSING timer...');
|
|
86
50
|
if (this.callTimer) {
|
|
87
51
|
clearTimeout(this.callTimer);
|
|
88
52
|
}
|
|
89
|
-
this.callTimer = undefined; // タイマーをクリア
|
|
90
|
-
this.paused = true;
|
|
91
|
-
this.emit('onCallPause');
|
|
92
|
-
}
|
|
93
53
|
|
|
94
|
-
|
|
95
|
-
console.log('ProcessManager: RESUMING timer...');
|
|
96
|
-
this.paused = false;
|
|
54
|
+
this.callTimer = undefined;
|
|
97
55
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.resetTimer();
|
|
56
|
+
if (error) {
|
|
57
|
+
throw error;
|
|
101
58
|
}
|
|
102
|
-
|
|
59
|
+
|
|
60
|
+
// we can't return undefined bcs an exception is
|
|
61
|
+
// thrown above on error
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
return result;
|
|
103
64
|
}
|
|
104
65
|
}
|
|
105
66
|
|