@konemono/nostr-login 1.7.57 → 1.7.59
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,8 +1,8 @@
|
|
|
1
|
-
import { NDKUser } from '@nostr-dev-kit/ndk';
|
|
2
1
|
import { Signer } from './Nostr';
|
|
3
2
|
|
|
4
3
|
export class AmberDirectSigner implements Signer {
|
|
5
4
|
private _pubkey: string = '';
|
|
5
|
+
private static pendingResolves: Map<string, (result: any) => void> = new Map();
|
|
6
6
|
|
|
7
7
|
constructor(pubkey?: string) {
|
|
8
8
|
this._pubkey = pubkey || '';
|
|
@@ -29,9 +29,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
29
29
|
private getHash(content: string): string {
|
|
30
30
|
let hash = 0;
|
|
31
31
|
for (let i = 0; i < content.length; i++) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const char = content.charCodeAt(i);
|
|
33
|
+
hash = (hash << 5) - hash + char;
|
|
34
|
+
hash |= 0;
|
|
35
35
|
}
|
|
36
36
|
return hash.toString(36);
|
|
37
37
|
}
|
|
@@ -41,8 +41,8 @@ export class AmberDirectSigner implements Signer {
|
|
|
41
41
|
const cacheKey = `amber_result_${type}_${hash}`;
|
|
42
42
|
const cached = sessionStorage.getItem(cacheKey);
|
|
43
43
|
if (cached) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
sessionStorage.removeItem(cacheKey);
|
|
45
|
+
return cached;
|
|
46
46
|
}
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
@@ -52,19 +52,58 @@ export class AmberDirectSigner implements Signer {
|
|
|
52
52
|
sessionStorage.setItem(`amber_pending_${id}`, JSON.stringify({ hash, type }));
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
public static resolvePending(id: string, type: string, result: string) {
|
|
56
|
+
// Try resolving by ID first
|
|
57
|
+
let resolve = this.pendingResolves.get(id);
|
|
58
|
+
|
|
59
|
+
// Fallback: If no ID match, try resolving by type if only one is pending of that type
|
|
60
|
+
if (!resolve) {
|
|
61
|
+
console.log('No direct ID match for Amber resolve, searching by type', { id, type });
|
|
62
|
+
for (const [pendingId, pendingResolve] of this.pendingResolves.entries()) {
|
|
63
|
+
const pending = sessionStorage.getItem(`amber_pending_${pendingId}`);
|
|
64
|
+
if (pending) {
|
|
65
|
+
const { type: pendingType } = JSON.parse(pending);
|
|
66
|
+
if (pendingType === type) {
|
|
67
|
+
resolve = pendingResolve;
|
|
68
|
+
id = pendingId;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (resolve) {
|
|
76
|
+
console.log('Resolving pending Amber promise', { id, type });
|
|
77
|
+
resolve(result);
|
|
78
|
+
this.pendingResolves.delete(id);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
55
84
|
async signEvent(event: any): Promise<any> {
|
|
56
85
|
const content = JSON.stringify(event);
|
|
57
86
|
const cached = this.checkCache(content, 'sign_event');
|
|
58
87
|
if (cached) {
|
|
59
|
-
|
|
88
|
+
return JSON.parse(cached);
|
|
60
89
|
}
|
|
61
90
|
|
|
62
91
|
const id = Math.random().toString(36).substring(7);
|
|
63
92
|
this.setPending(id, content, 'sign_event');
|
|
64
93
|
const url = this.generateUrl(content, 'sign_event', id);
|
|
65
94
|
window.location.href = url;
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
return new Promise((resolve) => {
|
|
96
|
+
AmberDirectSigner.pendingResolves.set(id, (res) => resolve(JSON.parse(res)));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async getPublicKey(): Promise<string> {
|
|
101
|
+
const id = Math.random().toString(36).substring(7);
|
|
102
|
+
const url = this.generateUrl('', 'get_public_key', id);
|
|
103
|
+
window.location.href = url;
|
|
104
|
+
return new Promise((resolve) => {
|
|
105
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
106
|
+
});
|
|
68
107
|
}
|
|
69
108
|
|
|
70
109
|
async encrypt04(pubkey: string, plaintext: string): Promise<string> {
|
|
@@ -75,7 +114,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
75
114
|
this.setPending(id, plaintext, 'nip04_encrypt');
|
|
76
115
|
const url = this.generateUrl(plaintext, 'nip04_encrypt', id, pubkey);
|
|
77
116
|
window.location.href = url;
|
|
78
|
-
return new Promise(() => {
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
119
|
+
});
|
|
79
120
|
}
|
|
80
121
|
|
|
81
122
|
async decrypt04(pubkey: string, ciphertext: string): Promise<string> {
|
|
@@ -86,7 +127,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
86
127
|
this.setPending(id, ciphertext, 'nip04_decrypt');
|
|
87
128
|
const url = this.generateUrl(ciphertext, 'nip04_decrypt', id, pubkey);
|
|
88
129
|
window.location.href = url;
|
|
89
|
-
return new Promise(() => {
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
132
|
+
});
|
|
90
133
|
}
|
|
91
134
|
|
|
92
135
|
async encrypt44(pubkey: string, plaintext: string): Promise<string> {
|
|
@@ -97,7 +140,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
97
140
|
this.setPending(id, plaintext, 'nip44_encrypt');
|
|
98
141
|
const url = this.generateUrl(plaintext, 'nip44_encrypt', id, pubkey);
|
|
99
142
|
window.location.href = url;
|
|
100
|
-
return new Promise(() => {
|
|
143
|
+
return new Promise((resolve) => {
|
|
144
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
145
|
+
});
|
|
101
146
|
}
|
|
102
147
|
|
|
103
148
|
async decrypt44(pubkey: string, ciphertext: string): Promise<string> {
|
|
@@ -108,30 +153,40 @@ export class AmberDirectSigner implements Signer {
|
|
|
108
153
|
this.setPending(id, ciphertext, 'nip44_decrypt');
|
|
109
154
|
const url = this.generateUrl(ciphertext, 'nip44_decrypt', id, pubkey);
|
|
110
155
|
window.location.href = url;
|
|
111
|
-
return new Promise(() => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
public async getPublicKey(): Promise<string> {
|
|
115
|
-
const id = Math.random().toString(36).substring(7);
|
|
116
|
-
const url = this.generateUrl('', 'get_public_key', id);
|
|
117
|
-
window.location.href = url;
|
|
118
|
-
return new Promise(() => {});
|
|
156
|
+
return new Promise((resolve) => {
|
|
157
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
158
|
+
});
|
|
119
159
|
}
|
|
120
160
|
|
|
121
161
|
private generateUrl(content: string, type: string, id: string, recipient?: string): string {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
162
|
+
const callbackUrl = new URL(window.location.origin + window.location.pathname);
|
|
163
|
+
|
|
164
|
+
// Preserve other relevant current URL params if necessary, but avoid amber internal ones
|
|
165
|
+
const currentParams = new URLSearchParams(window.location.search);
|
|
166
|
+
currentParams.forEach((value, key) => {
|
|
167
|
+
if (!['amberType', 'amberId', 'signature', 'result', 'pubKey', 'pubkey'].includes(key)) {
|
|
168
|
+
callbackUrl.searchParams.set(key, value);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
callbackUrl.searchParams.set('amberType', type);
|
|
173
|
+
callbackUrl.searchParams.set('amberId', id);
|
|
174
|
+
|
|
175
|
+
const name = document.title || window.location.hostname || 'Nostr Login';
|
|
125
176
|
|
|
126
177
|
const params = new URLSearchParams();
|
|
127
178
|
params.set('type', type);
|
|
128
179
|
params.set('id', id);
|
|
129
|
-
params.set('callbackUrl',
|
|
130
|
-
params.set('name',
|
|
180
|
+
params.set('callbackUrl', callbackUrl.toString());
|
|
181
|
+
params.set('name', name);
|
|
182
|
+
params.set('app_name', name); // Alias just in case
|
|
183
|
+
|
|
131
184
|
if (recipient) {
|
|
132
|
-
|
|
185
|
+
params.set('pubkey', recipient);
|
|
186
|
+
params.set('pubKey', recipient); // Alias
|
|
133
187
|
} else if (this._pubkey) {
|
|
134
|
-
|
|
188
|
+
params.set('pubkey', this._pubkey);
|
|
189
|
+
params.set('pubKey', this._pubkey); // Alias
|
|
135
190
|
}
|
|
136
191
|
|
|
137
192
|
const dataPart = content ? encodeURIComponent(content) : '/';
|
|
@@ -143,19 +198,25 @@ export class AmberDirectSigner implements Signer {
|
|
|
143
198
|
const params = new URLSearchParams(url.search);
|
|
144
199
|
const hashParams = new URLSearchParams(url.hash.substring(1));
|
|
145
200
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
201
|
+
const getParam = (name: string) => params.get(name) || hashParams.get(name);
|
|
202
|
+
|
|
203
|
+
const type = getParam('amberType') || getParam('type');
|
|
204
|
+
const id = getParam('amberId') || getParam('id');
|
|
205
|
+
const result = getParam('signature') || getParam('result') || getParam('pubKey') || getParam('pubkey');
|
|
206
|
+
|
|
207
|
+
if (type && result) {
|
|
208
|
+
// ID might be missing in some older redirect cases, but we need it for precise resolution
|
|
209
|
+
const finalId = id || '';
|
|
150
210
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
211
|
+
// Clean up URL
|
|
212
|
+
const newUrl = new URL(window.location.href);
|
|
213
|
+
['amberType', 'amberId', 'signature', 'result', 'pubKey', 'pubkey', 'type', 'id'].forEach(p => {
|
|
214
|
+
newUrl.searchParams.delete(p);
|
|
215
|
+
});
|
|
216
|
+
newUrl.hash = '';
|
|
217
|
+
window.history.replaceState({}, '', newUrl.toString());
|
|
157
218
|
|
|
158
|
-
|
|
219
|
+
return { type, id: finalId, result };
|
|
159
220
|
}
|
|
160
221
|
return null;
|
|
161
222
|
}
|
|
@@ -98,6 +98,10 @@ class AuthNostrService extends EventEmitter implements Signer {
|
|
|
98
98
|
const response = AmberDirectSigner.parseResponse();
|
|
99
99
|
if (response) {
|
|
100
100
|
console.log('Amber response detected', response);
|
|
101
|
+
|
|
102
|
+
// Resolve pending promises if any (for non-reload cases)
|
|
103
|
+
AmberDirectSigner.resolvePending(response.id, response.type, response.result);
|
|
104
|
+
|
|
101
105
|
if (response.type === 'get_public_key') {
|
|
102
106
|
const info: Info = {
|
|
103
107
|
pubkey: response.result,
|