@konemono/nostr-login 1.7.57 → 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,6 +1,6 @@
1
1
  {
2
2
  "name": "@konemono/nostr-login",
3
- "version": "1.7.57",
3
+ "version": "1.7.58",
4
4
  "description": "",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
@@ -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
- const char = content.charCodeAt(i);
33
- hash = (hash << 5) - hash + char;
34
- hash |= 0;
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
- sessionStorage.removeItem(cacheKey);
45
- return cached;
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
- return JSON.parse(cached);
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
- // This will never resolve because of page reload
67
- return new Promise(() => {});
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,34 +135,39 @@ 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 url = new URL(window.location.origin + window.location.pathname);
123
- url.searchParams.set('amberType', type);
124
- url.searchParams.set('amberId', id);
125
-
126
- const params = new URLSearchParams();
127
- params.set('type', type);
128
- params.set('id', id);
129
- params.set('callbackUrl', url.toString());
130
- params.set('name', document.title || window.location.hostname || 'Nostr Login');
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
+
131
158
  if (recipient) {
132
- params.set('pubkey', recipient);
159
+ params.push(`S.pubKey=${encodeURIComponent(recipient)}`);
133
160
  } else if (this._pubkey) {
134
- params.set('pubkey', this._pubkey);
161
+ params.push(`S.pubKey=${encodeURIComponent(this._pubkey)}`);
162
+ }
163
+
164
+ if (type === 'sign_event') {
165
+ params.push(`S.event=${encodeURIComponent(content)}`);
166
+ } else {
167
+ params.push(`S.content=${encodeURIComponent(content)}`);
135
168
  }
136
169
 
137
- const dataPart = content ? encodeURIComponent(content) : '/';
138
- return `nostrsigner:${dataPart}?${params.toString()}`;
170
+ return `intent:#Intent;action=${action};package=com.greenart7c3.nostrsigner;${params.join(';')};end`;
139
171
  }
140
172
 
141
173
  public static parseResponse(): { type: string; id: string; result: string } | null {
@@ -143,19 +175,19 @@ export class AmberDirectSigner implements Signer {
143
175
  const params = new URLSearchParams(url.search);
144
176
  const hashParams = new URLSearchParams(url.hash.substring(1));
145
177
 
146
- let type = params.get('amberType') || hashParams.get('amberType');
147
- let id = params.get('amberId') || hashParams.get('amberId');
148
- let result = params.get('signature') || params.get('result') || params.get('pubKey') ||
149
- hashParams.get('signature') || hashParams.get('result') || hashParams.get('pubKey');
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');
150
182
 
151
183
  if (type && id && result) {
152
- // Clean up URL
153
- const newUrl = new URL(window.location.href);
154
- ['amberType', 'amberId', 'signature', 'result', 'pubKey'].forEach(p => newUrl.searchParams.delete(p));
155
- newUrl.hash = '';
156
- window.history.replaceState({}, '', newUrl.toString());
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());
157
189
 
158
- return { type, id, result };
190
+ return { type, id, result };
159
191
  }
160
192
  return null;
161
193
  }
@@ -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.result);
104
+
101
105
  if (response.type === 'get_public_key') {
102
106
  const info: Info = {
103
107
  pubkey: response.result,