@konemono/nostr-login 1.11.0 → 1.11.1

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.1",
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,21 +1,16 @@
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
3
  import { generateSecretKey, 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';
15
9
  import { Nip44 } from '../utils/nip44';
16
- import { IframeNostrRpc, Nip46Signer, ReadyListener } from './Nip46';
10
+ import { IframeNostrRpc, Nip46Signer, ReadyListener, ensureNIP46Connection } from './Nip46';
17
11
  import { PrivateKeySigner } from './Signer';
18
12
  import { DEFAULT_NIP46_RELAYS } from '../const';
13
+ import { bytesToHex, hexToBytes } from 'nostr-tools/lib/types/utils';
19
14
 
20
15
  const OUTBOX_RELAYS = ['wss://user.kindpag.es', 'wss://purplepag.es', 'wss://relay.nos.social'];
21
16
  const NOSTRCONNECT_APPS: ConnectionString[] = [
@@ -39,7 +34,8 @@ const NOSTRCONNECT_APPS: ConnectionString[] = [
39
34
  ];
40
35
 
41
36
  class AuthNostrService extends EventEmitter implements Signer {
42
- private rxNostr: RxNostr;
37
+ private ndk: NDK;
38
+ private profileNdk: NDK;
43
39
  private signer: Nip46Signer | null = null;
44
40
  private localSigner: PrivateKeySigner | null = null;
45
41
  private params: NostrParams;
@@ -66,11 +62,17 @@ class AuthNostrService extends EventEmitter implements Signer {
66
62
  constructor(params: NostrParams) {
67
63
  super();
68
64
  this.params = params;
65
+ this.ndk = new NDK({
66
+ enableOutboxModel: false,
67
+ autoConnectUserRelays: false,
68
+ autoFetchUserMutelist: false,
69
+ });
69
70
 
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);
71
+ this.profileNdk = new NDK({
72
+ enableOutboxModel: true,
73
+ explicitRelayUrls: OUTBOX_RELAYS,
74
+ });
75
+ this.profileNdk.connect();
74
76
 
75
77
  this.nip04 = {
76
78
  encrypt: this.encrypt04.bind(this),
@@ -82,11 +84,11 @@ class AuthNostrService extends EventEmitter implements Signer {
82
84
  };
83
85
  }
84
86
 
85
- public isIframe(): boolean {
87
+ public isIframe() {
86
88
  return !!this.iframe;
87
89
  }
88
90
 
89
- public async waitReady(): Promise<void> {
91
+ public async waitReady() {
90
92
  if (this.signerPromise) {
91
93
  try {
92
94
  await this.signerPromise;
@@ -100,12 +102,12 @@ class AuthNostrService extends EventEmitter implements Signer {
100
102
  }
101
103
  }
102
104
 
103
- public cancelNostrConnect(): void {
105
+ public cancelNostrConnect() {
104
106
  this.releaseSigner();
105
107
  this.resetAuth();
106
108
  }
107
109
 
108
- public cancelSignerInit(): void {
110
+ public cancelSignerInit() {
109
111
  if (this.signerAbortController) {
110
112
  this.signerAbortController.abort();
111
113
  this.signerAbortController = undefined;
@@ -134,7 +136,7 @@ class AuthNostrService extends EventEmitter implements Signer {
134
136
  iframeUrl?: string;
135
137
  customRelays?: string[];
136
138
  } = {},
137
- ): Promise<Info> {
139
+ ) {
138
140
  // カスタムリレーが指定されていれば使用、そうでなければ単一リレーまたはデフォルト
139
141
  const relays = customRelays && customRelays.length > 0 ? customRelays : relay ? [relay] : DEFAULT_NIP46_RELAYS;
140
142
 
@@ -169,13 +171,11 @@ class AuthNostrService extends EventEmitter implements Signer {
169
171
  return info;
170
172
  }
171
173
 
172
- public async createNostrConnect(): Promise<string> {
173
- const skBytes = generateSecretKey();
174
- // @ts-ignore
175
- this.nostrConnectKey = bytesToHex(skBytes);
174
+ public async createNostrConnect() {
175
+ this.nostrConnectKey = bytesToHex(generateSecretKey());
176
176
  this.nostrConnectSecret = Math.random().toString(36).substring(7);
177
177
 
178
- const pubkey = getPublicKey(skBytes);
178
+ const pubkey = getPublicKey(hexToBytes(this.nostrConnectKey));
179
179
  const meta = {
180
180
  name: encodeURIComponent(document.location.host),
181
181
  url: encodeURIComponent(document.location.origin),
@@ -232,14 +232,10 @@ class AuthNostrService extends EventEmitter implements Signer {
232
232
  return [nostrconnect, apps];
233
233
  }
234
234
 
235
- public async localSignup(name: string, sk?: string): Promise<void> {
235
+ public async localSignup(name: string, sk?: string) {
236
236
  const signup = !sk;
237
- if (!sk) {
238
- const skBytes = generateSecretKey();
239
- sk = bytesToHex(skBytes);
240
- }
241
- // @ts-ignore
242
- const pubkey = getPublicKey(hexToBytes(sk!));
237
+ sk = sk || bytesToHex(generateSecretKey());
238
+ const pubkey = getPublicKey(hexToBytes(sk));
243
239
  const info: Info = {
244
240
  pubkey,
245
241
  sk,
@@ -250,118 +246,25 @@ class AuthNostrService extends EventEmitter implements Signer {
250
246
  await this.setLocal(info, signup);
251
247
  }
252
248
 
253
- public async setLocal(info: Info, signup?: boolean): Promise<void> {
249
+ public async setLocal(info: Info, signup?: boolean) {
254
250
  this.releaseSigner();
255
- this.localSigner = new PrivateKeySigner(hexToBytes(info.sk!));
251
+ this.localSigner = new PrivateKeySigner(info.sk!);
256
252
 
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
- }
253
+ if (signup) await createProfile(info, this.profileNdk, this.localSigner, this.params.optionsModal.signupRelays, this.params.optionsModal.outboxRelays);
261
254
 
262
255
  this.onAuth(signup ? 'signup' : 'login', info);
263
256
  }
264
257
 
265
- public prepareImportUrl(url: string): string {
258
+ public prepareImportUrl(url: string) {
266
259
  // for OTP we choose interactive import
267
260
  if (this.params.userInfo?.authMethod === 'otp') return url + '&import=true';
268
261
 
269
262
  // for local we export our existing key
270
263
  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);
264
+ return url + '#import=' + nip19.nsecEncode(hexToBytes(this.localSigner.privateKey!));
274
265
  }
275
266
 
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
- }
338
- }
339
-
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> {
267
+ public async importAndConnect(cs: ConnectionString) {
365
268
  const { relay, domain, link, iframeUrl } = cs;
366
269
  if (!domain) throw new Error('Domain required');
367
270
 
@@ -378,22 +281,22 @@ class AuthNostrService extends EventEmitter implements Signer {
378
281
  this.onAuth('login', info);
379
282
  }
380
283
 
381
- public setReadOnly(pubkey: string): void {
284
+ public setReadOnly(pubkey: string) {
382
285
  const info: Info = { pubkey, authMethod: 'readOnly' };
383
286
  this.onAuth('login', info);
384
287
  }
385
288
 
386
- public setExtension(pubkey: string): void {
289
+ public setExtension(pubkey: string) {
387
290
  const info: Info = { pubkey, authMethod: 'extension' };
388
291
  this.onAuth('login', info);
389
292
  }
390
293
 
391
- public setOTP(pubkey: string, data: string): void {
294
+ public setOTP(pubkey: string, data: string) {
392
295
  const info: Info = { pubkey, authMethod: 'otp', otpData: data };
393
296
  this.onAuth('login', info);
394
297
  }
395
298
 
396
- public async setConnect(info: Info): Promise<void> {
299
+ public async setConnect(info: Info) {
397
300
  this.releaseSigner();
398
301
  await this.startAuth();
399
302
  await this.initSigner(info);
@@ -401,7 +304,7 @@ class AuthNostrService extends EventEmitter implements Signer {
401
304
  await this.endAuth();
402
305
  }
403
306
 
404
- public async createAccount(nip05: string): Promise<{ bunkerUrl: string; sk: string | undefined }> {
307
+ public async createAccount(nip05: string) {
405
308
  const [name, domain] = nip05.split('@');
406
309
 
407
310
  // bunker's own url
@@ -425,19 +328,18 @@ class AuthNostrService extends EventEmitter implements Signer {
425
328
  };
426
329
  }
427
330
 
428
- private releaseSigner(): void {
331
+ private releaseSigner() {
429
332
  this.signer = null;
430
333
  this.signerErrCallback?.('cancelled');
431
334
  this.localSigner = null;
432
335
 
433
336
  // 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?
337
+ for (const r of this.ndk.pool.relays.keys()) {
338
+ this.ndk.pool.removeRelay(r);
339
+ }
438
340
  }
439
341
 
440
- public async logout(keepSigner = false): Promise<void> {
342
+ public async logout(keepSigner = false) {
441
343
  if (!keepSigner) this.releaseSigner();
442
344
 
443
345
  // move current to recent
@@ -449,7 +351,7 @@ class AuthNostrService extends EventEmitter implements Signer {
449
351
  this.emit('updateAccounts');
450
352
  }
451
353
 
452
- private setUserInfo(userInfo: Info | null): void {
354
+ private setUserInfo(userInfo: Info | null) {
453
355
  this.params.userInfo = userInfo;
454
356
  this.emit('onUserInfo', userInfo);
455
357
 
@@ -459,14 +361,13 @@ class AuthNostrService extends EventEmitter implements Signer {
459
361
  }
460
362
  }
461
363
 
462
- public exportKeys(): string {
364
+ public exportKeys() {
463
365
  if (!this.params.userInfo) return '';
464
366
  if (this.params.userInfo.authMethod !== 'local') return '';
465
- const skBytes = hexToBytes(this.params.userInfo.sk!);
466
- return nip19.nsecEncode(skBytes);
367
+ return nip19.nsecEncode(hexToBytes(this.params.userInfo.sk!));
467
368
  }
468
369
 
469
- private onAuth(type: 'login' | 'signup' | 'logout', info: Info | null = null): void {
370
+ private onAuth(type: 'login' | 'signup' | 'logout', info: Info | null = null) {
470
371
  if (type !== 'logout' && !info) throw new Error('No user info in onAuth');
471
372
 
472
373
  // make sure we emulate logout first
@@ -480,8 +381,7 @@ class AuthNostrService extends EventEmitter implements Signer {
480
381
 
481
382
  if (info) {
482
383
  // async profile fetch
483
- // TODO: nostr-toolsを使用するようにfetchProfileをリファクタリングする
484
- fetchProfile(info, this.rxNostr as any).then(p => {
384
+ fetchProfile(info, this.profileNdk).then(p => {
485
385
  if (this.params.userInfo !== info) return;
486
386
 
487
387
  const userInfo = {
@@ -540,7 +440,7 @@ class AuthNostrService extends EventEmitter implements Signer {
540
440
  }
541
441
  }
542
442
 
543
- private async createIframe(iframeUrl?: string): Promise<{ iframe: HTMLIFrameElement; port: MessagePort } | undefined> {
443
+ private async createIframe(iframeUrl?: string) {
544
444
  if (!iframeUrl) return undefined;
545
445
 
546
446
  // ensure iframe
@@ -599,18 +499,18 @@ class AuthNostrService extends EventEmitter implements Signer {
599
499
  // }
600
500
  // }
601
501
 
602
- public async sendNeedAuth(): Promise<void> {
502
+ public async sendNeedAuth() {
603
503
  const [nostrconnect] = await this.getNostrConnectServices();
604
504
  const event = new CustomEvent('nlNeedAuth', { detail: { nostrconnect } });
605
505
  console.log('nostr-login need auth', nostrconnect);
606
506
  document.dispatchEvent(event);
607
507
  }
608
508
 
609
- public isAuthing(): boolean {
509
+ public isAuthing() {
610
510
  return !!this.readyCallback;
611
511
  }
612
512
 
613
- public async startAuth(): Promise<void> {
513
+ public async startAuth() {
614
514
  console.log('startAuth');
615
515
  if (this.readyCallback) throw new Error('Already started');
616
516
 
@@ -618,7 +518,7 @@ class AuthNostrService extends EventEmitter implements Signer {
618
518
  this.readyPromise = new Promise<void>(ok => (this.readyCallback = ok));
619
519
  }
620
520
 
621
- public async endAuth(): Promise<void> {
521
+ public async endAuth() {
622
522
  console.log('endAuth', this.params.userInfo);
623
523
  if (this.params.userInfo && this.params.userInfo.iframeUrl) {
624
524
  // create iframe
@@ -634,23 +534,23 @@ class AuthNostrService extends EventEmitter implements Signer {
634
534
  this.readyCallback = undefined;
635
535
  }
636
536
 
637
- public resetAuth(): void {
537
+ public resetAuth() {
638
538
  if (this.readyCallback) this.readyCallback();
639
539
  this.readyCallback = undefined;
640
540
  }
641
541
 
642
- private async listen(info: Info): Promise<void> {
542
+ private async listen(info: Info) {
643
543
  if (!info.iframeUrl) return this.signer!.listen(this.nostrConnectSecret);
644
544
  const r = await this.starterReady!.wait();
645
545
  if (r[0] === 'starterError') throw new Error(r[1]);
646
546
  return this.signer!.setListenReply(r[1], this.nostrConnectSecret);
647
547
  }
648
548
 
649
- public async connect(info: Info, perms?: string): Promise<void> {
549
+ public async connect(info: Info, perms?: string) {
650
550
  return this.signer!.connect(info.token, perms);
651
551
  }
652
552
 
653
- public async initSigner(info: Info, { listen = false, connect = false, eventToAddAccount = false } = {}): Promise<void> {
553
+ public async initSigner(info: Info, { listen = false, connect = false, eventToAddAccount = false } = {}) {
654
554
  // mutex
655
555
  if (this.signerPromise) {
656
556
  try {
@@ -696,28 +596,23 @@ class AuthNostrService extends EventEmitter implements Signer {
696
596
  return this.signerPromise;
697
597
  }
698
598
 
699
- private async initSignerInternal(info: Info, listen: boolean, connect: boolean, eventToAddAccount: boolean, resolve: () => void): Promise<void> {
599
+ private async initSignerInternal(info: Info, listen: boolean, connect: boolean, eventToAddAccount: boolean, resolve: () => void) {
700
600
  // pre-connect if we're creating the connection (listen|connect) or
701
601
  // not iframe mode
702
602
  if (info.relays && !info.iframeUrl) {
703
- // @ts-ignore
704
- this.rxNostr.switchRelays(info.relays);
603
+ for (const r of info.relays) {
604
+ this.ndk.addExplicitRelay(r, undefined);
605
+ }
705
606
  }
706
607
 
707
- // rx-nostr connects automatically
608
+ // wait until we connect, otherwise
609
+ // signer won't start properly
610
+ // NOTE: Deferred connection. ensureNIP46Connection will be called on demand.
611
+ // await this.ndk.connect();
708
612
 
709
613
  // 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);
614
+ const localSigner = new PrivateKeySigner(info.sk!);
615
+ this.signer = new Nip46Signer(this.ndk, localSigner, info.signerPubkey!, info.iframeUrl ? new URL(info.iframeUrl!).origin : undefined);
721
616
 
722
617
  // we should notify the banner the same way as
723
618
  // the onAuthUrl does
@@ -769,7 +664,7 @@ class AuthNostrService extends EventEmitter implements Signer {
769
664
  iframeUrl = '',
770
665
  customRelays,
771
666
  }: { name: string; bunkerUrl: string; sk?: string; domain?: string; iframeUrl?: string; customRelays?: string[] },
772
- ): Promise<void> {
667
+ ) {
773
668
  try {
774
669
  const info = bunkerUrlToInfo(bunkerUrl, sk);
775
670
  if (isBunkerUrl(name)) info.bunkerUrl = name;
@@ -806,15 +701,17 @@ class AuthNostrService extends EventEmitter implements Signer {
806
701
  }
807
702
  }
808
703
 
809
- public async signEvent(event: any): Promise<any> {
704
+ public async signEvent(event: any) {
810
705
  if (this.localSigner) {
811
- // this.localSigner.privateKey is Uint8Array
812
- event.pubkey = getPublicKey(this.localSigner.privateKey!);
706
+ event.pubkey = getPublicKey(hexToBytes(this.localSigner.privateKey!));
813
707
  event.id = getEventHash(event);
814
708
  event.sig = await this.localSigner.sign(event);
815
709
  } else {
816
710
  await this.ensureSigner();
817
711
 
712
+ // 署名前に接続を確認 (rpc.sendRequest内でも行われるが、安全のため)
713
+ await ensureNIP46Connection(this.ndk, 5000);
714
+
818
715
  event.pubkey = this.signer!.remotePubkey;
819
716
  event.id = getEventHash(event);
820
717
  event.sig = await this.signer!.sign(event);
@@ -823,89 +720,72 @@ class AuthNostrService extends EventEmitter implements Signer {
823
720
  return event;
824
721
  }
825
722
 
826
- private async ensureSigner(): Promise<void> {
723
+ private async ensureSigner() {
827
724
  // signerがキャンセル等で破棄されている場合は再初期化
828
725
  if (!this.signer && this.params.userInfo) {
829
726
  console.log('Signer was destroyed, reinitializing...');
830
727
  await this.initSigner(this.params.userInfo);
831
- return; // initSignerで接続も行われるので終了
728
+ return;
832
729
  }
833
730
 
834
731
  if (!this.signer) {
835
732
  throw new Error('No signer available');
836
733
  }
837
734
 
838
- // リレー接続を確認・再接続
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...');
856
-
857
- // リレーが完全に切断されている場合、signerも再初期化する必要がある
858
- // (RPCサブスクリプションも切断されているため)
859
- if (this.params.userInfo) {
860
- // 古いsignerを破棄
861
- this.signer = null;
862
-
863
- // 既存のリレーを一度切断 (rx-nostr reconnects automatically, but we might want to force it)
864
- this.rxNostr.reconnect(Object.keys(relayStates)[0]);
865
-
866
- // signerを再初期化(リレー接続も含む)
867
- await this.initSigner(this.params.userInfo);
868
- } else {
869
- throw new Error('Cannot reconnect: no user info');
870
- }
871
- }
735
+ // 接続確立は署名時またはRPCリクエスト時に行われるため、
736
+ // ここでの冗長な接続チェックは削除
872
737
  }
873
738
 
739
+ private async codec_call(method: string, pubkey: string, param: string) {
740
+ return new Promise<string>((resolve, reject) => {
741
+ this.signer!.rpc.sendRequest(this.signer!.remotePubkey!, method, [pubkey, param], 24133, (response: NDKRpcResponse) => {
742
+ if (!response.error) {
743
+ resolve(response.result);
744
+ } else {
745
+ reject(response.error);
746
+ }
747
+ });
748
+ });
749
+ }
874
750
 
875
-
876
- public async encrypt04(pubkey: string, plaintext: string): Promise<string> {
751
+ public async encrypt04(pubkey: string, plaintext: string) {
877
752
  if (this.localSigner) {
878
- return this.localSigner.encrypt(pubkey as any, plaintext);
753
+ return this.localSigner.encrypt(new NDKUser({ pubkey }), plaintext);
879
754
  } else {
880
755
  await this.ensureSigner();
881
- return this.signer!.encrypt(pubkey, plaintext);
756
+ return this.signer!.encrypt(new NDKUser({ pubkey }), plaintext);
882
757
  }
883
758
  }
884
759
 
885
- public async decrypt04(pubkey: string, ciphertext: string): Promise<string> {
760
+ public async decrypt04(pubkey: string, ciphertext: string) {
886
761
  if (this.localSigner) {
887
- return this.localSigner.decrypt(pubkey as any, ciphertext);
762
+ return this.localSigner.decrypt(new NDKUser({ pubkey }), ciphertext);
888
763
  } else {
764
+ // decrypt is broken in ndk v2.3.1, and latest
765
+ // ndk v2.8.1 doesn't allow to override connect easily,
766
+ // so we reimplement and fix decrypt here as a temporary fix
889
767
  await this.ensureSigner();
890
- return this.signer!.decrypt(pubkey, ciphertext);
768
+ return this.codec_call('nip04_decrypt', pubkey, ciphertext);
891
769
  }
892
770
  }
893
771
 
894
- public async encrypt44(pubkey: string, plaintext: string): Promise<string> {
772
+ public async encrypt44(pubkey: string, plaintext: string) {
895
773
  if (this.localSigner) {
896
774
  return this.nip44Codec.encrypt(this.localSigner.privateKey!, pubkey, plaintext);
897
775
  } else {
776
+ // no support of nip44 in ndk yet
898
777
  await this.ensureSigner();
899
- return this.signer!.encryptNip44(pubkey, plaintext);
778
+ return this.codec_call('nip44_encrypt', pubkey, plaintext);
900
779
  }
901
780
  }
902
781
 
903
- public async decrypt44(pubkey: string, ciphertext: string): Promise<string> {
782
+ public async decrypt44(pubkey: string, ciphertext: string) {
904
783
  if (this.localSigner) {
905
784
  return this.nip44Codec.decrypt(this.localSigner.privateKey!, pubkey, ciphertext);
906
785
  } else {
786
+ // no support of nip44 in ndk yet
907
787
  await this.ensureSigner();
908
- return this.signer!.decryptNip44(pubkey, ciphertext);
788
+ return this.codec_call('nip44_decrypt', pubkey, ciphertext);
909
789
  }
910
790
  }
911
791
  }