@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,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
|
-
|
|
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
|
|
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
|
|
64
|
+
// Fallback by type if only one pending of that type
|
|
62
65
|
if (!resolve) {
|
|
63
|
-
console.log('AmberDirectSigner:
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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:
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
216
|
-
|
|
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
|
-
|
|
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,
|