@konemono/nostr-login 1.7.48 → 1.7.50

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.
@@ -2,7 +2,7 @@ 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, pubkey: string): Uint8Array<ArrayBufferLike>;
5
+ createKey(privkey: string, pubkey: string): Uint8Array;
6
6
  private getKey;
7
7
  encrypt(privkey: string, pubkey: string, text: string): string;
8
8
  decrypt(privkey: string, pubkey: string, data: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konemono/nostr-login",
3
- "version": "1.7.48",
3
+ "version": "1.7.50",
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-dev-kit/ndk": "^2.18.1",
14
+ "@nostr-dev-kit/ndk": "^2.3.1",
15
15
  "nostr-tools": "^1.17.0",
16
- "tseep": "^1.3.1"
16
+ "tseep": "^1.2.1"
17
17
  },
18
18
  "devDependencies": {
19
- "@rollup/plugin-commonjs": "^25.0.8",
20
- "@rollup/plugin-node-resolve": "^15.3.1",
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.53.5",
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,19 +1,18 @@
1
- //AuthNostrService.ts
2
1
  import { localStorageAddAccount, bunkerUrlToInfo, isBunkerUrl, fetchProfile, getBunkerUrl, localStorageRemoveCurrentAccount, createProfile, getIcon } from '../utils';
3
2
  import { ConnectionString, Info } from 'nostr-login-components/dist/types/types';
4
3
  import { generatePrivateKey, getEventHash, getPublicKey, nip19 } from 'nostr-tools';
5
4
  import { NostrLoginAuthOptions, Response } from '../types';
6
- import NDK, { NDKEvent, NDKNip46Signer, NDKPrivateKeySigner, NDKRpcResponse, NDKUser, NostrEvent } from '@nostr-dev-kit/ndk';
5
+ import NDK, { NDKEvent, NDKNip46Signer, NDKRpcResponse, NDKUser, NostrEvent } from '@nostr-dev-kit/ndk';
7
6
  import { NostrParams } from './';
8
7
  import { EventEmitter } from 'tseep';
9
8
  import { Signer } from './Nostr';
10
9
  import { Nip44 } from '../utils/nip44';
11
10
  import { IframeNostrRpc, Nip46Signer, ReadyListener } from './Nip46';
12
- //import { PrivateKeySigner } from './Signer';
11
+ import { PrivateKeySigner } from './Signer';
13
12
 
14
13
  const OUTBOX_RELAYS = ['wss://user.kindpag.es', 'wss://purplepag.es', 'wss://relay.nos.social'];
15
14
  const DEFAULT_NOSTRCONNECT_RELAYS = ['wss://relay.nsec.app/', 'wss://ephemeral.snowflare.cc/'];
16
- const CONNECT_TIMEOUT = 20000;
15
+ const CONNECT_TIMEOUT = 5000;
17
16
  const NOSTRCONNECT_APPS: ConnectionString[] = [
18
17
  {
19
18
  name: 'Nsec.app',
@@ -41,7 +40,7 @@ class AuthNostrService extends EventEmitter implements Signer {
41
40
  private ndk: NDK;
42
41
  private profileNdk: NDK;
43
42
  private signer: Nip46Signer | null = null;
44
- private localSigner: NDKPrivateKeySigner | null = null;
43
+ private localSigner: PrivateKeySigner | null = null;
45
44
  private params: NostrParams;
46
45
  private signerPromise?: Promise<void>;
47
46
  private signerErrCallback?: (err: string) => void;
@@ -93,13 +92,13 @@ class AuthNostrService extends EventEmitter implements Signer {
93
92
  if (this.signerPromise) {
94
93
  try {
95
94
  await this.signerPromise;
96
- } catch {}
95
+ } catch { }
97
96
  }
98
97
 
99
98
  if (this.readyPromise) {
100
99
  try {
101
100
  await this.readyPromise;
102
- } catch {}
101
+ } catch { }
103
102
  }
104
103
  }
105
104
 
@@ -124,6 +123,7 @@ class AuthNostrService extends EventEmitter implements Signer {
124
123
  ) {
125
124
  relays = relays && relays.length > 0 ? relays : DEFAULT_NOSTRCONNECT_RELAYS;
126
125
 
126
+
127
127
  const info: Info = {
128
128
  authMethod: 'connect',
129
129
  pubkey: '', // unknown yet!
@@ -154,6 +154,13 @@ class AuthNostrService extends EventEmitter implements Signer {
154
154
  }
155
155
 
156
156
  public async createNostrConnect(relays?: string[]) {
157
+ /*const relayList = relays
158
+ ? relays
159
+ .split(",")
160
+ .map(r => r.trim().replace(/['"]/g, ""))
161
+ .filter(r => r.length > 0)
162
+ : [];*/
163
+
157
164
  this.nostrConnectKey = generatePrivateKey();
158
165
  this.nostrConnectSecret = Math.random().toString(36).substring(7);
159
166
 
@@ -165,16 +172,24 @@ class AuthNostrService extends EventEmitter implements Signer {
165
172
  perms: encodeURIComponent(this.params.optionsModal.perms || ''),
166
173
  };
167
174
 
168
- // .join('') を追加
169
- const relayParams = (relays || []).length > 0 ? (relays || []).map(r => `&relay=${encodeURIComponent(r)}`).join('') : '';
170
-
171
- return `nostrconnect://${pubkey}?image=${meta.icon}&url=${meta.url}&name=${meta.name}&perms=${meta.perms}&secret=${this.nostrConnectSecret}${relayParams}`;
175
+ return `nostrconnect://${pubkey}?image=${meta.icon}&url=${meta.url}&name=${meta.name}&perms=${meta.perms}&secret=${this.nostrConnectSecret}${(relays || []).length > 0 ? (relays || []).map((r, i) => `&relay=${r}`) : ""}`;
172
176
  }
173
177
 
174
178
  public async getNostrConnectServices(): Promise<[string, ConnectionString[]]> {
175
- const nostrconnect = await this.createNostrConnect(DEFAULT_NOSTRCONNECT_RELAYS);
179
+ const nostrconnect = await this.createNostrConnect();
176
180
 
181
+ // copy defaults
177
182
  const apps = NOSTRCONNECT_APPS.map(a => ({ ...a }));
183
+ // if (this.params.optionsModal.dev) {
184
+ // apps.push({
185
+ // name: 'Dev.Nsec.app',
186
+ // domain: 'new.nsec.app',
187
+ // canImport: true,
188
+ // img: 'https://new.nsec.app/assets/favicon.ico',
189
+ // link: 'https://dev.nsec.app/<nostrconnect>',
190
+ // relay: 'wss://relay.nsec.app/',
191
+ // });
192
+ // }
178
193
 
179
194
  for (const a of apps) {
180
195
  let relays: string[] = [...DEFAULT_NOSTRCONNECT_RELAYS];
@@ -196,12 +211,18 @@ class AuthNostrService extends EventEmitter implements Signer {
196
211
  }
197
212
  }
198
213
 
199
- // nostrconnectから既存のリレーを削除して新しいリレーを追加
200
- const baseUrl = nostrconnect.split('&relay=')[0];
201
- const relayParams = relays.map(r => `&relay=${encodeURIComponent(r)}`).join('');
202
- const nc = baseUrl + relayParams;
214
+ const relayParams = relays
215
+ .map(r => r.replace(/['"]/g, ''))
216
+ .map(r => `&relay=${encodeURIComponent(r)}`)
217
+ .join('');
203
218
 
204
- a.link = a.iframeUrl ? nc : a.link.replace('<nostrconnect>', nc);
219
+ const nc = nostrconnect + relayParams;
220
+
221
+ if (a.iframeUrl) {
222
+ a.link = nc;
223
+ } else {
224
+ a.link = a.link.replace('<nostrconnect>', nc);
225
+ }
205
226
  }
206
227
 
207
228
  return [nostrconnect, apps];
@@ -223,7 +244,7 @@ class AuthNostrService extends EventEmitter implements Signer {
223
244
 
224
245
  public async setLocal(info: Info, signup?: boolean) {
225
246
  this.releaseSigner();
226
- this.localSigner = new NDKPrivateKeySigner(info.sk!);
247
+ this.localSigner = new PrivateKeySigner(info.sk!);
227
248
 
228
249
  if (signup) await createProfile(info, this.profileNdk, this.localSigner, this.params.optionsModal.signupRelays, this.params.optionsModal.outboxRelays);
229
250
 
@@ -297,7 +318,9 @@ class AuthNostrService extends EventEmitter implements Signer {
297
318
  const userPubkey = await this.signer!.createAccount2({ bunkerPubkey: info.signerPubkey!, name, domain, perms: this.params.optionsModal.perms });
298
319
 
299
320
  return {
300
- bunkerUrl: `bunker://${userPubkey}?` + (info.relays ?? []).map((r: string) => `relay=${encodeURIComponent(r)}`).join('&'),
321
+ bunkerUrl:
322
+ `bunker://${userPubkey}?` +
323
+ (info.relays ?? []).map((r: string) => `relay=${encodeURIComponent(r)}`).join('&'),
301
324
  sk: info.sk,
302
325
  };
303
326
  }
@@ -348,7 +371,7 @@ class AuthNostrService extends EventEmitter implements Signer {
348
371
  if (info && this.params.userInfo && (info.pubkey !== this.params.userInfo.pubkey || info.authMethod !== this.params.userInfo.authMethod)) {
349
372
  const event = new CustomEvent('nlAuth', { detail: { type: 'logout' } });
350
373
  console.log('nostr-login auth', event.detail);
351
- document.dispatchEvent(event);
374
+ document.dispatchEvent(event)
352
375
  }
353
376
 
354
377
  this.setUserInfo(info);
@@ -485,7 +508,7 @@ class AuthNostrService extends EventEmitter implements Signer {
485
508
  }
486
509
 
487
510
  public async startAuth() {
488
- console.log('startAuth');
511
+ console.log("startAuth");
489
512
  if (this.readyCallback) throw new Error('Already started');
490
513
 
491
514
  // start the new promise
@@ -529,100 +552,81 @@ class AuthNostrService extends EventEmitter implements Signer {
529
552
  if (this.signerPromise) {
530
553
  try {
531
554
  await this.signerPromise;
532
- } catch {}
555
+ } catch { }
533
556
  }
534
557
 
558
+ // we remove support for iframe from nip05 and bunker-url methods,
559
+ // only nostrconnect flow will use it.
560
+ // info.iframeUrl = info.iframeUrl || (await this.getIframeUrl(info.domain));
535
561
  console.log('initSigner info', info);
536
562
 
563
+ // start listening for the ready signal
537
564
  const iframeOrigin = info.iframeUrl ? new URL(info.iframeUrl!).origin : undefined;
565
+ if (iframeOrigin) this.starterReady = new ReadyListener(['starterDone', 'starterError'], iframeOrigin);
538
566
 
539
- if (iframeOrigin) {
540
- this.starterReady = new ReadyListener(['starterDone', 'starterError'], iframeOrigin);
541
- }
542
-
567
+ // notify modals so they could show the starter iframe,
568
+ // FIXME shouldn't this come from nostrconnect service list?
543
569
  this.emit('onIframeUrl', info.iframeUrl);
544
570
 
545
571
  this.signerPromise = new Promise<void>(async (ok, err) => {
546
572
  this.signerErrCallback = err;
547
-
548
573
  try {
549
- console.log('NDK relays before connect:', Array.from(this.ndk.pool.relays.keys()));
550
-
574
+ // pre-connect if we're creating the connection (listen|connect) or
575
+ // not iframe mode
551
576
  if (info.relays && !info.iframeUrl) {
552
577
  for (const r of info.relays) {
553
578
  this.ndk.addExplicitRelay(r, undefined);
554
- console.log('Added relay:', r);
555
579
  }
556
580
  }
557
581
 
558
- console.log('NDK relays after add:', Array.from(this.ndk.pool.relays.keys()));
582
+ // wait until we connect, otherwise
583
+ // signer won't start properly
584
+ await this.ndk.connect(CONNECT_TIMEOUT);
559
585
 
560
- // 接続開始(失敗しても続行)
561
- this.ndk.connect(CONNECT_TIMEOUT).then(value => {
562
- console.log(value);
563
- });
564
-
565
- // 少なくとも1つ接続されるのを待つ(致命扱いしない)
566
- await new Promise<void>(resolve => {
567
- const start = Date.now();
568
-
569
- const timer = setInterval(() => {
570
- const connected = this.ndk.pool.connectedRelays();
571
-
572
- if (connected.length > 0) {
573
- clearInterval(timer);
574
- resolve();
575
- return;
576
- }
577
-
578
- if (Date.now() - start > CONNECT_TIMEOUT) {
579
- // タイムアウトしても続行
580
- clearInterval(timer);
581
- resolve();
582
- }
583
- }, 5000);
584
- });
585
-
586
- console.log(
587
- 'NDK connected relays:',
588
- this.ndk.pool.connectedRelays().map(r => r.url),
589
- );
590
-
591
- const localSigner = new NDKPrivateKeySigner(info.sk!);
586
+ // create and prepare the signer
587
+ const localSigner = new PrivateKeySigner(info.sk!);
592
588
  this.signer = new Nip46Signer(this.ndk, localSigner, info.signerPubkey!, iframeOrigin);
593
589
 
594
- this.signer.on('iframeRestart', async () => {
590
+ // we should notify the banner the same way as
591
+ // the onAuthUrl does
592
+ this.signer.on(`iframeRestart`, async () => {
595
593
  const iframeUrl = info.iframeUrl + (info.iframeUrl!.includes('?') ? '&' : '?') + 'pubkey=' + info.pubkey + '&rebind=' + localSigner.pubkey;
596
-
597
- this.emit('iframeRestart', {
598
- pubkey: info.pubkey,
599
- iframeUrl,
600
- });
594
+ this.emit('iframeRestart', { pubkey: info.pubkey, iframeUrl });
601
595
  });
602
596
 
597
+ // OAuth flow
598
+ // if (!listen) {
603
599
  this.signer.on('authUrl', (url: string) => {
604
600
  console.log('nostr login auth url', url);
605
- this.emit('onAuthUrl', {
606
- url,
607
- iframeUrl: info.iframeUrl,
608
- eventToAddAccount,
609
- });
601
+
602
+ // notify our UI
603
+ this.emit('onAuthUrl', { url, iframeUrl: info.iframeUrl, eventToAddAccount });
610
604
  });
605
+ // }
611
606
 
612
607
  if (listen) {
608
+ // nostrconnect: flow
609
+ // wait for the incoming message from signer
613
610
  await this.listen(info);
614
611
  } else if (connect) {
612
+ // bunker: flow
613
+ // send 'connect' message to signer
615
614
  await this.connect(info, this.params.optionsModal.perms);
616
615
  } else {
617
- await this.signer.initUserPubkey(info.pubkey);
616
+ // provide saved pubkey as a hint
617
+ await this.signer!.initUserPubkey(info.pubkey);
618
618
  }
619
619
 
620
- info.pubkey = this.signer.userPubkey!;
621
- info.signerPubkey = this.signer.remotePubkey;
620
+ // ensure, we're using it in callbacks above
621
+ // and expect info to be valid after this call
622
+ info.pubkey = this.signer!.userPubkey;
623
+ // learned after nostrconnect flow
624
+ info.signerPubkey = this.signer!.remotePubkey;
622
625
 
623
626
  ok();
624
627
  } catch (e) {
625
628
  console.log('initSigner failure', e);
629
+ // make sure signer isn't set
626
630
  this.signer = null;
627
631
  err(e);
628
632
  }
@@ -1,27 +1,15 @@
1
- //Nip46.ts
2
- import NDK, {
3
- NDKEvent,
4
- NDKFilter,
5
- NDKNip46Signer,
6
- NDKNostrRpc,
7
- NDKPrivateKeySigner,
8
- NDKRpcRequest,
9
- NDKRpcResponse,
10
- NDKSubscription,
11
- NDKSubscriptionCacheUsage,
12
- NostrEvent,
13
- } from '@nostr-dev-kit/ndk';
1
+ import NDK, { NDKEvent, NDKFilter, NDKNip46Signer, NDKNostrRpc, NDKRpcRequest, NDKRpcResponse, NDKSubscription, NDKSubscriptionCacheUsage, NostrEvent } from '@nostr-dev-kit/ndk';
14
2
  import { validateEvent, verifySignature } from 'nostr-tools';
15
- //import { PrivateKeySigner } from './Signer';
3
+ import { PrivateKeySigner } from './Signer';
16
4
 
17
5
  class NostrRpc extends NDKNostrRpc {
18
6
  protected _ndk: NDK;
19
- protected _signer: NDKPrivateKeySigner;
7
+ protected _signer: PrivateKeySigner;
20
8
  protected requests: Set<string> = new Set();
21
9
  private sub?: NDKSubscription;
22
10
  protected _useNip44: boolean = false;
23
11
 
24
- public constructor(ndk: NDK, signer: NDKPrivateKeySigner) {
12
+ public constructor(ndk: NDK, signer: PrivateKeySigner) {
25
13
  super(ndk, signer, ndk.debug.extend('nip46:signer:rpc'));
26
14
  this._ndk = ndk;
27
15
  this._signer = signer;
@@ -55,10 +43,8 @@ class NostrRpc extends NDKNostrRpc {
55
43
  public async parseEvent(event: NDKEvent): Promise<NDKRpcRequest | NDKRpcResponse> {
56
44
  const remoteUser = this._ndk.getUser({ pubkey: event.pubkey });
57
45
  remoteUser.ndk = this._ndk;
58
- const decryptedContent = this.isNip04(event.content)
59
- ? await this._signer.decrypt(remoteUser, event.content, 'nip04')
60
- : await this._signer.decrypt(remoteUser, event.content, 'nip44');
61
- //const decryptedContent = await decrypt.call(this._signer, remoteUser, event.content);
46
+ const decrypt = this.isNip04(event.content) ? this._signer.decrypt : this._signer.decryptNip44;
47
+ const decryptedContent = await decrypt.call(this._signer, remoteUser, event.content);
62
48
  const parsedContent = JSON.parse(decryptedContent);
63
49
  const { id, method, params, result, error } = parsedContent;
64
50
 
@@ -143,48 +129,45 @@ class NostrRpc extends NDKNostrRpc {
143
129
  public async sendRequest(remotePubkey: string, method: string, params: string[] = [], kind = 24133, cb?: (res: NDKRpcResponse) => void): Promise<NDKRpcResponse> {
144
130
  const id = this.getId();
145
131
 
146
- // 1. Promiseを変数に格納
147
- const responsePromise = this.setResponseHandler(id, cb);
132
+ // response handler will deduplicate auth urls and responses
133
+ this.setResponseHandler(id, cb);
148
134
 
135
+ // create and sign request
149
136
  const event = await this.createRequestEvent(id, remotePubkey, method, params, kind);
137
+ console.log("sendRequest", { event, method, remotePubkey, params });
150
138
 
151
- // 2. 送信
139
+ // send to relays
152
140
  await event.publish();
153
141
 
154
- // 3. undefined ではなく、レスポンスを待つ Promise を返す
155
- return responsePromise;
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.
147
+ // @ts-ignore
148
+ return undefined as NDKRpcResponse;
156
149
  }
157
150
 
158
151
  protected setResponseHandler(id: string, cb?: (res: NDKRpcResponse) => void) {
159
- const now = Date.now();
160
152
  let authUrlSent = false;
161
-
162
- // 1. 外部から解決できるように Promise を作成
163
- return new Promise<NDKRpcResponse>(resolve => {
153
+ const now = Date.now();
154
+ return new Promise<NDKRpcResponse>(() => {
164
155
  const responseHandler = (response: NDKRpcResponse) => {
165
- console.log(`[NIP46] Received response for ID: ${response.id}`, response);
166
-
167
156
  if (response.result === 'auth_url') {
168
157
  this.once(`response-${id}`, responseHandler);
169
158
  if (!authUrlSent) {
170
159
  authUrlSent = true;
171
160
  this.emit('authUrl', response.error);
172
161
  }
173
- } else {
174
- // IDが一致しているか、リクエストリストに存在するか確認
162
+ } else if (cb) {
175
163
  if (this.requests.has(id)) {
176
164
  this.requests.delete(id);
177
165
  console.log('nostr-login processed nip46 request in', Date.now() - now, 'ms');
178
-
179
- if (cb) cb(response); // 既存のコールバックを実行
180
- resolve(response); // ★Promise を解決する(これで await が終わる)
181
- } else {
182
- console.warn(`[NIP46] Received response for unknown ID: ${id}`);
166
+ cb(response);
183
167
  }
184
168
  }
185
169
  };
186
170
 
187
- // イベント登録
188
171
  this.once(`response-${id}`, responseHandler);
189
172
  });
190
173
  }
@@ -203,8 +186,8 @@ class NostrRpc extends NDKNostrRpc {
203
186
  } as NostrEvent);
204
187
 
205
188
  const useNip44 = this._useNip44 && method !== 'create_account';
206
- event.content = useNip44 ? await this._signer.encrypt(remoteUser, event.content, 'nip44') : await this._signer.encrypt(remoteUser, event.content, 'nip04');
207
- //event.content = await encrypt.call(this._signer, remoteUser, event.content);
189
+ const encrypt = useNip44 ? this._signer.encryptNip44 : this._signer.encrypt;
190
+ event.content = await encrypt.call(this._signer, remoteUser, event.content);
208
191
  await event.sign(this._signer);
209
192
 
210
193
  return event;
@@ -216,7 +199,7 @@ export class IframeNostrRpc extends NostrRpc {
216
199
  private iframePort?: MessagePort;
217
200
  private iframeRequests = new Map<string, { id: string; pubkey: string }>();
218
201
 
219
- public constructor(ndk: NDK, localSigner: NDKPrivateKeySigner, iframePeerOrigin?: string) {
202
+ public constructor(ndk: NDK, localSigner: PrivateKeySigner, iframePeerOrigin?: string) {
220
203
  super(ndk, localSigner);
221
204
  this._ndk = ndk;
222
205
  this.peerOrigin = iframePeerOrigin;
@@ -355,54 +338,53 @@ export class ReadyListener {
355
338
  }
356
339
 
357
340
  export class Nip46Signer extends NDKNip46Signer {
341
+ private _userPubkey: string = '';
358
342
  private _rpc: IframeNostrRpc;
359
- private _remotePubkey: string = '';
360
343
 
361
- constructor(ndk: NDK, localSigner: NDKPrivateKeySigner, signerPubkey: string, iframeOrigin?: string) {
344
+ constructor(ndk: NDK, localSigner: PrivateKeySigner, signerPubkey: string, iframeOrigin?: string) {
362
345
  super(ndk, signerPubkey, localSigner);
363
- this._remotePubkey = signerPubkey;
364
346
 
347
+ // override with our own rpc implementation
365
348
  this._rpc = new IframeNostrRpc(ndk, localSigner, iframeOrigin);
366
- this._rpc.setUseNip44(true);
349
+ this._rpc.setUseNip44(true); // !!this.params.optionsModal.dev);
367
350
  this._rpc.on('authUrl', (url: string) => {
368
351
  this.emit('authUrl', url);
369
352
  });
370
- this.rpc = this._rpc;
371
- }
372
353
 
373
- get remotePubkey(): string {
374
- return this._remotePubkey;
354
+ this.rpc = this._rpc;
375
355
  }
376
356
 
377
- set remotePubkey(value: string) {
378
- this._remotePubkey = value;
357
+ get userPubkey() {
358
+ return this._userPubkey;
379
359
  }
380
360
 
381
- // userPubkeyのgetterを削除し、親クラスのプロパティを直接使用
382
-
383
361
  private async setSignerPubkey(signerPubkey: string, sameAsUser: boolean = false) {
384
- console.log('setSignerPubkey', signerPubkey);
362
+ console.log("setSignerPubkey", signerPubkey);
363
+
364
+ // ensure it's set
385
365
  this.remotePubkey = signerPubkey;
386
366
 
367
+ // when we're sure it's known
387
368
  this._rpc.on(`iframeRestart-${signerPubkey}`, () => {
388
369
  this.emit('iframeRestart');
389
370
  });
390
371
 
372
+ // now call getPublicKey and swap remotePubkey w/ that
391
373
  await this.initUserPubkey(sameAsUser ? signerPubkey : '');
392
374
  }
393
375
 
394
376
  public async initUserPubkey(hintPubkey?: string) {
395
- // 親クラスのuserPubkeyプロパティを直接設定
396
- if (this.userPubkey) throw new Error('Already called initUserPubkey');
377
+ if (this._userPubkey) throw new Error('Already called initUserPubkey');
397
378
 
398
379
  if (hintPubkey) {
399
- this.userPubkey = hintPubkey;
380
+ this._userPubkey = hintPubkey;
400
381
  return;
401
382
  }
402
383
 
403
- this.userPubkey = await new Promise((ok, err) => {
384
+ this._userPubkey = await new Promise<string>((ok, err) => {
404
385
  if (!this.remotePubkey) throw new Error('Signer pubkey not set');
405
- console.log('get_public_key', this.remotePubkey);
386
+
387
+ console.log("get_public_key", this.remotePubkey);
406
388
  this._rpc.sendRequest(this.remotePubkey, 'get_public_key', [], 24133, (response: NDKRpcResponse) => {
407
389
  ok(response.result);
408
390
  });
@@ -426,7 +408,12 @@ export class Nip46Signer extends NDKNip46Signer {
426
408
  }
427
409
 
428
410
  public async createAccount2({ bunkerPubkey, name, domain, perms = '' }: { bunkerPubkey: string; name: string; domain: string; perms?: string }) {
429
- const params = [name, domain, '', perms];
411
+ const params = [
412
+ name,
413
+ domain,
414
+ '', // email
415
+ perms,
416
+ ];
430
417
 
431
418
  const r = await new Promise<NDKRpcResponse>(ok => {
432
419
  this.rpc.sendRequest(bunkerPubkey, 'create_account', params, undefined, ok);
@@ -436,6 +423,7 @@ export class Nip46Signer extends NDKNip46Signer {
436
423
  if (r.result === 'error') {
437
424
  throw new Error(r.error);
438
425
  }
426
+
439
427
  return r.result;
440
428
  }
441
429
  }
@@ -1,4 +1,4 @@
1
- /* import { NDKPrivateKeySigner, NDKUser } from '@nostr-dev-kit/ndk';
1
+ import { NDKPrivateKeySigner, NDKUser } from '@nostr-dev-kit/ndk';
2
2
  import { Nip44 } from '../utils/nip44';
3
3
  import { getPublicKey } from 'nostr-tools';
4
4
 
@@ -23,4 +23,3 @@ export class PrivateKeySigner extends NDKPrivateKeySigner {
23
23
  return Promise.resolve(this.nip44.decrypt(this.privateKey!, sender.pubkey, value));
24
24
  }
25
25
  }
26
- */
@@ -102,9 +102,7 @@ export const bunkerUrlToInfo = (bunkerUrl: string, sk = ''): Info => {
102
102
  export const isBunkerUrl = (value: string) => value.startsWith('bunker://');
103
103
 
104
104
  export const getBunkerUrl = async (value: string, optionsModal: NostrLoginOptions) => {
105
- if (!value) {
106
- return '';
107
- }
105
+ if (!value) return '';
108
106
 
109
107
  if (isBunkerUrl(value)) {
110
108
  return value;
@@ -113,24 +111,28 @@ export const getBunkerUrl = async (value: string, optionsModal: NostrLoginOption
113
111
  if (value.includes('@')) {
114
112
  const [name, domain] = value.toLocaleLowerCase().split('@');
115
113
  const origin = optionsModal.devOverrideBunkerOrigin || `https://${domain}`;
114
+
116
115
  const bunkerUrl = `${origin}/.well-known/nostr.json?name=_`;
117
- const userUrl = `${origin}/.well-known/nostr.json?name=${name}`;
118
- const bunker = await fetch(bunkerUrl);
119
- const bunkerData = await bunker.json();
116
+ const userUrl = `${origin}/.well-known/nostr.json?name=${name}`;
117
+
118
+ const bunkerRes = await fetch(bunkerUrl);
119
+ const bunkerData = await bunkerRes.json();
120
120
  const bunkerPubkey = bunkerData.names['_'];
121
- const bunkerRelays = bunkerData.nip46[bunkerPubkey];
122
- const user = await fetch(userUrl);
123
- const userData = await user.json();
121
+ const bunkerRelays: string[] = bunkerData.nip46[bunkerPubkey];
122
+
123
+ const userRes = await fetch(userUrl);
124
+ const userData = await userRes.json();
124
125
  const userPubkey = userData.names[name];
125
- // console.log({
126
- // bunkerData, userData, bunkerPubkey, bunkerRelays, userPubkey,
127
- // name, domain, origin
128
- // })
129
- if (!bunkerRelays.length) {
126
+
127
+ if (!bunkerRelays || bunkerRelays.length === 0) {
130
128
  throw new Error('Bunker relay not provided');
131
129
  }
132
130
 
133
- return `bunker://${userPubkey}?relay=${bunkerRelays[0]}`;
131
+ const relayParams = bunkerRelays
132
+ .map(r => `relay=${encodeURIComponent(r)}`)
133
+ .join('&');
134
+
135
+ return `bunker://${userPubkey}?${relayParams}`;
134
136
  }
135
137
 
136
138
  throw new Error('Invalid user name or bunker url');