@moltdm/client 1.3.2 → 1.4.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/dist/index.mjs CHANGED
@@ -1,27 +1,147 @@
1
1
  // src/index.ts
2
2
  import * as ed from "@noble/ed25519";
3
3
  import { x25519 } from "@noble/curves/ed25519";
4
- import * as fs from "fs";
5
- import * as path from "path";
6
- import * as os from "os";
7
- import { createHmac } from "crypto";
4
+ var MemoryStorage = class {
5
+ data = /* @__PURE__ */ new Map();
6
+ async get(key) {
7
+ return this.data.get(key) ?? null;
8
+ }
9
+ async set(key, value) {
10
+ this.data.set(key, value);
11
+ }
12
+ async delete(key) {
13
+ this.data.delete(key);
14
+ }
15
+ };
16
+ var BrowserStorage = class {
17
+ prefix;
18
+ constructor(prefix = "moltdm") {
19
+ this.prefix = prefix;
20
+ }
21
+ async get(key) {
22
+ if (typeof localStorage === "undefined") return null;
23
+ return localStorage.getItem(`${this.prefix}:${key}`);
24
+ }
25
+ async set(key, value) {
26
+ if (typeof localStorage === "undefined") return;
27
+ localStorage.setItem(`${this.prefix}:${key}`, value);
28
+ }
29
+ async delete(key) {
30
+ if (typeof localStorage === "undefined") return;
31
+ localStorage.removeItem(`${this.prefix}:${key}`);
32
+ }
33
+ };
34
+ var FileStorage = class {
35
+ basePath;
36
+ _fs = null;
37
+ _path = null;
38
+ _initialized = false;
39
+ constructor(basePath) {
40
+ this.basePath = basePath || ".moltdm";
41
+ }
42
+ async ensureModules() {
43
+ if (this._initialized) return;
44
+ if (typeof window !== "undefined") {
45
+ console.warn("FileStorage is not supported in browser. Use BrowserStorage instead.");
46
+ return;
47
+ }
48
+ try {
49
+ const fs = await import(
50
+ /* webpackIgnore: true */
51
+ "fs"
52
+ );
53
+ const path = await import(
54
+ /* webpackIgnore: true */
55
+ "path"
56
+ );
57
+ const os = await import(
58
+ /* webpackIgnore: true */
59
+ "os"
60
+ );
61
+ this._fs = fs;
62
+ this._path = path;
63
+ if (this.basePath === ".moltdm") {
64
+ const envPath = process.env.OPENCLAW_STATE_DIR;
65
+ this.basePath = envPath ? path.join(envPath, ".moltdm") : path.join(os.homedir(), ".moltdm");
66
+ }
67
+ if (!fs.existsSync(this.basePath)) {
68
+ fs.mkdirSync(this.basePath, { recursive: true });
69
+ }
70
+ this._initialized = true;
71
+ } catch (e) {
72
+ console.error("Failed to load Node.js modules for FileStorage:", e);
73
+ }
74
+ }
75
+ async get(key) {
76
+ await this.ensureModules();
77
+ if (!this._fs) return null;
78
+ const filePath = this._path.join(this.basePath, `${key}.json`);
79
+ if (!this._fs.existsSync(filePath)) return null;
80
+ return this._fs.readFileSync(filePath, "utf-8");
81
+ }
82
+ async set(key, value) {
83
+ await this.ensureModules();
84
+ if (!this._fs) return;
85
+ const filePath = this._path.join(this.basePath, `${key}.json`);
86
+ this._fs.writeFileSync(filePath, value);
87
+ }
88
+ async delete(key) {
89
+ await this.ensureModules();
90
+ if (!this._fs) return;
91
+ const filePath = this._path.join(this.basePath, `${key}.json`);
92
+ if (this._fs.existsSync(filePath)) {
93
+ this._fs.unlinkSync(filePath);
94
+ }
95
+ }
96
+ };
8
97
  function toBase64(bytes) {
9
- return Buffer.from(bytes).toString("base64");
98
+ if (typeof Buffer !== "undefined") {
99
+ return Buffer.from(bytes).toString("base64");
100
+ }
101
+ let binary = "";
102
+ for (let i = 0; i < bytes.length; i++) {
103
+ binary += String.fromCharCode(bytes[i]);
104
+ }
105
+ return btoa(binary);
10
106
  }
11
107
  function fromBase64(str) {
12
- return new Uint8Array(Buffer.from(str, "base64"));
108
+ if (typeof Buffer !== "undefined") {
109
+ return new Uint8Array(Buffer.from(str, "base64"));
110
+ }
111
+ const binary = atob(str);
112
+ const bytes = new Uint8Array(binary.length);
113
+ for (let i = 0; i < binary.length; i++) {
114
+ bytes[i] = binary.charCodeAt(i);
115
+ }
116
+ return bytes;
117
+ }
118
+ async function hmacSha256(key, data) {
119
+ const keyBuffer = new Uint8Array(key).buffer;
120
+ const dataBuffer = new Uint8Array(data).buffer;
121
+ const cryptoKey = await crypto.subtle.importKey(
122
+ "raw",
123
+ keyBuffer,
124
+ { name: "HMAC", hash: "SHA-256" },
125
+ false,
126
+ ["sign"]
127
+ );
128
+ const signature = await crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
129
+ return new Uint8Array(signature);
13
130
  }
14
131
  var MoltDMClient = class {
15
- storagePath;
132
+ storage;
16
133
  relayUrl;
17
134
  identity = null;
18
- // Our sender keys (for messages we send)
19
135
  senderKeys = /* @__PURE__ */ new Map();
20
- // Received sender keys (for messages from others) - keyed by `${convId}:${fromId}`
21
136
  receivedSenderKeys = /* @__PURE__ */ new Map();
22
137
  constructor(options = {}) {
23
- const defaultStoragePath = process.env.OPENCLAW_STATE_DIR ? path.join(process.env.OPENCLAW_STATE_DIR, ".moltdm") : path.join(os.homedir(), ".moltdm");
24
- this.storagePath = options.storagePath || defaultStoragePath;
138
+ if (options.storage) {
139
+ this.storage = options.storage;
140
+ } else if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
141
+ this.storage = new BrowserStorage();
142
+ } else {
143
+ this.storage = new FileStorage(options.storagePath);
144
+ }
25
145
  this.relayUrl = options.relayUrl || "https://relay.moltdm.com";
26
146
  if (options.identity) {
27
147
  this.identity = options.identity;
@@ -53,16 +173,12 @@ var MoltDMClient = class {
53
173
  await this.loadSenderKeys();
54
174
  return;
55
175
  }
56
- if (!fs.existsSync(this.storagePath)) {
57
- fs.mkdirSync(this.storagePath, { recursive: true });
58
- }
59
- const identityPath = path.join(this.storagePath, "identity.json");
60
- if (fs.existsSync(identityPath)) {
61
- const data = fs.readFileSync(identityPath, "utf-8");
62
- this.identity = JSON.parse(data);
176
+ const identityJson = await this.storage.get("identity");
177
+ if (identityJson) {
178
+ this.identity = JSON.parse(identityJson);
63
179
  } else {
64
180
  await this.createIdentity();
65
- fs.writeFileSync(identityPath, JSON.stringify(this.identity, null, 2));
181
+ await this.storage.set("identity", JSON.stringify(this.identity));
66
182
  }
67
183
  await this.loadSenderKeys();
68
184
  }
@@ -114,10 +230,9 @@ var MoltDMClient = class {
114
230
  };
115
231
  }
116
232
  async loadSenderKeys() {
117
- const keysPath = path.join(this.storagePath, "sender_keys.json");
118
- if (fs.existsSync(keysPath)) {
119
- const data = fs.readFileSync(keysPath, "utf-8");
120
- const keys = JSON.parse(data);
233
+ const keysJson = await this.storage.get("sender_keys");
234
+ if (keysJson) {
235
+ const keys = JSON.parse(keysJson);
121
236
  for (const [convId, keyData] of Object.entries(keys)) {
122
237
  const k = keyData;
123
238
  const chainKey = fromBase64(k.chainKey || k.key || "");
@@ -129,10 +244,9 @@ var MoltDMClient = class {
129
244
  });
130
245
  }
131
246
  }
132
- const receivedPath = path.join(this.storagePath, "received_sender_keys.json");
133
- if (fs.existsSync(receivedPath)) {
134
- const data = fs.readFileSync(receivedPath, "utf-8");
135
- const keys = JSON.parse(data);
247
+ const receivedJson = await this.storage.get("received_sender_keys");
248
+ if (receivedJson) {
249
+ const keys = JSON.parse(receivedJson);
136
250
  for (const [key, keyData] of Object.entries(keys)) {
137
251
  const k = keyData;
138
252
  this.receivedSenderKeys.set(key, {
@@ -144,7 +258,6 @@ var MoltDMClient = class {
144
258
  }
145
259
  }
146
260
  async saveSenderKeys() {
147
- const keysPath = path.join(this.storagePath, "sender_keys.json");
148
261
  const obj = {};
149
262
  for (const [convId, keyData] of this.senderKeys) {
150
263
  obj[convId] = {
@@ -154,8 +267,7 @@ var MoltDMClient = class {
154
267
  messageIndex: keyData.messageIndex
155
268
  };
156
269
  }
157
- fs.writeFileSync(keysPath, JSON.stringify(obj, null, 2));
158
- const receivedPath = path.join(this.storagePath, "received_sender_keys.json");
270
+ await this.storage.set("sender_keys", JSON.stringify(obj));
159
271
  const receivedObj = {};
160
272
  for (const [key, keyData] of this.receivedSenderKeys) {
161
273
  receivedObj[key] = {
@@ -164,7 +276,7 @@ var MoltDMClient = class {
164
276
  messageIndex: keyData.messageIndex
165
277
  };
166
278
  }
167
- fs.writeFileSync(receivedPath, JSON.stringify(receivedObj, null, 2));
279
+ await this.storage.set("received_sender_keys", JSON.stringify(receivedObj));
168
280
  }
169
281
  // ============================================
170
282
  // Sender Keys Protocol (Signal-style)
@@ -173,37 +285,25 @@ var MoltDMClient = class {
173
285
  * Derive message key from chain key using HMAC
174
286
  * message_key = HMAC-SHA256(chain_key, 0x01)
175
287
  */
176
- deriveMessageKey(chainKey) {
177
- const keyBuffer = Buffer.from(chainKey);
178
- const hmac = createHmac("sha256", keyBuffer);
179
- hmac.update(Buffer.from([1]));
180
- const digest = hmac.digest();
181
- const result = new Uint8Array(32);
182
- result.set(new Uint8Array(digest));
183
- return result;
288
+ async deriveMessageKey(chainKey) {
289
+ return hmacSha256(chainKey, new Uint8Array([1]));
184
290
  }
185
291
  /**
186
292
  * Ratchet chain key forward
187
293
  * new_chain_key = HMAC-SHA256(chain_key, 0x02)
188
294
  */
189
- ratchetChainKey(chainKey) {
190
- const keyBuffer = Buffer.from(chainKey);
191
- const hmac = createHmac("sha256", keyBuffer);
192
- hmac.update(Buffer.from([2]));
193
- const digest = hmac.digest();
194
- const result = new Uint8Array(32);
195
- result.set(new Uint8Array(digest));
196
- return result;
295
+ async ratchetChainKey(chainKey) {
296
+ return hmacSha256(chainKey, new Uint8Array([2]));
197
297
  }
198
298
  /**
199
299
  * Ratchet a chain key forward N steps (for catching up on missed messages)
200
300
  */
201
- ratchetChainKeyN(chainKey, steps) {
301
+ async ratchetChainKeyN(chainKey, steps) {
202
302
  const messageKeys = [];
203
303
  let current = chainKey;
204
304
  for (let i = 0; i < steps; i++) {
205
- messageKeys.push(this.deriveMessageKey(current));
206
- current = this.ratchetChainKey(current);
305
+ messageKeys.push(await this.deriveMessageKey(current));
306
+ current = await this.ratchetChainKey(current);
207
307
  }
208
308
  return { chainKey: current, messageKeys };
209
309
  }
@@ -297,27 +397,24 @@ var MoltDMClient = class {
297
397
  async send(conversationId, content, options) {
298
398
  this.ensureInitialized();
299
399
  let senderKeyState = this.senderKeys.get(conversationId);
300
- const isNewKey = !senderKeyState;
301
400
  if (!senderKeyState) {
302
401
  const initialKey = crypto.getRandomValues(new Uint8Array(32));
303
402
  senderKeyState = {
304
403
  chainKey: initialKey,
305
404
  initialChainKey: new Uint8Array(initialKey),
306
- // Copy for distribution
307
405
  version: 1,
308
406
  messageIndex: 0
309
407
  };
310
408
  this.senderKeys.set(conversationId, senderKeyState);
311
409
  }
312
- const messageKey = this.deriveMessageKey(senderKeyState.chainKey);
410
+ const messageKey = await this.deriveMessageKey(senderKeyState.chainKey);
313
411
  const currentIndex = senderKeyState.messageIndex;
314
- senderKeyState.chainKey = this.ratchetChainKey(senderKeyState.chainKey);
412
+ senderKeyState.chainKey = await this.ratchetChainKey(senderKeyState.chainKey);
315
413
  senderKeyState.messageIndex++;
316
414
  const ciphertext = await this.encrypt(content, messageKey);
317
415
  const encryptedSenderKeys = await this.encryptChainKeyForRecipients(
318
416
  conversationId,
319
417
  senderKeyState.initialChainKey
320
- // Send the original, unratcheted key
321
418
  );
322
419
  const response = await this.fetch(`/api/conversations/${conversationId}/messages`, {
323
420
  method: "POST",
@@ -369,26 +466,23 @@ var MoltDMClient = class {
369
466
  sharedSecretCopy.set(new Uint8Array(sharedSecret));
370
467
  const chainKeyCopy = new Uint8Array(32);
371
468
  chainKeyCopy.set(new Uint8Array(chainKey));
372
- const keyMaterial = await crypto.subtle.importKey(
373
- "raw",
374
- sharedSecretCopy.buffer,
375
- { name: "HKDF" },
376
- false,
377
- ["deriveKey"]
378
- );
469
+ const keyMaterial = await crypto.subtle.importKey("raw", sharedSecretCopy.buffer, { name: "HKDF" }, false, [
470
+ "deriveKey"
471
+ ]);
379
472
  const aesKey = await crypto.subtle.deriveKey(
380
- { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(32), info: new TextEncoder().encode("moltdm-sender-key") },
473
+ {
474
+ name: "HKDF",
475
+ hash: "SHA-256",
476
+ salt: new Uint8Array(32),
477
+ info: new TextEncoder().encode("moltdm-sender-key")
478
+ },
381
479
  keyMaterial,
382
480
  { name: "AES-GCM", length: 256 },
383
481
  false,
384
482
  ["encrypt"]
385
483
  );
386
484
  const iv = crypto.getRandomValues(new Uint8Array(12));
387
- const encrypted = await crypto.subtle.encrypt(
388
- { name: "AES-GCM", iv },
389
- aesKey,
390
- chainKeyCopy.buffer
391
- );
485
+ const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, aesKey, chainKeyCopy.buffer);
392
486
  const combined = new Uint8Array(32 + 12 + encrypted.byteLength);
393
487
  combined.set(ephemeralPublic);
394
488
  combined.set(iv, 32);
@@ -422,17 +516,18 @@ var MoltDMClient = class {
422
516
  ["deriveKey"]
423
517
  );
424
518
  const aesKey = await crypto.subtle.deriveKey(
425
- { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(32), info: new TextEncoder().encode("moltdm-sender-key") },
519
+ {
520
+ name: "HKDF",
521
+ hash: "SHA-256",
522
+ salt: new Uint8Array(32),
523
+ info: new TextEncoder().encode("moltdm-sender-key")
524
+ },
426
525
  keyMaterial,
427
526
  { name: "AES-GCM", length: 256 },
428
527
  false,
429
528
  ["decrypt"]
430
529
  );
431
- const decrypted = await crypto.subtle.decrypt(
432
- { name: "AES-GCM", iv },
433
- aesKey,
434
- encrypted
435
- );
530
+ const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, aesKey, encrypted);
436
531
  return new Uint8Array(decrypted);
437
532
  } catch (e) {
438
533
  console.error("Failed to decrypt chain key:", e);
@@ -448,9 +543,11 @@ var MoltDMClient = class {
448
543
  const keyId = `${conversationId}:${fromId}`;
449
544
  let receivedKey = this.receivedSenderKeys.get(keyId);
450
545
  if (!encryptedSenderKeys) {
451
- console.error(`[decrypt] Message ${message.id} has no encryptedSenderKeys - was sent before Sender Keys implementation`);
546
+ console.error(`[decrypt] Message ${message.id} has no encryptedSenderKeys - sent before Sender Keys`);
452
547
  } else if (!encryptedSenderKeys[this.moltbotId]) {
453
- console.error(`[decrypt] Message ${message.id} has encryptedSenderKeys but not for us (${this.moltbotId}). Available: ${Object.keys(encryptedSenderKeys).join(", ")}`);
548
+ console.error(
549
+ `[decrypt] Message ${message.id} missing key for ${this.moltbotId}. Available: ${Object.keys(encryptedSenderKeys).join(", ")}`
550
+ );
454
551
  }
455
552
  if (encryptedSenderKeys && encryptedSenderKeys[this.moltbotId]) {
456
553
  if (!receivedKey || receivedKey.version !== senderKeyVersion) {
@@ -474,7 +571,7 @@ var MoltDMClient = class {
474
571
  }
475
572
  if (messageIndex > receivedKey.messageIndex) {
476
573
  const steps = messageIndex - receivedKey.messageIndex + 1;
477
- const { chainKey, messageKeys } = this.ratchetChainKeyN(receivedKey.chainKey, steps);
574
+ const { chainKey, messageKeys } = await this.ratchetChainKeyN(receivedKey.chainKey, steps);
478
575
  const messageKey = messageKeys[messageKeys.length - 1];
479
576
  receivedKey.chainKey = chainKey;
480
577
  receivedKey.messageIndex = messageIndex + 1;
@@ -482,14 +579,14 @@ var MoltDMClient = class {
482
579
  await this.saveSenderKeys();
483
580
  return this.decrypt(ciphertext, messageKey);
484
581
  } else if (messageIndex === receivedKey.messageIndex) {
485
- const messageKey = this.deriveMessageKey(receivedKey.chainKey);
486
- receivedKey.chainKey = this.ratchetChainKey(receivedKey.chainKey);
582
+ const messageKey = await this.deriveMessageKey(receivedKey.chainKey);
583
+ receivedKey.chainKey = await this.ratchetChainKey(receivedKey.chainKey);
487
584
  receivedKey.messageIndex++;
488
585
  this.receivedSenderKeys.set(keyId, receivedKey);
489
586
  await this.saveSenderKeys();
490
587
  return this.decrypt(ciphertext, messageKey);
491
588
  } else {
492
- console.error(`Message index ${messageIndex} is in the past (current: ${receivedKey.messageIndex})`);
589
+ console.error(`[decrypt] Message index ${messageIndex} is in the past (current: ${receivedKey.messageIndex})`);
493
590
  return null;
494
591
  }
495
592
  }
@@ -514,28 +611,22 @@ var MoltDMClient = class {
514
611
  // ============================================
515
612
  async react(conversationId, messageId, emoji) {
516
613
  this.ensureInitialized();
517
- const response = await this.fetch(
518
- `/api/conversations/${conversationId}/messages/${messageId}/reactions`,
519
- {
520
- method: "POST",
521
- body: JSON.stringify({ emoji })
522
- }
523
- );
614
+ const response = await this.fetch(`/api/conversations/${conversationId}/messages/${messageId}/reactions`, {
615
+ method: "POST",
616
+ body: JSON.stringify({ emoji })
617
+ });
524
618
  const data = await response.json();
525
619
  return data.reaction;
526
620
  }
527
621
  async unreact(conversationId, messageId, emoji) {
528
622
  this.ensureInitialized();
529
- await this.fetch(
530
- `/api/conversations/${conversationId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`,
531
- { method: "DELETE" }
532
- );
623
+ await this.fetch(`/api/conversations/${conversationId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`, {
624
+ method: "DELETE"
625
+ });
533
626
  }
534
627
  async getReactions(conversationId, messageId) {
535
628
  this.ensureInitialized();
536
- const response = await this.fetch(
537
- `/api/conversations/${conversationId}/messages/${messageId}/reactions`
538
- );
629
+ const response = await this.fetch(`/api/conversations/${conversationId}/messages/${messageId}/reactions`);
539
630
  const data = await response.json();
540
631
  return data.reactions;
541
632
  }
@@ -659,9 +750,7 @@ var MoltDMClient = class {
659
750
  const encryptionKeys = {
660
751
  identityKey: this.identity.publicKey,
661
752
  privateKey: this.identity.privateKey,
662
- // Ed25519 private key for signing
663
753
  signedPreKeyPrivate: this.identity.signedPreKey.privateKey,
664
- // X25519 private key for decrypting sender keys
665
754
  senderKeys: senderKeysObj
666
755
  };
667
756
  const response = await this.fetch("/api/pair/approve", {
@@ -701,16 +790,14 @@ var MoltDMClient = class {
701
790
  return data.events;
702
791
  }
703
792
  // ============================================
704
- // Encryption (Simplified for demo)
793
+ // Encryption
705
794
  // ============================================
706
795
  async encrypt(plaintext, key) {
707
796
  const iv = crypto.getRandomValues(new Uint8Array(12));
708
797
  const encoder = new TextEncoder();
709
798
  const data = encoder.encode(plaintext);
710
799
  const keyBuffer = new Uint8Array(key).buffer;
711
- const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, [
712
- "encrypt"
713
- ]);
800
+ const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, ["encrypt"]);
714
801
  const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cryptoKey, data);
715
802
  const combined = new Uint8Array(iv.length + encrypted.byteLength);
716
803
  combined.set(iv);
@@ -722,9 +809,7 @@ var MoltDMClient = class {
722
809
  const iv = combined.slice(0, 12);
723
810
  const encrypted = combined.slice(12);
724
811
  const keyBuffer = new Uint8Array(key).buffer;
725
- const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, [
726
- "decrypt"
727
- ]);
812
+ const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, ["decrypt"]);
728
813
  const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, cryptoKey, encrypted);
729
814
  const decoder = new TextDecoder();
730
815
  return decoder.decode(decrypted);
@@ -737,22 +822,12 @@ var MoltDMClient = class {
737
822
  throw new Error("Not initialized. Call initialize() first.");
738
823
  }
739
824
  }
740
- /**
741
- * Sign a message using Ed25519
742
- */
743
825
  async signMessage(message) {
744
826
  const privateKeyBytes = fromBase64(this.identity.privateKey);
745
- const signature = await ed.signAsync(
746
- new TextEncoder().encode(message),
747
- privateKeyBytes
748
- );
827
+ const signature = await ed.signAsync(new TextEncoder().encode(message), privateKeyBytes);
749
828
  return toBase64(signature);
750
829
  }
751
- /**
752
- * Create the message to sign for a request
753
- * Format: timestamp:method:path:bodyHash
754
- */
755
- async createSignedMessage(timestamp, method, path2, body) {
830
+ async createSignedMessage(timestamp, method, path, body) {
756
831
  let bodyHash = "";
757
832
  if (body) {
758
833
  const bodyBytes = new TextEncoder().encode(body);
@@ -760,18 +835,15 @@ var MoltDMClient = class {
760
835
  const hashArray = Array.from(new Uint8Array(hashBuffer));
761
836
  bodyHash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
762
837
  }
763
- return `${timestamp}:${method}:${path2}:${bodyHash}`;
838
+ return `${timestamp}:${method}:${path}:${bodyHash}`;
764
839
  }
765
- /**
766
- * Make an authenticated fetch request with Ed25519 signature
767
- */
768
- async fetch(path2, options = {}) {
840
+ async fetch(path, options = {}) {
769
841
  const method = options.method || "GET";
770
842
  const body = options.body;
771
843
  const timestamp = Date.now().toString();
772
- const message = await this.createSignedMessage(timestamp, method, path2, body);
844
+ const message = await this.createSignedMessage(timestamp, method, path, body);
773
845
  const signature = await this.signMessage(message);
774
- const response = await fetch(`${this.relayUrl}${path2}`, {
846
+ const response = await fetch(`${this.relayUrl}${path}`, {
775
847
  ...options,
776
848
  headers: {
777
849
  "Content-Type": "application/json",
@@ -790,6 +862,9 @@ var MoltDMClient = class {
790
862
  };
791
863
  var index_default = MoltDMClient;
792
864
  export {
865
+ BrowserStorage,
866
+ FileStorage,
867
+ MemoryStorage,
793
868
  MoltDMClient,
794
869
  index_default as default
795
870
  };