@konemono/nostr-login 1.7.36 → 1.7.38

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,6 +1,6 @@
1
1
  import { NostrLoginOptions, TypeBanner } from '../types';
2
2
  import { NostrParams } from '.';
3
- import { Info } from 'nostr-login-components';
3
+ import { Info } from 'nostr-login-components/dist/types/types';
4
4
  import { EventEmitter } from 'tseep';
5
5
  import { getDarkMode } from '../utils';
6
6
  import { ReadyListener } from './Nip46';
@@ -1,13 +1,11 @@
1
1
  import { NostrLoginOptions, StartScreens, TypeModal } from '../types';
2
- import { checkNip05, getBunkerUrl, getDarkMode, localStorageRemoveRecent, localStorageSetItem, prepareSignupRelays, localStorageGetItem } from '../utils';
2
+ import { checkNip05, getBunkerUrl, getDarkMode, localStorageRemoveRecent, localStorageSetItem, prepareSignupRelays } from '../utils';
3
3
  import { AuthNostrService, NostrExtensionService, NostrParams } from '.';
4
4
  import { EventEmitter } from 'tseep';
5
5
  import { ConnectionString, Info, RecentType } from 'nostr-login-components/dist/types/types';
6
6
  import { nip19 } from 'nostr-tools';
7
7
  import { setDarkMode } from '..';
8
8
 
9
- const RELAY_STORAGE_KEY = '__nostrlogin_user_relays';
10
-
11
9
  class ModalManager extends EventEmitter {
12
10
  private modal: TypeModal | null = null;
13
11
  private params: NostrParams;
@@ -25,18 +23,6 @@ class ModalManager extends EventEmitter {
25
23
  this.authNostrService = authNostrService;
26
24
  }
27
25
 
28
- private getUserRelays(): string[] {
29
- const stored = localStorageGetItem(RELAY_STORAGE_KEY);
30
- if (stored && Array.isArray(stored)) {
31
- return stored;
32
- }
33
- return [];
34
- }
35
-
36
- private saveUserRelays(relays: string[]) {
37
- localStorageSetItem(RELAY_STORAGE_KEY, JSON.stringify(relays));
38
- }
39
-
40
26
  public async waitReady() {
41
27
  if (this.launcherPromise) {
42
28
  try {
@@ -48,8 +34,10 @@ class ModalManager extends EventEmitter {
48
34
 
49
35
  public async launch(opt: NostrLoginOptions) {
50
36
  console.log('nostr-login launch', opt);
37
+ // mutex
51
38
  if (this.launcherPromise) await this.waitReady();
52
39
 
40
+ // hmm?!
53
41
  if (this.authNostrService.isAuthing()) this.authNostrService.resetAuth();
54
42
 
55
43
  this.opt = opt;
@@ -73,6 +61,7 @@ class ModalManager extends EventEmitter {
73
61
  this.modal.setAttribute('bunkers', opt.bunkers);
74
62
  } else {
75
63
  let bunkers = 'nsec.app,highlighter.com';
64
+ // if (opt.dev) bunkers += ',new.nsec.app';
76
65
  this.modal.setAttribute('bunkers', bunkers);
77
66
  }
78
67
 
@@ -102,11 +91,6 @@ class ModalManager extends EventEmitter {
102
91
  this.modal.isLoadingExtension = false;
103
92
  this.modal.isLoading = false;
104
93
 
105
- const userRelays = this.getUserRelays();
106
- if (userRelays.length > 0) {
107
- this.params.optionsModal.connectRelays = userRelays;
108
- }
109
-
110
94
  [this.modal.connectionString, this.modal.connectionStringServices] = await this.authNostrService.getNostrConnectServices();
111
95
 
112
96
  dialog.appendChild(this.modal);
@@ -116,11 +100,21 @@ class ModalManager extends EventEmitter {
116
100
 
117
101
  this.launcherPromise = new Promise<void>((ok, err) => {
118
102
  dialog.addEventListener('close', () => {
103
+ // noop if already resolved
119
104
  err(new Error('Closed'));
120
105
 
121
106
  this.authNostrService.resetAuth();
122
107
 
123
108
  if (this.modal) {
109
+ // it's reset on modal creation
110
+ // // reset state
111
+ // this.modal.isLoading = false;
112
+ // this.modal.authUrl = '';
113
+ // this.modal.iframeUrl = '';
114
+ // this.modal.error = '';
115
+ // this.modal.isLoadingExtension = false;
116
+
117
+ // drop it
124
118
  // @ts-ignore
125
119
  document.body.removeChild(this.modal.parentNode);
126
120
  this.modal = null;
@@ -163,16 +157,20 @@ class ModalManager extends EventEmitter {
163
157
 
164
158
  const login = async (name: string, domain?: string) => {
165
159
  await exec(async () => {
160
+ // convert name to bunker url
166
161
  const bunkerUrl = await getBunkerUrl(name, this.params.optionsModal);
167
162
 
163
+ // connect to bunker by url
168
164
  await this.authNostrService.authNip46('login', { name, bunkerUrl, domain });
169
165
  });
170
166
  };
171
167
 
172
168
  const signup = async (name: string) => {
173
169
  await exec(async () => {
170
+ // create acc on service and get bunker url
174
171
  const { bunkerUrl, sk } = await this.authNostrService.createAccount(name);
175
172
 
173
+ // connect to bunker by url
176
174
  await this.authNostrService.authNip46('signup', { name, bunkerUrl, sk });
177
175
  });
178
176
  };
@@ -192,6 +190,7 @@ class ModalManager extends EventEmitter {
192
190
  cs.link = this.authNostrService.prepareImportUrl(cs.link);
193
191
 
194
192
  if (this.modal && iframeUrl) {
193
+ // we pass the link down to iframe so it could open it
195
194
  this.modal.authUrl = cs.link;
196
195
  this.modal.iframeUrl = iframeUrl;
197
196
  this.modal.isLoading = false;
@@ -204,11 +203,12 @@ class ModalManager extends EventEmitter {
204
203
 
205
204
  const nostrConnect = async (cs?: ConnectionString) => {
206
205
  await exec(async () => {
207
- const { relay, domain, link, iframeUrl } = cs || {};
208
- console.log('nostrConnect', cs, relay, domain, link, iframeUrl);
206
+ const { relays, domain, link, iframeUrl } = cs || {};
207
+ console.log('nostrConnect', cs, relays, domain, link, iframeUrl);
209
208
 
210
209
  if (this.modal) {
211
210
  if (iframeUrl) {
211
+ // we pass the link down to iframe so it could open it
212
212
  this.modal.authUrl = link;
213
213
  this.modal.iframeUrl = iframeUrl;
214
214
  this.modal.isLoading = false;
@@ -218,7 +218,7 @@ class ModalManager extends EventEmitter {
218
218
  if (!cs) this.modal.isLoading = false;
219
219
  }
220
220
 
221
- await this.authNostrService.nostrConnect(relay, { domain, link, iframeUrl });
221
+ await this.authNostrService.nostrConnect(relays, { domain, link, iframeUrl });
222
222
  });
223
223
  };
224
224
 
@@ -239,6 +239,8 @@ class ModalManager extends EventEmitter {
239
239
  .charAt(0)
240
240
  .toUpperCase() + self.hostname.slice(1);
241
241
  const relays = prepareSignupRelays(this.params.optionsModal.signupRelays);
242
+ // const url = `https://start.njump.me/?an=${name}&at=popup&ac=${window.location.href}&s=${this.opt!.followNpubs || ''}&arr=${relays}&awr=${relays}`;
243
+ // console.log('njump url', url);
242
244
 
243
245
  this.modal!.njumpIframe = `
244
246
  <html><body>
@@ -246,15 +248,18 @@ class ModalManager extends EventEmitter {
246
248
  <script>
247
249
  new NstartModal({
248
250
  baseUrl: 'https://start.njump.me',
251
+ // Required parameters
249
252
  an: '${name}',
253
+ // Optional parameters
250
254
  s: [${this.opt!.followNpubs ? `'${this.opt!.followNpubs}'` : ''}],
251
- afb: false,
252
- asb: false,
253
- aan: false,
254
- aac: true,
255
- ahc: true,
256
- arr: ${JSON.stringify(relays)},
257
- awr: ${JSON.stringify(relays)},
255
+ afb: false, // forceBunker
256
+ asb: false, // skipBunker
257
+ aan: false, // avoidNsec
258
+ aac: true, // avoidNcryptsec
259
+ ahc: true, // hide close button
260
+ arr: ${JSON.stringify(relays)}, //readRelays
261
+ awr: ${JSON.stringify(relays)}, //writeRelays
262
+ // Callbacks
258
263
  onComplete: (result) => {
259
264
  console.log('Login token:', result.nostrLogin);
260
265
  window.parent.location.href='${window.location.href}#nostr-login='+result.nostrLogin;
@@ -265,10 +270,11 @@ class ModalManager extends EventEmitter {
265
270
  }).open();
266
271
  </script>
267
272
  </body></html>
268
- `.replaceAll('&', '&amp;');
273
+ `.replaceAll('&', '&amp;'); // needed?
269
274
 
270
275
  return new Promise((ok, err) => {
271
276
  const process = async (nsecOrBunker: string) => {
277
+ // process the returned value
272
278
  console.log('nsecOrBunker', nsecOrBunker);
273
279
  if (nsecOrBunker.startsWith('nsec1')) {
274
280
  let decoded;
@@ -294,6 +300,7 @@ class ModalManager extends EventEmitter {
294
300
  if (window.location.hash.startsWith('#nostr-login=')) {
295
301
  const nsecOrBunker = window.location.hash.split('#nostr-login=')[1];
296
302
 
303
+ // clear hash from history
297
304
  const url = new URL(window.location.toString());
298
305
  url.hash = '';
299
306
  window.history.replaceState({}, '', url.toString());
@@ -302,6 +309,9 @@ class ModalManager extends EventEmitter {
302
309
  }
303
310
  };
304
311
 
312
+ // // use random 'target' to make sure window.opener is
313
+ // // accessible to the popup
314
+ // window.open(url, '' + Date.now(), 'popup=true,width=600,height=950');
305
315
  window.addEventListener('hashchange', onOpen);
306
316
  });
307
317
  });
@@ -349,6 +359,7 @@ class ModalManager extends EventEmitter {
349
359
  });
350
360
 
351
361
  this.modal.addEventListener('nlNostrConnectDefault', () => {
362
+ // dedup the calls
352
363
  if (!this.authNostrService.isAuthing()) nostrConnect();
353
364
  });
354
365
 
@@ -357,30 +368,18 @@ class ModalManager extends EventEmitter {
357
368
  this.authNostrService.cancelNostrConnect();
358
369
  });
359
370
 
360
- this.modal.addEventListener('nlSaveUserRelays', (event: any) => {
361
- const relays = event.detail as string[];
362
- console.log('nlSaveUserRelays', relays);
363
- this.saveUserRelays(relays);
364
- this.params.optionsModal.connectRelays = relays;
365
- });
366
-
367
- this.modal.addEventListener('nlGetUserRelays', () => {
368
- const relays = this.getUserRelays();
369
- console.log('nlGetUserRelays', relays);
370
- if (this.modal) {
371
- this.modal.dispatchEvent(
372
- new CustomEvent('nlUserRelaysReply', {
373
- detail: relays,
374
- }),
375
- );
376
- }
377
- });
378
-
379
371
  this.modal.addEventListener('nlSwitchAccount', (event: any) => {
380
372
  const eventInfo: Info = event.detail as Info;
381
373
 
382
374
  this.emit('onSwitchAccount', eventInfo);
383
375
 
376
+ // wait a bit, if dialog closes before
377
+ // switching finishes then launched promise rejects
378
+
379
+ // FIXME this calls resetAuth which then prevents
380
+ // endAuth from getting properly called. 300 is not
381
+ // enough to init iframe, so there should be a
382
+ // feedback from switchAccount here
384
383
  setTimeout(() => dialog.close(), 300);
385
384
  });
386
385
 
@@ -427,7 +426,7 @@ class ModalManager extends EventEmitter {
427
426
  else throw new Error('Bad npub');
428
427
  } else if (nameNpub.trim().length === 64) {
429
428
  pubkey = nameNpub.trim();
430
- nip19.npubEncode(pubkey);
429
+ nip19.npubEncode(pubkey); // check
431
430
  }
432
431
  return pubkey;
433
432
  };
@@ -467,10 +466,13 @@ class ModalManager extends EventEmitter {
467
466
  throw new Error('Failed to send DM');
468
467
  }
469
468
 
469
+ // switch to 'enter code' mode
470
470
  this.modal.isOTP = true;
471
471
 
472
+ // remember for code handler below
472
473
  otpPubkey = pubkey;
473
474
 
475
+ // spinner off
474
476
  this.modal.isLoading = false;
475
477
  },
476
478
  { start: true },
@@ -527,6 +529,8 @@ class ModalManager extends EventEmitter {
527
529
  this.modal.isLoading = false;
528
530
  }
529
531
 
532
+ // this.authNostrService.cancelListenNostrConnect();
533
+
530
534
  dialog.close();
531
535
  err(new Error('Cancelled'));
532
536
  };
@@ -551,6 +555,9 @@ class ModalManager extends EventEmitter {
551
555
  }
552
556
 
553
557
  public async showIframeUrl(url: string) {
558
+ // make sure we consume the previous promise,
559
+ // otherwise launch will start await-ing
560
+ // before modal is created and setting iframeUrl will fail
554
561
  await this.waitReady();
555
562
 
556
563
  this.launch({