@konemono/nostr-login 1.7.60 → 1.7.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konemono/nostr-login",
3
- "version": "1.7.60",
3
+ "version": "1.7.61",
4
4
  "description": "",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,5 +1,7 @@
1
1
  import { Signer } from './Nostr';
2
2
 
3
+ const PENDING_KEY = 'amber_pending_request';
4
+
3
5
  export class AmberDirectSigner implements Signer {
4
6
  private _pubkey: string = '';
5
7
  private static pendingResolves: Map<string, (result: any) => void> = new Map();
@@ -49,49 +51,47 @@ export class AmberDirectSigner implements Signer {
49
51
 
50
52
  private setPending(id: string, content: string, type: string) {
51
53
  const hash = this.getHash(content);
52
- sessionStorage.setItem(`amber_pending_${id}`, JSON.stringify({ hash, type }));
54
+ const data = JSON.stringify({ id, type, hash, timestamp: Date.now() });
55
+ sessionStorage.setItem(`amber_pending_${id}`, data);
56
+ localStorage.setItem(PENDING_KEY, data); // Backup for reloads
53
57
  }
54
58
 
55
59
  public static resolvePending(id: string, type: string, result: string) {
56
- console.log('AmberDirectSigner: resolvePending called', { id, type, pendingCount: this.pendingResolves.size });
60
+ console.log('AmberDirectSigner: resolvePending', { id, type, pendingCount: this.pendingResolves.size });
57
61
 
58
- // Try resolving by ID first
59
62
  let resolve = this.pendingResolves.get(id);
60
63
 
61
- // Fallback: If no ID match, try resolving by type if only one is pending of that type
64
+ // Fallback by type if only one pending of that type
62
65
  if (!resolve) {
63
- console.log('AmberDirectSigner: No direct ID match for resolve, searching by type', { id, type });
66
+ console.log('AmberDirectSigner: Falling back to resolve by type', type);
64
67
  for (const [pendingId, pendingResolve] of this.pendingResolves.entries()) {
65
- const pending = sessionStorage.getItem(`amber_pending_${pendingId}`);
68
+ const pending = sessionStorage.getItem(`amber_pending_${pendingId}`) || localStorage.getItem(PENDING_KEY);
66
69
  if (pending) {
67
- const { type: pendingType } = JSON.parse(pending);
68
- if (pendingType === type) {
69
- resolve = pendingResolve;
70
- id = pendingId;
71
- console.log('AmberDirectSigner: Found match by type', { id, type });
72
- break;
73
- }
70
+ try {
71
+ const { type: pendingType } = JSON.parse(pending);
72
+ if (pendingType === type || type.startsWith(pendingType)) {
73
+ resolve = pendingResolve;
74
+ id = pendingId;
75
+ break;
76
+ }
77
+ } catch (e) {}
74
78
  }
75
79
  }
76
80
  }
77
81
 
78
82
  if (resolve) {
79
- console.log('AmberDirectSigner: Resolving pending promise', { id, type });
83
+ console.log('AmberDirectSigner: Promise resolved', id);
80
84
  resolve(result);
81
85
  this.pendingResolves.delete(id);
82
86
  return true;
83
87
  }
84
-
85
- console.log('AmberDirectSigner: No pending promise found to resolve', { id, type });
86
88
  return false;
87
89
  }
88
90
 
89
91
  async signEvent(event: any): Promise<any> {
90
92
  const content = JSON.stringify(event);
91
93
  const cached = this.checkCache(content, 'sign_event');
92
- if (cached) {
93
- return JSON.parse(cached);
94
- }
94
+ if (cached) return JSON.parse(cached);
95
95
 
96
96
  const id = Math.random().toString(36).substring(7);
97
97
  this.setPending(id, content, 'sign_event');
@@ -104,6 +104,7 @@ export class AmberDirectSigner implements Signer {
104
104
 
105
105
  async getPublicKey(): Promise<string> {
106
106
  const id = Math.random().toString(36).substring(7);
107
+ this.setPending(id, '', 'get_public_key');
107
108
  const url = this.generateUrl('', 'get_public_key', id);
108
109
  window.location.href = url;
109
110
  return new Promise((resolve) => {
@@ -166,35 +167,27 @@ export class AmberDirectSigner implements Signer {
166
167
  private generateUrl(content: string, type: string, id: string, recipient?: string): string {
167
168
  const callbackUrl = new URL(window.location.origin + window.location.pathname);
168
169
 
169
- // Amber parameters we want to carry back
170
+ // Minimal parameters in callbackUrl to avoid conflicts
170
171
  callbackUrl.searchParams.set('amberType', type);
171
172
  callbackUrl.searchParams.set('amberId', id);
172
173
 
173
174
  const name = document.title || window.location.hostname || 'Nostr Login';
174
175
 
175
- // NIP-55 standard and some common extensions
176
176
  const params: string[] = [];
177
177
  params.push(`type=${encodeURIComponent(type)}`);
178
178
  params.push(`id=${encodeURIComponent(id)}`);
179
179
  params.push(`callbackUrl=${encodeURIComponent(callbackUrl.toString())}`);
180
-
181
- // Multi-alias for app name to fix the "null" issue
182
180
  params.push(`name=${encodeURIComponent(name)}`);
183
181
  params.push(`app_name=${encodeURIComponent(name)}`);
184
- params.push(`title=${encodeURIComponent(name)}`);
185
182
 
186
183
  if (recipient) {
187
184
  params.push(`pubkey=${encodeURIComponent(recipient)}`);
188
- params.push(`pubKey=${encodeURIComponent(recipient)}`);
189
- params.push(`current_user=${encodeURIComponent(recipient)}`);
190
185
  } else if (this._pubkey) {
191
186
  params.push(`pubkey=${encodeURIComponent(this._pubkey)}`);
192
- params.push(`pubKey=${encodeURIComponent(this._pubkey)}`);
193
- params.push(`current_user=${encodeURIComponent(this._pubkey)}`);
194
187
  }
195
188
 
196
- const dataPart = content ? encodeURIComponent(content) : '';
197
- // Format: nostrsigner:<content>?<params>
189
+ const dataPart = content ? encodeURIComponent(content) : 'get_public_key';
190
+ // Use nostrsigner: scheme as primary which is standard NIP-55
198
191
  return `nostrsigner:${dataPart}?${params.join('&')}`;
199
192
  }
200
193
 
@@ -203,23 +196,33 @@ export class AmberDirectSigner implements Signer {
203
196
  const params = new URLSearchParams(url.search);
204
197
  const hashParams = new URLSearchParams(url.hash.substring(1));
205
198
 
206
- if (url.search || url.hash) {
207
- console.log('AmberDirectSigner: Checking URL for response', {
208
- search: url.search,
209
- hash: url.hash
210
- });
211
- }
212
-
213
199
  const getParam = (name: string) => params.get(name) || hashParams.get(name);
214
200
 
215
- // Support both our custom names and original intent names
216
- const type = getParam('amberType') || getParam('type');
217
- const id = getParam('amberId') || getParam('id');
201
+ let type = getParam('amberType') || getParam('type');
202
+ let id = getParam('amberId') || getParam('id');
218
203
  const result = getParam('signature') || getParam('result') || getParam('pubKey') || getParam('pubkey');
219
204
 
205
+ // Fallback to localStorage pending if params are missing/merged
206
+ if (result && (!type || !id)) {
207
+ const pending = localStorage.getItem(PENDING_KEY);
208
+ if (pending) {
209
+ try {
210
+ const { id: pId, type: pType } = JSON.parse(pending);
211
+ if (!type) type = pType;
212
+ if (!id) id = pId;
213
+ console.log('AmberDirectSigner: Recovered type/id from localStorage');
214
+ } catch (e) {}
215
+ }
216
+ }
217
+
220
218
  if (type && result) {
221
- console.log('AmberDirectSigner: Response params detected', { type, id, resultLength: result.length });
222
-
219
+ // Handle "ID stuck to type" or typo cases
220
+ let finalType = type.toLowerCase();
221
+ if (finalType.includes('get_pub')) finalType = 'get_public_key';
222
+ else if (finalType.includes('sign_event')) finalType = 'sign_event';
223
+ else if (finalType.includes('encrypt')) finalType = finalType.includes('44') ? 'nip44_encrypt' : 'nip04_encrypt';
224
+ else if (finalType.includes('decrypt')) finalType = finalType.includes('44') ? 'nip44_decrypt' : 'nip04_decrypt';
225
+
223
226
  const finalId = id || '';
224
227
 
225
228
  // Clean up URL
@@ -229,8 +232,10 @@ export class AmberDirectSigner implements Signer {
229
232
  });
230
233
  newUrl.hash = '';
231
234
  window.history.replaceState({}, '', newUrl.toString());
235
+
236
+ localStorage.removeItem(PENDING_KEY); // Done
232
237
 
233
- return { type, id: finalId, result };
238
+ return { type: finalType, id: finalId, result };
234
239
  }
235
240
  return null;
236
241
  }
@@ -108,13 +108,16 @@ class AuthNostrService extends EventEmitter implements Signer {
108
108
  if (response) {
109
109
  console.log('Amber response detected', response);
110
110
 
111
+ // Stop the "Connecting..." spinner
112
+ this.emit('onAuthUrl', { url: '' });
113
+
111
114
  // Resolve pending promises if any (for non-reload cases)
112
115
  const resolved = AmberDirectSigner.resolvePending(response.id, response.type, response.result);
113
116
  if (resolved) {
114
117
  console.log('Resolved pending Amber promise via resolvePending');
115
118
  }
116
119
 
117
- if (response.type === 'get_public_key') {
120
+ if (response.type === 'get_public_key' || response.type.includes('pub')) {
118
121
  const info: Info = {
119
122
  pubkey: response.result,
120
123
  authMethod: 'amber' as any,