@konemono/nostr-login 1.13.2 → 1.13.3
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 +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/modules/Nip46.d.ts +12 -0
- package/dist/unpkg.js +1 -1
- package/package.json +2 -2
- package/src/modules/AuthNostrService.ts +3 -3
- package/src/modules/Nip46.ts +50 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@konemono/nostr-login",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.3",
|
|
4
4
|
"description": "Extended fork of nostr-login with multi-relay support, QR scanner, and improved stability",
|
|
5
5
|
"main": "./dist/index.esm.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@rollup/plugin-commonjs": "^25.0.7",
|
|
31
31
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
32
32
|
"@rollup/plugin-terser": "^0.4.4",
|
|
33
|
-
"@konemono/nostr-login-components": "^1.2.
|
|
33
|
+
"@konemono/nostr-login-components": "^1.2.3",
|
|
34
34
|
"prettier": "^3.2.2",
|
|
35
35
|
"rollup": "^4.9.6",
|
|
36
36
|
"rollup-plugin-typescript2": "^0.36.0"
|
|
@@ -653,7 +653,7 @@ class AuthNostrService extends EventEmitter implements Signer {
|
|
|
653
653
|
}
|
|
654
654
|
}
|
|
655
655
|
|
|
656
|
-
await this.ndk.connect();
|
|
656
|
+
await this.ndk.connect(10000); // 10秒のタイムアウトでリレー接続
|
|
657
657
|
|
|
658
658
|
const localSigner = new PrivateKeySigner(info.sk!);
|
|
659
659
|
this.signer = new Nip46Signer(this.ndk, localSigner, info.signerPubkey!, iframeOrigin);
|
|
@@ -797,7 +797,7 @@ class AuthNostrService extends EventEmitter implements Signer {
|
|
|
797
797
|
this.ensureRelaysInPool();
|
|
798
798
|
|
|
799
799
|
try {
|
|
800
|
-
await this.ndk.connect();
|
|
800
|
+
await this.ndk.connect(10000);
|
|
801
801
|
} catch (e) {
|
|
802
802
|
console.warn('forceReconnect: ndk.connect() threw, will poll for connection...', e);
|
|
803
803
|
}
|
|
@@ -819,7 +819,7 @@ class AuthNostrService extends EventEmitter implements Signer {
|
|
|
819
819
|
this.ensureRelaysInPool();
|
|
820
820
|
|
|
821
821
|
try {
|
|
822
|
-
await this.ndk.connect();
|
|
822
|
+
await this.ndk.connect(10000);
|
|
823
823
|
} catch (e) {
|
|
824
824
|
console.warn('ensureRelayConnection: ndk.connect() threw, will poll for connection...', e);
|
|
825
825
|
}
|
package/src/modules/Nip46.ts
CHANGED
|
@@ -42,28 +42,43 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
42
42
|
// リレーが不安定な状態ではEOSEが届かず無限にハングする。
|
|
43
43
|
// NIP-46ではリアルタイムのレスポンスのみ必要なので、
|
|
44
44
|
// EOSE待ちをスキップして直接subscribeする。
|
|
45
|
+
// cacheUsage: ONLY_RELAY で確実にリレーからのみ購読する。
|
|
46
|
+
// onEvent を使って race condition を回避(NDK推奨)。
|
|
45
47
|
const sub = this._ndk.subscribe(filter, {
|
|
46
48
|
closeOnEose: false,
|
|
47
49
|
groupable: false,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
cacheUsage: NDKSubscriptionCacheUsage.ONLY_RELAY,
|
|
51
|
+
onEvent: async (event: NDKEvent) => {
|
|
52
|
+
try {
|
|
53
|
+
const parsedEvent = await this.parseEvent(event);
|
|
54
|
+
if ((parsedEvent as NDKRpcRequest).method) {
|
|
55
|
+
this.emit('request', parsedEvent);
|
|
56
|
+
} else {
|
|
57
|
+
this.emit(`response-${parsedEvent.id}`, parsedEvent);
|
|
58
|
+
}
|
|
59
|
+
} catch (e) {
|
|
60
|
+
console.error('error parsing event in subscription', e);
|
|
57
61
|
}
|
|
58
|
-
}
|
|
59
|
-
console.error('error parsing event in subscription', e);
|
|
60
|
-
}
|
|
62
|
+
},
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
this.sub = sub;
|
|
64
66
|
return sub;
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
/**
|
|
70
|
+
* subscription が無ければ作る。localSigner の pubkey で kind:24133 を購読。
|
|
71
|
+
*/
|
|
72
|
+
public async ensureSubscription(): Promise<void> {
|
|
73
|
+
if (this.sub) return;
|
|
74
|
+
const pubkey = this._signer.pubkey;
|
|
75
|
+
console.log('ensureSubscription: subscribing for', pubkey);
|
|
76
|
+
await this.subscribe({
|
|
77
|
+
'kinds': [24133],
|
|
78
|
+
'#p': [pubkey],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
public stop() {
|
|
68
83
|
if (this.sub) {
|
|
69
84
|
this.sub.stop();
|
|
@@ -147,23 +162,27 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
147
162
|
}
|
|
148
163
|
}
|
|
149
164
|
|
|
150
|
-
|
|
165
|
+
/**
|
|
166
|
+
* subscriptionを開始してから connect response を待つ。
|
|
167
|
+
* listen 後もsubscriptionは維持する(後続の get_public_key 等で必要)。
|
|
168
|
+
*/
|
|
151
169
|
public async listen(nostrConnectSecret: string): Promise<string> {
|
|
152
170
|
const pubkey = this._signer.pubkey;
|
|
153
171
|
console.log('nostr-login listening for conn to', pubkey, 'expecting secret:', nostrConnectSecret);
|
|
154
172
|
|
|
155
|
-
|
|
156
|
-
'kinds': [24133],
|
|
157
|
-
'#p': [pubkey],
|
|
158
|
-
});
|
|
173
|
+
await this.ensureSubscription();
|
|
159
174
|
|
|
160
175
|
return new Promise<string>((ok, err) => {
|
|
161
176
|
const timeout = setTimeout(() => {
|
|
162
|
-
this.stop();
|
|
163
177
|
err(new Error('Connection timeout: no response from signer'));
|
|
164
178
|
}, 60000); // 60秒のタイムアウト
|
|
165
179
|
|
|
166
|
-
|
|
180
|
+
// subscribe の onEvent ハンドラが response-${id} を emit するが、
|
|
181
|
+
// listen のレスポンスは request id が無い(unsolicited)ので
|
|
182
|
+
// 'request' イベントとして来る可能性がある。
|
|
183
|
+
// 代わりに subscribe 側でパースされたイベントを
|
|
184
|
+
// 直接 NDKSubscription の event で受け取る。
|
|
185
|
+
const handler = async (event: NDKEvent) => {
|
|
167
186
|
try {
|
|
168
187
|
const parsedEvent = await this.parseEvent(event);
|
|
169
188
|
console.log('listen parsedEvent', parsedEvent);
|
|
@@ -180,36 +199,41 @@ class NostrRpc extends NDKNostrRpc {
|
|
|
180
199
|
// secretの厳密な検証
|
|
181
200
|
if (response.result === nostrConnectSecret) {
|
|
182
201
|
clearTimeout(timeout);
|
|
183
|
-
|
|
202
|
+
// subscriptionは維持する(後続リクエストで使うため stop しない)
|
|
184
203
|
console.log('Connection established with signer:', event.pubkey);
|
|
185
204
|
ok(event.pubkey);
|
|
186
205
|
} else if (response.result === 'ack') {
|
|
187
206
|
// ackは古い実装用の互換性のため警告のみ
|
|
188
207
|
console.warn('Received "ack" instead of secret. This may indicate an older signer implementation.');
|
|
189
208
|
clearTimeout(timeout);
|
|
190
|
-
this.stop();
|
|
191
209
|
ok(event.pubkey);
|
|
192
210
|
} else {
|
|
193
211
|
console.error('Invalid response:', response);
|
|
194
212
|
clearTimeout(timeout);
|
|
195
|
-
this.stop();
|
|
196
213
|
err(new Error(response.error || 'Invalid connection response'));
|
|
197
214
|
}
|
|
198
215
|
}
|
|
199
216
|
} catch (e) {
|
|
200
217
|
console.error('Error parsing event in listen', e, event.rawEvent());
|
|
201
218
|
}
|
|
202
|
-
}
|
|
219
|
+
};
|
|
203
220
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
221
|
+
if (this.sub) {
|
|
222
|
+
this.sub.on('event', handler);
|
|
223
|
+
}
|
|
207
224
|
});
|
|
208
225
|
}
|
|
209
226
|
|
|
227
|
+
/**
|
|
228
|
+
* subscriptionが無ければ開始してから connect リクエストを送る。
|
|
229
|
+
* レスポンスは subscription の event ハンドラ経由で受け取る。
|
|
230
|
+
*/
|
|
210
231
|
public async connect(pubkey: string, token?: string, perms?: string) {
|
|
211
232
|
console.log('Sending connect request to', pubkey, 'with perms:', perms);
|
|
212
233
|
|
|
234
|
+
// connect のレスポンスを受け取るために subscription が必要
|
|
235
|
+
await this.ensureSubscription();
|
|
236
|
+
|
|
213
237
|
return new Promise<void>((ok, err) => {
|
|
214
238
|
const timeout = setTimeout(() => {
|
|
215
239
|
err(new Error('Connect timeout: no response from signer'));
|