@fileverse/api 0.0.21 → 0.0.23

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
@@ -116,12 +116,7 @@ var init_config = __esm({
116
116
  init_constants();
117
117
  projectEnvPath = path2.join(process.cwd(), "config", ".env");
118
118
  userEnvPath = path2.join(os.homedir(), ".fileverse", ".env");
119
- if (typeof globalThis.process !== "undefined" && typeof globalThis.process.cwd === "function") {
120
- try {
121
- loadConfig(false);
122
- } catch {
123
- }
124
- }
119
+ loadConfig(false);
125
120
  config = {
126
121
  ...STATIC_CONFIG,
127
122
  get SERVICE_NAME() {
@@ -669,9 +664,7 @@ var init_files_model = __esm({
669
664
  linkKey: fileRaw.linkKey,
670
665
  linkKeyNonce: fileRaw.linkKeyNonce,
671
666
  commentKey: fileRaw.commentKey,
672
- link: fileRaw.link,
673
- derivedKey: fileRaw.derivedKey,
674
- secretKey: fileRaw.secretKey
667
+ link: fileRaw.link
675
668
  };
676
669
  }
677
670
  static async findAll(portalAddress, limit, skip) {
@@ -755,20 +748,10 @@ var init_files_model = __esm({
755
748
  const _id = uuidv7();
756
749
  const sql = `
757
750
  INSERT INTO ${this.TABLE}
758
- (_id, title, content, ddocId, portalAddress, linkKey, linkKeyNonce, derivedKey, secretKey)
759
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
751
+ (_id, title, content, ddocId, portalAddress)
752
+ VALUES (?, ?, ?, ?, ?)
760
753
  `;
761
- await QueryBuilder.execute(sql, [
762
- _id,
763
- input.title,
764
- input.content,
765
- input.ddocId,
766
- input.portalAddress,
767
- input.linkKey ?? null,
768
- input.linkKeyNonce ?? null,
769
- input.derivedKey ?? null,
770
- input.secretKey ?? null
771
- ]);
754
+ await QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
772
755
  const created = await this.findById(_id, input.portalAddress);
773
756
  if (!created) {
774
757
  throw new Error("Failed to create file");
@@ -1148,29 +1131,6 @@ var init_events_model = __esm({
1148
1131
  `;
1149
1132
  await QueryBuilder.execute(sql, [Date.now(), _id]);
1150
1133
  }
1151
- static async markSubmitted(_id) {
1152
- const sql = `
1153
- UPDATE ${this.TABLE}
1154
- SET status = 'submitted',
1155
- lockedAt = NULL
1156
- WHERE _id = ?
1157
- `;
1158
- await QueryBuilder.execute(sql, [_id]);
1159
- }
1160
- static async findNextSubmitted(lockedFileIds) {
1161
- const exclusionClause = lockedFileIds.length > 0 ? `AND fileId NOT IN (${lockedFileIds.map(() => "?").join(", ")})` : "";
1162
- const sql = `
1163
- SELECT * FROM ${this.TABLE}
1164
- WHERE status = 'submitted'
1165
- AND userOpHash IS NOT NULL
1166
- ${exclusionClause}
1167
- ORDER BY timestamp ASC
1168
- LIMIT 1
1169
- `;
1170
- const params = [...lockedFileIds];
1171
- const row = await QueryBuilder.selectOne(sql, params);
1172
- return row ? this.parseEvent(row) : void 0;
1173
- }
1174
1134
  static async markProcessed(_id) {
1175
1135
  const sql = `
1176
1136
  UPDATE ${this.TABLE}
@@ -1373,114 +1333,13 @@ var init_key_store = __esm({
1373
1333
  }
1374
1334
  });
1375
1335
 
1376
- // src/sdk/ucan.ts
1377
- import { sign, extractPublicKeyFromSecretKey } from "@stablelib/ed25519";
1378
- import { toUint8Array } from "js-base64";
1379
- function base58btcEncode(bytes) {
1380
- const digits = [0];
1381
- for (const byte of bytes) {
1382
- let carry = byte;
1383
- for (let j = 0; j < digits.length; j++) {
1384
- carry += digits[j] << 8;
1385
- digits[j] = carry % 58;
1386
- carry = carry / 58 | 0;
1387
- }
1388
- while (carry > 0) {
1389
- digits.push(carry % 58);
1390
- carry = carry / 58 | 0;
1391
- }
1392
- }
1393
- let result = "";
1394
- for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
1395
- result += BASE58_ALPHABET[0];
1396
- }
1397
- for (let i = digits.length - 1; i >= 0; i--) {
1398
- result += BASE58_ALPHABET[digits[i]];
1399
- }
1400
- return result;
1401
- }
1402
- function base64urlEncode(data) {
1403
- const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
1404
- let binary = "";
1405
- for (let i = 0; i < bytes.length; i++) {
1406
- binary += String.fromCharCode(bytes[i]);
1407
- }
1408
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1409
- }
1410
- async function buildAndEncode(params) {
1411
- const {
1412
- issuer,
1413
- audience,
1414
- capabilities = [],
1415
- lifetimeInSeconds = 30,
1416
- expiration,
1417
- notBefore,
1418
- facts,
1419
- proofs = []
1420
- } = params;
1421
- const currentTime = Math.floor(Date.now() / 1e3);
1422
- const exp = expiration ?? currentTime + lifetimeInSeconds;
1423
- const header = { alg: issuer.jwtAlg, typ: "JWT", ucv: "0.8.1" };
1424
- const att = capabilities.map((cap) => ({
1425
- with: `${cap.with.scheme}:${cap.with.hierPart}`,
1426
- can: [cap.can.namespace, ...cap.can.segments].join("/")
1427
- }));
1428
- const payload = {
1429
- iss: issuer.did(),
1430
- aud: audience,
1431
- exp,
1432
- att,
1433
- prf: proofs
1434
- };
1435
- if (notBefore !== void 0) payload.nbf = notBefore;
1436
- if (facts !== void 0) payload.fct = facts;
1437
- const encodedHeader = base64urlEncode(JSON.stringify(header));
1438
- const encodedPayload = base64urlEncode(JSON.stringify(payload));
1439
- const signedData = `${encodedHeader}.${encodedPayload}`;
1440
- const sig = await issuer.sign(new TextEncoder().encode(signedData));
1441
- const signature = base64urlEncode(sig);
1442
- return `${signedData}.${signature}`;
1443
- }
1444
- var BASE58_ALPHABET, EDWARDS_DID_PREFIX, EdKeypair;
1445
- var init_ucan = __esm({
1446
- "src/sdk/ucan.ts"() {
1447
- "use strict";
1448
- init_esm_shims();
1449
- BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
1450
- EDWARDS_DID_PREFIX = new Uint8Array([237, 1]);
1451
- EdKeypair = class _EdKeypair {
1452
- jwtAlg = "EdDSA";
1453
- secretKey;
1454
- publicKey;
1455
- constructor(secretKey, publicKey) {
1456
- this.secretKey = secretKey;
1457
- this.publicKey = publicKey;
1458
- }
1459
- static fromSecretKey(key) {
1460
- const secretKey = toUint8Array(key);
1461
- const publicKey = extractPublicKeyFromSecretKey(secretKey);
1462
- return new _EdKeypair(secretKey, publicKey);
1463
- }
1464
- did() {
1465
- const bytes = new Uint8Array(EDWARDS_DID_PREFIX.length + this.publicKey.length);
1466
- bytes.set(EDWARDS_DID_PREFIX);
1467
- bytes.set(this.publicKey, EDWARDS_DID_PREFIX.length);
1468
- return "did:key:z" + base58btcEncode(bytes);
1469
- }
1470
- async sign(msg) {
1471
- return sign(this.secretKey, msg);
1472
- }
1473
- };
1474
- }
1475
- });
1476
-
1477
1336
  // src/sdk/auth-token-provider.ts
1337
+ import * as ucans from "@ucans/ucans";
1478
1338
  var AuthTokenProvider;
1479
1339
  var init_auth_token_provider = __esm({
1480
1340
  "src/sdk/auth-token-provider.ts"() {
1481
1341
  "use strict";
1482
1342
  init_esm_shims();
1483
- init_ucan();
1484
1343
  AuthTokenProvider = class {
1485
1344
  DEFAULT_OPTIONS = {
1486
1345
  namespace: "file",
@@ -1494,7 +1353,7 @@ var init_auth_token_provider = __esm({
1494
1353
  this.portalAddress = portalAddress;
1495
1354
  }
1496
1355
  async getAuthToken(audienceDid, options = this.DEFAULT_OPTIONS) {
1497
- return buildAndEncode({
1356
+ const ucan = await ucans.build({
1498
1357
  audience: audienceDid,
1499
1358
  issuer: this.keyPair,
1500
1359
  lifetimeInSeconds: 7 * 86400,
@@ -1508,6 +1367,7 @@ var init_auth_token_provider = __esm({
1508
1367
  }
1509
1368
  ]
1510
1369
  });
1370
+ return ucans.encode(ucan);
1511
1371
  }
1512
1372
  };
1513
1373
  }
@@ -2675,20 +2535,60 @@ var init_file_encryption = __esm({
2675
2535
  });
2676
2536
 
2677
2537
  // src/sdk/file-utils.ts
2538
+ import { getArgon2idHash } from "@fileverse/crypto/argon";
2678
2539
  import { bytesToBase64, generateRandomBytes as generateRandomBytes2 } from "@fileverse/crypto/utils";
2679
2540
  import { derivePBKDF2Key, encryptAesCBC } from "@fileverse/crypto/kdf";
2680
2541
  import { secretBoxEncrypt } from "@fileverse/crypto/nacl";
2542
+ import hkdf from "futoin-hkdf";
2681
2543
  import tweetnacl from "tweetnacl";
2682
- import { fromUint8Array, toUint8Array as toUint8Array2 } from "js-base64";
2544
+ import { fromUint8Array, toUint8Array } from "js-base64";
2683
2545
  import { toAESKey, aesEncrypt } from "@fileverse/crypto/webcrypto";
2546
+ import axios from "axios";
2684
2547
  import { encodeFunctionData, parseEventLogs } from "viem";
2685
- var jsonToFile, appendAuthTagIvToBlob, encryptFile, getNonceAppendedCipherText, jsonToBytes, buildLinklock, encryptTitleWithFileKey, uploadFileToIPFS, getEditFileTrxCalldata, getAddFileTrxCalldata, prepareCallData, prepareDeleteFileCallData, createEncryptedContentFile, buildFileMetadata, parseFileEventLog, uploadAllFilesToIPFS;
2548
+ var deriveKeyFromAg2Hash, decryptSecretKey, getExistingEncryptionMaterial, getNaclSecretKey, generateLinkKeyMaterial, jsonToFile, appendAuthTagIvToBlob, encryptFile, getNonceAppendedCipherText, jsonToBytes, buildLinklock, encryptTitleWithFileKey, uploadFileToIPFS, getEditFileTrxCalldata, getAddFileTrxCalldata, prepareCallData, prepareDeleteFileCallData, createEncryptedContentFile, buildFileMetadata, parseFileEventLog, uploadAllFilesToIPFS;
2686
2549
  var init_file_utils = __esm({
2687
2550
  "src/sdk/file-utils.ts"() {
2688
2551
  "use strict";
2689
2552
  init_esm_shims();
2690
2553
  init_file_encryption();
2691
2554
  init_constants3();
2555
+ deriveKeyFromAg2Hash = async (pass, salt) => {
2556
+ const key = await getArgon2idHash(pass, salt);
2557
+ return hkdf(Buffer.from(key), tweetnacl.secretbox.keyLength, {
2558
+ info: Buffer.from("encryptionKey")
2559
+ });
2560
+ };
2561
+ decryptSecretKey = async (docId, nonce, encryptedSecretKey) => {
2562
+ const derivedKey = await deriveKeyFromAg2Hash(docId, toUint8Array(nonce));
2563
+ return tweetnacl.secretbox.open(toUint8Array(encryptedSecretKey), toUint8Array(nonce), derivedKey);
2564
+ };
2565
+ getExistingEncryptionMaterial = async (existingEncryptedSecretKey, existingNonce, docId) => {
2566
+ const secretKey = await decryptSecretKey(docId, existingNonce, existingEncryptedSecretKey);
2567
+ return {
2568
+ encryptedSecretKey: existingEncryptedSecretKey,
2569
+ nonce: toUint8Array(existingNonce),
2570
+ secretKey
2571
+ };
2572
+ };
2573
+ getNaclSecretKey = async (ddocId) => {
2574
+ const { secretKey } = tweetnacl.box.keyPair();
2575
+ const nonce = tweetnacl.randomBytes(tweetnacl.secretbox.nonceLength);
2576
+ const derivedKey = await deriveKeyFromAg2Hash(ddocId, nonce);
2577
+ const encryptedSecretKey = fromUint8Array(tweetnacl.secretbox(secretKey, nonce, derivedKey), true);
2578
+ return { nonce, encryptedSecretKey, secretKey };
2579
+ };
2580
+ generateLinkKeyMaterial = async (params) => {
2581
+ if (params.linkKeyNonce && params.linkKey) {
2582
+ const { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2 } = await getExistingEncryptionMaterial(
2583
+ params.linkKey,
2584
+ params.linkKeyNonce,
2585
+ params.ddocId
2586
+ );
2587
+ if (secretKey2) return { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2 };
2588
+ }
2589
+ const { secretKey, nonce, encryptedSecretKey } = await getNaclSecretKey(params.ddocId);
2590
+ return { secretKey, nonce, encryptedSecretKey };
2591
+ };
2692
2592
  jsonToFile = (json2, fileName) => {
2693
2593
  const blob = new Blob([JSON.stringify(json2)], {
2694
2594
  type: "application/json"
@@ -2718,8 +2618,8 @@ var init_file_utils = __esm({
2718
2618
  const encryptedBlob = new Blob([ciphertext], { type: file2.type });
2719
2619
  const encryptedBlobWithAuthTagIv = await appendAuthTagIvToBlob(
2720
2620
  encryptedBlob,
2721
- toUint8Array2(authTag),
2722
- toUint8Array2(iv)
2621
+ toUint8Array(authTag),
2622
+ toUint8Array(iv)
2723
2623
  );
2724
2624
  return {
2725
2625
  encryptedFile: new File([encryptedBlobWithAuthTagIv], file2.name),
@@ -2765,7 +2665,7 @@ var init_file_utils = __esm({
2765
2665
  };
2766
2666
  };
2767
2667
  encryptTitleWithFileKey = async (args) => {
2768
- const key = await toAESKey(toUint8Array2(args.key));
2668
+ const key = await toAESKey(toUint8Array(args.key));
2769
2669
  if (!key) throw new Error("Key is undefined");
2770
2670
  const titleBytes = new TextEncoder().encode(args.title);
2771
2671
  const encryptedTitle = await aesEncrypt(key, titleBytes, "base64");
@@ -2779,21 +2679,16 @@ var init_file_utils = __esm({
2779
2679
  body.append("ipfsType", ipfsType);
2780
2680
  body.append("appFileId", appFileId);
2781
2681
  body.append("sourceApp", "ddoc");
2782
- const response = await fetch(UPLOAD_SERVER_URL + "upload", {
2783
- method: "POST",
2682
+ const uploadEndpoint = UPLOAD_SERVER_URL + "upload";
2683
+ const response = await axios.post(uploadEndpoint, body, {
2784
2684
  headers: {
2785
2685
  Authorization: `Bearer ${token}`,
2786
2686
  contract: contractAddress,
2787
2687
  invoker,
2788
- chain: NETWORK_NAME
2789
- },
2790
- body
2688
+ chain: process.env.chainId
2689
+ }
2791
2690
  });
2792
- if (!response.ok) {
2793
- throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
2794
- }
2795
- const data = await response.json();
2796
- return data.ipfsHash;
2691
+ return response.data.ipfsHash;
2797
2692
  };
2798
2693
  getEditFileTrxCalldata = (args) => {
2799
2694
  return encodeFunctionData({
@@ -2888,7 +2783,7 @@ var init_file_utils = __esm({
2888
2783
  });
2889
2784
 
2890
2785
  // src/sdk/file-manager.ts
2891
- import { fromUint8Array as fromUint8Array2, toUint8Array as toUint8Array3 } from "js-base64";
2786
+ import { fromUint8Array as fromUint8Array2, toUint8Array as toUint8Array2 } from "js-base64";
2892
2787
  import { generateAESKey, exportAESKey } from "@fileverse/crypto/webcrypto";
2893
2788
  import { markdownToYjs } from "@fileverse/content-processor";
2894
2789
  var FileManager;
@@ -2909,8 +2804,8 @@ var init_file_manager = __esm({
2909
2804
  }
2910
2805
  createLocks(key, encryptedSecretKey, commentKey) {
2911
2806
  const appLock = {
2912
- lockedFileKey: this.keyStore.encryptData(toUint8Array3(key)),
2913
- lockedLinkKey: this.keyStore.encryptData(toUint8Array3(encryptedSecretKey)),
2807
+ lockedFileKey: this.keyStore.encryptData(toUint8Array2(key)),
2808
+ lockedLinkKey: this.keyStore.encryptData(toUint8Array2(encryptedSecretKey)),
2914
2809
  lockedChatKey: this.keyStore.encryptData(commentKey)
2915
2810
  };
2916
2811
  return { appLock, ownerLock: { ...appLock } };
@@ -2944,28 +2839,22 @@ var init_file_manager = __esm({
2944
2839
  return this.agentClient.getAuthParams();
2945
2840
  }
2946
2841
  async submitAddFileTrx(file2) {
2947
- console.log("Submitting add file trx");
2948
2842
  logger.debug(`Preparing to add file ${file2.ddocId}`);
2949
- const encryptedSecretKey = file2.linkKey;
2950
- const nonce = toUint8Array3(file2.linkKeyNonce);
2951
- const secretKey = toUint8Array3(file2.secretKey);
2952
- console.log("Got encrypted secret key, nonce, and secret key");
2843
+ const { encryptedSecretKey, nonce, secretKey } = await generateLinkKeyMaterial({
2844
+ ddocId: file2.ddocId,
2845
+ linkKey: file2.linkKey,
2846
+ linkKeyNonce: file2.linkKeyNonce
2847
+ });
2953
2848
  const yJSContent = markdownToYjs(file2.content);
2954
- console.log("Generated yjs content");
2955
2849
  const { encryptedFile, key } = await createEncryptedContentFile(yJSContent);
2956
- console.log("Generated encrypted content file");
2957
2850
  logger.debug(`Generated encrypted content file for file ${file2.ddocId}`);
2958
2851
  const commentKey = await exportAESKey(await generateAESKey(128));
2959
- console.log("Generated comment key");
2960
2852
  const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
2961
- console.log("Built app lock and owner lock");
2962
- const linkLock = buildLinklock(secretKey, toUint8Array3(key), commentKey);
2963
- console.log("Built link lock");
2853
+ const linkLock = buildLinklock(secretKey, toUint8Array2(key), commentKey);
2964
2854
  const encryptedTitle = await encryptTitleWithFileKey({
2965
2855
  title: file2.title || "Untitled",
2966
2856
  key
2967
2857
  });
2968
- console.log("Built encrypted title");
2969
2858
  const metadata = buildFileMetadata({
2970
2859
  encryptedTitle,
2971
2860
  encryptedFileSize: encryptedFile.size,
@@ -2975,15 +2864,11 @@ var init_file_manager = __esm({
2975
2864
  nonce: fromUint8Array2(nonce),
2976
2865
  owner: this.agentClient.getAgentAddress()
2977
2866
  });
2978
- console.log("Built metadata");
2979
2867
  const authParams = await this.getAuthParams();
2980
- console.log("Got auth params");
2981
- console.log("Uploading files to IPFS");
2982
2868
  const { metadataHash, contentHash, gateHash } = await uploadAllFilesToIPFS(
2983
2869
  { metadata, encryptedFile, linkLock, ddocId: file2.ddocId },
2984
2870
  authParams
2985
2871
  );
2986
- console.log("Uploaded files to IPFS");
2987
2872
  logger.debug(`Uploaded files to IPFS for file ${file2.ddocId}`);
2988
2873
  const callData = prepareCallData({
2989
2874
  metadataHash,
@@ -2992,10 +2877,8 @@ var init_file_manager = __esm({
2992
2877
  appFileId: file2.ddocId,
2993
2878
  fileId: file2.fileId
2994
2879
  });
2995
- console.log("Prepared call data");
2996
2880
  logger.debug(`Prepared call data for file ${file2.ddocId}`);
2997
2881
  const userOpHash = await this.sendFileOperation(callData);
2998
- console.log("Submitted user op");
2999
2882
  logger.debug(`Submitted user op for file ${file2.ddocId}`);
3000
2883
  return {
3001
2884
  userOpHash,
@@ -3005,65 +2888,19 @@ var init_file_manager = __esm({
3005
2888
  metadata
3006
2889
  };
3007
2890
  }
3008
- async submitUpdateFile(file2) {
3009
- logger.debug(`Submitting update for file ${file2.ddocId} with onChainFileId ${file2.onChainFileId}`);
3010
- const encryptedSecretKey = file2.linkKey;
3011
- const nonce = toUint8Array3(file2.linkKeyNonce);
3012
- const secretKey = toUint8Array3(file2.secretKey);
3013
- const yjsContent = markdownToYjs(file2.content);
3014
- const { encryptedFile, key } = await createEncryptedContentFile(yjsContent);
3015
- const commentKey = toUint8Array3(file2.commentKey);
3016
- const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
3017
- const linkLock = buildLinklock(secretKey, toUint8Array3(key), commentKey);
3018
- const encryptedTitle = await encryptTitleWithFileKey({
3019
- title: file2.title || "Untitled",
3020
- key
3021
- });
3022
- const metadata = buildFileMetadata({
3023
- encryptedTitle,
3024
- encryptedFileSize: encryptedFile.size,
3025
- appLock,
3026
- ownerLock,
3027
- ddocId: file2.ddocId,
3028
- nonce: fromUint8Array2(nonce),
3029
- owner: this.agentClient.getAgentAddress()
3030
- });
3031
- const authParams = await this.getAuthParams();
3032
- const { metadataHash, contentHash, gateHash } = await uploadAllFilesToIPFS(
3033
- { metadata, encryptedFile, linkLock, ddocId: file2.ddocId },
3034
- authParams
3035
- );
3036
- const callData = prepareCallData({
3037
- metadataHash,
3038
- contentHash,
3039
- gateHash,
3040
- appFileId: file2.ddocId,
3041
- fileId: file2.onChainFileId
3042
- });
3043
- const userOpHash = await this.sendFileOperation(callData);
3044
- logger.debug(`Submitted update user op for file ${file2.ddocId}`);
3045
- return { userOpHash, metadata };
3046
- }
3047
- async submitDeleteFile(file2) {
3048
- logger.debug(`Submitting delete for file ${file2.ddocId} with onChainFileId ${file2.onChainFileId}`);
3049
- const callData = prepareDeleteFileCallData({
3050
- onChainFileId: file2.onChainFileId
3051
- });
3052
- const userOpHash = await this.sendFileOperation(callData);
3053
- logger.debug(`Submitted delete user op for file ${file2.ddocId}`);
3054
- return { userOpHash };
3055
- }
3056
2891
  async updateFile(file2) {
3057
2892
  logger.debug(`Updating file ${file2.ddocId} with onChainFileId ${file2.onChainFileId}`);
3058
- const encryptedSecretKey = file2.linkKey;
3059
- const nonce = toUint8Array3(file2.linkKeyNonce);
3060
- const secretKey = toUint8Array3(file2.secretKey);
2893
+ const { encryptedSecretKey, nonce, secretKey } = await generateLinkKeyMaterial({
2894
+ ddocId: file2.ddocId,
2895
+ linkKey: file2.linkKey,
2896
+ linkKeyNonce: file2.linkKeyNonce
2897
+ });
3061
2898
  logger.debug(`Generating encrypted content file for file ${file2.ddocId} with onChainFileId ${file2.onChainFileId}`);
3062
2899
  const yjsContent = markdownToYjs(file2.content);
3063
2900
  const { encryptedFile, key } = await createEncryptedContentFile(yjsContent);
3064
- const commentKey = toUint8Array3(file2.commentKey);
2901
+ const commentKey = toUint8Array2(file2.commentKey);
3065
2902
  const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
3066
- const linkLock = buildLinklock(secretKey, toUint8Array3(key), commentKey);
2903
+ const linkLock = buildLinklock(secretKey, toUint8Array2(key), commentKey);
3067
2904
  const encryptedTitle = await encryptTitleWithFileKey({
3068
2905
  title: file2.title || "Untitled",
3069
2906
  key
@@ -3115,10 +2952,11 @@ var init_file_manager = __esm({
3115
2952
  });
3116
2953
 
3117
2954
  // src/domain/portal/publish.ts
3118
- import { fromUint8Array as fromUint8Array3, toUint8Array as toUint8Array4 } from "js-base64";
2955
+ import { fromUint8Array as fromUint8Array3, toUint8Array as toUint8Array3 } from "js-base64";
3119
2956
  import { stringToBytes } from "viem";
3120
2957
  import { deriveHKDFKey } from "@fileverse/crypto/kdf";
3121
2958
  import { generateKeyPairFromSeed } from "@stablelib/ed25519";
2959
+ import * as ucans2 from "@ucans/ucans";
3122
2960
  async function getPortalData(fileId) {
3123
2961
  const file2 = await FilesModel.findByIdIncludingDeleted(fileId);
3124
2962
  if (!file2) {
@@ -3150,23 +2988,17 @@ var init_publish = __esm({
3150
2988
  init_infra();
3151
2989
  init_key_store();
3152
2990
  init_auth_token_provider();
3153
- init_ucan();
3154
2991
  init_smart_agent();
3155
2992
  init_file_manager();
3156
2993
  init_config();
3157
- init_pimlico_utils();
3158
2994
  createFileManager = async (portalSeed, portalAddress, ucanSecret, privateAccountKey) => {
3159
- console.log("Creating file manager");
3160
- const keyPair = EdKeypair.fromSecretKey(fromUint8Array3(ucanSecret));
3161
- console.log("Created key pair");
2995
+ const keyPair = ucans2.EdKeypair.fromSecretKey(fromUint8Array3(ucanSecret), {
2996
+ exportable: true
2997
+ });
3162
2998
  const authTokenProvider = new AuthTokenProvider(keyPair, portalAddress);
3163
- console.log("Created auth token provider");
3164
- const keyStore = new KeyStore(toUint8Array4(portalSeed), portalAddress, authTokenProvider);
3165
- console.log("Created key store");
2999
+ const keyStore = new KeyStore(toUint8Array3(portalSeed), portalAddress, authTokenProvider);
3166
3000
  const agentClient = new AgentClient(authTokenProvider);
3167
- console.log("Created agent client");
3168
3001
  await agentClient.initializeAgentClient(privateAccountKey);
3169
- console.log("Initialized agent client");
3170
3002
  return new FileManager(keyStore, agentClient);
3171
3003
  };
3172
3004
  executeOperation = async (fileManager, file2, operation) => {
@@ -3183,7 +3015,7 @@ var init_publish = __esm({
3183
3015
  handleExistingFileOp = async (fileId, operation) => {
3184
3016
  try {
3185
3017
  const { file: file2, portalDetails, apiKey } = await getPortalData(fileId);
3186
- const apiKeySeed = toUint8Array4(apiKey);
3018
+ const apiKeySeed = toUint8Array3(apiKey);
3187
3019
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
3188
3020
  const fileManager = await createFileManager(
3189
3021
  portalDetails.portalSeed,
@@ -3199,22 +3031,19 @@ var init_publish = __esm({
3199
3031
  };
3200
3032
  handleNewFileOp = async (fileId) => {
3201
3033
  const { file: file2, portalDetails, apiKey } = await getPortalData(fileId);
3202
- console.log("Got portal data");
3203
- const apiKeySeed = toUint8Array4(apiKey);
3034
+ const apiKeySeed = toUint8Array3(apiKey);
3204
3035
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
3205
- console.log("Derived collaborator keys");
3206
3036
  const fileManager = await createFileManager(
3207
3037
  portalDetails.portalSeed,
3208
3038
  portalDetails.portalAddress,
3209
3039
  ucanSecret,
3210
3040
  privateAccountKey
3211
3041
  );
3212
- console.log("Created file manager");
3213
3042
  return fileManager.submitAddFileTrx(file2);
3214
3043
  };
3215
3044
  getProxyAuthParams = async (fileId) => {
3216
3045
  const { portalDetails, apiKey } = await getPortalData(fileId);
3217
- const apiKeySeed = toUint8Array4(apiKey);
3046
+ const apiKeySeed = toUint8Array3(apiKey);
3218
3047
  const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
3219
3048
  const fileManager = await createFileManager(
3220
3049
  portalDetails.portalSeed,
@@ -3736,9 +3565,7 @@ CREATE TABLE IF NOT EXISTS files (
3736
3565
  commentKey TEXT,
3737
3566
  linkKey TEXT,
3738
3567
  linkKeyNonce TEXT,
3739
- link TEXT,
3740
- derivedKey TEXT,
3741
- secretKey TEXT
3568
+ link TEXT
3742
3569
  );
3743
3570
  CREATE INDEX IF NOT EXISTS idx_files_createdAt ON files(createdAt);
3744
3571
  CREATE INDEX IF NOT EXISTS idx_files_syncStatus ON files(syncStatus);
@@ -3769,7 +3596,7 @@ CREATE TABLE IF NOT EXISTS events (
3769
3596
  type TEXT NOT NULL CHECK (type IN ('create', 'update', 'delete')),
3770
3597
  timestamp BIGINT NOT NULL,
3771
3598
  fileId TEXT NOT NULL,
3772
- status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'submitted', 'processed', 'failed')),
3599
+ status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'processed', 'failed')),
3773
3600
  retryCount INTEGER NOT NULL DEFAULT 0,
3774
3601
  lastError TEXT,
3775
3602
  lockedAt BIGINT,
@@ -3819,17 +3646,30 @@ init_esm_shims();
3819
3646
  // src/cli/fetch-api-key.ts
3820
3647
  init_esm_shims();
3821
3648
  init_constants();
3822
- import { toUint8Array as toUint8Array5 } from "js-base64";
3649
+ import axios2 from "axios";
3650
+ import { toUint8Array as toUint8Array4 } from "js-base64";
3823
3651
  import { sha256 } from "viem";
3824
3652
  var fetchApiKeyData = async (apiKey) => {
3825
3653
  try {
3826
- const keyHash = sha256(toUint8Array5(apiKey));
3654
+ const keyHash = sha256(toUint8Array4(apiKey));
3827
3655
  const fullUrl = BASE_CONFIG.API_URL + `api-access/${keyHash}`;
3828
- const response = await fetch(fullUrl);
3829
- const { encryptedKeyMaterial, encryptedAppMaterial, id } = await response.json();
3656
+ const response = await axios2.get(fullUrl);
3657
+ const { encryptedKeyMaterial, encryptedAppMaterial, id } = response.data;
3830
3658
  return { encryptedKeyMaterial, encryptedAppMaterial, id };
3831
3659
  } catch (error48) {
3832
- throw new Error(`Server error: ${error48.message}`);
3660
+ if (axios2.isAxiosError(error48)) {
3661
+ if (error48.response?.status === 401) {
3662
+ throw new Error("Invalid API key");
3663
+ }
3664
+ if (error48.response?.status === 404) {
3665
+ throw new Error("API key not found");
3666
+ }
3667
+ if (error48.code === "ECONNREFUSED") {
3668
+ throw new Error(`Cannot connect to server at ${BASE_CONFIG.API_URL}`);
3669
+ }
3670
+ throw new Error(`Server error: ${error48.response?.data?.message || error48.message}`);
3671
+ }
3672
+ throw error48;
3833
3673
  }
3834
3674
  };
3835
3675
 
@@ -3839,7 +3679,7 @@ init_saveApiKey();
3839
3679
  init_apikeys_model();
3840
3680
  init_infra();
3841
3681
  import { deriveHKDFKey as deriveHKDFKey2 } from "@fileverse/crypto/hkdf";
3842
- import { toUint8Array as toUint8Array6 } from "js-base64";
3682
+ import { toUint8Array as toUint8Array5 } from "js-base64";
3843
3683
  import { stringToBytes as stringToBytes2 } from "viem";
3844
3684
  import { toAESKey as toAESKey2, aesDecrypt } from "@fileverse/crypto/webcrypto";
3845
3685
  var SAVED_DATA_ENCRYPTION_KEY_INFO = "SAVED_DATA_ENCRYPTION_KEY";
@@ -3864,7 +3704,7 @@ async function initializeWithData(data) {
3864
3704
  }
3865
3705
  var getAesKeyFromApiKey = async (apiKey) => {
3866
3706
  const rawSecret = deriveHKDFKey2(
3867
- toUint8Array6(apiKey),
3707
+ toUint8Array5(apiKey),
3868
3708
  new Uint8Array([0]),
3869
3709
  stringToBytes2(SAVED_DATA_ENCRYPTION_KEY_INFO)
3870
3710
  );
@@ -3875,7 +3715,7 @@ var bytestToJSON = (bytes) => {
3875
3715
  };
3876
3716
  var decryptSavedData = async (apiKey, encryptedData) => {
3877
3717
  const aesKey = await getAesKeyFromApiKey(apiKey);
3878
- const decryptedBytes = await aesDecrypt(aesKey, toUint8Array6(encryptedData));
3718
+ const decryptedBytes = await aesDecrypt(aesKey, toUint8Array5(encryptedData));
3879
3719
  const data = bytestToJSON(decryptedBytes);
3880
3720
  return data;
3881
3721
  };
@@ -3920,55 +3760,6 @@ init_esm_shims();
3920
3760
  init_models();
3921
3761
  init_constants2();
3922
3762
  import { generate } from "short-uuid";
3923
- import { fromUint8Array as fromUint8Array5 } from "js-base64";
3924
-
3925
- // src/sdk/link-key-utils.ts
3926
- init_esm_shims();
3927
- import { getArgon2idHash } from "@fileverse/crypto/argon";
3928
- import hkdf from "futoin-hkdf";
3929
- import tweetnacl2 from "tweetnacl";
3930
- import { fromUint8Array as fromUint8Array4, toUint8Array as toUint8Array7 } from "js-base64";
3931
- var deriveKeyFromAg2Hash = async (pass, salt) => {
3932
- const key = await getArgon2idHash(pass, salt);
3933
- return hkdf(Buffer.from(key), tweetnacl2.secretbox.keyLength, {
3934
- info: Buffer.from("encryptionKey")
3935
- });
3936
- };
3937
- var getExistingEncryptionMaterial = async (existingEncryptedSecretKey, existingNonce, docId) => {
3938
- const derivedKey = await deriveKeyFromAg2Hash(docId, toUint8Array7(existingNonce));
3939
- const secretKey = tweetnacl2.secretbox.open(
3940
- toUint8Array7(existingEncryptedSecretKey),
3941
- toUint8Array7(existingNonce),
3942
- derivedKey
3943
- );
3944
- return {
3945
- encryptedSecretKey: existingEncryptedSecretKey,
3946
- nonce: toUint8Array7(existingNonce),
3947
- secretKey,
3948
- derivedKey: new Uint8Array(derivedKey)
3949
- };
3950
- };
3951
- var getNaclSecretKey = async (ddocId) => {
3952
- const { secretKey } = tweetnacl2.box.keyPair();
3953
- const nonce = tweetnacl2.randomBytes(tweetnacl2.secretbox.nonceLength);
3954
- const derivedKey = await deriveKeyFromAg2Hash(ddocId, nonce);
3955
- const encryptedSecretKey = fromUint8Array4(tweetnacl2.secretbox(secretKey, nonce, derivedKey), true);
3956
- return { nonce, encryptedSecretKey, secretKey, derivedKey: new Uint8Array(derivedKey) };
3957
- };
3958
- var generateLinkKeyMaterial = async (params) => {
3959
- if (params.linkKeyNonce && params.linkKey) {
3960
- const { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2, derivedKey: derivedKey2 } = await getExistingEncryptionMaterial(
3961
- params.linkKey,
3962
- params.linkKeyNonce,
3963
- params.ddocId
3964
- );
3965
- if (secretKey2) return { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2, derivedKey: derivedKey2 };
3966
- }
3967
- const { secretKey, nonce, encryptedSecretKey, derivedKey } = await getNaclSecretKey(params.ddocId);
3968
- return { secretKey, nonce, encryptedSecretKey, derivedKey };
3969
- };
3970
-
3971
- // src/domain/file/index.ts
3972
3763
  async function listFiles(params) {
3973
3764
  const { limit, skip, portalAddress } = params;
3974
3765
  const effectiveLimit = limit || DEFAULT_LIST_LIMIT;
@@ -4021,20 +3812,11 @@ var createFile = async (input) => {
4021
3812
  throw new Error("title, content, and portalAddress are required");
4022
3813
  }
4023
3814
  const ddocId = generate();
4024
- const { encryptedSecretKey, nonce, secretKey, derivedKey } = await generateLinkKeyMaterial({
4025
- ddocId,
4026
- linkKey: void 0,
4027
- linkKeyNonce: void 0
4028
- });
4029
3815
  const file2 = await FilesModel.create({
4030
3816
  title: input.title,
4031
3817
  content: input.content,
4032
3818
  ddocId,
4033
- portalAddress: input.portalAddress,
4034
- linkKey: encryptedSecretKey,
4035
- linkKeyNonce: fromUint8Array5(nonce),
4036
- derivedKey: fromUint8Array5(derivedKey),
4037
- secretKey: fromUint8Array5(secretKey)
3819
+ portalAddress: input.portalAddress
4038
3820
  });
4039
3821
  await EventsModel.create({ type: "create", fileId: file2._id, portalAddress: file2.portalAddress });
4040
3822
  return file2;
@@ -4846,7 +4628,7 @@ __export(external_exports, {
4846
4628
  e164: () => e1642,
4847
4629
  email: () => email2,
4848
4630
  emoji: () => emoji2,
4849
- encode: () => encode2,
4631
+ encode: () => encode3,
4850
4632
  encodeAsync: () => encodeAsync2,
4851
4633
  endsWith: () => _endsWith,
4852
4634
  enum: () => _enum2,
@@ -5220,7 +5002,7 @@ __export(core_exports2, {
5220
5002
  decode: () => decode,
5221
5003
  decodeAsync: () => decodeAsync,
5222
5004
  describe: () => describe,
5223
- encode: () => encode,
5005
+ encode: () => encode2,
5224
5006
  encodeAsync: () => encodeAsync,
5225
5007
  extractDefs: () => extractDefs,
5226
5008
  finalize: () => finalize,
@@ -6207,7 +5989,7 @@ var _encode = (_Err) => (schema, value, _ctx) => {
6207
5989
  const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" }) : { direction: "backward" };
6208
5990
  return _parse(_Err)(schema, value, ctx);
6209
5991
  };
6210
- var encode = /* @__PURE__ */ _encode($ZodRealError);
5992
+ var encode2 = /* @__PURE__ */ _encode($ZodRealError);
6211
5993
  var _decode = (_Err) => (schema, value, _ctx) => {
6212
5994
  return _parse(_Err)(schema, value, _ctx);
6213
5995
  };
@@ -16971,7 +16753,7 @@ var parse2 = /* @__PURE__ */ _parse(ZodRealError);
16971
16753
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
16972
16754
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
16973
16755
  var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
16974
- var encode2 = /* @__PURE__ */ _encode(ZodRealError);
16756
+ var encode3 = /* @__PURE__ */ _encode(ZodRealError);
16975
16757
  var decode2 = /* @__PURE__ */ _decode(ZodRealError);
16976
16758
  var encodeAsync2 = /* @__PURE__ */ _encodeAsync(ZodRealError);
16977
16759
  var decodeAsync2 = /* @__PURE__ */ _decodeAsync(ZodRealError);
@@ -17015,7 +16797,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
17015
16797
  inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
17016
16798
  inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
17017
16799
  inst.spa = inst.safeParseAsync;
17018
- inst.encode = (data, params) => encode2(inst, data, params);
16800
+ inst.encode = (data, params) => encode3(inst, data, params);
17019
16801
  inst.decode = (data, params) => decode2(inst, data, params);
17020
16802
  inst.encodeAsync = async (data, params) => encodeAsync2(inst, data, params);
17021
16803
  inst.decodeAsync = async (data, params) => decodeAsync2(inst, data, params);
@@ -18746,6 +18528,7 @@ function createMcpRouter(config3) {
18746
18528
  }
18747
18529
 
18748
18530
  // src/index.ts
18531
+ import { join as join2 } from "path";
18749
18532
  var port = parseInt(config.PORT || "8001", 10);
18750
18533
  var ip = config.IP || "0.0.0.0";
18751
18534
  var server;
@@ -18771,6 +18554,9 @@ var startServer = async () => {
18771
18554
  if (req.method === "POST" && req.path === "/" && req.body?.jsonrpc) {
18772
18555
  req.url = "/mcp";
18773
18556
  }
18557
+ if (req.method === "GET" && req.path === "/") {
18558
+ return _res.sendFile(join2(__dirname, "../public/guide.md"));
18559
+ }
18774
18560
  next();
18775
18561
  });
18776
18562
  app_default.use("/mcp", createMcpRouter({ serverUrl: `http://localhost:${port}`, apiKey }));