glow.ts 1.1.2 → 1.1.4

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/dist/glow.es.js CHANGED
@@ -1,993 +1,722 @@
1
- import { secretbox as k, box as f, randomBytes as K, hash as C } from "tweetnacl";
2
- import { Mutex as R } from "async-mutex";
3
- class o {
4
- static toBase64(e) {
5
- return typeof btoa < "u" ? btoa(this.decode_latin1(e)) : Buffer.from(this.decode_latin1(e), "latin1").toString("base64");
6
- }
7
- static fromBase64(e) {
8
- return typeof btoa < "u" ? this.encode_latin1(atob(e)) : this.encode_latin1(Buffer.from(e, "base64").toString("latin1"));
9
- }
10
- static encode_latin1(e) {
11
- const t = new Uint8Array(e.length);
12
- for (let s = 0; s < e.length; s++) {
13
- const n = e.charCodeAt(s);
14
- if ((n & 255) !== n) throw { message: "Cannot encode string in Latin1", str: e };
15
- t[s] = n & 255;
16
- }
17
- return t;
18
- }
19
- static decode_latin1(e) {
20
- const t = [];
21
- for (let s = 0; s < e.length; s++)
22
- t.push(String.fromCharCode(e[s]));
23
- return t.join("");
24
- }
25
- static toObject(e) {
26
- return Array.from(e).reduce(
27
- (t, [s, n]) => Object.assign(t, { [s]: n }),
28
- {}
29
- );
30
- }
31
- }
32
- class B {
33
- constructor() {
34
- this.crypto_secretbox_KEYBYTES = k.keyLength, this.crypto_box_NONCEBYTES = f.nonceLength;
35
- }
36
- async crypto_secretbox_random_nonce() {
37
- return K(k.nonceLength);
38
- }
39
- async crypto_secretbox(e, t, s) {
40
- return k(e, t, s);
41
- }
42
- async crypto_secretbox_open(e, t, s) {
43
- return k.open(e, t, s);
44
- }
45
- async crypto_box(e, t, s, n) {
46
- return f(e, t, s, n);
47
- }
48
- async crypto_box_open(e, t, s, n) {
49
- return f.open(e, t, s, n);
50
- }
51
- async crypto_box_random_nonce() {
52
- return K(f.nonceLength);
53
- }
54
- async crypto_box_keypair() {
55
- const e = f.keyPair();
56
- return {
57
- boxPk: e.publicKey,
58
- boxSk: e.secretKey
59
- };
60
- }
61
- async crypto_box_keypair_from_raw_sk(e) {
62
- const t = f.keyPair.fromSecretKey(e);
63
- return {
64
- boxPk: t.publicKey,
65
- boxSk: t.secretKey
66
- };
67
- }
68
- async crypto_box_keypair_from_seed(e) {
69
- return this.crypto_box_keypair_from_raw_sk(C(e).subarray(0, f.secretKeyLength));
70
- }
71
- async crypto_hash_sha256(e) {
72
- const t = globalThis.crypto;
73
- if (!t || !t.subtle)
74
- throw new Error("Web Crypto API is not available. Please use a modern browser or Node.js 16+.");
75
- const s = await t.subtle.digest("SHA-256", e);
76
- return new Uint8Array(s);
77
- }
78
- async random_bytes(e) {
79
- return K(e);
80
- }
81
- // Helper methods are based on `js-nacl` implementations
82
- // https://github.com/tonyg/js-nacl/blob/cc70775cfc9d68a04905ca65c7f179b33a18066e/nacl_cooked.js
83
- async encode_latin1(e) {
84
- return o.encode_latin1(e);
85
- }
86
- async decode_latin1(e) {
87
- return o.decode_latin1(e);
88
- }
89
- async encode_utf8(e) {
90
- return this.encode_latin1(unescape(encodeURIComponent(e)));
91
- }
92
- async decode_utf8(e) {
93
- return decodeURIComponent(escape(await this.decode_latin1(e)));
94
- }
95
- async to_hex(e) {
96
- const t = [];
97
- for (let s = 0; s < e.length; s++) {
98
- const n = "0123456789abcdef";
99
- t.push(n[e[s] >> 4 & 15]), t.push(n[e[s] & 15]);
100
- }
101
- return t.join("");
102
- }
103
- async from_hex(e) {
104
- const t = new Uint8Array(e.length / 2);
105
- for (let s = 0; s < e.length / 2; s++)
106
- t[s] = parseInt(e.substr(2 * s, 2), 16);
107
- return t;
108
- }
109
- /**
110
- * h2(m) = sha256(sha256(64x0 + m))
111
- * Zero out initial sha256 block, and double hash 0-padded message
112
- * http://cs.nyu.edu/~dodis/ps/h-of-h.pdf
113
- */
114
- async h2(e) {
115
- e instanceof Uint8Array || (e = await this.encode_latin1(e));
116
- const t = 64, s = new Uint8Array(t + e.length);
117
- return s.fill(0), s.set(e, t), this.crypto_hash_sha256(await this.crypto_hash_sha256(s));
118
- }
119
- }
120
- class h {
121
- constructor() {
122
- }
123
- static setDefaultInstance() {
124
- return this.setInstance(new B());
125
- }
126
- static setInstance(e) {
127
- if (this.driverInstance)
128
- throw new Error("[NaCl] NaCl driver has been already set, it is supposed to be set only once");
129
- return this.driverInstance = e, !0;
130
- }
131
- static getInstance() {
132
- if (!this.driverInstance)
133
- throw new Error("[NaCl] NaCl instance is not yet set");
134
- return this.driverInstance;
135
- }
136
- }
137
- class w {
138
- constructor(e) {
139
- if (this.keys = e, typeof e == "string") {
140
- const { boxPk: t, boxSk: s } = JSON.parse(e);
141
- this.keyPair = {
142
- boxPk: o.fromBase64(t),
143
- boxSk: o.fromBase64(s)
144
- };
145
- } else
146
- this.keyPair = e;
147
- }
148
- static isEqual(e, t) {
149
- return e.toString() === t.toString();
150
- }
151
- toString() {
152
- return JSON.stringify({
153
- boxPk: this.publicKey,
154
- boxSk: this.privateKey
155
- });
156
- }
157
- get publicKey() {
158
- return o.toBase64(this.keyPair.boxPk);
159
- }
160
- get privateKey() {
161
- return o.toBase64(this.keyPair.boxSk);
162
- }
163
- }
164
- const v = 30 * 1e3, u = {
165
- NONCE_TAG: "__nc",
166
- SKEY_TAG: "storage_key",
167
- STORAGE_ROOT: ".v1.stor.vlt12",
168
- // Relay tokens, keys and hashes are 32 bytes
169
- RELAY_TOKEN_LEN: 32,
170
- // 5 min - Token expiration on the server side, matched with config.x.relay.token_timeout on Zax server
171
- RELAY_TOKEN_TIMEOUT: 5 * 60 * 1e3 - v,
172
- // 20 min - Session expiration on the server side, matched with config.x.relay.session_timeout on Zax server
173
- RELAY_SESSION_TIMEOUT: 20 * 60 * 1e3 - v,
174
- // 5 sec - Ajax request timeout
175
- RELAY_AJAX_TIMEOUT: 5 * 1e3
1
+ import { box as e, hash as t, randomBytes as n, secretbox as r } from "tweetnacl";
2
+ import { Mutex as i } from "async-mutex";
3
+ //#region src/utils/utils.ts
4
+ var a = class {
5
+ static toBase64(e) {
6
+ return typeof btoa < "u" ? btoa(this.decode_latin1(e)) : Buffer.from(this.decode_latin1(e), "latin1").toString("base64");
7
+ }
8
+ static fromBase64(e) {
9
+ return typeof btoa < "u" ? this.encode_latin1(atob(e)) : this.encode_latin1(Buffer.from(e, "base64").toString("latin1"));
10
+ }
11
+ static encode_latin1(e) {
12
+ let t = new Uint8Array(e.length);
13
+ for (let n = 0; n < e.length; n++) {
14
+ let r = e.charCodeAt(n);
15
+ if ((r & 255) !== r) throw {
16
+ message: "Cannot encode string in Latin1",
17
+ str: e
18
+ };
19
+ t[n] = r & 255;
20
+ }
21
+ return t;
22
+ }
23
+ static decode_latin1(e) {
24
+ let t = [];
25
+ for (let n = 0; n < e.length; n++) t.push(String.fromCharCode(e[n]));
26
+ return t.join("");
27
+ }
28
+ static toObject(e) {
29
+ return Array.from(e).reduce((e, [t, n]) => Object.assign(e, { [t]: n }), {});
30
+ }
31
+ }, o = class {
32
+ constructor() {
33
+ this.crypto_secretbox_KEYBYTES = r.keyLength, this.crypto_box_NONCEBYTES = e.nonceLength;
34
+ }
35
+ async crypto_secretbox_random_nonce() {
36
+ return n(r.nonceLength);
37
+ }
38
+ async crypto_secretbox(e, t, n) {
39
+ return r(e, t, n);
40
+ }
41
+ async crypto_secretbox_open(e, t, n) {
42
+ return r.open(e, t, n);
43
+ }
44
+ async crypto_box(t, n, r, i) {
45
+ return e(t, n, r, i);
46
+ }
47
+ async crypto_box_open(t, n, r, i) {
48
+ return e.open(t, n, r, i);
49
+ }
50
+ async crypto_box_random_nonce() {
51
+ return n(e.nonceLength);
52
+ }
53
+ async crypto_box_keypair() {
54
+ let t = e.keyPair();
55
+ return {
56
+ boxPk: t.publicKey,
57
+ boxSk: t.secretKey
58
+ };
59
+ }
60
+ async crypto_box_keypair_from_raw_sk(t) {
61
+ let n = e.keyPair.fromSecretKey(t);
62
+ return {
63
+ boxPk: n.publicKey,
64
+ boxSk: n.secretKey
65
+ };
66
+ }
67
+ async crypto_box_keypair_from_seed(n) {
68
+ return this.crypto_box_keypair_from_raw_sk(t(n).subarray(0, e.secretKeyLength));
69
+ }
70
+ async crypto_hash_sha256(e) {
71
+ let t = globalThis.crypto;
72
+ if (!t || !t.subtle) throw Error("Web Crypto API is not available. Please use a modern browser or Node.js 16+.");
73
+ let n = await t.subtle.digest("SHA-256", e);
74
+ return new Uint8Array(n);
75
+ }
76
+ async random_bytes(e) {
77
+ return n(e);
78
+ }
79
+ async encode_latin1(e) {
80
+ return a.encode_latin1(e);
81
+ }
82
+ async decode_latin1(e) {
83
+ return a.decode_latin1(e);
84
+ }
85
+ async encode_utf8(e) {
86
+ return this.encode_latin1(unescape(encodeURIComponent(e)));
87
+ }
88
+ async decode_utf8(e) {
89
+ return decodeURIComponent(escape(await this.decode_latin1(e)));
90
+ }
91
+ async to_hex(e) {
92
+ let t = [];
93
+ for (let n = 0; n < e.length; n++) {
94
+ let r = "0123456789abcdef";
95
+ t.push(r[e[n] >> 4 & 15]), t.push(r[e[n] & 15]);
96
+ }
97
+ return t.join("");
98
+ }
99
+ async from_hex(e) {
100
+ let t = new Uint8Array(e.length / 2);
101
+ for (let n = 0; n < e.length / 2; n++) t[n] = parseInt(e.substr(2 * n, 2), 16);
102
+ return t;
103
+ }
104
+ async h2(e) {
105
+ e instanceof Uint8Array || (e = await this.encode_latin1(e));
106
+ let t = new Uint8Array(64 + e.length);
107
+ return t.fill(0), t.set(e, 64), this.crypto_hash_sha256(await this.crypto_hash_sha256(t));
108
+ }
109
+ }, s = class {
110
+ constructor() {}
111
+ static setDefaultInstance() {
112
+ return this.setInstance(new o());
113
+ }
114
+ static setInstance(e) {
115
+ if (this.driverInstance) throw Error("[NaCl] NaCl driver has been already set, it is supposed to be set only once");
116
+ return this.driverInstance = e, !0;
117
+ }
118
+ static getInstance() {
119
+ if (!this.driverInstance) throw Error("[NaCl] NaCl instance is not yet set");
120
+ return this.driverInstance;
121
+ }
122
+ }, c = class {
123
+ constructor(e) {
124
+ if (this.keys = e, typeof e == "string") {
125
+ let { boxPk: t, boxSk: n } = JSON.parse(e);
126
+ this.keyPair = {
127
+ boxPk: a.fromBase64(t),
128
+ boxSk: a.fromBase64(n)
129
+ };
130
+ } else this.keyPair = e;
131
+ }
132
+ static isEqual(e, t) {
133
+ return e.toString() === t.toString();
134
+ }
135
+ toString() {
136
+ return JSON.stringify({
137
+ boxPk: this.publicKey,
138
+ boxSk: this.privateKey
139
+ });
140
+ }
141
+ get publicKey() {
142
+ return a.toBase64(this.keyPair.boxPk);
143
+ }
144
+ get privateKey() {
145
+ return a.toBase64(this.keyPair.boxSk);
146
+ }
147
+ }, l = 30 * 1e3, u = {
148
+ NONCE_TAG: "__nc",
149
+ SKEY_TAG: "storage_key",
150
+ STORAGE_ROOT: ".v1.stor.vlt12",
151
+ RELAY_TOKEN_LEN: 32,
152
+ RELAY_TOKEN_TIMEOUT: 300 * 1e3 - l,
153
+ RELAY_SESSION_TIMEOUT: 1200 * 1e3 - l,
154
+ RELAY_AJAX_TIMEOUT: 5 * 1e3
155
+ }, d = class {
156
+ constructor(e = "storage.") {
157
+ this.rootTag = `__glow.${e}`;
158
+ }
159
+ async get(e) {
160
+ return (await this.getMultiple([e]))[0];
161
+ }
162
+ async getMultiple(e) {
163
+ return e.map((e) => localStorage.getItem(this.tag(e)) || null);
164
+ }
165
+ async set(e, t) {
166
+ return this.setMultiple({ [e]: t });
167
+ }
168
+ async setMultiple(e) {
169
+ for (let t in e) {
170
+ let n = e[t];
171
+ n !== null && localStorage.setItem(this.tag(t), n);
172
+ }
173
+ }
174
+ async remove(e) {
175
+ this.removeMultiple([e]);
176
+ }
177
+ async removeMultiple(e) {
178
+ e.forEach((e) => localStorage.removeItem(this.tag(e)));
179
+ }
180
+ tag(e) {
181
+ return `${this.rootTag}.${e}`;
182
+ }
183
+ }, f = class e {
184
+ constructor(e, t) {
185
+ let n = s.getInstance();
186
+ this.nacl = n, this.driver = e, this.id = t ? `.${t}${u.STORAGE_ROOT}` : u.STORAGE_ROOT;
187
+ }
188
+ static async new(t) {
189
+ let n = this.getStorageDriver(), r = new e(n, t), i = r.addPrefix(u.SKEY_TAG), o = await n.get(i);
190
+ if (o) {
191
+ let { key: e } = JSON.parse(o);
192
+ r.storageKey = a.fromBase64(e);
193
+ } else r.storageKey = await r.nacl.random_bytes(r.nacl.crypto_secretbox_KEYBYTES), await n.set(i, JSON.stringify({ key: a.toBase64(r.storageKey) }));
194
+ return r;
195
+ }
196
+ static getStorageDriver() {
197
+ if (this.storageDriver) return this.storageDriver;
198
+ throw Error("[CryptoStorage] StorageDriver instance is not yet set");
199
+ }
200
+ static setDefaultStorageDriver() {
201
+ return this.setStorageDriver(new d());
202
+ }
203
+ static setStorageDriver(e) {
204
+ if (this.storageDriver) throw Error("[CryptoStorage] StorageDriver has been already set, it is supposed to be set only once");
205
+ return this.storageDriver = e, !0;
206
+ }
207
+ async save(e, t) {
208
+ if (!this.driver) throw Error("[CryptoStorage] Storage driver is not set");
209
+ if (!this.storageKey) throw Error("[CryptoStorage] Storage key is not set");
210
+ let n = JSON.stringify(t), r = await this.nacl.encode_utf8(n), i = await this.nacl.crypto_secretbox_random_nonce(), o = await this.nacl.crypto_secretbox(r, i, this.storageKey);
211
+ return await this.driver.setMultiple({
212
+ [this.addPrefix(e)]: a.toBase64(o),
213
+ [this.addNonceTag(e)]: a.toBase64(i)
214
+ }), !0;
215
+ }
216
+ async get(e) {
217
+ if (!this.driver) throw Error("[CryptoStorage] Storage driver is not set");
218
+ if (!this.storageKey) throw Error("[CryptoStorage] Storage key is not set");
219
+ let [t, n] = await this.driver.getMultiple([this.addPrefix(e), this.addNonceTag(e)]);
220
+ if (!t || !n) return null;
221
+ let r = a.fromBase64(t), i = a.fromBase64(n), o = await this.nacl.crypto_secretbox_open(r, i, this.storageKey);
222
+ if (o) {
223
+ let e = await this.nacl.decode_utf8(o);
224
+ return JSON.parse(e);
225
+ } else throw Error("[CryptoStorage] crypto_secretbox_open: decryption error");
226
+ }
227
+ async remove(e) {
228
+ if (!this.driver) throw Error("[CryptoStorage] Storage driver is not set");
229
+ return await this.driver.removeMultiple([this.addPrefix(e), this.addNonceTag(e)]), !0;
230
+ }
231
+ async selfDestruct() {
232
+ if (!this.driver) throw Error("[CryptoStorage] Storage driver is not set");
233
+ await this.driver.remove(this.addPrefix(u.SKEY_TAG));
234
+ }
235
+ addPrefix(e) {
236
+ return this.id ? e + this.id : e;
237
+ }
238
+ addNonceTag(e) {
239
+ return this.addPrefix(`${u.NONCE_TAG}.${e}`);
240
+ }
241
+ }, p = "__::commKey::__", m = class e {
242
+ static {
243
+ this.commKeyTag = "comm_key";
244
+ }
245
+ static {
246
+ this.guestRegistryTag = "guest_registry";
247
+ }
248
+ constructor(e, t, n) {
249
+ this.guestKeys = /* @__PURE__ */ new Map(), this.nacl = e, this.storage = t, this.commKey = n;
250
+ }
251
+ static async new(t) {
252
+ let n = s.getInstance(), r = await f.new(t), i = new e(n, r, await e.getCommKeyOrCreate(n, r));
253
+ return await i.loadGuestKeys(), i;
254
+ }
255
+ static async fromBackup(t, n) {
256
+ let r = JSON.parse(n), i = a.fromBase64(r[p]), o = await e.new(t);
257
+ await o.setCommFromSecKey(i);
258
+ for (let [e, t] of Object.entries(r)) e !== p && await o.addGuest(e, t);
259
+ return o;
260
+ }
261
+ getNumberOfGuests() {
262
+ return this.guestKeys.size;
263
+ }
264
+ get guests() {
265
+ return this.guestKeys;
266
+ }
267
+ getPubCommKey() {
268
+ return this.commKey.publicKey;
269
+ }
270
+ getPrivateCommKey() {
271
+ return this.commKey.privateKey;
272
+ }
273
+ async getHpk() {
274
+ let e = await this.nacl.h2(a.fromBase64(this.commKey.publicKey));
275
+ return a.toBase64(e);
276
+ }
277
+ getTagByHpk(e) {
278
+ for (let [t, n] of this.guestKeys) if (n.hpk === e) return t;
279
+ return null;
280
+ }
281
+ getGuestKey(e) {
282
+ let t = this.guestKeys.get(e);
283
+ return t ? t.pk : null;
284
+ }
285
+ async backup() {
286
+ let e = { [p]: this.commKey.privateKey };
287
+ if (this.getNumberOfGuests() > 0) for (let [t, n] of this.guestKeys) t && n && (e[t] = n.pk);
288
+ return JSON.stringify(e);
289
+ }
290
+ async setCommFromSeed(t) {
291
+ this.commKey = new c(await this.nacl.crypto_box_keypair_from_seed(t)), await this.storage.save(e.commKeyTag, this.commKey.toString());
292
+ }
293
+ async setCommFromSecKey(t) {
294
+ this.commKey = new c(await this.nacl.crypto_box_keypair_from_raw_sk(t)), await this.storage.save(e.commKeyTag, this.commKey.toString());
295
+ }
296
+ async addGuest(e, t) {
297
+ let n = a.toBase64(await this.nacl.h2(a.fromBase64(t)));
298
+ return this.guestKeys.set(e, {
299
+ pk: t,
300
+ hpk: n
301
+ }), await this.saveGuests(), n;
302
+ }
303
+ async removeGuest(e) {
304
+ return this.guestKeys.has(e) && (this.guestKeys.delete(e), await this.saveGuests()), !0;
305
+ }
306
+ async loadGuestKeys() {
307
+ let t = await this.storage.get(e.guestRegistryTag);
308
+ if (t) if (typeof t == "object") this.guestKeys = new Map(Object.entries(t));
309
+ else throw Error("[Keyring] Guest keys is not an object");
310
+ }
311
+ async saveGuests() {
312
+ await this.storage.save(e.guestRegistryTag, a.toObject(this.guestKeys.entries()));
313
+ }
314
+ static async getCommKeyOrCreate(t, n) {
315
+ let r = await n.get(e.commKeyTag);
316
+ if (r && typeof r == "string") return new c(r);
317
+ {
318
+ let r = new c(await t.crypto_box_keypair());
319
+ return await n.save(e.commKeyTag, r.toString()), r;
320
+ }
321
+ }
322
+ async selfDestruct() {
323
+ await this.storage.remove(e.guestRegistryTag), await this.storage.remove(e.commKeyTag), await this.storage.selfDestruct();
324
+ }
325
+ }, h = class e {
326
+ constructor() {}
327
+ static async encodeMessage(e, t, n, r) {
328
+ let i = s.getInstance(), o = await this.makeNonce(r), c = await i.crypto_box(e, o, t, n);
329
+ return {
330
+ nonce: a.toBase64(o),
331
+ ctext: a.toBase64(c)
332
+ };
333
+ }
334
+ static async decodeMessage(e, t, n, r) {
335
+ let i = s.getInstance(), a = await i.crypto_box_open(t, e, n, r);
336
+ return a && await i.decode_utf8(a);
337
+ }
338
+ static async encodeMessageSymmetric(t, n) {
339
+ let r = s.getInstance(), i = await e.makeNonce(), o = await r.crypto_secretbox(t, i, n);
340
+ return {
341
+ nonce: a.toBase64(i),
342
+ ctext: a.toBase64(o)
343
+ };
344
+ }
345
+ static async decodeMessageSymmetric(e, t, n) {
346
+ return await s.getInstance().crypto_secretbox_open(a.fromBase64(t), a.fromBase64(e), n);
347
+ }
348
+ static async makeNonce(e) {
349
+ let t = s.getInstance(), n = await t.crypto_box_random_nonce(), r;
350
+ if (n.length !== t.crypto_box_NONCEBYTES) throw Error("[Mailbox] Wrong crypto_box nonce length");
351
+ r = 8;
352
+ let i = this.itoa(Math.floor(Date.now() / 1e3));
353
+ if (e && (r += 4), n.fill(0, 0, r), n.set(i, 8 - i.length), e) {
354
+ let t = this.itoa(e);
355
+ n.set(t, 12 - t.length);
356
+ }
357
+ return n;
358
+ }
359
+ static itoa(e) {
360
+ let t = e.toString(16);
361
+ t = t.length & 1 ? `0${t}` : t;
362
+ let n = t.length / 2, r = new Uint8Array(n);
363
+ for (let e = 0, n = 0; n < t.length; n += 2, e++) r[e] = parseInt(t[n] + t[n + 1], 16);
364
+ return r;
365
+ }
366
+ }, g = /* @__PURE__ */ function(e) {
367
+ return e.count = "count", e.upload = "upload", e.download = "download", e.messageStatus = "messageStatus", e.delete = "delete", e.startFileUpload = "startFileUpload", e.uploadFileChunk = "uploadFileChunk", e.downloadFileChunk = "downloadFileChunk", e.fileStatus = "fileStatus", e.deleteFile = "deleteFile", e;
368
+ }({}), _ = /* @__PURE__ */ function(e) {
369
+ return e.message = "message", e.file = "file", e.plain = "plain", e;
370
+ }({}), v = class extends Error {
371
+ constructor(e) {
372
+ super(`GlowNetworkError status: ${e}`), this.status = e, this.name = "GlowNetworkError";
373
+ }
374
+ }, y = class {
375
+ constructor(e) {
376
+ this.url = e, this.difficulty = 0, this.nacl = s.getInstance();
377
+ }
378
+ get isConnected() {
379
+ return !!(this.sessionKeys && this.publicKey);
380
+ }
381
+ async openConnection() {
382
+ this.sessionKeys = new c(await this.nacl.crypto_box_keypair()), this.clientToken = await this.nacl.random_bytes(u.RELAY_TOKEN_LEN);
383
+ let e = await this.fetchRelayToken();
384
+ return this.publicKey = await this.fetchRelayPublicKey(e), {
385
+ h2Signature: await this.getSignature(e, this.sessionKeys),
386
+ relayPublicKey: this.publicKey
387
+ };
388
+ }
389
+ async fetchRelayToken() {
390
+ if (!this.clientToken) throw Error("[Relay] clientToken is required please openConnection first");
391
+ let e = await this.httpCall("start_session", a.toBase64(this.clientToken));
392
+ this.scheduleTokenExpiration();
393
+ let [t, n] = this.parseResponse("start_session", e);
394
+ return this.difficulty = parseInt(n, 10), this.difficulty > 10 && console.log(`[Relay] ${this.url} requested difficulty ${this.difficulty}. Session handshake may take longer.`), a.fromBase64(t);
395
+ }
396
+ async fetchRelayPublicKey(e) {
397
+ if (!this.clientToken) throw Error("[Relay] clientToken is required please openConnection first");
398
+ let t = a.toBase64(await this.nacl.h2(this.clientToken)), n = new Uint8Array([...this.clientToken, ...e]), r;
399
+ r = this.difficulty === 0 ? await this.nacl.h2(n) : await this.ensureNonceDifficulty(n);
400
+ let i = await this.httpCall("verify_session", t, a.toBase64(r));
401
+ return a.fromBase64(i);
402
+ }
403
+ async prove(e) {
404
+ if (!this.clientToken) throw Error("[Relay] clientToken is required please openConnection first");
405
+ if (!this.sessionKeys) throw Error("[Relay] No session key found, open the connection first");
406
+ let t = a.toBase64(await this.nacl.h2(this.clientToken)), n = await this.httpCall("prove", t, this.sessionKeys.publicKey, e.nonce, e.ctext);
407
+ return this.scheduleSessionExpiration(), n;
408
+ }
409
+ async encodeMessage(e) {
410
+ if (!this.publicKey) throw Error("[Relay] No relay public key found, open the connection first");
411
+ if (!this.sessionKeys) throw Error("[Relay] No session key found, open the connection first");
412
+ return await h.encodeMessage(await this.nacl.encode_utf8(e), this.publicKey, a.fromBase64(this.sessionKeys?.privateKey));
413
+ }
414
+ async decodeMessage(e, t) {
415
+ let n = this.publicKey;
416
+ if (!n) throw Error("[Relay] No relay public key found, open the connection first");
417
+ if (!this.sessionKeys) throw Error("[Relay] No session key found, open the connection first");
418
+ let r = await h.decodeMessage(a.fromBase64(e), a.fromBase64(t), n, a.fromBase64(this.sessionKeys.privateKey));
419
+ if (r === null) throw Error("[Relay] failed to decode message");
420
+ return JSON.parse(r);
421
+ }
422
+ async runCmd(e, t, n, r) {
423
+ if (!Object.keys(g).includes(e)) throw Error(`[Relay] ${this.url} doesn't support command ${e}`);
424
+ let i = [
425
+ t,
426
+ n.nonce,
427
+ n.ctext
428
+ ];
429
+ r && i.push(r);
430
+ let a = await this.httpCall("command", ...i);
431
+ return this.parseResponse(e, a);
432
+ }
433
+ async getSignature(e, t) {
434
+ if (!this.clientToken) throw Error("[Relay] clientToken is required please openConnection first");
435
+ let n = a.fromBase64(t.publicKey), r = new Uint8Array([
436
+ ...n,
437
+ ...e,
438
+ ...this.clientToken
439
+ ]);
440
+ return await this.nacl.h2(r);
441
+ }
442
+ async httpCall(e, ...t) {
443
+ let n = new AbortController(), r = setTimeout(() => n.abort(), u.RELAY_AJAX_TIMEOUT), i = {
444
+ method: "POST",
445
+ headers: {
446
+ Accept: "text/plain",
447
+ "Content-Type": "text/plain"
448
+ },
449
+ body: t.join("\r\n"),
450
+ signal: n.signal
451
+ };
452
+ try {
453
+ let t = await fetch(`${this.url}/${e}`, i);
454
+ if (!t.ok) throw t.status === 401 && (this.clearSession(), this.clearToken()), new v(t.status);
455
+ return await t.text();
456
+ } catch (e) {
457
+ throw e instanceof Error && e.name === "AbortError" ? new v(408) : e instanceof v ? e : e instanceof TypeError ? new v(0) : e;
458
+ } finally {
459
+ clearTimeout(r);
460
+ }
461
+ }
462
+ parseResponse(e, t) {
463
+ let n = t.split("\r\n");
464
+ if (!t || !this.validateResponse(e, n.length)) throw console.log(n), Error(`[Relay] ${this.url} - ${e}: Bad response`);
465
+ return n;
466
+ }
467
+ validateResponse(e, t) {
468
+ switch (e) {
469
+ case g.upload:
470
+ case g.messageStatus:
471
+ case g.delete: return t === 1;
472
+ case g.downloadFileChunk: return t === 3;
473
+ default: return t === 2;
474
+ }
475
+ }
476
+ scheduleTokenExpiration() {
477
+ this.tokenExpirationTimeoutHandle && clearTimeout(this.tokenExpirationTimeoutHandle), this.tokenExpirationTimeoutHandle = setTimeout(() => this.clearToken(), u.RELAY_TOKEN_TIMEOUT);
478
+ }
479
+ clearToken() {
480
+ this.tokenExpirationTimeoutHandle && clearTimeout(this.tokenExpirationTimeoutHandle), this.clientToken && delete this.clientToken;
481
+ }
482
+ scheduleSessionExpiration() {
483
+ this.sessionExpirationTimeoutHandle && clearTimeout(this.sessionExpirationTimeoutHandle), this.sessionExpirationTimeoutHandle = setTimeout(() => {
484
+ this.clearSession();
485
+ }, u.RELAY_SESSION_TIMEOUT);
486
+ }
487
+ clearSession() {
488
+ this.sessionExpirationTimeoutHandle && clearTimeout(this.sessionExpirationTimeoutHandle), this.sessionKeys && delete this.sessionKeys;
489
+ }
490
+ async ensureNonceDifficulty(e) {
491
+ let t, n;
492
+ do
493
+ t = await this.nacl.random_bytes(32), n = await this.nacl.h2(new Uint8Array([...e, ...t]));
494
+ while (!this.arrayZeroBits(n));
495
+ return t;
496
+ }
497
+ arrayZeroBits(e) {
498
+ let t, n = this.difficulty;
499
+ for (let r = 0; r <= 1 + this.difficulty / 8; r++) {
500
+ if (t = e[r], n <= 0) return !0;
501
+ if (n > 8) {
502
+ if (n -= 8, t > 0) return !1;
503
+ } else return this.firstZeroBits(t, n);
504
+ }
505
+ return !1;
506
+ }
507
+ firstZeroBits(e, t) {
508
+ return e === e >> t << t;
509
+ }
510
+ }, b = class {
511
+ constructor() {
512
+ this.relays = {};
513
+ }
514
+ getInstance(e) {
515
+ let t = this.relays[e];
516
+ return t ||= this.relays[e] = new y(e), t;
517
+ }
518
+ }, x = class e {
519
+ constructor(e, t, n) {
520
+ this.relayFactory = new b(), this.relayConnectionMutexes = /* @__PURE__ */ new Map(), this.nacl = e, this.keyRing = t, this.identity = n;
521
+ }
522
+ static async new(t) {
523
+ return new e(s.getInstance(), await m.new(t), t);
524
+ }
525
+ static async fromSeed(e, t) {
526
+ let n = await this.new(e);
527
+ return t instanceof Uint8Array || (t = a.encode_latin1(t)), await n.keyRing.setCommFromSeed(t), n;
528
+ }
529
+ static async fromSecKey(e, t) {
530
+ let n = await this.new(e);
531
+ return t instanceof Uint8Array || (t = a.fromBase64(t)), await n.keyRing.setCommFromSecKey(t), n;
532
+ }
533
+ static async fromBackup(t, n) {
534
+ return new e(s.getInstance(), await m.fromBackup(t, n), t);
535
+ }
536
+ async upload(e, t, n, r = !0) {
537
+ let i = await this.prepareRelay(e), o = this.getGuestKey(t), s = r ? await this.encodeMessage(t, n) : n, c = a.toBase64(await this.nacl.h2(a.fromBase64(o))), [l] = await this.runRelayCommand(i, g.upload, {
538
+ to: c,
539
+ payload: s
540
+ });
541
+ return l;
542
+ }
543
+ async download(e) {
544
+ let t = await this.prepareRelay(e), n = await this.runRelayCommand(t, g.download), r = await this.decryptResponse(t, n), i = [];
545
+ for (let e of r) {
546
+ let t = this.keyRing.getTagByHpk(e.from);
547
+ if (!t) i.push(await this.parsePlainMessage(e));
548
+ else if (e.kind === "message") i.push(await this.parseTextMessage(e, t));
549
+ else if (e.kind === "file") i.push(await this.parseFileMessage(e, t));
550
+ else throw Error("[Mailbox] download - Unknown message type");
551
+ }
552
+ return i;
553
+ }
554
+ async parsePlainMessage({ data: e, time: t, from: n, nonce: r }) {
555
+ return {
556
+ data: e,
557
+ time: t,
558
+ from: n,
559
+ nonce: r,
560
+ kind: _.plain
561
+ };
562
+ }
563
+ async parseFileMessage(e, t) {
564
+ let { nonce: n, ctext: r, uploadID: i } = JSON.parse(e.data), a = await this.decodeMessage(t, n, r);
565
+ if (a === null) throw Error("[Mailbox] Failed to decode file message");
566
+ return {
567
+ data: JSON.parse(a),
568
+ time: e.time,
569
+ senderTag: t,
570
+ uploadID: i,
571
+ nonce: n,
572
+ kind: _.file
573
+ };
574
+ }
575
+ async parseTextMessage(e, t) {
576
+ let n = await this.decodeMessage(t, e.nonce, e.data);
577
+ return n ||= e.data, {
578
+ data: n,
579
+ time: e.time,
580
+ senderTag: t,
581
+ nonce: e.nonce,
582
+ kind: _.message
583
+ };
584
+ }
585
+ async count(e) {
586
+ let t = await this.prepareRelay(e), n = await this.runRelayCommand(t, g.count);
587
+ return await this.decryptResponse(t, n);
588
+ }
589
+ async delete(e, t) {
590
+ let n = await this.prepareRelay(e), [r] = await this.runRelayCommand(n, g.delete, { payload: t });
591
+ return parseInt(r, 10);
592
+ }
593
+ async messageStatus(e, t) {
594
+ let n = await this.prepareRelay(e), [r] = await this.runRelayCommand(n, g.messageStatus, { token: t });
595
+ return parseInt(r, 10);
596
+ }
597
+ async startFileUpload(e, t, n) {
598
+ let r = await this.prepareRelay(e), i = this.getGuestKey(t), o = a.toBase64(await this.nacl.h2(a.fromBase64(i))), s = await this.nacl.random_bytes(this.nacl.crypto_secretbox_KEYBYTES);
599
+ n.skey = a.toBase64(s);
600
+ let c = await this.encodeMessage(t, JSON.stringify(n)), l = await this.runRelayCommand(r, g.startFileUpload, {
601
+ to: o,
602
+ file_size: n.orig_size,
603
+ metadata: c
604
+ }), u = await this.decryptResponse(r, l);
605
+ return u.skey = s, u;
606
+ }
607
+ async uploadFileChunk(e, t, n, r, i, a) {
608
+ let o = await this.prepareRelay(e), s = await h.encodeMessageSymmetric(n, a), c = await this.runRelayCommand(o, g.uploadFileChunk, {
609
+ uploadID: t,
610
+ part: r,
611
+ last_chunk: i - 1 === r,
612
+ nonce: s.nonce
613
+ }, s.ctext);
614
+ return await this.decryptResponse(o, c);
615
+ }
616
+ async getFileStatus(e, t) {
617
+ let n = await this.prepareRelay(e), r = await this.runRelayCommand(n, g.fileStatus, { uploadID: t });
618
+ return await this.decryptResponse(n, r);
619
+ }
620
+ async getFileMetadata(e, t) {
621
+ return (await this.download(e)).filter((e) => e.kind === "file").find((e) => e.uploadID === t)?.data;
622
+ }
623
+ async downloadFileChunk(e, t, n, r) {
624
+ r instanceof Uint8Array || (r = a.fromBase64(r));
625
+ let i = await this.prepareRelay(e), [o, s, c] = await this.runRelayCommand(i, g.downloadFileChunk, {
626
+ uploadID: t,
627
+ part: n
628
+ }), l = await i.decodeMessage(o, s);
629
+ return await h.decodeMessageSymmetric(l.nonce, c, r);
630
+ }
631
+ async deleteFile(e, t) {
632
+ let n = await this.prepareRelay(e), r = await this.runRelayCommand(n, g.deleteFile, { uploadID: t });
633
+ return await this.decryptResponse(n, r);
634
+ }
635
+ async connectToRelay(e) {
636
+ let t = this.relayFactory.getInstance(e), n = await t.openConnection(), r = await this.encryptSignature(n), i = await t.prove(await t.encodeMessage(JSON.stringify({
637
+ pub_key: this.keyRing.getPubCommKey(),
638
+ nonce: r.nonce,
639
+ ctext: r.ctext
640
+ })));
641
+ return parseInt(i, 10);
642
+ }
643
+ clearSession(e) {
644
+ let t = this.relayFactory.getInstance(e);
645
+ t.clearToken(), t.clearSession();
646
+ }
647
+ async encryptSignature(e) {
648
+ let t = a.fromBase64(this.keyRing.getPrivateCommKey());
649
+ return await h.encodeMessage(e.h2Signature, e.relayPublicKey, t);
650
+ }
651
+ async prepareRelay(e) {
652
+ let t = this.relayFactory.getInstance(e);
653
+ return await this.getRelayConnectionMutex(e).runExclusive(async () => {
654
+ t.isConnected || await this.connectToRelay(e);
655
+ }), t;
656
+ }
657
+ async runRelayCommand(e, t, n, r) {
658
+ n = {
659
+ cmd: t,
660
+ ...n
661
+ };
662
+ let i = await this.keyRing.getHpk(), a = await e.encodeMessage(JSON.stringify(n));
663
+ return await e.runCmd(t, i, a, r);
664
+ }
665
+ async decryptResponse(e, t) {
666
+ let [n, r] = t;
667
+ return await e.decodeMessage(n, r);
668
+ }
669
+ async encodeMessage(e, t) {
670
+ let n = this.getGuestKey(e), r = this.keyRing.getPrivateCommKey();
671
+ return await h.encodeMessage(await this.nacl.encode_utf8(t), a.fromBase64(n), a.fromBase64(r));
672
+ }
673
+ async decodeMessage(e, t, n) {
674
+ let r = this.getGuestKey(e), i = this.keyRing.getPrivateCommKey(), o;
675
+ try {
676
+ o = a.fromBase64(n);
677
+ } catch {
678
+ return null;
679
+ }
680
+ return await h.decodeMessage(a.fromBase64(t), o, a.fromBase64(r), a.fromBase64(i));
681
+ }
682
+ getGuestKey(e) {
683
+ let t = this.keyRing.getGuestKey(e);
684
+ if (!t) throw Error(`[Mailbox] Unknown guest ${e}`);
685
+ return t;
686
+ }
687
+ async selfDestruct() {
688
+ await this.keyRing.selfDestruct();
689
+ }
690
+ getRelayConnectionMutex(e) {
691
+ return this.relayConnectionMutexes.has(e) || this.relayConnectionMutexes.set(e, new i()), this.relayConnectionMutexes.get(e);
692
+ }
693
+ }, S = class {
694
+ constructor() {
695
+ this.storage = {};
696
+ }
697
+ async get(e) {
698
+ return (await this.getMultiple([e]))[0];
699
+ }
700
+ async getMultiple(e) {
701
+ return e.map((e) => this.storage[e]);
702
+ }
703
+ set(e, t) {
704
+ return this.setMultiple({ [e]: t });
705
+ }
706
+ async setMultiple(e) {
707
+ for (let t in e) this.storage[t] = e[t];
708
+ }
709
+ remove(e) {
710
+ return this.removeMultiple([e]);
711
+ }
712
+ async removeMultiple(e) {
713
+ e.forEach((e) => delete this.storage[e]);
714
+ }
715
+ reset() {
716
+ this.storage = {};
717
+ }
176
718
  };
177
- class M {
178
- constructor(e = "storage.") {
179
- this.rootTag = `__glow.${e}`;
180
- }
181
- async get(e) {
182
- return (await this.getMultiple([e]))[0];
183
- }
184
- async getMultiple(e) {
185
- return e.map((t) => localStorage.getItem(this.tag(t)) || null);
186
- }
187
- async set(e, t) {
188
- return this.setMultiple({ [e]: t });
189
- }
190
- async setMultiple(e) {
191
- for (const t in e) {
192
- const s = e[t];
193
- s !== null && localStorage.setItem(this.tag(t), s);
194
- }
195
- }
196
- async remove(e) {
197
- this.removeMultiple([e]);
198
- }
199
- async removeMultiple(e) {
200
- e.forEach((t) => localStorage.removeItem(this.tag(t)));
201
- }
202
- tag(e) {
203
- return `${this.rootTag}.${e}`;
204
- }
205
- }
206
- class E {
207
- constructor(e, t) {
208
- const s = h.getInstance();
209
- this.nacl = s, this.driver = e, this.id = t ? `.${t}${u.STORAGE_ROOT}` : u.STORAGE_ROOT;
210
- }
211
- static async new(e) {
212
- const t = this.getStorageDriver(), s = new E(t, e), n = s.addPrefix(u.SKEY_TAG), r = await t.get(n);
213
- if (r) {
214
- const { key: a } = JSON.parse(r);
215
- s.storageKey = o.fromBase64(a);
216
- } else
217
- s.storageKey = await s.nacl.random_bytes(s.nacl.crypto_secretbox_KEYBYTES), await t.set(n, JSON.stringify({ key: o.toBase64(s.storageKey) }));
218
- return s;
219
- }
220
- static getStorageDriver() {
221
- if (this.storageDriver)
222
- return this.storageDriver;
223
- throw new Error("[CryptoStorage] StorageDriver instance is not yet set");
224
- }
225
- static setDefaultStorageDriver() {
226
- return this.setStorageDriver(new M());
227
- }
228
- static setStorageDriver(e) {
229
- if (this.storageDriver)
230
- throw new Error("[CryptoStorage] StorageDriver has been already set, it is supposed to be set only once");
231
- return this.storageDriver = e, !0;
232
- }
233
- async save(e, t) {
234
- if (!this.driver)
235
- throw new Error("[CryptoStorage] Storage driver is not set");
236
- if (!this.storageKey)
237
- throw new Error("[CryptoStorage] Storage key is not set");
238
- const s = JSON.stringify(t), n = await this.nacl.encode_utf8(s), r = await this.nacl.crypto_secretbox_random_nonce(), a = await this.nacl.crypto_secretbox(n, r, this.storageKey);
239
- return await this.driver.setMultiple({
240
- [this.addPrefix(e)]: o.toBase64(a),
241
- [this.addNonceTag(e)]: o.toBase64(r)
242
- }), !0;
243
- }
244
- async get(e) {
245
- if (!this.driver)
246
- throw new Error("[CryptoStorage] Storage driver is not set");
247
- if (!this.storageKey)
248
- throw new Error("[CryptoStorage] Storage key is not set");
249
- const [t, s] = await this.driver.getMultiple([this.addPrefix(e), this.addNonceTag(e)]);
250
- if (!t || !s)
251
- return null;
252
- const n = o.fromBase64(t), r = o.fromBase64(s), a = await this.nacl.crypto_secretbox_open(n, r, this.storageKey);
253
- if (a) {
254
- const c = await this.nacl.decode_utf8(a);
255
- return JSON.parse(c);
256
- } else
257
- throw new Error("[CryptoStorage] crypto_secretbox_open: decryption error");
258
- }
259
- async remove(e) {
260
- if (!this.driver)
261
- throw new Error("[CryptoStorage] Storage driver is not set");
262
- return await this.driver.removeMultiple([this.addPrefix(e), this.addNonceTag(e)]), !0;
263
- }
264
- async selfDestruct() {
265
- if (!this.driver)
266
- throw new Error("[CryptoStorage] Storage driver is not set");
267
- await this.driver.remove(this.addPrefix(u.SKEY_TAG));
268
- }
269
- // Keys are tagged in the storage with a versioned prefix
270
- addPrefix(e) {
271
- return this.id ? e + this.id : e;
272
- }
273
- addNonceTag(e) {
274
- return this.addPrefix(`${u.NONCE_TAG}.${e}`);
275
- }
276
- }
277
- const T = "__::commKey::__", y = class y {
278
- constructor(e, t, s) {
279
- this.guestKeys = /* @__PURE__ */ new Map(), this.nacl = e, this.storage = t, this.commKey = s;
280
- }
281
- static async new(e) {
282
- const t = h.getInstance(), s = await E.new(e), n = await y.getCommKeyOrCreate(t, s), r = new y(t, s, n);
283
- return await r.loadGuestKeys(), r;
284
- }
285
- static async fromBackup(e, t) {
286
- const s = JSON.parse(t), n = o.fromBase64(s[T]), r = await y.new(e);
287
- await r.setCommFromSecKey(n);
288
- for (const [a, c] of Object.entries(s))
289
- a !== T && await r.addGuest(a, c);
290
- return r;
291
- }
292
- getNumberOfGuests() {
293
- return this.guestKeys.size;
294
- }
295
- get guests() {
296
- return this.guestKeys;
297
- }
298
- /**
299
- * Returns public identity, which is the default communication key.
300
- * Correspondents can know it, whereas Relays do not need it (other than
301
- * temporarily for internal use during the ownership proof)
302
- */
303
- getPubCommKey() {
304
- return this.commKey.publicKey;
305
- }
306
- getPrivateCommKey() {
307
- return this.commKey.privateKey;
308
- }
309
- /**
310
- * Returns HPK (hash of the public key) of the mailbox. This is what Zax relays
311
- * uses as the universal address of the mailbox
312
- */
313
- async getHpk() {
314
- const e = await this.nacl.h2(o.fromBase64(this.commKey.publicKey));
315
- return o.toBase64(e);
316
- }
317
- getTagByHpk(e) {
318
- for (const [t, s] of this.guestKeys)
319
- if (s.hpk === e)
320
- return t;
321
- return null;
322
- }
323
- getGuestKey(e) {
324
- const t = this.guestKeys.get(e);
325
- return t ? t.pk : null;
326
- }
327
- // Backups
328
- async backup() {
329
- const e = {
330
- [T]: this.commKey.privateKey
331
- };
332
- if (this.getNumberOfGuests() > 0)
333
- for (const [t, s] of this.guestKeys)
334
- t && s && (e[t] = s.pk);
335
- return JSON.stringify(e);
336
- }
337
- async setCommFromSeed(e) {
338
- this.commKey = new w(await this.nacl.crypto_box_keypair_from_seed(e)), await this.storage.save(y.commKeyTag, this.commKey.toString());
339
- }
340
- async setCommFromSecKey(e) {
341
- this.commKey = new w(await this.nacl.crypto_box_keypair_from_raw_sk(e)), await this.storage.save(y.commKeyTag, this.commKey.toString());
342
- }
343
- async addGuest(e, t) {
344
- const s = o.toBase64(await this.nacl.h2(o.fromBase64(t)));
345
- return this.guestKeys.set(e, {
346
- pk: t,
347
- hpk: s
348
- }), await this.saveGuests(), s;
349
- }
350
- async removeGuest(e) {
351
- return this.guestKeys.has(e) && (this.guestKeys.delete(e), await this.saveGuests()), !0;
352
- }
353
- async loadGuestKeys() {
354
- const e = await this.storage.get(y.guestRegistryTag);
355
- if (e)
356
- if (typeof e == "object")
357
- this.guestKeys = new Map(Object.entries(e));
358
- else
359
- throw new Error("[Keyring] Guest keys is not an object");
360
- else return;
361
- }
362
- async saveGuests() {
363
- await this.storage.save(y.guestRegistryTag, o.toObject(this.guestKeys.entries()));
364
- }
365
- static async getCommKeyOrCreate(e, t) {
366
- const s = await t.get(y.commKeyTag);
367
- if (s && typeof s == "string")
368
- return new w(s);
369
- {
370
- const n = await e.crypto_box_keypair(), r = new w(n);
371
- return await t.save(y.commKeyTag, r.toString()), r;
372
- }
373
- }
374
- async selfDestruct() {
375
- await this.storage.remove(y.guestRegistryTag), await this.storage.remove(y.commKeyTag), await this.storage.selfDestruct();
376
- }
377
- };
378
- y.commKeyTag = "comm_key", y.guestRegistryTag = "guest_registry";
379
- let S = y;
380
- class p {
381
- constructor() {
382
- }
383
- /**
384
- * Encodes a binary message with `cryptobox`
385
- */
386
- static async encodeMessage(e, t, s, n) {
387
- const r = h.getInstance(), a = await this.makeNonce(n), c = await r.crypto_box(e, a, t, s);
388
- return {
389
- nonce: o.toBase64(a),
390
- ctext: o.toBase64(c)
391
- };
392
- }
393
- /**
394
- * Decodes a binary message with `cryptobox_open`
395
- * @returns null if failed to decode
396
- */
397
- static async decodeMessage(e, t, s, n) {
398
- const r = h.getInstance(), a = await r.crypto_box_open(t, e, s, n);
399
- return a && await r.decode_utf8(a);
400
- }
401
- /**
402
- * Encodes a binary message with `secretbox` (used for file chunk encryption)
403
- */
404
- static async encodeMessageSymmetric(e, t) {
405
- const s = h.getInstance(), n = await p.makeNonce(), r = await s.crypto_secretbox(e, n, t);
406
- return {
407
- nonce: o.toBase64(n),
408
- ctext: o.toBase64(r)
409
- };
410
- }
411
- /**
412
- * Decodes a binary message with `secretbox_open` (used for file chunk decryption)
413
- */
414
- static async decodeMessageSymmetric(e, t, s) {
415
- return await h.getInstance().crypto_secretbox_open(o.fromBase64(t), o.fromBase64(e), s);
416
- }
417
- // ---------- Nonce helper ----------
418
- /**
419
- * Makes a timestamp nonce that a relay expects for any crypto operations.
420
- * Timestamp is the first 8 bytes, the rest is random, unless custom `data`
421
- * is specified. `data` will be packed as next 4 bytes after timestamp.
422
- */
423
- static async makeNonce(e) {
424
- const t = h.getInstance(), s = await t.crypto_box_random_nonce();
425
- let n;
426
- if (s.length !== t.crypto_box_NONCEBYTES)
427
- throw new Error("[Mailbox] Wrong crypto_box nonce length");
428
- n = 8;
429
- const r = this.itoa(Math.floor(Date.now() / 1e3));
430
- if (e && (n += 4), s.fill(0, 0, n), s.set(r, 8 - r.length), e) {
431
- const a = this.itoa(e);
432
- s.set(a, 12 - a.length);
433
- }
434
- return s;
435
- }
436
- /**
437
- * Splits an integer into an array of bytes
438
- */
439
- static itoa(e) {
440
- let t = e.toString(16);
441
- t = t.length & 1 ? `0${t}` : t;
442
- const s = t.length / 2, n = new Uint8Array(s);
443
- for (let r = 0, a = 0; a < t.length; a += 2, r++)
444
- n[r] = parseInt(t[a] + t[a + 1], 16);
445
- return n;
446
- }
447
- }
448
- var l = /* @__PURE__ */ ((i) => (i.count = "count", i.upload = "upload", i.download = "download", i.messageStatus = "messageStatus", i.delete = "delete", i.startFileUpload = "startFileUpload", i.uploadFileChunk = "uploadFileChunk", i.downloadFileChunk = "downloadFileChunk", i.fileStatus = "fileStatus", i.deleteFile = "deleteFile", i))(l || {}), b = /* @__PURE__ */ ((i) => (i.message = "message", i.file = "file", i.plain = "plain", i))(b || {});
449
- class _ extends Error {
450
- constructor(e) {
451
- super(`GlowNetworkError status: ${e}`), this.status = e, this.name = "GlowNetworkError";
452
- }
453
- }
454
- class N {
455
- constructor(e) {
456
- this.url = e, this.difficulty = 0, this.nacl = h.getInstance();
457
- }
458
- get isConnected() {
459
- return !!(this.sessionKeys && this.publicKey);
460
- }
461
- // ---------- Connection initialization ----------
462
- /**
463
- * Exchanges tokens with a relay and gets a temp session key for this relay.
464
- * Returns h₂(signature) and a relay public key
465
- */
466
- async openConnection() {
467
- this.sessionKeys = new w(await this.nacl.crypto_box_keypair()), this.clientToken = await this.nacl.random_bytes(u.RELAY_TOKEN_LEN);
468
- const e = await this.fetchRelayToken();
469
- return this.publicKey = await this.fetchRelayPublicKey(e), {
470
- h2Signature: await this.getSignature(e, this.sessionKeys),
471
- relayPublicKey: this.publicKey
472
- };
473
- }
474
- /**
475
- * Sends a client token to a relay and saves a relay token
476
- */
477
- async fetchRelayToken() {
478
- if (!this.clientToken)
479
- throw new Error("[Relay] clientToken is required please openConnection first");
480
- const e = await this.httpCall("start_session", o.toBase64(this.clientToken));
481
- this.scheduleTokenExpiration();
482
- const [t, s] = this.parseResponse("start_session", e);
483
- return this.difficulty = parseInt(s, 10), this.difficulty > 10 && console.log(`[Relay] ${this.url} requested difficulty ${this.difficulty}. Session handshake may take longer.`), o.fromBase64(t);
484
- }
485
- /**
486
- * Completes the handshake and saves a relay pubic key
487
- */
488
- async fetchRelayPublicKey(e) {
489
- if (!this.clientToken)
490
- throw new Error("[Relay] clientToken is required please openConnection first");
491
- const t = o.toBase64(await this.nacl.h2(this.clientToken)), s = new Uint8Array([...this.clientToken, ...e]);
492
- let n;
493
- this.difficulty === 0 ? n = await this.nacl.h2(s) : n = await this.ensureNonceDifficulty(s);
494
- const r = await this.httpCall("verify_session", t, o.toBase64(n));
495
- return o.fromBase64(r);
496
- }
497
- /**
498
- * Attaches a mailbox and fetches number of messages
499
- */
500
- async prove(e) {
501
- if (!this.clientToken)
502
- throw new Error("[Relay] clientToken is required please openConnection first");
503
- if (!this.sessionKeys)
504
- throw new Error("[Relay] No session key found, open the connection first");
505
- const t = o.toBase64(await this.nacl.h2(this.clientToken)), s = await this.httpCall(
506
- "prove",
507
- t,
508
- this.sessionKeys.publicKey,
509
- e.nonce,
510
- e.ctext
511
- );
512
- return this.scheduleSessionExpiration(), s;
513
- }
514
- async encodeMessage(e) {
515
- if (!this.publicKey)
516
- throw new Error("[Relay] No relay public key found, open the connection first");
517
- if (!this.sessionKeys)
518
- throw new Error("[Relay] No session key found, open the connection first");
519
- return await p.encodeMessage(
520
- await this.nacl.encode_utf8(e),
521
- this.publicKey,
522
- o.fromBase64(this.sessionKeys?.privateKey)
523
- );
524
- }
525
- async decodeMessage(e, t) {
526
- const s = this.publicKey;
527
- if (!s)
528
- throw new Error("[Relay] No relay public key found, open the connection first");
529
- if (!this.sessionKeys)
530
- throw new Error("[Relay] No session key found, open the connection first");
531
- const n = await p.decodeMessage(
532
- o.fromBase64(e),
533
- o.fromBase64(t),
534
- s,
535
- o.fromBase64(this.sessionKeys.privateKey)
536
- );
537
- if (n === null)
538
- throw new Error("[Relay] failed to decode message");
539
- return JSON.parse(n);
540
- }
541
- // ---------- Low-level server request handling ----------
542
- /**
543
- * Executes a message/file command on a relay, parses and validates the response
544
- */
545
- async runCmd(e, t, s, n) {
546
- if (!Object.keys(l).includes(e))
547
- throw new Error(`[Relay] ${this.url} doesn't support command ${e}`);
548
- const r = [t, s.nonce, s.ctext];
549
- n && r.push(n);
550
- const a = await this.httpCall("command", ...r);
551
- return this.parseResponse(e, a);
552
- }
553
- async getSignature(e, t) {
554
- if (!this.clientToken)
555
- throw new Error("[Relay] clientToken is required please openConnection first");
556
- const s = o.fromBase64(t.publicKey), n = new Uint8Array([...s, ...e, ...this.clientToken]);
557
- return await this.nacl.h2(n);
558
- }
559
- /**
560
- * Executes a call to a relay and return raw string response
561
- */
562
- // TODO: extract fetching into separate function
563
- async httpCall(e, ...t) {
564
- const s = new AbortController(), n = setTimeout(() => s.abort(), u.RELAY_AJAX_TIMEOUT), r = {
565
- method: "POST",
566
- headers: {
567
- Accept: "text/plain",
568
- "Content-Type": "text/plain"
569
- },
570
- body: t.join(`\r
571
- `),
572
- signal: s.signal
573
- };
574
- try {
575
- const a = await fetch(`${this.url}/${e}`, r);
576
- if (!a.ok)
577
- throw a.status === 401 && (this.clearSession(), this.clearToken()), new _(a.status);
578
- return await a.text();
579
- } catch (a) {
580
- throw a instanceof Error && a.name === "AbortError" ? new _(408) : a instanceof _ ? a : a instanceof TypeError ? new _(0) : a;
581
- } finally {
582
- clearTimeout(n);
583
- }
584
- }
585
- /**
586
- * Parses relay response and throws an error if its format is unexpected
587
- */
588
- parseResponse(e, t) {
589
- const s = t.split(`\r
590
- `);
591
- if (!t || !this.validateResponse(e, s.length))
592
- throw console.log(s), new Error(`[Relay] ${this.url} - ${e}: Bad response`);
593
- return s;
594
- }
595
- /**
596
- * Compares the expected number of lines in response with what was actually received from a relay
597
- */
598
- validateResponse(e, t) {
599
- switch (e) {
600
- case l.upload:
601
- case l.messageStatus:
602
- case l.delete:
603
- return t === 1;
604
- case l.downloadFileChunk:
605
- return t === 3;
606
- default:
607
- return t === 2;
608
- }
609
- }
610
- /**
611
- * delete token locally before it was removed on server so will reconnect without getting unauthorized error
612
- */
613
- scheduleTokenExpiration() {
614
- this.tokenExpirationTimeoutHandle && clearTimeout(this.tokenExpirationTimeoutHandle), this.tokenExpirationTimeoutHandle = setTimeout(() => this.clearToken(), u.RELAY_TOKEN_TIMEOUT);
615
- }
616
- clearToken() {
617
- this.tokenExpirationTimeoutHandle && clearTimeout(this.tokenExpirationTimeoutHandle), this.clientToken && delete this.clientToken;
618
- }
619
- /**
620
- * established session is valid only for some period need to remove it after it's ttl
621
- * so relay will reconnect without receiving error from server
622
- */
623
- scheduleSessionExpiration() {
624
- this.sessionExpirationTimeoutHandle && clearTimeout(this.sessionExpirationTimeoutHandle), this.sessionExpirationTimeoutHandle = setTimeout(() => {
625
- this.clearSession();
626
- }, u.RELAY_SESSION_TIMEOUT);
627
- }
628
- clearSession() {
629
- this.sessionExpirationTimeoutHandle && clearTimeout(this.sessionExpirationTimeoutHandle), this.sessionKeys && delete this.sessionKeys;
630
- }
631
- // ---------- Difficulty adjustment ----------
632
- /**
633
- * Continuously calculates the nonce until one requested by a relay is found
634
- */
635
- async ensureNonceDifficulty(e) {
636
- let t, s;
637
- do
638
- t = await this.nacl.random_bytes(32), s = await this.nacl.h2(new Uint8Array([...e, ...t]));
639
- while (!this.arrayZeroBits(s));
640
- return t;
641
- }
642
- /**
643
- * Returns `true` if the rightmost n bits of a byte are 0.
644
- * Check whether the rightmost difficulty bits of an Uint8Array are 0, where
645
- * the lowest indexes of the array represent those rightmost bits. Thus if
646
- * the difficulty is 17, then array[0] and array[1] should be 0, as should the
647
- * rightmost bit of array[2]. This is used for our difficulty settings in Zax to
648
- * reduce burden on a busy server by ensuring clients have to do some
649
- * additional work during the session handshake
650
- */
651
- arrayZeroBits(e) {
652
- let t, s = this.difficulty;
653
- for (let n = 0; n <= 1 + this.difficulty / 8; n++) {
654
- if (t = e[n], s <= 0)
655
- return !0;
656
- if (s > 8) {
657
- if (s -= 8, t > 0)
658
- return !1;
659
- } else
660
- return this.firstZeroBits(t, s);
661
- }
662
- return !1;
663
- }
664
- /**
665
- * Returns `true` if the rightmost n bits of a byte are 0
666
- */
667
- firstZeroBits(e, t) {
668
- return e === e >> t << t;
669
- }
670
- }
671
- class O {
672
- constructor() {
673
- this.relays = {};
674
- }
675
- /**
676
- * Relay factory, that returns a Relay instance for a given URL,
677
- * or creates a new one if it hasn't yet been initialized.
678
- */
679
- getInstance(e) {
680
- let t = this.relays[e];
681
- return t || (t = this.relays[e] = new N(e)), t;
682
- }
683
- }
684
- class x {
685
- constructor(e, t, s) {
686
- this.relayFactory = new O(), this.relayConnectionMutexes = /* @__PURE__ */ new Map(), this.nacl = e, this.keyRing = t, this.identity = s;
687
- }
688
- static async new(e) {
689
- return new x(h.getInstance(), await S.new(e), e);
690
- }
691
- // ---------- Alternative initializers ----------
692
- /**
693
- * Create a Mailbox where the secret identity key is derived from a well-known seed
694
- */
695
- static async fromSeed(e, t) {
696
- const s = await this.new(e);
697
- return t instanceof Uint8Array || (t = o.encode_latin1(t)), await s.keyRing.setCommFromSeed(t), s;
698
- }
699
- /**
700
- * Create a Mailbox from the known secret identity key
701
- */
702
- static async fromSecKey(e, t) {
703
- const s = await this.new(e);
704
- return t instanceof Uint8Array || (t = o.fromBase64(t)), await s.keyRing.setCommFromSecKey(t), s;
705
- }
706
- /**
707
- * Create a Mailbox from the backup string
708
- */
709
- static async fromBackup(e, t) {
710
- return new x(h.getInstance(), await S.fromBackup(e, t), e);
711
- }
712
- // ---------- Relay message commands (public API) ----------
713
- /**
714
- * Sends a free-form object to a guest we already have in our keyring. Set `encrypt` to `false` to
715
- * send a plaintext message. Returns a token that can be used with `messageStatus` command to check
716
- * the status of the message
717
- */
718
- async upload(e, t, s, n = !0) {
719
- const r = await this.prepareRelay(e), a = this.getGuestKey(t), c = n ? await this.encodeMessage(t, s) : s, d = o.toBase64(await this.nacl.h2(o.fromBase64(a))), [g] = await this.runRelayCommand(r, l.upload, { to: d, payload: c });
720
- return g;
721
- }
722
- /**
723
- * Downloads all messages from a relay, decrypts them with a relay key,
724
- * and then parses each message to find out if it's a text message, file message,
725
- * or if it can't be decrypted because HPK is missing in the keyring.
726
- * Returns an array of mixed messages
727
- */
728
- async download(e) {
729
- const t = await this.prepareRelay(e), s = await this.runRelayCommand(t, l.download), n = await this.decryptResponse(t, s), r = [];
730
- for (const a of n) {
731
- const c = this.keyRing.getTagByHpk(a.from);
732
- if (!c)
733
- r.push(await this.parsePlainMessage(a));
734
- else if (a.kind === "message")
735
- r.push(await this.parseTextMessage(a, c));
736
- else if (a.kind === "file")
737
- r.push(await this.parseFileMessage(a, c));
738
- else
739
- throw new Error("[Mailbox] download - Unknown message type");
740
- }
741
- return r;
742
- }
743
- /**
744
- * Marks a raw Zax message as one that can't be decrypted,
745
- * because sender's HPK is not found in the keyring
746
- */
747
- async parsePlainMessage({ data: e, time: t, from: s, nonce: n }) {
748
- return { data: e, time: t, from: s, nonce: n, kind: b.plain };
749
- }
750
- /**
751
- * Decrypts a message that represents uploaded file metadata
752
- */
753
- async parseFileMessage(e, t) {
754
- const { nonce: s, ctext: n, uploadID: r } = JSON.parse(e.data), a = await this.decodeMessage(t, s, n);
755
- if (a === null)
756
- throw new Error("[Mailbox] Failed to decode file message");
757
- return { data: JSON.parse(a), time: e.time, senderTag: t, uploadID: r, nonce: s, kind: b.file };
758
- }
759
- /**
760
- * Attempts to decrypt a regular encrypted Zax message. Returns plain message if it was sent encrypted
761
- */
762
- async parseTextMessage(e, t) {
763
- let s = await this.decodeMessage(t, e.nonce, e.data);
764
- return s || (s = e.data), { data: s, time: e.time, senderTag: t, nonce: e.nonce, kind: b.message };
765
- }
766
- /**
767
- * Returns the number of messages in the mailbox on a given relay
768
- */
769
- async count(e) {
770
- const t = await this.prepareRelay(e), s = await this.runRelayCommand(t, l.count);
771
- return await this.decryptResponse(t, s);
772
- }
773
- /**
774
- * Deletes messages from a relay given a list of base64 message nonces,
775
- * and returns the number of remaining messages
776
- */
777
- async delete(e, t) {
778
- const s = await this.prepareRelay(e), [n] = await this.runRelayCommand(s, l.delete, { payload: t });
779
- return parseInt(n, 10);
780
- }
781
- /**
782
- * Gets the status of a previously sent Zax message by a storage token.
783
- * Returns "time to live" in seconds or a negative value if it's not applicable.
784
- * See `MessageStatusResponse` values for reference
785
- */
786
- async messageStatus(e, t) {
787
- const s = await this.prepareRelay(e), [n] = await this.runRelayCommand(s, l.messageStatus, { token: t });
788
- return parseInt(n, 10);
789
- }
790
- // ---------- Relay file commands (public API) ----------
791
- /**
792
- * Asks Zax to start a new upload session, and returns a unique file identifier
793
- * required to upload file chunks.
794
- */
795
- async startFileUpload(e, t, s) {
796
- const n = await this.prepareRelay(e), r = this.getGuestKey(t), a = o.toBase64(await this.nacl.h2(o.fromBase64(r))), c = await this.nacl.random_bytes(this.nacl.crypto_secretbox_KEYBYTES);
797
- s.skey = o.toBase64(c);
798
- const d = await this.encodeMessage(t, JSON.stringify(s)), g = await this.runRelayCommand(n, l.startFileUpload, {
799
- to: a,
800
- file_size: s.orig_size,
801
- metadata: d
802
- }), m = await this.decryptResponse(n, g);
803
- return m.skey = c, m;
804
- }
805
- /**
806
- * Encrypts the file chunk symmetrically and transfers it to a relay
807
- */
808
- async uploadFileChunk(e, t, s, n, r, a) {
809
- const c = await this.prepareRelay(e), d = await p.encodeMessageSymmetric(s, a), g = await this.runRelayCommand(c, l.uploadFileChunk, {
810
- uploadID: t,
811
- part: n,
812
- last_chunk: r - 1 === n,
813
- // marker of the last chunk, sent only once
814
- nonce: d.nonce
815
- }, d.ctext);
816
- return await this.decryptResponse(c, g);
817
- }
818
- /**
819
- * Returns the status of a file upload by its relay-specific uploadID. Uploader can call it
820
- * to verify the correct transfer, and downloader can check if the file exists and retrieve
821
- * the number of chunks
822
- */
823
- async getFileStatus(e, t) {
824
- const s = await this.prepareRelay(e), n = await this.runRelayCommand(s, l.fileStatus, { uploadID: t });
825
- return await this.decryptResponse(s, n);
826
- }
827
- /**
828
- * Fetches the file metadata by uploadID, which was declared by the uploader
829
- */
830
- async getFileMetadata(e, t) {
831
- return (await this.download(e)).filter((r) => r.kind === "file").find((r) => r.uploadID === t)?.data;
832
- }
833
- /**
834
- * Downloads a binary chunk of a file from a relay by a given uploadID. The total number of chunks
835
- * can be retrieved via a `getFileStatus` request
836
- */
837
- async downloadFileChunk(e, t, s, n) {
838
- n instanceof Uint8Array || (n = o.fromBase64(n));
839
- const r = await this.prepareRelay(e), a = await this.runRelayCommand(r, l.downloadFileChunk, { uploadID: t, part: s }), [c, d, g] = a, m = await r.decodeMessage(c, d);
840
- return await p.decodeMessageSymmetric(m.nonce, g, n);
841
- }
842
- /**
843
- * Deletes a file from the relay (or all chunks uploaded so far, if the upload was not completed).
844
- * Can be called by either the sender or recipient
845
- */
846
- async deleteFile(e, t) {
847
- const s = await this.prepareRelay(e), n = await this.runRelayCommand(s, l.deleteFile, { uploadID: t });
848
- return await this.decryptResponse(s, n);
849
- }
850
- // ---------- Dealing with Relay ----------
851
- /**
852
- * Establishes a session, exchanges temp keys and proves our ownership of this
853
- * Mailbox to this specific relay. This is the first function to start
854
- * communications with any relay. Returns the number of messages in the mailbox
855
- */
856
- async connectToRelay(e) {
857
- const t = this.relayFactory.getInstance(e), s = await t.openConnection(), n = await this.encryptSignature(s), r = await t.prove(await t.encodeMessage(JSON.stringify({
858
- pub_key: this.keyRing.getPubCommKey(),
859
- nonce: n.nonce,
860
- ctext: n.ctext
861
- })));
862
- return parseInt(r, 10);
863
- }
864
- clearSession(e) {
865
- const t = this.relayFactory.getInstance(e);
866
- t.clearToken(), t.clearSession();
867
- }
868
- async encryptSignature(e) {
869
- const t = o.fromBase64(this.keyRing.getPrivateCommKey());
870
- return await p.encodeMessage(e.h2Signature, e.relayPublicKey, t);
871
- }
872
- /**
873
- * Gets a singleton Relay instance, and reconnects to a relay if a previous token has expired
874
- */
875
- async prepareRelay(e) {
876
- const t = this.relayFactory.getInstance(e);
877
- return await this.getRelayConnectionMutex(e).runExclusive(async () => {
878
- t.isConnected || await this.connectToRelay(e);
879
- }), t;
880
- }
881
- /**
882
- * Encrypts the payload of the command and sends it to a relay
883
- */
884
- async runRelayCommand(e, t, s, n) {
885
- s = { cmd: t, ...s };
886
- const r = await this.keyRing.getHpk(), a = await e.encodeMessage(JSON.stringify(s));
887
- return await e.runCmd(t, r, a, n);
888
- }
889
- /**
890
- * Parses relay's response to a command, for those commands that expect an encrypted message in return.
891
- * Two lines of POST response will be nonce and ctext
892
- */
893
- async decryptResponse(e, t) {
894
- const [s, n] = t;
895
- return await e.decodeMessage(s, n);
896
- }
897
- // ---------- Message encoding / decoding ----------
898
- /**
899
- * Encodes `message` to the guest key of a guest already
900
- * added to the keyring
901
- */
902
- async encodeMessage(e, t) {
903
- const s = this.getGuestKey(e), n = this.keyRing.getPrivateCommKey();
904
- return await p.encodeMessage(
905
- await this.nacl.encode_utf8(t),
906
- o.fromBase64(s),
907
- o.fromBase64(n)
908
- );
909
- }
910
- /**
911
- * Decodes a ciphertext from a guest key already in our keyring with this nonce
912
- * @returns null if failed to decode
913
- */
914
- async decodeMessage(e, t, s) {
915
- const n = this.getGuestKey(e), r = this.keyRing.getPrivateCommKey();
916
- let a;
917
- try {
918
- a = o.fromBase64(s);
919
- } catch {
920
- return null;
921
- }
922
- return await p.decodeMessage(
923
- o.fromBase64(t),
924
- a,
925
- o.fromBase64(n),
926
- o.fromBase64(r)
927
- );
928
- }
929
- /**
930
- * Wrapper around `keyring.getGuestKey` that handles unknown guests
931
- */
932
- getGuestKey(e) {
933
- const t = this.keyRing.getGuestKey(e);
934
- if (!t)
935
- throw new Error(`[Mailbox] Unknown guest ${e}`);
936
- return t;
937
- }
938
- // ---------- Destroying Mailbox ----------
939
- /**
940
- * Deletes a Mailbox and all its data from local CryptoStorage. This is a very
941
- * destructive operation, use with caution - it will delete the Mailbox
942
- * keyring along with all stored public keys. To restore that information, you
943
- * will need to do another key exchange with all the guests on your keyring.
944
- */
945
- async selfDestruct() {
946
- await this.keyRing.selfDestruct();
947
- }
948
- getRelayConnectionMutex(e) {
949
- return this.relayConnectionMutexes.has(e) || this.relayConnectionMutexes.set(e, new R()), this.relayConnectionMutexes.get(e);
950
- }
951
- }
952
- class A {
953
- constructor() {
954
- this.storage = {};
955
- }
956
- async get(e) {
957
- return (await this.getMultiple([e]))[0];
958
- }
959
- async getMultiple(e) {
960
- return e.map((t) => this.storage[t]);
961
- }
962
- set(e, t) {
963
- return this.setMultiple({ [e]: t });
964
- }
965
- async setMultiple(e) {
966
- for (const t in e)
967
- this.storage[t] = e[t];
968
- }
969
- remove(e) {
970
- return this.removeMultiple([e]);
971
- }
972
- async removeMultiple(e) {
973
- e.forEach((t) => delete this.storage[t]);
974
- }
975
- reset() {
976
- this.storage = {};
977
- }
978
- }
979
- export {
980
- E as CryptoStorage,
981
- _ as GlowNetworkError,
982
- A as InMemoryStorage,
983
- B as JsNaClDriver,
984
- S as KeyRing,
985
- w as Keys,
986
- M as LocalStorageDriver,
987
- x as Mailbox,
988
- h as NaCl,
989
- N as Relay,
990
- o as Utils,
991
- b as ZaxMessageKind
992
- };
993
- //# sourceMappingURL=glow.es.js.map
719
+ //#endregion
720
+ export { f as CryptoStorage, v as GlowNetworkError, S as InMemoryStorage, o as JsNaClDriver, m as KeyRing, c as Keys, d as LocalStorageDriver, x as Mailbox, s as NaCl, y as Relay, a as Utils, _ as ZaxMessageKind };
721
+
722
+ //# sourceMappingURL=glow.es.js.map