@konemono/nostr-login 1.7.56 → 1.7.58
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,40 @@ 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, result: string) {
|
|
56
|
+
const resolve = this.pendingResolves.get(id);
|
|
57
|
+
if (resolve) {
|
|
58
|
+
console.log('Resolving pending Amber promise', id);
|
|
59
|
+
resolve(result);
|
|
60
|
+
this.pendingResolves.delete(id);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
55
66
|
async signEvent(event: any): Promise<any> {
|
|
56
67
|
const content = JSON.stringify(event);
|
|
57
68
|
const cached = this.checkCache(content, 'sign_event');
|
|
58
69
|
if (cached) {
|
|
59
|
-
|
|
70
|
+
return JSON.parse(cached);
|
|
60
71
|
}
|
|
61
72
|
|
|
62
73
|
const id = Math.random().toString(36).substring(7);
|
|
63
74
|
this.setPending(id, content, 'sign_event');
|
|
64
75
|
const url = this.generateUrl(content, 'sign_event', id);
|
|
65
76
|
window.location.href = url;
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
AmberDirectSigner.pendingResolves.set(id, (res) => resolve(JSON.parse(res)));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async getPublicKey(): Promise<string> {
|
|
83
|
+
const id = Math.random().toString(36).substring(7);
|
|
84
|
+
const url = this.generateUrl('', 'get_public_key', id);
|
|
85
|
+
window.location.href = url;
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
88
|
+
});
|
|
68
89
|
}
|
|
69
90
|
|
|
70
91
|
async encrypt04(pubkey: string, plaintext: string): Promise<string> {
|
|
@@ -75,7 +96,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
75
96
|
this.setPending(id, plaintext, 'nip04_encrypt');
|
|
76
97
|
const url = this.generateUrl(plaintext, 'nip04_encrypt', id, pubkey);
|
|
77
98
|
window.location.href = url;
|
|
78
|
-
return new Promise(() => {
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
101
|
+
});
|
|
79
102
|
}
|
|
80
103
|
|
|
81
104
|
async decrypt04(pubkey: string, ciphertext: string): Promise<string> {
|
|
@@ -86,7 +109,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
86
109
|
this.setPending(id, ciphertext, 'nip04_decrypt');
|
|
87
110
|
const url = this.generateUrl(ciphertext, 'nip04_decrypt', id, pubkey);
|
|
88
111
|
window.location.href = url;
|
|
89
|
-
return new Promise(() => {
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
114
|
+
});
|
|
90
115
|
}
|
|
91
116
|
|
|
92
117
|
async encrypt44(pubkey: string, plaintext: string): Promise<string> {
|
|
@@ -97,7 +122,9 @@ export class AmberDirectSigner implements Signer {
|
|
|
97
122
|
this.setPending(id, plaintext, 'nip44_encrypt');
|
|
98
123
|
const url = this.generateUrl(plaintext, 'nip44_encrypt', id, pubkey);
|
|
99
124
|
window.location.href = url;
|
|
100
|
-
return new Promise(() => {
|
|
125
|
+
return new Promise((resolve) => {
|
|
126
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
127
|
+
});
|
|
101
128
|
}
|
|
102
129
|
|
|
103
130
|
async decrypt44(pubkey: string, ciphertext: string): Promise<string> {
|
|
@@ -108,67 +135,59 @@ export class AmberDirectSigner implements Signer {
|
|
|
108
135
|
this.setPending(id, ciphertext, 'nip44_decrypt');
|
|
109
136
|
const url = this.generateUrl(ciphertext, 'nip44_decrypt', id, pubkey);
|
|
110
137
|
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(() => {});
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
AmberDirectSigner.pendingResolves.set(id, resolve);
|
|
140
|
+
});
|
|
119
141
|
}
|
|
120
142
|
|
|
121
143
|
private generateUrl(content: string, type: string, id: string, recipient?: string): string {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
searchParams.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
params.set('callbackUrl', url.toString());
|
|
137
|
-
params.set('name', document.location.host);
|
|
144
|
+
const callbackUrl = new URL(window.location.origin + window.location.pathname);
|
|
145
|
+
callbackUrl.searchParams.set('amberType', type);
|
|
146
|
+
callbackUrl.searchParams.set('amberId', id);
|
|
147
|
+
|
|
148
|
+
const action = `com.greenart7c3.nostrsigner.${type.toUpperCase()}`;
|
|
149
|
+
const name = document.title || window.location.hostname || 'Nostr Login';
|
|
150
|
+
|
|
151
|
+
const params = [
|
|
152
|
+
`S.type=${encodeURIComponent(type)}`,
|
|
153
|
+
`S.name=${encodeURIComponent(name)}`,
|
|
154
|
+
`S.callbackUrl=${encodeURIComponent(callbackUrl.toString())}`,
|
|
155
|
+
`S.id=${encodeURIComponent(id)}`
|
|
156
|
+
];
|
|
157
|
+
|
|
138
158
|
if (recipient) {
|
|
139
|
-
|
|
159
|
+
params.push(`S.pubKey=${encodeURIComponent(recipient)}`);
|
|
140
160
|
} else if (this._pubkey) {
|
|
141
|
-
|
|
161
|
+
params.push(`S.pubKey=${encodeURIComponent(this._pubkey)}`);
|
|
142
162
|
}
|
|
143
163
|
|
|
144
|
-
|
|
164
|
+
if (type === 'sign_event') {
|
|
165
|
+
params.push(`S.event=${encodeURIComponent(content)}`);
|
|
166
|
+
} else {
|
|
167
|
+
params.push(`S.content=${encodeURIComponent(content)}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return `intent:#Intent;action=${action};package=com.greenart7c3.nostrsigner;${params.join(';')};end`;
|
|
145
171
|
}
|
|
146
172
|
|
|
147
173
|
public static parseResponse(): { type: string; id: string; result: string } | null {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
type = type || hashParams.get('amberType');
|
|
157
|
-
id = id || hashParams.get('amberId');
|
|
158
|
-
result = result || hashParams.get('signature') || hashParams.get('result');
|
|
159
|
-
}
|
|
174
|
+
const url = new URL(window.location.href);
|
|
175
|
+
const params = new URLSearchParams(url.search);
|
|
176
|
+
const hashParams = new URLSearchParams(url.hash.substring(1));
|
|
177
|
+
|
|
178
|
+
const type = params.get('amberType') || hashParams.get('amberType');
|
|
179
|
+
const id = params.get('amberId') || hashParams.get('amberId');
|
|
180
|
+
const result = params.get('signature') || params.get('result') || params.get('pubKey') || params.get('pubkey') ||
|
|
181
|
+
hashParams.get('signature') || hashParams.get('result') || hashParams.get('pubKey') || hashParams.get('pubkey');
|
|
160
182
|
|
|
161
183
|
if (type && id && result) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
window.history.replaceState({}, '', newUrl.toString());
|
|
170
|
-
|
|
171
|
-
return { type, id, result };
|
|
184
|
+
// Clean up URL
|
|
185
|
+
const newUrl = new URL(window.location.href);
|
|
186
|
+
['amberType', 'amberId', 'signature', 'result', 'pubKey', 'pubkey'].forEach(p => newUrl.searchParams.delete(p));
|
|
187
|
+
newUrl.hash = '';
|
|
188
|
+
window.history.replaceState({}, '', newUrl.toString());
|
|
189
|
+
|
|
190
|
+
return { type, id, result };
|
|
172
191
|
}
|
|
173
192
|
return null;
|
|
174
193
|
}
|
|
@@ -86,9 +86,10 @@ class AuthNostrService extends EventEmitter implements Signer {
|
|
|
86
86
|
decrypt: this.decrypt44.bind(this),
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
setTimeout(() => this.checkAmberResponse(),
|
|
89
|
+
setTimeout(() => this.checkAmberResponse(), 100);
|
|
90
90
|
|
|
91
91
|
window.addEventListener('focus', () => {
|
|
92
|
+
console.log('Window focused, checking Amber response');
|
|
92
93
|
this.checkAmberResponse();
|
|
93
94
|
});
|
|
94
95
|
}
|
|
@@ -96,11 +97,17 @@ class AuthNostrService extends EventEmitter implements Signer {
|
|
|
96
97
|
private checkAmberResponse() {
|
|
97
98
|
const response = AmberDirectSigner.parseResponse();
|
|
98
99
|
if (response) {
|
|
100
|
+
console.log('Amber response detected', response);
|
|
101
|
+
|
|
102
|
+
// Resolve pending promises if any (for non-reload cases)
|
|
103
|
+
AmberDirectSigner.resolvePending(response.id, response.result);
|
|
104
|
+
|
|
99
105
|
if (response.type === 'get_public_key') {
|
|
100
106
|
const info: Info = {
|
|
101
107
|
pubkey: response.result,
|
|
102
108
|
authMethod: 'amber' as any,
|
|
103
109
|
};
|
|
110
|
+
console.log('Amber login success', info);
|
|
104
111
|
this.onAuth('login', info);
|
|
105
112
|
} else {
|
|
106
113
|
const pendingKey = `amber_pending_${response.id}`;
|