@moltdm/client 1.3.1 → 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.js CHANGED
@@ -30,33 +30,156 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ BrowserStorage: () => BrowserStorage,
34
+ FileStorage: () => FileStorage,
35
+ MemoryStorage: () => MemoryStorage,
33
36
  MoltDMClient: () => MoltDMClient,
34
37
  default: () => index_default
35
38
  });
36
39
  module.exports = __toCommonJS(index_exports);
37
40
  var ed = __toESM(require("@noble/ed25519"));
38
41
  var import_ed25519 = require("@noble/curves/ed25519");
39
- var fs = __toESM(require("fs"));
40
- var path = __toESM(require("path"));
41
- var os = __toESM(require("os"));
42
- var import_crypto = require("crypto");
42
+ var MemoryStorage = class {
43
+ data = /* @__PURE__ */ new Map();
44
+ async get(key) {
45
+ return this.data.get(key) ?? null;
46
+ }
47
+ async set(key, value) {
48
+ this.data.set(key, value);
49
+ }
50
+ async delete(key) {
51
+ this.data.delete(key);
52
+ }
53
+ };
54
+ var BrowserStorage = class {
55
+ prefix;
56
+ constructor(prefix = "moltdm") {
57
+ this.prefix = prefix;
58
+ }
59
+ async get(key) {
60
+ if (typeof localStorage === "undefined") return null;
61
+ return localStorage.getItem(`${this.prefix}:${key}`);
62
+ }
63
+ async set(key, value) {
64
+ if (typeof localStorage === "undefined") return;
65
+ localStorage.setItem(`${this.prefix}:${key}`, value);
66
+ }
67
+ async delete(key) {
68
+ if (typeof localStorage === "undefined") return;
69
+ localStorage.removeItem(`${this.prefix}:${key}`);
70
+ }
71
+ };
72
+ var FileStorage = class {
73
+ basePath;
74
+ _fs = null;
75
+ _path = null;
76
+ _initialized = false;
77
+ constructor(basePath) {
78
+ this.basePath = basePath || ".moltdm";
79
+ }
80
+ async ensureModules() {
81
+ if (this._initialized) return;
82
+ if (typeof window !== "undefined") {
83
+ console.warn("FileStorage is not supported in browser. Use BrowserStorage instead.");
84
+ return;
85
+ }
86
+ try {
87
+ const fs = await import(
88
+ /* webpackIgnore: true */
89
+ "fs"
90
+ );
91
+ const path = await import(
92
+ /* webpackIgnore: true */
93
+ "path"
94
+ );
95
+ const os = await import(
96
+ /* webpackIgnore: true */
97
+ "os"
98
+ );
99
+ this._fs = fs;
100
+ this._path = path;
101
+ if (this.basePath === ".moltdm") {
102
+ const envPath = process.env.OPENCLAW_STATE_DIR;
103
+ this.basePath = envPath ? path.join(envPath, ".moltdm") : path.join(os.homedir(), ".moltdm");
104
+ }
105
+ if (!fs.existsSync(this.basePath)) {
106
+ fs.mkdirSync(this.basePath, { recursive: true });
107
+ }
108
+ this._initialized = true;
109
+ } catch (e) {
110
+ console.error("Failed to load Node.js modules for FileStorage:", e);
111
+ }
112
+ }
113
+ async get(key) {
114
+ await this.ensureModules();
115
+ if (!this._fs) return null;
116
+ const filePath = this._path.join(this.basePath, `${key}.json`);
117
+ if (!this._fs.existsSync(filePath)) return null;
118
+ return this._fs.readFileSync(filePath, "utf-8");
119
+ }
120
+ async set(key, value) {
121
+ await this.ensureModules();
122
+ if (!this._fs) return;
123
+ const filePath = this._path.join(this.basePath, `${key}.json`);
124
+ this._fs.writeFileSync(filePath, value);
125
+ }
126
+ async delete(key) {
127
+ await this.ensureModules();
128
+ if (!this._fs) return;
129
+ const filePath = this._path.join(this.basePath, `${key}.json`);
130
+ if (this._fs.existsSync(filePath)) {
131
+ this._fs.unlinkSync(filePath);
132
+ }
133
+ }
134
+ };
43
135
  function toBase64(bytes) {
44
- return Buffer.from(bytes).toString("base64");
136
+ if (typeof Buffer !== "undefined") {
137
+ return Buffer.from(bytes).toString("base64");
138
+ }
139
+ let binary = "";
140
+ for (let i = 0; i < bytes.length; i++) {
141
+ binary += String.fromCharCode(bytes[i]);
142
+ }
143
+ return btoa(binary);
45
144
  }
46
145
  function fromBase64(str) {
47
- return new Uint8Array(Buffer.from(str, "base64"));
146
+ if (typeof Buffer !== "undefined") {
147
+ return new Uint8Array(Buffer.from(str, "base64"));
148
+ }
149
+ const binary = atob(str);
150
+ const bytes = new Uint8Array(binary.length);
151
+ for (let i = 0; i < binary.length; i++) {
152
+ bytes[i] = binary.charCodeAt(i);
153
+ }
154
+ return bytes;
155
+ }
156
+ async function hmacSha256(key, data) {
157
+ const keyBuffer = new Uint8Array(key).buffer;
158
+ const dataBuffer = new Uint8Array(data).buffer;
159
+ const cryptoKey = await crypto.subtle.importKey(
160
+ "raw",
161
+ keyBuffer,
162
+ { name: "HMAC", hash: "SHA-256" },
163
+ false,
164
+ ["sign"]
165
+ );
166
+ const signature = await crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
167
+ return new Uint8Array(signature);
48
168
  }
49
169
  var MoltDMClient = class {
50
- storagePath;
170
+ storage;
51
171
  relayUrl;
52
172
  identity = null;
53
- // Our sender keys (for messages we send)
54
173
  senderKeys = /* @__PURE__ */ new Map();
55
- // Received sender keys (for messages from others) - keyed by `${convId}:${fromId}`
56
174
  receivedSenderKeys = /* @__PURE__ */ new Map();
57
175
  constructor(options = {}) {
58
- const defaultStoragePath = process.env.OPENCLAW_STATE_DIR ? path.join(process.env.OPENCLAW_STATE_DIR, ".moltdm") : path.join(os.homedir(), ".moltdm");
59
- this.storagePath = options.storagePath || defaultStoragePath;
176
+ if (options.storage) {
177
+ this.storage = options.storage;
178
+ } else if (typeof window !== "undefined" && typeof localStorage !== "undefined") {
179
+ this.storage = new BrowserStorage();
180
+ } else {
181
+ this.storage = new FileStorage(options.storagePath);
182
+ }
60
183
  this.relayUrl = options.relayUrl || "https://relay.moltdm.com";
61
184
  if (options.identity) {
62
185
  this.identity = options.identity;
@@ -88,16 +211,12 @@ var MoltDMClient = class {
88
211
  await this.loadSenderKeys();
89
212
  return;
90
213
  }
91
- if (!fs.existsSync(this.storagePath)) {
92
- fs.mkdirSync(this.storagePath, { recursive: true });
93
- }
94
- const identityPath = path.join(this.storagePath, "identity.json");
95
- if (fs.existsSync(identityPath)) {
96
- const data = fs.readFileSync(identityPath, "utf-8");
97
- this.identity = JSON.parse(data);
214
+ const identityJson = await this.storage.get("identity");
215
+ if (identityJson) {
216
+ this.identity = JSON.parse(identityJson);
98
217
  } else {
99
218
  await this.createIdentity();
100
- fs.writeFileSync(identityPath, JSON.stringify(this.identity, null, 2));
219
+ await this.storage.set("identity", JSON.stringify(this.identity));
101
220
  }
102
221
  await this.loadSenderKeys();
103
222
  }
@@ -149,10 +268,9 @@ var MoltDMClient = class {
149
268
  };
150
269
  }
151
270
  async loadSenderKeys() {
152
- const keysPath = path.join(this.storagePath, "sender_keys.json");
153
- if (fs.existsSync(keysPath)) {
154
- const data = fs.readFileSync(keysPath, "utf-8");
155
- const keys = JSON.parse(data);
271
+ const keysJson = await this.storage.get("sender_keys");
272
+ if (keysJson) {
273
+ const keys = JSON.parse(keysJson);
156
274
  for (const [convId, keyData] of Object.entries(keys)) {
157
275
  const k = keyData;
158
276
  const chainKey = fromBase64(k.chainKey || k.key || "");
@@ -164,10 +282,9 @@ var MoltDMClient = class {
164
282
  });
165
283
  }
166
284
  }
167
- const receivedPath = path.join(this.storagePath, "received_sender_keys.json");
168
- if (fs.existsSync(receivedPath)) {
169
- const data = fs.readFileSync(receivedPath, "utf-8");
170
- const keys = JSON.parse(data);
285
+ const receivedJson = await this.storage.get("received_sender_keys");
286
+ if (receivedJson) {
287
+ const keys = JSON.parse(receivedJson);
171
288
  for (const [key, keyData] of Object.entries(keys)) {
172
289
  const k = keyData;
173
290
  this.receivedSenderKeys.set(key, {
@@ -179,7 +296,6 @@ var MoltDMClient = class {
179
296
  }
180
297
  }
181
298
  async saveSenderKeys() {
182
- const keysPath = path.join(this.storagePath, "sender_keys.json");
183
299
  const obj = {};
184
300
  for (const [convId, keyData] of this.senderKeys) {
185
301
  obj[convId] = {
@@ -189,8 +305,7 @@ var MoltDMClient = class {
189
305
  messageIndex: keyData.messageIndex
190
306
  };
191
307
  }
192
- fs.writeFileSync(keysPath, JSON.stringify(obj, null, 2));
193
- const receivedPath = path.join(this.storagePath, "received_sender_keys.json");
308
+ await this.storage.set("sender_keys", JSON.stringify(obj));
194
309
  const receivedObj = {};
195
310
  for (const [key, keyData] of this.receivedSenderKeys) {
196
311
  receivedObj[key] = {
@@ -199,7 +314,7 @@ var MoltDMClient = class {
199
314
  messageIndex: keyData.messageIndex
200
315
  };
201
316
  }
202
- fs.writeFileSync(receivedPath, JSON.stringify(receivedObj, null, 2));
317
+ await this.storage.set("received_sender_keys", JSON.stringify(receivedObj));
203
318
  }
204
319
  // ============================================
205
320
  // Sender Keys Protocol (Signal-style)
@@ -208,37 +323,25 @@ var MoltDMClient = class {
208
323
  * Derive message key from chain key using HMAC
209
324
  * message_key = HMAC-SHA256(chain_key, 0x01)
210
325
  */
211
- deriveMessageKey(chainKey) {
212
- const keyBuffer = Buffer.from(chainKey);
213
- const hmac = (0, import_crypto.createHmac)("sha256", keyBuffer);
214
- hmac.update(Buffer.from([1]));
215
- const digest = hmac.digest();
216
- const result = new Uint8Array(32);
217
- result.set(new Uint8Array(digest));
218
- return result;
326
+ async deriveMessageKey(chainKey) {
327
+ return hmacSha256(chainKey, new Uint8Array([1]));
219
328
  }
220
329
  /**
221
330
  * Ratchet chain key forward
222
331
  * new_chain_key = HMAC-SHA256(chain_key, 0x02)
223
332
  */
224
- ratchetChainKey(chainKey) {
225
- const keyBuffer = Buffer.from(chainKey);
226
- const hmac = (0, import_crypto.createHmac)("sha256", keyBuffer);
227
- hmac.update(Buffer.from([2]));
228
- const digest = hmac.digest();
229
- const result = new Uint8Array(32);
230
- result.set(new Uint8Array(digest));
231
- return result;
333
+ async ratchetChainKey(chainKey) {
334
+ return hmacSha256(chainKey, new Uint8Array([2]));
232
335
  }
233
336
  /**
234
337
  * Ratchet a chain key forward N steps (for catching up on missed messages)
235
338
  */
236
- ratchetChainKeyN(chainKey, steps) {
339
+ async ratchetChainKeyN(chainKey, steps) {
237
340
  const messageKeys = [];
238
341
  let current = chainKey;
239
342
  for (let i = 0; i < steps; i++) {
240
- messageKeys.push(this.deriveMessageKey(current));
241
- current = this.ratchetChainKey(current);
343
+ messageKeys.push(await this.deriveMessageKey(current));
344
+ current = await this.ratchetChainKey(current);
242
345
  }
243
346
  return { chainKey: current, messageKeys };
244
347
  }
@@ -332,27 +435,24 @@ var MoltDMClient = class {
332
435
  async send(conversationId, content, options) {
333
436
  this.ensureInitialized();
334
437
  let senderKeyState = this.senderKeys.get(conversationId);
335
- const isNewKey = !senderKeyState;
336
438
  if (!senderKeyState) {
337
439
  const initialKey = crypto.getRandomValues(new Uint8Array(32));
338
440
  senderKeyState = {
339
441
  chainKey: initialKey,
340
442
  initialChainKey: new Uint8Array(initialKey),
341
- // Copy for distribution
342
443
  version: 1,
343
444
  messageIndex: 0
344
445
  };
345
446
  this.senderKeys.set(conversationId, senderKeyState);
346
447
  }
347
- const messageKey = this.deriveMessageKey(senderKeyState.chainKey);
448
+ const messageKey = await this.deriveMessageKey(senderKeyState.chainKey);
348
449
  const currentIndex = senderKeyState.messageIndex;
349
- senderKeyState.chainKey = this.ratchetChainKey(senderKeyState.chainKey);
450
+ senderKeyState.chainKey = await this.ratchetChainKey(senderKeyState.chainKey);
350
451
  senderKeyState.messageIndex++;
351
452
  const ciphertext = await this.encrypt(content, messageKey);
352
453
  const encryptedSenderKeys = await this.encryptChainKeyForRecipients(
353
454
  conversationId,
354
455
  senderKeyState.initialChainKey
355
- // Send the original, unratcheted key
356
456
  );
357
457
  const response = await this.fetch(`/api/conversations/${conversationId}/messages`, {
358
458
  method: "POST",
@@ -404,26 +504,23 @@ var MoltDMClient = class {
404
504
  sharedSecretCopy.set(new Uint8Array(sharedSecret));
405
505
  const chainKeyCopy = new Uint8Array(32);
406
506
  chainKeyCopy.set(new Uint8Array(chainKey));
407
- const keyMaterial = await crypto.subtle.importKey(
408
- "raw",
409
- sharedSecretCopy.buffer,
410
- { name: "HKDF" },
411
- false,
412
- ["deriveKey"]
413
- );
507
+ const keyMaterial = await crypto.subtle.importKey("raw", sharedSecretCopy.buffer, { name: "HKDF" }, false, [
508
+ "deriveKey"
509
+ ]);
414
510
  const aesKey = await crypto.subtle.deriveKey(
415
- { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(32), info: new TextEncoder().encode("moltdm-sender-key") },
511
+ {
512
+ name: "HKDF",
513
+ hash: "SHA-256",
514
+ salt: new Uint8Array(32),
515
+ info: new TextEncoder().encode("moltdm-sender-key")
516
+ },
416
517
  keyMaterial,
417
518
  { name: "AES-GCM", length: 256 },
418
519
  false,
419
520
  ["encrypt"]
420
521
  );
421
522
  const iv = crypto.getRandomValues(new Uint8Array(12));
422
- const encrypted = await crypto.subtle.encrypt(
423
- { name: "AES-GCM", iv },
424
- aesKey,
425
- chainKeyCopy.buffer
426
- );
523
+ const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, aesKey, chainKeyCopy.buffer);
427
524
  const combined = new Uint8Array(32 + 12 + encrypted.byteLength);
428
525
  combined.set(ephemeralPublic);
429
526
  combined.set(iv, 32);
@@ -457,17 +554,18 @@ var MoltDMClient = class {
457
554
  ["deriveKey"]
458
555
  );
459
556
  const aesKey = await crypto.subtle.deriveKey(
460
- { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(32), info: new TextEncoder().encode("moltdm-sender-key") },
557
+ {
558
+ name: "HKDF",
559
+ hash: "SHA-256",
560
+ salt: new Uint8Array(32),
561
+ info: new TextEncoder().encode("moltdm-sender-key")
562
+ },
461
563
  keyMaterial,
462
564
  { name: "AES-GCM", length: 256 },
463
565
  false,
464
566
  ["decrypt"]
465
567
  );
466
- const decrypted = await crypto.subtle.decrypt(
467
- { name: "AES-GCM", iv },
468
- aesKey,
469
- encrypted
470
- );
568
+ const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, aesKey, encrypted);
471
569
  return new Uint8Array(decrypted);
472
570
  } catch (e) {
473
571
  console.error("Failed to decrypt chain key:", e);
@@ -482,6 +580,13 @@ var MoltDMClient = class {
482
580
  const { conversationId, fromId, ciphertext, senderKeyVersion, messageIndex, encryptedSenderKeys } = message;
483
581
  const keyId = `${conversationId}:${fromId}`;
484
582
  let receivedKey = this.receivedSenderKeys.get(keyId);
583
+ if (!encryptedSenderKeys) {
584
+ console.error(`[decrypt] Message ${message.id} has no encryptedSenderKeys - sent before Sender Keys`);
585
+ } else if (!encryptedSenderKeys[this.moltbotId]) {
586
+ console.error(
587
+ `[decrypt] Message ${message.id} missing key for ${this.moltbotId}. Available: ${Object.keys(encryptedSenderKeys).join(", ")}`
588
+ );
589
+ }
485
590
  if (encryptedSenderKeys && encryptedSenderKeys[this.moltbotId]) {
486
591
  if (!receivedKey || receivedKey.version !== senderKeyVersion) {
487
592
  const chainKey = await this.decryptChainKey(encryptedSenderKeys[this.moltbotId]);
@@ -493,16 +598,18 @@ var MoltDMClient = class {
493
598
  };
494
599
  this.receivedSenderKeys.set(keyId, receivedKey);
495
600
  await this.saveSenderKeys();
601
+ } else {
602
+ console.error(`[decrypt] Failed to decrypt chain key for ${keyId}`);
496
603
  }
497
604
  }
498
605
  }
499
606
  if (!receivedKey) {
500
- console.error(`No sender key for ${keyId}`);
607
+ console.error(`[decrypt] No sender key for ${keyId}`);
501
608
  return null;
502
609
  }
503
610
  if (messageIndex > receivedKey.messageIndex) {
504
611
  const steps = messageIndex - receivedKey.messageIndex + 1;
505
- const { chainKey, messageKeys } = this.ratchetChainKeyN(receivedKey.chainKey, steps);
612
+ const { chainKey, messageKeys } = await this.ratchetChainKeyN(receivedKey.chainKey, steps);
506
613
  const messageKey = messageKeys[messageKeys.length - 1];
507
614
  receivedKey.chainKey = chainKey;
508
615
  receivedKey.messageIndex = messageIndex + 1;
@@ -510,14 +617,14 @@ var MoltDMClient = class {
510
617
  await this.saveSenderKeys();
511
618
  return this.decrypt(ciphertext, messageKey);
512
619
  } else if (messageIndex === receivedKey.messageIndex) {
513
- const messageKey = this.deriveMessageKey(receivedKey.chainKey);
514
- receivedKey.chainKey = this.ratchetChainKey(receivedKey.chainKey);
620
+ const messageKey = await this.deriveMessageKey(receivedKey.chainKey);
621
+ receivedKey.chainKey = await this.ratchetChainKey(receivedKey.chainKey);
515
622
  receivedKey.messageIndex++;
516
623
  this.receivedSenderKeys.set(keyId, receivedKey);
517
624
  await this.saveSenderKeys();
518
625
  return this.decrypt(ciphertext, messageKey);
519
626
  } else {
520
- console.error(`Message index ${messageIndex} is in the past (current: ${receivedKey.messageIndex})`);
627
+ console.error(`[decrypt] Message index ${messageIndex} is in the past (current: ${receivedKey.messageIndex})`);
521
628
  return null;
522
629
  }
523
630
  }
@@ -542,28 +649,22 @@ var MoltDMClient = class {
542
649
  // ============================================
543
650
  async react(conversationId, messageId, emoji) {
544
651
  this.ensureInitialized();
545
- const response = await this.fetch(
546
- `/api/conversations/${conversationId}/messages/${messageId}/reactions`,
547
- {
548
- method: "POST",
549
- body: JSON.stringify({ emoji })
550
- }
551
- );
652
+ const response = await this.fetch(`/api/conversations/${conversationId}/messages/${messageId}/reactions`, {
653
+ method: "POST",
654
+ body: JSON.stringify({ emoji })
655
+ });
552
656
  const data = await response.json();
553
657
  return data.reaction;
554
658
  }
555
659
  async unreact(conversationId, messageId, emoji) {
556
660
  this.ensureInitialized();
557
- await this.fetch(
558
- `/api/conversations/${conversationId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`,
559
- { method: "DELETE" }
560
- );
661
+ await this.fetch(`/api/conversations/${conversationId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`, {
662
+ method: "DELETE"
663
+ });
561
664
  }
562
665
  async getReactions(conversationId, messageId) {
563
666
  this.ensureInitialized();
564
- const response = await this.fetch(
565
- `/api/conversations/${conversationId}/messages/${messageId}/reactions`
566
- );
667
+ const response = await this.fetch(`/api/conversations/${conversationId}/messages/${messageId}/reactions`);
567
668
  const data = await response.json();
568
669
  return data.reactions;
569
670
  }
@@ -687,9 +788,7 @@ var MoltDMClient = class {
687
788
  const encryptionKeys = {
688
789
  identityKey: this.identity.publicKey,
689
790
  privateKey: this.identity.privateKey,
690
- // Ed25519 private key for signing
691
791
  signedPreKeyPrivate: this.identity.signedPreKey.privateKey,
692
- // X25519 private key for decrypting sender keys
693
792
  senderKeys: senderKeysObj
694
793
  };
695
794
  const response = await this.fetch("/api/pair/approve", {
@@ -729,16 +828,14 @@ var MoltDMClient = class {
729
828
  return data.events;
730
829
  }
731
830
  // ============================================
732
- // Encryption (Simplified for demo)
831
+ // Encryption
733
832
  // ============================================
734
833
  async encrypt(plaintext, key) {
735
834
  const iv = crypto.getRandomValues(new Uint8Array(12));
736
835
  const encoder = new TextEncoder();
737
836
  const data = encoder.encode(plaintext);
738
837
  const keyBuffer = new Uint8Array(key).buffer;
739
- const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, [
740
- "encrypt"
741
- ]);
838
+ const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, ["encrypt"]);
742
839
  const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cryptoKey, data);
743
840
  const combined = new Uint8Array(iv.length + encrypted.byteLength);
744
841
  combined.set(iv);
@@ -750,9 +847,7 @@ var MoltDMClient = class {
750
847
  const iv = combined.slice(0, 12);
751
848
  const encrypted = combined.slice(12);
752
849
  const keyBuffer = new Uint8Array(key).buffer;
753
- const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, [
754
- "decrypt"
755
- ]);
850
+ const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, { name: "AES-GCM" }, false, ["decrypt"]);
756
851
  const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, cryptoKey, encrypted);
757
852
  const decoder = new TextDecoder();
758
853
  return decoder.decode(decrypted);
@@ -765,22 +860,12 @@ var MoltDMClient = class {
765
860
  throw new Error("Not initialized. Call initialize() first.");
766
861
  }
767
862
  }
768
- /**
769
- * Sign a message using Ed25519
770
- */
771
863
  async signMessage(message) {
772
864
  const privateKeyBytes = fromBase64(this.identity.privateKey);
773
- const signature = await ed.signAsync(
774
- new TextEncoder().encode(message),
775
- privateKeyBytes
776
- );
865
+ const signature = await ed.signAsync(new TextEncoder().encode(message), privateKeyBytes);
777
866
  return toBase64(signature);
778
867
  }
779
- /**
780
- * Create the message to sign for a request
781
- * Format: timestamp:method:path:bodyHash
782
- */
783
- async createSignedMessage(timestamp, method, path2, body) {
868
+ async createSignedMessage(timestamp, method, path, body) {
784
869
  let bodyHash = "";
785
870
  if (body) {
786
871
  const bodyBytes = new TextEncoder().encode(body);
@@ -788,18 +873,15 @@ var MoltDMClient = class {
788
873
  const hashArray = Array.from(new Uint8Array(hashBuffer));
789
874
  bodyHash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
790
875
  }
791
- return `${timestamp}:${method}:${path2}:${bodyHash}`;
876
+ return `${timestamp}:${method}:${path}:${bodyHash}`;
792
877
  }
793
- /**
794
- * Make an authenticated fetch request with Ed25519 signature
795
- */
796
- async fetch(path2, options = {}) {
878
+ async fetch(path, options = {}) {
797
879
  const method = options.method || "GET";
798
880
  const body = options.body;
799
881
  const timestamp = Date.now().toString();
800
- const message = await this.createSignedMessage(timestamp, method, path2, body);
882
+ const message = await this.createSignedMessage(timestamp, method, path, body);
801
883
  const signature = await this.signMessage(message);
802
- const response = await fetch(`${this.relayUrl}${path2}`, {
884
+ const response = await fetch(`${this.relayUrl}${path}`, {
803
885
  ...options,
804
886
  headers: {
805
887
  "Content-Type": "application/json",
@@ -819,5 +901,8 @@ var MoltDMClient = class {
819
901
  var index_default = MoltDMClient;
820
902
  // Annotate the CommonJS export names for ESM import in node:
821
903
  0 && (module.exports = {
904
+ BrowserStorage,
905
+ FileStorage,
906
+ MemoryStorage,
822
907
  MoltDMClient
823
908
  });