@vex-chat/libvex 5.0.0 → 5.2.0

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/README.md CHANGED
@@ -7,13 +7,12 @@
7
7
  [![Types](https://img.shields.io/npm/types/@vex-chat/libvex?style=flat-square&logo=typescript&color=3178c6)](./dist/index.d.ts)
8
8
  [![Type Coverage](https://img.shields.io/badge/dynamic/json?style=flat-square&label=type-coverage&prefix=%E2%89%A5&suffix=%25&query=$.typeCoverage.atLeast&url=https://raw.githubusercontent.com/vex-protocol/libvex-js/master/package.json&color=3178c6&logo=typescript)](https://github.com/plantain-00/type-coverage)
9
9
  [![Node](https://img.shields.io/node/v/@vex-chat/libvex?style=flat-square&color=339933&logo=nodedotjs)](./package.json)
10
- [![Bundle](https://deno.bundlejs.com/badge?q=@vex-chat/libvex&treeshake=[*])](https://bundlejs.com/?q=@vex-chat/libvex&treeshake=[*])
11
10
  [![OpenSSF Scorecard](https://img.shields.io/ossf-scorecard/github.com/vex-protocol/libvex-js?style=flat-square&label=Scorecard)](https://securityscorecards.dev/viewer/?uri=github.com/vex-protocol/libvex-js)
12
11
  [![Socket](https://socket.dev/api/badge/npm/package/@vex-chat/libvex)](https://socket.dev/npm/package/@vex-chat/libvex)
13
12
 
14
- Reference TypeScript client for the [Vex](https://vex.wtf) encrypted chat platform. Builds against the wire protocol defined in [@vex-chat/types](https://github.com/vex-protocol/types-js) and the cryptographic primitives in [@vex-chat/crypto](https://github.com/vex-protocol/crypto-js). Use it to build a chat client, a bot, or any application that needs to talk to a [spire](https://github.com/vex-protocol/spire) server.
13
+ Reference TypeScript client for the [Vex](https://vex.wtf) protocol. Use it to build a chat client, a bot, or between two clients that need encrypted comms via [spire](https://github.com/vex-protocol/spire) server.
15
14
 
16
- [Documentation](https://vex-chat.github.io/libvex-js/)
15
+ [Documentation](https://lib.vex.wtf/)
17
16
 
18
17
  ## What's in the box
19
18
 
@@ -22,8 +21,7 @@ The client implements an X3DH-style handshake (X25519 DH + KDF), XSalsa20-Poly13
22
21
  - **End-to-end encrypted messaging** with X3DH key agreement — sessions, prekeys, and one-time keys handled internally.
23
22
  - **Tree-shakable subpath exports** for platform-specific code: `./preset/node`, `./preset/test`, `./storage/node`, `./storage/sqlite`, `./storage/schema`, `./keystore/node`, `./keystore/memory`. Browser bundles never pull in `better-sqlite3` or other native modules.
24
23
  - **Pluggable storage backend** via Kysely so node consumers can use SQLite and browser/tauri/expo consumers can wire their own.
25
- - **Pluggable key store** so secrets can live in memory (tests), the OS keychain (`./keystore/node`), or wherever the embedding app keeps them.
26
- - **WebSocket transport** for live message delivery with automatic reconnection and HTTP fallback for the REST API.
24
+ - **Pluggable key store** so secrets can live in memory (tests), passphrase-encrypted files on disk (`./keystore/node`), or wherever the embedding app keeps them.
27
25
 
28
26
  ## Install
29
27
 
@@ -31,7 +29,7 @@ The client implements an X3DH-style handshake (X25519 DH + KDF), XSalsa20-Poly13
31
29
  npm install @vex-chat/libvex
32
30
  ```
33
31
 
34
- `@vex-chat/types`, `@vex-chat/crypto`, `axios`, `kysely`, `winston`, and `zod` are required runtime dependencies and install automatically.
32
+ `@vex-chat/types`, `@vex-chat/crypto`, `axios`, `eventemitter3`, `kysely`, `msgpackr`, `uuid`, and `zod` are required runtime dependencies and install automatically.
35
33
 
36
34
  `better-sqlite3` is an **optional peer dependency** — install it explicitly only if you plan to use the SQLite storage backend on Node:
37
35
 
@@ -46,17 +44,20 @@ Browser, Tauri, and Expo consumers should leave `better-sqlite3` out and supply
46
44
  ```ts
47
45
  import { Client } from "@vex-chat/libvex";
48
46
 
49
- // Generate or load a long-lived secret key — store it in the OS keychain.
47
+ // Generate or load a long-lived secret key.
50
48
  const secretKey = Client.generateSecretKey();
51
49
 
52
50
  const client = await Client.create(secretKey);
53
51
 
54
52
  // First-time devices must register before logging in.
55
- await client.register(Client.randomUsername());
56
- await client.login();
53
+ await client.register("myUsername", "myPassword");
54
+ await client.login("myUsername", "myPassword");
57
55
 
58
- client.on("authed", async () => {
59
- const me = await client.users.me();
56
+ // connect() authenticates the WebSocket and fires "ready" when done.
57
+ await client.connect();
58
+
59
+ client.on("ready", async () => {
60
+ const me = client.me.user();
60
61
  await client.messages.send(me.userID, "Hello world!");
61
62
  });
62
63
 
@@ -70,27 +71,19 @@ client.on("message", (message) => {
70
71
  libvex ships per-platform "presets" that wire together the appropriate storage and keystore:
71
72
 
72
73
  ```ts
73
- // Node — sqlite storage + OS keychain
74
- import {
75
- Client,
76
- makeStorage,
77
- BootstrapConfig,
78
- } from "@vex-chat/libvex/preset/node";
79
-
80
- // Tests / ephemeral — in-memory storage + memory keystore
81
- import {
82
- Client,
83
- makeStorage,
84
- BootstrapConfig,
85
- } from "@vex-chat/libvex/preset/test";
74
+ // Node — sqlite storage + encrypted file keystore
75
+ import { nodePreset } from "@vex-chat/libvex/preset/node";
76
+
77
+ // Tests / ephemeral — in-memory storage, no persistence
78
+ import { testPreset } from "@vex-chat/libvex/preset/test";
86
79
  ```
87
80
 
88
- For a custom platform (browser, tauri, expo), import `Client` from `@vex-chat/libvex` directly and supply your own `Storage` (implementing the schema in `@vex-chat/libvex/storage/schema`) and `KeyStore` to `Client.create`.
81
+ Presets return a `PlatformPreset` with a `createStorage()` factory and a `deviceName`. For a custom platform (browser, tauri, expo), import `Client` from `@vex-chat/libvex` directly and supply your own `Storage` (implementing the schema in `@vex-chat/libvex/storage/schema`) and `KeyStore` to `Client.create`.
89
82
 
90
83
  ## Development
91
84
 
92
85
  ```sh
93
- npm run build # tsc -p tsconfig.build.json
86
+ npm run build # rimraf dist && tsc -p tsconfig.build.json
94
87
  npm run lint # eslint
95
88
  npm run lint:fix # eslint --fix
96
89
  npm run format # prettier --write
@@ -105,7 +98,7 @@ npm run license:check # license allowlist gate
105
98
  npm run docs # typedoc — writes ./docs
106
99
  ```
107
100
 
108
- The unit suite (`npm test`) runs browser-safe and offline. The e2e suite (`npm run test:e2e`) spins up a real spire server in a separate process point `VEX_API_URL` at a running spire if you want to test against a different host.
101
+ The unit suite (`npm test`) runs browser-safe and offline. The e2e suite (`npm run test:e2e`) requires a running spire server — set `VEX_API_URL` to point at it (defaults to `localhost`).
109
102
 
110
103
  See [AGENTS.md](./AGENTS.md) for the release flow (changesets → publish) and the rules for writing changesets.
111
104
 
package/dist/Client.d.ts CHANGED
@@ -55,6 +55,12 @@ export interface ClientOptions {
55
55
  saveHistory?: boolean;
56
56
  /** Use `http/ws` instead of `https/wss`. Intended for local/dev environments. */
57
57
  unsafeHttp?: boolean;
58
+ /**
59
+ * When set (non-empty), sent as `x-dev-api-key` on every HTTP request.
60
+ * Spire omits in-process rate limits when this matches the server's `DEV_API_KEY`
61
+ * (local / load-testing only — never use in production).
62
+ */
63
+ devApiKey?: string;
58
64
  }
59
65
  /**
60
66
  * @ignore
@@ -506,6 +512,13 @@ export declare class Client {
506
512
  private firstMailFetch;
507
513
  private readonly forwarded;
508
514
  private readonly host;
515
+ /**
516
+ * Node-only: per-client HTTP(S) agents (see `init()` + `storage/node/http-agents`).
517
+ * Dropped on `close()` so idle keep-alive sockets do not keep the process alive.
518
+ */
519
+ private nodeHttpAgents?;
520
+ /** Cancels in-flight axios work on `close()` so `postAuth`/`getMail` cannot hang forever. */
521
+ private readonly httpAbortController;
509
522
  private readonly http;
510
523
  private readonly idKeys;
511
524
  private isAlive;
@@ -553,12 +566,24 @@ export declare class Client {
553
566
  static randomUsername(): string;
554
567
  private static deserializeExtra;
555
568
  private static getMnemonic;
569
+ /**
570
+ * True when running under Node (has `process.versions`).
571
+ * Uses indirect lookup so the bare `process` global never appears in
572
+ * source that the platform-guard plugin scans.
573
+ */
574
+ private static isNodeRuntime;
556
575
  /**
557
576
  * Browser-safe NODE_ENV accessor.
558
577
  * Uses indirect lookup so the bare `process` global never appears in
559
578
  * source that the platform-guard plugin scans.
560
579
  */
561
580
  private static getNodeEnv;
581
+ /**
582
+ * Fresh read of the `manuallyClosing` flag for async loops — direct property checks
583
+ * after `await` are flagged as always-false by control-flow analysis even though
584
+ * `close()` can run concurrently.
585
+ */
586
+ private isManualCloseInFlight;
562
587
  /**
563
588
  * Closes the client — disconnects the WebSocket, shuts down storage,
564
589
  * and emits `closed` unless `muteEvent` is `true`.
@@ -700,9 +725,28 @@ export declare class Client {
700
725
  private getSessionList;
701
726
  private getToken;
702
727
  private getUser;
728
+ private deviceListFailureDetail;
729
+ /**
730
+ * Single GET for `/user/:id/devices`. On failure returns `null` (swallows errors)
731
+ * — callers that need reliability should use `fetchUserDeviceListWithBackoff`.
732
+ * Similar “best effort null” patterns elsewhere: `getChannelByID`,
733
+ * `getDeviceByID` (HTTP leg), `getToken`, emoji upload fallbacks.
734
+ */
703
735
  private getUserDeviceList;
736
+ private fetchUserDeviceListOnce;
737
+ /**
738
+ * DM / forward paths need the peer’s (or self) device rows under load: bounded
739
+ * retries with exponential backoff (same shape as session pubkey hydration).
740
+ */
741
+ private fetchUserDeviceListWithBackoff;
704
742
  private getUserList;
705
743
  private handleNotify;
744
+ /**
745
+ * Pipeline for decrypted messages — registered in `init`. After `close()` sets
746
+ * `manuallyClosing`, this becomes a no-op so fire-and-forget `forward` does not
747
+ * race HTTP teardown (we avoid `off()` here — it can interact badly with emit).
748
+ */
749
+ private readonly onInternalMessage;
706
750
  /**
707
751
  * Initializes the keyring. This must be called before anything else.
708
752
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"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"}
package/dist/Client.js CHANGED
@@ -307,6 +307,13 @@ export class Client {
307
307
  firstMailFetch = true;
308
308
  forwarded = new Set();
309
309
  host;
310
+ /**
311
+ * Node-only: per-client HTTP(S) agents (see `init()` + `storage/node/http-agents`).
312
+ * Dropped on `close()` so idle keep-alive sockets do not keep the process alive.
313
+ */
314
+ nodeHttpAgents;
315
+ /** Cancels in-flight axios work on `close()` so `postAuth`/`getMail` cannot hang forever. */
316
+ httpAbortController = new AbortController();
310
317
  http;
311
318
  idKeys;
312
319
  isAlive = true;
@@ -365,7 +372,14 @@ export class Client {
365
372
  this.database.on("error", (_error) => {
366
373
  void this.close(true);
367
374
  });
368
- this.http = axios.create({ responseType: "arraybuffer" });
375
+ this.http = axios.create({
376
+ responseType: "arraybuffer",
377
+ signal: this.httpAbortController.signal,
378
+ });
379
+ const devKey = options?.devApiKey?.trim();
380
+ if (devKey !== undefined && devKey.length > 0) {
381
+ this.http.defaults.headers.common["x-dev-api-key"] = devKey;
382
+ }
369
383
  this.socket = new WebSocketAdapter(this.prefixes.WS + this.host);
370
384
  this.socket.onerror = () => { };
371
385
  }
@@ -440,6 +454,27 @@ export class Client {
440
454
  static getMnemonic(session) {
441
455
  return xMnemonic(xKDF(XUtils.decodeHex(session.fingerprint)));
442
456
  }
457
+ /**
458
+ * True when running under Node (has `process.versions`).
459
+ * Uses indirect lookup so the bare `process` global never appears in
460
+ * source that the platform-guard plugin scans.
461
+ */
462
+ static isNodeRuntime() {
463
+ try {
464
+ const g = Object.getOwnPropertyDescriptor(globalThis, "\u0070rocess");
465
+ if (!g)
466
+ return false;
467
+ const proc = typeof g.get === "function" ? g.get() : g.value;
468
+ if (typeof proc !== "object" || proc === null) {
469
+ return false;
470
+ }
471
+ return ("versions" in proc &&
472
+ typeof proc.versions === "object");
473
+ }
474
+ catch {
475
+ return false;
476
+ }
477
+ }
443
478
  /**
444
479
  * Browser-safe NODE_ENV accessor.
445
480
  * Uses indirect lookup so the bare `process` global never appears in
@@ -476,6 +511,14 @@ export class Client {
476
511
  return undefined;
477
512
  }
478
513
  }
514
+ /**
515
+ * Fresh read of the `manuallyClosing` flag for async loops — direct property checks
516
+ * after `await` are flagged as always-false by control-flow analysis even though
517
+ * `close()` can run concurrently.
518
+ */
519
+ isManualCloseInFlight() {
520
+ return this.manuallyClosing;
521
+ }
479
522
  /**
480
523
  * Closes the client — disconnects the WebSocket, shuts down storage,
481
524
  * and emits `closed` unless `muteEvent` is `true`.
@@ -484,8 +527,14 @@ export class Client {
484
527
  */
485
528
  async close(muteEvent = false) {
486
529
  this.manuallyClosing = true;
530
+ this.httpAbortController.abort();
487
531
  this.socket.close();
488
532
  await this.database.close();
533
+ if (this.nodeHttpAgents) {
534
+ this.nodeHttpAgents.http.destroy();
535
+ this.nodeHttpAgents.https.destroy();
536
+ delete this.nodeHttpAgents;
537
+ }
489
538
  if (this.pingInterval) {
490
539
  clearInterval(this.pingInterval);
491
540
  }
@@ -810,6 +859,9 @@ export class Client {
810
859
  return;
811
860
  }
812
861
  if (!this.xKeyRing) {
862
+ if (this.manuallyClosing) {
863
+ return;
864
+ }
813
865
  throw new Error("Key ring not initialized.");
814
866
  }
815
867
  // my keys
@@ -988,6 +1040,9 @@ export class Client {
988
1040
  }
989
1041
  }
990
1042
  async forward(message) {
1043
+ if (this.isManualCloseInFlight()) {
1044
+ return;
1045
+ }
991
1046
  const copy = { ...message };
992
1047
  if (this.forwarded.has(copy.mailID)) {
993
1048
  return;
@@ -1000,10 +1055,7 @@ export class Client {
1000
1055
  this.forwarded.delete(first);
1001
1056
  }
1002
1057
  const msgBytes = Uint8Array.from(msgpack.encode(copy));
1003
- const devices = await this.getUserDeviceList(this.getUser().userID);
1004
- if (!devices) {
1005
- throw new Error("Couldn't get own devices.");
1006
- }
1058
+ const devices = await this.fetchUserDeviceListWithBackoff(this.getUser().userID, "own");
1007
1059
  const promises = [];
1008
1060
  for (const device of devices) {
1009
1061
  if (device.deviceID !== this.getDevice().deviceID) {
@@ -1074,6 +1126,9 @@ export class Client {
1074
1126
  return messages;
1075
1127
  }
1076
1128
  async getMail() {
1129
+ if (this.manuallyClosing) {
1130
+ return;
1131
+ }
1077
1132
  while (this.fetchingMail) {
1078
1133
  await sleep(500);
1079
1134
  }
@@ -1190,19 +1245,77 @@ export class Client {
1190
1245
  }
1191
1246
  return this.user;
1192
1247
  }
1248
+ deviceListFailureDetail(err) {
1249
+ if (!isAxiosError(err)) {
1250
+ return "";
1251
+ }
1252
+ const st = err.response?.status;
1253
+ if (typeof st === "number") {
1254
+ return ` (HTTP ${String(st)})`;
1255
+ }
1256
+ if (err.code !== undefined) {
1257
+ return ` (${err.code})`;
1258
+ }
1259
+ return "";
1260
+ }
1261
+ /**
1262
+ * Single GET for `/user/:id/devices`. On failure returns `null` (swallows errors)
1263
+ * — callers that need reliability should use `fetchUserDeviceListWithBackoff`.
1264
+ * Similar “best effort null” patterns elsewhere: `getChannelByID`,
1265
+ * `getDeviceByID` (HTTP leg), `getToken`, emoji upload fallbacks.
1266
+ */
1193
1267
  async getUserDeviceList(userID) {
1194
1268
  try {
1195
- const res = await this.http.get(this.getHost() + "/user/" + userID + "/devices");
1196
- const devices = decodeAxios(DeviceArrayCodec, res.data);
1197
- for (const device of devices) {
1198
- this.deviceRecords[device.deviceID] = device;
1199
- }
1200
- return devices;
1269
+ return await this.fetchUserDeviceListOnce(userID);
1201
1270
  }
1202
1271
  catch (_err) {
1203
1272
  return null;
1204
1273
  }
1205
1274
  }
1275
+ async fetchUserDeviceListOnce(userID) {
1276
+ if (this.isManualCloseInFlight()) {
1277
+ return [];
1278
+ }
1279
+ const res = await this.http.get(this.getHost() + "/user/" + userID + "/devices");
1280
+ const devices = decodeAxios(DeviceArrayCodec, res.data);
1281
+ for (const device of devices) {
1282
+ this.deviceRecords[device.deviceID] = device;
1283
+ }
1284
+ return devices;
1285
+ }
1286
+ /**
1287
+ * DM / forward paths need the peer’s (or self) device rows under load: bounded
1288
+ * retries with exponential backoff (same shape as session pubkey hydration).
1289
+ */
1290
+ async fetchUserDeviceListWithBackoff(userID, label) {
1291
+ const base = label === "own"
1292
+ ? "Couldn't get own devices"
1293
+ : "Couldn't get device list";
1294
+ let lastErr;
1295
+ for (let attempt = 0; attempt < 5; attempt++) {
1296
+ if (this.isManualCloseInFlight()) {
1297
+ return [];
1298
+ }
1299
+ if (attempt > 0) {
1300
+ const delayMs = 100 * 2 ** (attempt - 1);
1301
+ // Chunk the delay so close() can finish before we retry HTTP.
1302
+ const chunkMs = 10;
1303
+ for (let elapsed = 0; elapsed < delayMs; elapsed += chunkMs) {
1304
+ if (this.isManualCloseInFlight()) {
1305
+ return [];
1306
+ }
1307
+ await sleep(Math.min(chunkMs, delayMs - elapsed));
1308
+ }
1309
+ }
1310
+ try {
1311
+ return await this.fetchUserDeviceListOnce(userID);
1312
+ }
1313
+ catch (err) {
1314
+ lastErr = err;
1315
+ }
1316
+ }
1317
+ throw new Error(`${base}${this.deviceListFailureDetail(lastErr)}`);
1318
+ }
1206
1319
  async getUserList(channelID) {
1207
1320
  const res = await this.http.post(this.getHost() + "/userList/" + channelID);
1208
1321
  return decodeAxios(UserArrayCodec, res.data);
@@ -1223,6 +1336,24 @@ export class Client {
1223
1336
  break;
1224
1337
  }
1225
1338
  }
1339
+ /**
1340
+ * Pipeline for decrypted messages — registered in `init`. After `close()` sets
1341
+ * `manuallyClosing`, this becomes a no-op so fire-and-forget `forward` does not
1342
+ * race HTTP teardown (we avoid `off()` here — it can interact badly with emit).
1343
+ */
1344
+ onInternalMessage = (message) => {
1345
+ if (this.isManualCloseInFlight()) {
1346
+ return;
1347
+ }
1348
+ if (message.direction === "outgoing" && !message.forward) {
1349
+ void this.forward(message);
1350
+ }
1351
+ if (message.direction === "incoming" &&
1352
+ message.recipient === message.sender) {
1353
+ return;
1354
+ }
1355
+ void this.database.saveMessage(message);
1356
+ };
1226
1357
  /**
1227
1358
  * Initializes the keyring. This must be called before anything else.
1228
1359
  */
@@ -1231,17 +1362,14 @@ export class Client {
1231
1362
  throw new Error("You should only call init() once.");
1232
1363
  }
1233
1364
  this.hasInit = true;
1365
+ if (Client.isNodeRuntime()) {
1366
+ const { attachNodeAgentsToAxios, createNodeHttpAgents } = await import("./storage/node/http-agents.js");
1367
+ const agents = createNodeHttpAgents();
1368
+ this.nodeHttpAgents = agents;
1369
+ attachNodeAgentsToAxios(this.http, agents);
1370
+ }
1234
1371
  await this.populateKeyRing();
1235
- this.emitter.on("message", (message) => {
1236
- if (message.direction === "outgoing" && !message.forward) {
1237
- void this.forward(message);
1238
- }
1239
- if (message.direction === "incoming" &&
1240
- message.recipient === message.sender) {
1241
- return;
1242
- }
1243
- void this.database.saveMessage(message);
1244
- });
1372
+ this.emitter.on("message", this.onInternalMessage);
1245
1373
  this.emitter.emit("ready");
1246
1374
  }
1247
1375
  initSocket() {
@@ -1344,6 +1472,9 @@ export class Client {
1344
1472
  }
1345
1473
  newEphemeralKeys() {
1346
1474
  if (!this.xKeyRing) {
1475
+ if (this.manuallyClosing) {
1476
+ return;
1477
+ }
1347
1478
  throw new Error("Key ring not initialized.");
1348
1479
  }
1349
1480
  this.xKeyRing.ephemeralKeys = xBoxKeyPair();
@@ -1387,6 +1518,9 @@ export class Client {
1387
1518
  async postAuth() {
1388
1519
  let count = 0;
1389
1520
  for (;;) {
1521
+ if (this.isManualCloseInFlight()) {
1522
+ return;
1523
+ }
1390
1524
  try {
1391
1525
  await this.getMail();
1392
1526
  count++;
@@ -1397,7 +1531,17 @@ export class Client {
1397
1531
  }
1398
1532
  }
1399
1533
  catch { }
1400
- await sleep(1000 * 60);
1534
+ if (this.isManualCloseInFlight()) {
1535
+ return;
1536
+ }
1537
+ // Chunk the idle delay so `close()` can unwind instead of waiting
1538
+ // out one full 60s timer (which would keep the process alive).
1539
+ for (let i = 0; i < 60; i++) {
1540
+ if (this.isManualCloseInFlight()) {
1541
+ return;
1542
+ }
1543
+ await sleep(1000);
1544
+ }
1401
1545
  }
1402
1546
  }
1403
1547
  async purgeHistory() {
@@ -1408,6 +1552,9 @@ export class Client {
1408
1552
  return;
1409
1553
  }
1410
1554
  this.seenMailIDs.add(mail.mailID);
1555
+ if (this.manuallyClosing) {
1556
+ return;
1557
+ }
1411
1558
  this.sendReceipt(new Uint8Array(mail.nonce));
1412
1559
  let timeout = 1;
1413
1560
  while (this.reading) {
@@ -1417,6 +1564,9 @@ export class Client {
1417
1564
  this.reading = true;
1418
1565
  try {
1419
1566
  const healSession = async () => {
1567
+ if (this.manuallyClosing || !this.xKeyRing) {
1568
+ return;
1569
+ }
1420
1570
  const deviceEntry = await this.getDeviceByID(mail.sender);
1421
1571
  const [user, _err] = await this.fetchUser(mail.authorID);
1422
1572
  if (deviceEntry && user) {
@@ -1447,7 +1597,7 @@ export class Client {
1447
1597
  const IK_A = IK_A_raw;
1448
1598
  const EK_A = ephKey;
1449
1599
  if (!this.xKeyRing) {
1450
- throw new Error("Key ring not initialized.");
1600
+ return;
1451
1601
  }
1452
1602
  // my private keys
1453
1603
  const IK_B = this.xKeyRing.identityKeys.secretKey;
@@ -1868,17 +2018,7 @@ export class Client {
1868
2018
  if (!userEntry) {
1869
2019
  throw new Error("Couldn't get user entry.");
1870
2020
  }
1871
- let deviceList = await this.getUserDeviceList(userID);
1872
- if (!deviceList) {
1873
- let retries = 0;
1874
- while (!deviceList) {
1875
- deviceList = await this.getUserDeviceList(userID);
1876
- retries++;
1877
- if (retries > 3) {
1878
- throw new Error("Couldn't get device list.");
1879
- }
1880
- }
1881
- }
2021
+ const deviceList = await this.fetchUserDeviceListWithBackoff(userID, "peer");
1882
2022
  const mailID = uuid.v4();
1883
2023
  const promises = [];
1884
2024
  for (const device of deviceList) {