@konemono/nostr-login 1.7.52 → 1.7.54

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.52",
3
+ "version": "1.7.54",
4
4
  "description": "",
5
5
  "main": "./dist/index.esm.js",
6
6
  "types": "./dist/index.d.ts",
@@ -26,37 +26,86 @@ export class AmberDirectSigner implements Signer {
26
26
  decrypt: (pubkey: string, ciphertext: string) => this.decrypt44(pubkey, ciphertext),
27
27
  };
28
28
 
29
+ private getHash(content: string): string {
30
+ let hash = 0;
31
+ for (let i = 0; i < content.length; i++) {
32
+ const char = content.charCodeAt(i);
33
+ hash = (hash << 5) - hash + char;
34
+ hash |= 0;
35
+ }
36
+ return hash.toString(36);
37
+ }
38
+
39
+ private checkCache(content: string, type: string): string | null {
40
+ const hash = this.getHash(content);
41
+ const cacheKey = `amber_result_${type}_${hash}`;
42
+ const cached = sessionStorage.getItem(cacheKey);
43
+ if (cached) {
44
+ sessionStorage.removeItem(cacheKey);
45
+ return cached;
46
+ }
47
+ return null;
48
+ }
49
+
50
+ private setPending(id: string, content: string, type: string) {
51
+ const hash = this.getHash(content);
52
+ sessionStorage.setItem(`amber_pending_${id}`, JSON.stringify({ hash, type }));
53
+ }
54
+
29
55
  async signEvent(event: any): Promise<any> {
56
+ const content = JSON.stringify(event);
57
+ const cached = this.checkCache(content, 'sign_event');
58
+ if (cached) {
59
+ return JSON.parse(cached);
60
+ }
61
+
30
62
  const id = Math.random().toString(36).substring(7);
31
- const url = this.generateUrl(JSON.stringify(event), 'sign_event', id);
63
+ this.setPending(id, content, 'sign_event');
64
+ const url = this.generateUrl(content, 'sign_event', id);
32
65
  window.location.href = url;
33
66
  // This will never resolve because of page reload
34
67
  return new Promise(() => {});
35
68
  }
36
69
 
37
70
  async encrypt04(pubkey: string, plaintext: string): Promise<string> {
71
+ const cached = this.checkCache(plaintext, 'nip04_encrypt');
72
+ if (cached) return cached;
73
+
38
74
  const id = Math.random().toString(36).substring(7);
75
+ this.setPending(id, plaintext, 'nip04_encrypt');
39
76
  const url = this.generateUrl(plaintext, 'nip04_encrypt', id, pubkey);
40
77
  window.location.href = url;
41
78
  return new Promise(() => {});
42
79
  }
43
80
 
44
81
  async decrypt04(pubkey: string, ciphertext: string): Promise<string> {
82
+ const cached = this.checkCache(ciphertext, 'nip04_decrypt');
83
+ if (cached) return cached;
84
+
45
85
  const id = Math.random().toString(36).substring(7);
86
+ this.setPending(id, ciphertext, 'nip04_decrypt');
46
87
  const url = this.generateUrl(ciphertext, 'nip04_decrypt', id, pubkey);
47
88
  window.location.href = url;
48
89
  return new Promise(() => {});
49
90
  }
50
91
 
51
92
  async encrypt44(pubkey: string, plaintext: string): Promise<string> {
93
+ const cached = this.checkCache(plaintext, 'nip44_encrypt');
94
+ if (cached) return cached;
95
+
52
96
  const id = Math.random().toString(36).substring(7);
97
+ this.setPending(id, plaintext, 'nip44_encrypt');
53
98
  const url = this.generateUrl(plaintext, 'nip44_encrypt', id, pubkey);
54
99
  window.location.href = url;
55
100
  return new Promise(() => {});
56
101
  }
57
102
 
58
103
  async decrypt44(pubkey: string, ciphertext: string): Promise<string> {
104
+ const cached = this.checkCache(ciphertext, 'nip44_decrypt');
105
+ if (cached) return cached;
106
+
59
107
  const id = Math.random().toString(36).substring(7);
108
+ this.setPending(id, ciphertext, 'nip44_decrypt');
60
109
  const url = this.generateUrl(ciphertext, 'nip44_decrypt', id, pubkey);
61
110
  window.location.href = url;
62
111
  return new Promise(() => {});
@@ -86,9 +135,17 @@ export class AmberDirectSigner implements Signer {
86
135
 
87
136
  public static parseResponse(): { type: string; id: string; result: string } | null {
88
137
  const params = new URLSearchParams(window.location.search);
89
- const type = params.get('amberType');
90
- const id = params.get('amberId');
91
- const result = params.get('signature') || params.get('result'); // Amber uses signature for events, result for others?
138
+ let type = params.get('amberType');
139
+ let id = params.get('amberId');
140
+ let result = params.get('signature') || params.get('result'); // Amber uses signature for events, result for others?
141
+
142
+ // Also check hash
143
+ if (!type || !id || !result) {
144
+ const hashParams = new URLSearchParams(window.location.hash.substring(1));
145
+ type = type || hashParams.get('amberType');
146
+ id = id || hashParams.get('amberId');
147
+ result = result || hashParams.get('signature') || hashParams.get('result');
148
+ }
92
149
 
93
150
  if (type && id && result) {
94
151
  // Clean up URL
@@ -97,6 +154,7 @@ export class AmberDirectSigner implements Signer {
97
154
  newUrl.searchParams.delete('amberId');
98
155
  newUrl.searchParams.delete('signature');
99
156
  newUrl.searchParams.delete('result');
157
+ newUrl.hash = ''; // Clear hash too
100
158
  window.history.replaceState({}, '', newUrl.toString());
101
159
 
102
160
  return { type, id, result };
@@ -27,12 +27,6 @@ const NOSTRCONNECT_APPS: ConnectionString[] = [
27
27
  {
28
28
  name: 'Amber',
29
29
  img: 'https://raw.githubusercontent.com/greenart7c3/Amber/refs/heads/master/assets/android-icon.svg',
30
- link: '<nostrconnect>',
31
- relays: DEFAULT_NOSTRCONNECT_RELAYS,
32
- },
33
- {
34
- name: 'Amber (Direct)',
35
- img: 'https://raw.githubusercontent.com/greenart7c3/Amber/refs/heads/master/assets/android-icon.svg',
36
30
  link: 'amber',
37
31
  relays: DEFAULT_NOSTRCONNECT_RELAYS,
38
32
  },
@@ -92,7 +86,7 @@ class AuthNostrService extends EventEmitter implements Signer {
92
86
  decrypt: this.decrypt44.bind(this),
93
87
  };
94
88
 
95
- this.checkAmberResponse();
89
+ setTimeout(() => this.checkAmberResponse(), 500);
96
90
  }
97
91
 
98
92
  private checkAmberResponse() {
@@ -105,14 +99,16 @@ class AuthNostrService extends EventEmitter implements Signer {
105
99
  };
106
100
  this.onAuth('login', info);
107
101
  } else {
108
- // For other types, we might want to store the result in a way
109
- // that the next call to the same method can return it immediately
110
- // but for now, we just log it.
111
- console.log('Amber response', response);
112
- if (response.type === 'sign_event') {
113
- // If it's a signed event, we could potentially use it if someone asks for it.
114
- // But usually the app will re-request signing.
115
- // A better way would be to have a session-based cache.
102
+ const pendingKey = `amber_pending_${response.id}`;
103
+ const pending = sessionStorage.getItem(pendingKey);
104
+ if (pending) {
105
+ const { hash, type } = JSON.parse(pending);
106
+ sessionStorage.removeItem(pendingKey);
107
+ if (type === response.type) {
108
+ const cacheKey = `amber_result_${type}_${hash}`;
109
+ sessionStorage.setItem(cacheKey, response.result);
110
+ console.log('Stored Amber result', cacheKey);
111
+ }
116
112
  }
117
113
  }
118
114
  }