@konemono/nostr-login 1.11.0 → 1.11.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.
@@ -1,15 +1,12 @@
1
1
  import { Info, RecentType } from 'nostr-login-components/dist/types/types';
2
- import { RxNostr } from 'rx-nostr';
2
+ import NDK, { NDKSigner } from '@nostr-dev-kit/ndk';
3
3
  import { NostrLoginOptions } from '../types';
4
- import { PrivateKeySigner } from '../modules/Signer';
5
- export declare function bytesToHex(bytes: Uint8Array): string;
6
- export declare function hexToBytes(hex: string): Uint8Array;
7
4
  export declare const localStorageSetItem: (key: string, value: string) => void;
8
5
  export declare const localStorageGetItem: (key: string) => any;
9
6
  export declare const localStorageRemoveItem: (key: string) => void;
10
- export declare const fetchProfile: (info: Info, rxNostr: RxNostr) => Promise<any>;
7
+ export declare const fetchProfile: (info: Info, profileNdk: NDK) => Promise<import("@nostr-dev-kit/ndk").NDKUserProfile | null>;
11
8
  export declare const prepareSignupRelays: (signupRelays?: string) => string[];
12
- export declare const createProfile: (info: Info, rxNostr: RxNostr, signer: PrivateKeySigner, signupRelays?: string, outboxRelays?: string[]) => Promise<void>;
9
+ export declare const createProfile: (info: Info, profileNdk: NDK, signer: NDKSigner, signupRelays?: string, outboxRelays?: string[]) => Promise<void>;
13
10
  export declare const bunkerUrlToInfo: (bunkerUrl: string, sk?: string) => Info;
14
11
  export declare const isBunkerUrl: (value: string) => boolean;
15
12
  export declare const getBunkerUrl: (value: string, optionsModal: NostrLoginOptions) => Promise<string>;
@@ -2,8 +2,8 @@ export declare function encryptNip44(plaintext: string, conversationKey: Uint8Ar
2
2
  export declare function decryptNip44(payload: string, conversationKey: Uint8Array): string;
3
3
  export declare class Nip44 {
4
4
  private cache;
5
- createKey(privkey: string | Uint8Array, pubkey: string): Uint8Array;
5
+ createKey(privkey: string, pubkey: string): Uint8Array;
6
6
  private getKey;
7
- encrypt(privkey: string | Uint8Array, pubkey: string, text: string): string;
8
- decrypt(privkey: string | Uint8Array, pubkey: string, data: string): string;
7
+ encrypt(privkey: string, pubkey: string, text: string): string;
8
+ decrypt(privkey: string, pubkey: string, data: string): string;
9
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konemono/nostr-login",
3
- "version": "1.11.0",
3
+ "version": "1.11.3",
4
4
  "description": "",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,17 +11,17 @@
11
11
  },
12
12
  "author": "a-fralou",
13
13
  "dependencies": {
14
- "nostr-tools": "^2.19.4",
15
- "rx-nostr": "^3.6.2",
16
- "tseep": "^1.3.1"
14
+ "@nostr-dev-kit/ndk": "^2.3.1",
15
+ "nostr-tools": "^1.17.0",
16
+ "tseep": "^1.2.1"
17
17
  },
18
18
  "devDependencies": {
19
- "@rollup/plugin-commonjs": "^29.0.0",
20
- "@rollup/plugin-node-resolve": "^16.0.3",
19
+ "@rollup/plugin-commonjs": "^25.0.7",
20
+ "@rollup/plugin-node-resolve": "^15.2.3",
21
21
  "@rollup/plugin-terser": "^0.4.4",
22
22
  "nostr-login-components": "^1.0.3",
23
- "prettier": "^3.7.4",
24
- "rollup": "^4.55.1",
23
+ "prettier": "^3.2.2",
24
+ "rollup": "^4.9.6",
25
25
  "rollup-plugin-typescript2": "^0.36.0"
26
26
  },
27
27
  "license": "MIT"
@@ -1,14 +1,8 @@
1
- import { localStorageAddAccount, bunkerUrlToInfo, isBunkerUrl, fetchProfile, getBunkerUrl, localStorageRemoveCurrentAccount, createProfile, getIcon, bytesToHex, hexToBytes } from '../utils';
1
+ import { localStorageAddAccount, bunkerUrlToInfo, isBunkerUrl, fetchProfile, getBunkerUrl, localStorageRemoveCurrentAccount, createProfile, getIcon } from '../utils';
2
2
  import { ConnectionString, Info } from 'nostr-login-components/dist/types/types';
3
- import { createRxNostr, RxNostr } from 'rx-nostr';
4
- import { generateSecretKey, getEventHash, getPublicKey, nip19 } from 'nostr-tools';
3
+ import { generatePrivateKey, getEventHash, getPublicKey, nip19 } from 'nostr-tools';
5
4
  import { NostrLoginAuthOptions, Response } from '../types';
6
-
7
-
8
-
9
- // Placeholder types for SimplePool transition
10
- // private pool: SimplePool;
11
- // private outboxPool: SimplePool;
5
+ import NDK, { NDKEvent, NDKNip46Signer, NDKRpcResponse, NDKUser, NostrEvent } from '@nostr-dev-kit/ndk';
12
6
  import { NostrParams } from './';
13
7
  import { EventEmitter } from 'tseep';
14
8
  import { Signer } from './Nostr';
@@ -39,7 +33,8 @@ const NOSTRCONNECT_APPS: ConnectionString[] = [
39
33
  ];
40
34
 
41
35
  class AuthNostrService extends EventEmitter implements Signer {
42
- private rxNostr: RxNostr;
36
+ private ndk: NDK;
37
+ private profileNdk: NDK;
43
38
  private signer: Nip46Signer | null = null;
44
39
  private localSigner: PrivateKeySigner | null = null;
45
40
  private params: NostrParams;
@@ -66,11 +61,15 @@ class AuthNostrService extends EventEmitter implements Signer {
66
61
  constructor(params: NostrParams) {
67
62
  super();
68
63
  this.params = params;
64
+ this.ndk = new NDK({
65
+ enableOutboxModel: false,
66
+ });
69
67
 
70
- this.rxNostr = createRxNostr({} as any);
71
- // Default relays for initial connection if needed, though they are usually set per-action
72
- // @ts-ignore
73
- this.rxNostr.switchRelays(DEFAULT_NIP46_RELAYS);
68
+ this.profileNdk = new NDK({
69
+ enableOutboxModel: true,
70
+ explicitRelayUrls: OUTBOX_RELAYS,
71
+ });
72
+ this.profileNdk.connect();
74
73
 
75
74
  this.nip04 = {
76
75
  encrypt: this.encrypt04.bind(this),
@@ -82,30 +81,30 @@ class AuthNostrService extends EventEmitter implements Signer {
82
81
  };
83
82
  }
84
83
 
85
- public isIframe(): boolean {
84
+ public isIframe() {
86
85
  return !!this.iframe;
87
86
  }
88
87
 
89
- public async waitReady(): Promise<void> {
88
+ public async waitReady() {
90
89
  if (this.signerPromise) {
91
90
  try {
92
91
  await this.signerPromise;
93
- } catch { }
92
+ } catch {}
94
93
  }
95
94
 
96
95
  if (this.readyPromise) {
97
96
  try {
98
97
  await this.readyPromise;
99
- } catch { }
98
+ } catch {}
100
99
  }
101
100
  }
102
101
 
103
- public cancelNostrConnect(): void {
102
+ public cancelNostrConnect() {
104
103
  this.releaseSigner();
105
104
  this.resetAuth();
106
105
  }
107
106
 
108
- public cancelSignerInit(): void {
107
+ public cancelSignerInit() {
109
108
  if (this.signerAbortController) {
110
109
  this.signerAbortController.abort();
111
110
  this.signerAbortController = undefined;
@@ -134,7 +133,7 @@ class AuthNostrService extends EventEmitter implements Signer {
134
133
  iframeUrl?: string;
135
134
  customRelays?: string[];
136
135
  } = {},
137
- ): Promise<Info> {
136
+ ) {
138
137
  // カスタムリレーが指定されていれば使用、そうでなければ単一リレーまたはデフォルト
139
138
  const relays = customRelays && customRelays.length > 0 ? customRelays : relay ? [relay] : DEFAULT_NIP46_RELAYS;
140
139
 
@@ -169,13 +168,11 @@ class AuthNostrService extends EventEmitter implements Signer {
169
168
  return info;
170
169
  }
171
170
 
172
- public async createNostrConnect(): Promise<string> {
173
- const skBytes = generateSecretKey();
174
- // @ts-ignore
175
- this.nostrConnectKey = bytesToHex(skBytes);
171
+ public async createNostrConnect() {
172
+ this.nostrConnectKey = generatePrivateKey();
176
173
  this.nostrConnectSecret = Math.random().toString(36).substring(7);
177
174
 
178
- const pubkey = getPublicKey(skBytes);
175
+ const pubkey = getPublicKey(this.nostrConnectKey);
179
176
  const meta = {
180
177
  name: encodeURIComponent(document.location.host),
181
178
  url: encodeURIComponent(document.location.origin),
@@ -232,14 +229,10 @@ class AuthNostrService extends EventEmitter implements Signer {
232
229
  return [nostrconnect, apps];
233
230
  }
234
231
 
235
- public async localSignup(name: string, sk?: string): Promise<void> {
232
+ public async localSignup(name: string, sk?: string) {
236
233
  const signup = !sk;
237
- if (!sk) {
238
- const skBytes = generateSecretKey();
239
- sk = bytesToHex(skBytes);
240
- }
241
- // @ts-ignore
242
- const pubkey = getPublicKey(hexToBytes(sk!));
234
+ sk = sk || generatePrivateKey();
235
+ const pubkey = getPublicKey(sk);
243
236
  const info: Info = {
244
237
  pubkey,
245
238
  sk,
@@ -250,118 +243,25 @@ class AuthNostrService extends EventEmitter implements Signer {
250
243
  await this.setLocal(info, signup);
251
244
  }
252
245
 
253
- public async setLocal(info: Info, signup?: boolean): Promise<void> {
246
+ public async setLocal(info: Info, signup?: boolean) {
254
247
  this.releaseSigner();
255
- this.localSigner = new PrivateKeySigner(hexToBytes(info.sk!));
248
+ this.localSigner = new PrivateKeySigner(info.sk!);
256
249
 
257
- // TODO: nostr-toolsを使用するようにcreateProfileをリファクタリングする
258
- if (signup) {
259
- await createProfile(info, this.rxNostr, this.localSigner, this.params.optionsModal.signupRelays, this.params.optionsModal.outboxRelays);
260
- }
250
+ if (signup) await createProfile(info, this.profileNdk, this.localSigner, this.params.optionsModal.signupRelays, this.params.optionsModal.outboxRelays);
261
251
 
262
252
  this.onAuth(signup ? 'signup' : 'login', info);
263
253
  }
264
254
 
265
- public prepareImportUrl(url: string): string {
255
+ public prepareImportUrl(url: string) {
266
256
  // for OTP we choose interactive import
267
257
  if (this.params.userInfo?.authMethod === 'otp') return url + '&import=true';
268
258
 
269
259
  // for local we export our existing key
270
260
  if (!this.localSigner || this.params.userInfo?.authMethod !== 'local') throw new Error('Most be local keys');
271
- // Ensure privateKey is Uint8Array for nsecEncode if needed, but nip19.nsecEncode usually takes Uint8Array
272
- const skBytes = this.localSigner.privateKey!;
273
- return url + '#import=' + nip19.nsecEncode(skBytes);
274
- }
275
-
276
- // リレー管理メソッド
277
- public getRelayStatus(): Record<string, string> {
278
- const status = this.rxNostr.getAllRelayStatus();
279
- const result: Record<string, string> = {};
280
- for (const [url, state] of Object.entries(status)) {
281
- result[url] = String(state);
282
- }
283
- return result;
284
- }
285
-
286
- public getRelayStats(): {
287
- total: number;
288
- connected: number;
289
- connecting: number;
290
- disconnected: number;
291
- error: number;
292
- } {
293
- const status = this.rxNostr.getAllRelayStatus();
294
- const stats = {
295
- total: 0,
296
- connected: 0,
297
- connecting: 0,
298
- disconnected: 0,
299
- error: 0,
300
- };
301
-
302
- for (const state of Object.values(status)) {
303
- stats.total++;
304
- const stateStr = String(state).toLowerCase();
305
- if (stateStr === 'connected') stats.connected++;
306
- else if (stateStr === 'connecting') stats.connecting++;
307
- else if (stateStr === 'error') stats.error++;
308
- else stats.disconnected++;
309
- }
310
-
311
- return stats;
312
- }
313
-
314
- public async connectToRelay(relayUrl: string): Promise<void> {
315
- try {
316
- this.rxNostr.reconnect(relayUrl);
317
- console.log(`Connecting to relay: ${relayUrl}`);
318
- } catch (error) {
319
- console.error(`Failed to connect to relay ${relayUrl}:`, error);
320
- throw error;
321
- }
322
- }
323
-
324
- public async disconnectFromRelay(relayUrl: string): Promise<void> {
325
- try {
326
- // rx-nostrにはdisconnect APIがないため、リレーリストから除外する方法を使用
327
- const currentRelays = Object.keys(this.rxNostr.getAllRelayStatus());
328
- const newRelays = currentRelays.filter(url => url !== relayUrl);
329
- if (newRelays.length > 0) {
330
- // @ts-ignore
331
- this.rxNostr.switchRelays(newRelays);
332
- }
333
- console.log(`Disconnected from relay: ${relayUrl}`);
334
- } catch (error) {
335
- console.error(`Failed to disconnect from relay ${relayUrl}:`, error);
336
- throw error;
337
- }
261
+ return url + '#import=' + nip19.nsecEncode(this.localSigner.privateKey!);
338
262
  }
339
263
 
340
- public async reconnectAllRelays(): Promise<void> {
341
- try {
342
- const relays = Object.keys(this.rxNostr.getAllRelayStatus());
343
- console.log(`Reconnecting to ${relays.length} relays...`);
344
-
345
- for (const relay of relays) {
346
- try {
347
- this.rxNostr.reconnect(relay);
348
- } catch (error) {
349
- console.warn(`Failed to reconnect to ${relay}:`, error);
350
- }
351
- }
352
- } catch (error) {
353
- console.error('Failed to reconnect all relays:', error);
354
- throw error;
355
- }
356
- }
357
-
358
- public async checkRelayHealth(): Promise<boolean> {
359
- const stats = this.getRelayStats();
360
- // 少なくとも1つのリレーが接続されていればOK
361
- return stats.connected > 0;
362
- }
363
-
364
- public async importAndConnect(cs: ConnectionString): Promise<void> {
264
+ public async importAndConnect(cs: ConnectionString) {
365
265
  const { relay, domain, link, iframeUrl } = cs;
366
266
  if (!domain) throw new Error('Domain required');
367
267
 
@@ -378,22 +278,22 @@ class AuthNostrService extends EventEmitter implements Signer {
378
278
  this.onAuth('login', info);
379
279
  }
380
280
 
381
- public setReadOnly(pubkey: string): void {
281
+ public setReadOnly(pubkey: string) {
382
282
  const info: Info = { pubkey, authMethod: 'readOnly' };
383
283
  this.onAuth('login', info);
384
284
  }
385
285
 
386
- public setExtension(pubkey: string): void {
286
+ public setExtension(pubkey: string) {
387
287
  const info: Info = { pubkey, authMethod: 'extension' };
388
288
  this.onAuth('login', info);
389
289
  }
390
290
 
391
- public setOTP(pubkey: string, data: string): void {
291
+ public setOTP(pubkey: string, data: string) {
392
292
  const info: Info = { pubkey, authMethod: 'otp', otpData: data };
393
293
  this.onAuth('login', info);
394
294
  }
395
295
 
396
- public async setConnect(info: Info): Promise<void> {
296
+ public async setConnect(info: Info) {
397
297
  this.releaseSigner();
398
298
  await this.startAuth();
399
299
  await this.initSigner(info);
@@ -401,7 +301,7 @@ class AuthNostrService extends EventEmitter implements Signer {
401
301
  await this.endAuth();
402
302
  }
403
303
 
404
- public async createAccount(nip05: string): Promise<{ bunkerUrl: string; sk: string | undefined }> {
304
+ public async createAccount(nip05: string) {
405
305
  const [name, domain] = nip05.split('@');
406
306
 
407
307
  // bunker's own url
@@ -425,19 +325,18 @@ class AuthNostrService extends EventEmitter implements Signer {
425
325
  };
426
326
  }
427
327
 
428
- private releaseSigner(): void {
328
+ private releaseSigner() {
429
329
  this.signer = null;
430
330
  this.signerErrCallback?.('cancelled');
431
331
  this.localSigner = null;
432
332
 
433
333
  // disconnect from signer relays
434
- // rx-nostr manages relays, we can switch to empty or default if needed
435
- // or just leave them be as they might be reused?
436
- // For now, let's just clear the signer instance.
437
- // this.rxNostr.switchRelays([]); // Should we disconnect? Maybe better to keep connection for next signer?
334
+ for (const r of this.ndk.pool.relays.keys()) {
335
+ this.ndk.pool.removeRelay(r);
336
+ }
438
337
  }
439
338
 
440
- public async logout(keepSigner = false): Promise<void> {
339
+ public async logout(keepSigner = false) {
441
340
  if (!keepSigner) this.releaseSigner();
442
341
 
443
342
  // move current to recent
@@ -449,7 +348,7 @@ class AuthNostrService extends EventEmitter implements Signer {
449
348
  this.emit('updateAccounts');
450
349
  }
451
350
 
452
- private setUserInfo(userInfo: Info | null): void {
351
+ private setUserInfo(userInfo: Info | null) {
453
352
  this.params.userInfo = userInfo;
454
353
  this.emit('onUserInfo', userInfo);
455
354
 
@@ -459,14 +358,13 @@ class AuthNostrService extends EventEmitter implements Signer {
459
358
  }
460
359
  }
461
360
 
462
- public exportKeys(): string {
361
+ public exportKeys() {
463
362
  if (!this.params.userInfo) return '';
464
363
  if (this.params.userInfo.authMethod !== 'local') return '';
465
- const skBytes = hexToBytes(this.params.userInfo.sk!);
466
- return nip19.nsecEncode(skBytes);
364
+ return nip19.nsecEncode(this.params.userInfo.sk!);
467
365
  }
468
366
 
469
- private onAuth(type: 'login' | 'signup' | 'logout', info: Info | null = null): void {
367
+ private onAuth(type: 'login' | 'signup' | 'logout', info: Info | null = null) {
470
368
  if (type !== 'logout' && !info) throw new Error('No user info in onAuth');
471
369
 
472
370
  // make sure we emulate logout first
@@ -480,8 +378,7 @@ class AuthNostrService extends EventEmitter implements Signer {
480
378
 
481
379
  if (info) {
482
380
  // async profile fetch
483
- // TODO: nostr-toolsを使用するようにfetchProfileをリファクタリングする
484
- fetchProfile(info, this.rxNostr as any).then(p => {
381
+ fetchProfile(info, this.profileNdk).then(p => {
485
382
  if (this.params.userInfo !== info) return;
486
383
 
487
384
  const userInfo = {
@@ -514,7 +411,7 @@ class AuthNostrService extends EventEmitter implements Signer {
514
411
  options.name = info!.name;
515
412
 
516
413
  if (info!.sk) {
517
- options.localNsec = nip19.nsecEncode(hexToBytes(info!.sk));
414
+ options.localNsec = nip19.nsecEncode(info!.sk);
518
415
  }
519
416
 
520
417
  if (info!.relays) {
@@ -540,7 +437,7 @@ class AuthNostrService extends EventEmitter implements Signer {
540
437
  }
541
438
  }
542
439
 
543
- private async createIframe(iframeUrl?: string): Promise<{ iframe: HTMLIFrameElement; port: MessagePort } | undefined> {
440
+ private async createIframe(iframeUrl?: string) {
544
441
  if (!iframeUrl) return undefined;
545
442
 
546
443
  // ensure iframe
@@ -599,18 +496,18 @@ class AuthNostrService extends EventEmitter implements Signer {
599
496
  // }
600
497
  // }
601
498
 
602
- public async sendNeedAuth(): Promise<void> {
499
+ public async sendNeedAuth() {
603
500
  const [nostrconnect] = await this.getNostrConnectServices();
604
501
  const event = new CustomEvent('nlNeedAuth', { detail: { nostrconnect } });
605
502
  console.log('nostr-login need auth', nostrconnect);
606
503
  document.dispatchEvent(event);
607
504
  }
608
505
 
609
- public isAuthing(): boolean {
506
+ public isAuthing() {
610
507
  return !!this.readyCallback;
611
508
  }
612
509
 
613
- public async startAuth(): Promise<void> {
510
+ public async startAuth() {
614
511
  console.log('startAuth');
615
512
  if (this.readyCallback) throw new Error('Already started');
616
513
 
@@ -618,7 +515,7 @@ class AuthNostrService extends EventEmitter implements Signer {
618
515
  this.readyPromise = new Promise<void>(ok => (this.readyCallback = ok));
619
516
  }
620
517
 
621
- public async endAuth(): Promise<void> {
518
+ public async endAuth() {
622
519
  console.log('endAuth', this.params.userInfo);
623
520
  if (this.params.userInfo && this.params.userInfo.iframeUrl) {
624
521
  // create iframe
@@ -634,28 +531,28 @@ class AuthNostrService extends EventEmitter implements Signer {
634
531
  this.readyCallback = undefined;
635
532
  }
636
533
 
637
- public resetAuth(): void {
534
+ public resetAuth() {
638
535
  if (this.readyCallback) this.readyCallback();
639
536
  this.readyCallback = undefined;
640
537
  }
641
538
 
642
- private async listen(info: Info): Promise<void> {
539
+ private async listen(info: Info) {
643
540
  if (!info.iframeUrl) return this.signer!.listen(this.nostrConnectSecret);
644
541
  const r = await this.starterReady!.wait();
645
542
  if (r[0] === 'starterError') throw new Error(r[1]);
646
543
  return this.signer!.setListenReply(r[1], this.nostrConnectSecret);
647
544
  }
648
545
 
649
- public async connect(info: Info, perms?: string): Promise<void> {
546
+ public async connect(info: Info, perms?: string) {
650
547
  return this.signer!.connect(info.token, perms);
651
548
  }
652
549
 
653
- public async initSigner(info: Info, { listen = false, connect = false, eventToAddAccount = false } = {}): Promise<void> {
550
+ public async initSigner(info: Info, { listen = false, connect = false, eventToAddAccount = false } = {}) {
654
551
  // mutex
655
552
  if (this.signerPromise) {
656
553
  try {
657
554
  await this.signerPromise;
658
- } catch { }
555
+ } catch {}
659
556
  }
660
557
 
661
558
  // we remove support for iframe from nip05 and bunker-url methods,
@@ -696,28 +593,22 @@ class AuthNostrService extends EventEmitter implements Signer {
696
593
  return this.signerPromise;
697
594
  }
698
595
 
699
- private async initSignerInternal(info: Info, listen: boolean, connect: boolean, eventToAddAccount: boolean, resolve: () => void): Promise<void> {
596
+ private async initSignerInternal(info: Info, listen: boolean, connect: boolean, eventToAddAccount: boolean, resolve: () => void) {
700
597
  // pre-connect if we're creating the connection (listen|connect) or
701
598
  // not iframe mode
702
599
  if (info.relays && !info.iframeUrl) {
703
- // @ts-ignore
704
- this.rxNostr.switchRelays(info.relays);
600
+ for (const r of info.relays) {
601
+ this.ndk.addExplicitRelay(r, undefined);
602
+ }
705
603
  }
706
604
 
707
- // rx-nostr connects automatically
605
+ // wait until we connect, otherwise
606
+ // signer won't start properly
607
+ await this.ndk.connect();
708
608
 
709
609
  // create and prepare the signer
710
- const localSigner = new PrivateKeySigner(hexToBytes(info.sk!));
711
-
712
- // TODO: 元のNDKロジック:
713
- // This initialized the Nip46Signer with NDK instance.
714
- //
715
- // New Implementation Plan:
716
- // 1. Pass the SimplePool instance or relay list to Nip46Signer.
717
- // 2. Nip46Signer should manage its own connection or use the shared pool to publish/subscribe.
718
-
719
- // TODO: ndk引数を削除する
720
- this.signer = new Nip46Signer(this.rxNostr, localSigner, info.signerPubkey!, info.iframeUrl ? new URL(info.iframeUrl!).origin : undefined);
610
+ const localSigner = new PrivateKeySigner(info.sk!);
611
+ this.signer = new Nip46Signer(this.ndk, localSigner, info.signerPubkey!, info.iframeUrl ? new URL(info.iframeUrl!).origin : undefined);
721
612
 
722
613
  // we should notify the banner the same way as
723
614
  // the onAuthUrl does
@@ -769,7 +660,7 @@ class AuthNostrService extends EventEmitter implements Signer {
769
660
  iframeUrl = '',
770
661
  customRelays,
771
662
  }: { name: string; bunkerUrl: string; sk?: string; domain?: string; iframeUrl?: string; customRelays?: string[] },
772
- ): Promise<void> {
663
+ ) {
773
664
  try {
774
665
  const info = bunkerUrlToInfo(bunkerUrl, sk);
775
666
  if (isBunkerUrl(name)) info.bunkerUrl = name;
@@ -806,9 +697,8 @@ class AuthNostrService extends EventEmitter implements Signer {
806
697
  }
807
698
  }
808
699
 
809
- public async signEvent(event: any): Promise<any> {
700
+ public async signEvent(event: any) {
810
701
  if (this.localSigner) {
811
- // this.localSigner.privateKey is Uint8Array
812
702
  event.pubkey = getPublicKey(this.localSigner.privateKey!);
813
703
  event.id = getEventHash(event);
814
704
  event.sig = await this.localSigner.sign(event);
@@ -823,7 +713,7 @@ class AuthNostrService extends EventEmitter implements Signer {
823
713
  return event;
824
714
  }
825
715
 
826
- private async ensureSigner(): Promise<void> {
716
+ private async ensureSigner() {
827
717
  // signerがキャンセル等で破棄されている場合は再初期化
828
718
  if (!this.signer && this.params.userInfo) {
829
719
  console.log('Signer was destroyed, reinitializing...');
@@ -836,23 +726,11 @@ class AuthNostrService extends EventEmitter implements Signer {
836
726
  }
837
727
 
838
728
  // リレー接続を確認・再接続
839
- // TODO: 元のNDKロジック:
840
- // Checks ndk.pool.stats() for connectivity.
841
- //
842
- // New Implementation Plan:
843
- // 1. Iterate through SimplePool.relays or listConnectionStatus().
844
- // 2. If no relays are connected, modify code to reconnect.
845
-
846
- // TODO: rx-nostrの統計を確認する
847
- // const stats = this.pool.listConnectionStatus();
848
- // const stats = this.pool.listConnectionStatus();
849
- // const stats = this.ndk.pool.stats();
850
- // console.log('NDK pool stats:', stats);
851
- const relayStates = this.rxNostr.getAllRelayStatus();
852
- const connectedCount = Object.values(relayStates).filter(s => String(s) === 'connected').length;
853
-
854
- if (connectedCount === 0) {
855
- console.log('RxNostr relays disconnected, reinitializing signer...');
729
+ const stats = this.ndk.pool.stats();
730
+ console.log('NDK pool stats:', stats);
731
+
732
+ if (stats.connected === 0) {
733
+ console.log('NDK relays disconnected, reinitializing signer...');
856
734
 
857
735
  // リレーが完全に切断されている場合、signerも再初期化する必要がある
858
736
  // (RPCサブスクリプションも切断されているため)
@@ -860,8 +738,14 @@ class AuthNostrService extends EventEmitter implements Signer {
860
738
  // 古いsignerを破棄
861
739
  this.signer = null;
862
740
 
863
- // 既存のリレーを一度切断 (rx-nostr reconnects automatically, but we might want to force it)
864
- this.rxNostr.reconnect(Object.keys(relayStates)[0]);
741
+ // 既存のリレーを一度切断
742
+ for (const relay of this.ndk.pool.relays.values()) {
743
+ try {
744
+ relay.disconnect();
745
+ } catch (e) {
746
+ console.log('Error disconnecting relay:', e);
747
+ }
748
+ }
865
749
 
866
750
  // signerを再初期化(リレー接続も含む)
867
751
  await this.initSigner(this.params.userInfo);
@@ -871,41 +755,56 @@ class AuthNostrService extends EventEmitter implements Signer {
871
755
  }
872
756
  }
873
757
 
758
+ private async codec_call(method: string, pubkey: string, param: string) {
759
+ return new Promise<string>((resolve, reject) => {
760
+ this.signer!.rpc.sendRequest(this.signer!.remotePubkey!, method, [pubkey, param], 24133, (response: NDKRpcResponse) => {
761
+ if (!response.error) {
762
+ resolve(response.result);
763
+ } else {
764
+ reject(response.error);
765
+ }
766
+ });
767
+ });
768
+ }
874
769
 
875
-
876
- public async encrypt04(pubkey: string, plaintext: string): Promise<string> {
770
+ public async encrypt04(pubkey: string, plaintext: string) {
877
771
  if (this.localSigner) {
878
- return this.localSigner.encrypt(pubkey as any, plaintext);
772
+ return this.localSigner.encrypt(new NDKUser({ pubkey }), plaintext);
879
773
  } else {
880
774
  await this.ensureSigner();
881
- return this.signer!.encrypt(pubkey, plaintext);
775
+ return this.signer!.encrypt(new NDKUser({ pubkey }), plaintext);
882
776
  }
883
777
  }
884
778
 
885
- public async decrypt04(pubkey: string, ciphertext: string): Promise<string> {
779
+ public async decrypt04(pubkey: string, ciphertext: string) {
886
780
  if (this.localSigner) {
887
- return this.localSigner.decrypt(pubkey as any, ciphertext);
781
+ return this.localSigner.decrypt(new NDKUser({ pubkey }), ciphertext);
888
782
  } else {
783
+ // decrypt is broken in ndk v2.3.1, and latest
784
+ // ndk v2.8.1 doesn't allow to override connect easily,
785
+ // so we reimplement and fix decrypt here as a temporary fix
889
786
  await this.ensureSigner();
890
- return this.signer!.decrypt(pubkey, ciphertext);
787
+ return this.codec_call('nip04_decrypt', pubkey, ciphertext);
891
788
  }
892
789
  }
893
790
 
894
- public async encrypt44(pubkey: string, plaintext: string): Promise<string> {
791
+ public async encrypt44(pubkey: string, plaintext: string) {
895
792
  if (this.localSigner) {
896
793
  return this.nip44Codec.encrypt(this.localSigner.privateKey!, pubkey, plaintext);
897
794
  } else {
795
+ // no support of nip44 in ndk yet
898
796
  await this.ensureSigner();
899
- return this.signer!.encryptNip44(pubkey, plaintext);
797
+ return this.codec_call('nip44_encrypt', pubkey, plaintext);
900
798
  }
901
799
  }
902
800
 
903
- public async decrypt44(pubkey: string, ciphertext: string): Promise<string> {
801
+ public async decrypt44(pubkey: string, ciphertext: string) {
904
802
  if (this.localSigner) {
905
803
  return this.nip44Codec.decrypt(this.localSigner.privateKey!, pubkey, ciphertext);
906
804
  } else {
805
+ // no support of nip44 in ndk yet
907
806
  await this.ensureSigner();
908
- return this.signer!.decryptNip44(pubkey, ciphertext);
807
+ return this.codec_call('nip44_decrypt', pubkey, ciphertext);
909
808
  }
910
809
  }
911
810
  }