@fileverse/api 0.0.9 → 0.0.11

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/worker.js CHANGED
@@ -649,7 +649,9 @@ var init_files_model = __esm({
649
649
  linkKey: fileRaw.linkKey,
650
650
  linkKeyNonce: fileRaw.linkKeyNonce,
651
651
  commentKey: fileRaw.commentKey,
652
- link: fileRaw.link
652
+ link: fileRaw.link,
653
+ derivedKey: fileRaw.derivedKey,
654
+ secretKey: fileRaw.secretKey
653
655
  };
654
656
  }
655
657
  static async findAll(portalAddress, limit, skip) {
@@ -733,10 +735,20 @@ var init_files_model = __esm({
733
735
  const _id = uuidv7();
734
736
  const sql = `
735
737
  INSERT INTO ${this.TABLE}
736
- (_id, title, content, ddocId, portalAddress)
737
- VALUES (?, ?, ?, ?, ?)
738
+ (_id, title, content, ddocId, portalAddress, linkKey, linkKeyNonce, derivedKey, secretKey)
739
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
738
740
  `;
739
- await QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
741
+ await QueryBuilder.execute(sql, [
742
+ _id,
743
+ input.title,
744
+ input.content,
745
+ input.ddocId,
746
+ input.portalAddress,
747
+ input.linkKey ?? null,
748
+ input.linkKeyNonce ?? null,
749
+ input.derivedKey ?? null,
750
+ input.secretKey ?? null
751
+ ]);
740
752
  const created = await this.findById(_id, input.portalAddress);
741
753
  if (!created) {
742
754
  throw new Error("Failed to create file");
@@ -969,6 +981,29 @@ var init_events_model = __esm({
969
981
  `;
970
982
  await QueryBuilder.execute(sql, [Date.now(), _id]);
971
983
  }
984
+ static async markSubmitted(_id) {
985
+ const sql = `
986
+ UPDATE ${this.TABLE}
987
+ SET status = 'submitted',
988
+ lockedAt = NULL
989
+ WHERE _id = ?
990
+ `;
991
+ await QueryBuilder.execute(sql, [_id]);
992
+ }
993
+ static async findNextSubmitted(lockedFileIds) {
994
+ const exclusionClause = lockedFileIds.length > 0 ? `AND fileId NOT IN (${lockedFileIds.map(() => "?").join(", ")})` : "";
995
+ const sql = `
996
+ SELECT * FROM ${this.TABLE}
997
+ WHERE status = 'submitted'
998
+ AND userOpHash IS NOT NULL
999
+ ${exclusionClause}
1000
+ ORDER BY timestamp ASC
1001
+ LIMIT 1
1002
+ `;
1003
+ const params = [...lockedFileIds];
1004
+ const row = await QueryBuilder.selectOne(sql, params);
1005
+ return row ? this.parseEvent(row) : void 0;
1006
+ }
972
1007
  static async markProcessed(_id) {
973
1008
  const sql = `
974
1009
  UPDATE ${this.TABLE}
@@ -2383,50 +2418,13 @@ import { fromUint8Array, toUint8Array } from "js-base64";
2383
2418
  import { toAESKey, aesEncrypt } from "@fileverse/crypto/webcrypto";
2384
2419
  import axios from "axios";
2385
2420
  import { encodeFunctionData, parseEventLogs } from "viem";
2386
- var deriveKeyFromAg2Hash, decryptSecretKey, getExistingEncryptionMaterial, getNaclSecretKey, generateLinkKeyMaterial, jsonToFile, appendAuthTagIvToBlob, encryptFile, getNonceAppendedCipherText, jsonToBytes, buildLinklock, encryptTitleWithFileKey, uploadFileToIPFS, getEditFileTrxCalldata, getAddFileTrxCalldata, prepareCallData, prepareDeleteFileCallData, createEncryptedContentFile, buildFileMetadata, parseFileEventLog, uploadAllFilesToIPFS;
2421
+ var jsonToFile, appendAuthTagIvToBlob, encryptFile, getNonceAppendedCipherText, jsonToBytes, buildLinklock, encryptTitleWithFileKey, uploadFileToIPFS, getEditFileTrxCalldata, getAddFileTrxCalldata, prepareCallData, prepareDeleteFileCallData, createEncryptedContentFile, buildFileMetadata, parseFileEventLog, uploadAllFilesToIPFS;
2387
2422
  var init_file_utils = __esm({
2388
2423
  "src/sdk/file-utils.ts"() {
2389
2424
  "use strict";
2390
2425
  init_esm_shims();
2391
2426
  init_file_encryption();
2392
2427
  init_constants3();
2393
- deriveKeyFromAg2Hash = async (pass, salt) => {
2394
- const key = await getArgon2idHash(pass, salt);
2395
- return hkdf(Buffer.from(key), tweetnacl.secretbox.keyLength, {
2396
- info: Buffer.from("encryptionKey")
2397
- });
2398
- };
2399
- decryptSecretKey = async (docId, nonce, encryptedSecretKey) => {
2400
- const derivedKey = await deriveKeyFromAg2Hash(docId, toUint8Array(nonce));
2401
- return tweetnacl.secretbox.open(toUint8Array(encryptedSecretKey), toUint8Array(nonce), derivedKey);
2402
- };
2403
- getExistingEncryptionMaterial = async (existingEncryptedSecretKey, existingNonce, docId) => {
2404
- const secretKey = await decryptSecretKey(docId, existingNonce, existingEncryptedSecretKey);
2405
- return {
2406
- encryptedSecretKey: existingEncryptedSecretKey,
2407
- nonce: toUint8Array(existingNonce),
2408
- secretKey
2409
- };
2410
- };
2411
- getNaclSecretKey = async (ddocId) => {
2412
- const { secretKey } = tweetnacl.box.keyPair();
2413
- const nonce = tweetnacl.randomBytes(tweetnacl.secretbox.nonceLength);
2414
- const derivedKey = await deriveKeyFromAg2Hash(ddocId, nonce);
2415
- const encryptedSecretKey = fromUint8Array(tweetnacl.secretbox(secretKey, nonce, derivedKey), true);
2416
- return { nonce, encryptedSecretKey, secretKey };
2417
- };
2418
- generateLinkKeyMaterial = async (params) => {
2419
- if (params.linkKeyNonce && params.linkKey) {
2420
- const { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2 } = await getExistingEncryptionMaterial(
2421
- params.linkKey,
2422
- params.linkKeyNonce,
2423
- params.ddocId
2424
- );
2425
- if (secretKey2) return { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2 };
2426
- }
2427
- const { secretKey, nonce, encryptedSecretKey } = await getNaclSecretKey(params.ddocId);
2428
- return { secretKey, nonce, encryptedSecretKey };
2429
- };
2430
2428
  jsonToFile = (json, fileName) => {
2431
2429
  const blob = new Blob([JSON.stringify(json)], {
2432
2430
  type: "application/json"
@@ -2678,11 +2676,9 @@ var init_file_manager = __esm({
2678
2676
  }
2679
2677
  async submitAddFileTrx(file) {
2680
2678
  logger.debug(`Preparing to add file ${file.ddocId}`);
2681
- const { encryptedSecretKey, nonce, secretKey } = await generateLinkKeyMaterial({
2682
- ddocId: file.ddocId,
2683
- linkKey: file.linkKey,
2684
- linkKeyNonce: file.linkKeyNonce
2685
- });
2679
+ const encryptedSecretKey = file.linkKey;
2680
+ const nonce = toUint8Array2(file.linkKeyNonce);
2681
+ const secretKey = toUint8Array2(file.secretKey);
2686
2682
  const yJSContent = markdownToYjs(file.content);
2687
2683
  const { encryptedFile, key } = await createEncryptedContentFile(yJSContent);
2688
2684
  logger.debug(`Generated encrypted content file for file ${file.ddocId}`);
@@ -2726,13 +2722,59 @@ var init_file_manager = __esm({
2726
2722
  metadata
2727
2723
  };
2728
2724
  }
2729
- async updateFile(file) {
2730
- logger.debug(`Updating file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
2731
- const { encryptedSecretKey, nonce, secretKey } = await generateLinkKeyMaterial({
2725
+ async submitUpdateFile(file) {
2726
+ logger.debug(`Submitting update for file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
2727
+ const encryptedSecretKey = file.linkKey;
2728
+ const nonce = toUint8Array2(file.linkKeyNonce);
2729
+ const secretKey = toUint8Array2(file.secretKey);
2730
+ const yjsContent = markdownToYjs(file.content);
2731
+ const { encryptedFile, key } = await createEncryptedContentFile(yjsContent);
2732
+ const commentKey = toUint8Array2(file.commentKey);
2733
+ const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
2734
+ const linkLock = buildLinklock(secretKey, toUint8Array2(key), commentKey);
2735
+ const encryptedTitle = await encryptTitleWithFileKey({
2736
+ title: file.title || "Untitled",
2737
+ key
2738
+ });
2739
+ const metadata = buildFileMetadata({
2740
+ encryptedTitle,
2741
+ encryptedFileSize: encryptedFile.size,
2742
+ appLock,
2743
+ ownerLock,
2732
2744
  ddocId: file.ddocId,
2733
- linkKey: file.linkKey,
2734
- linkKeyNonce: file.linkKeyNonce
2745
+ nonce: fromUint8Array2(nonce),
2746
+ owner: this.agentClient.getAgentAddress()
2735
2747
  });
2748
+ const authParams = await this.getAuthParams();
2749
+ const { metadataHash, contentHash, gateHash } = await uploadAllFilesToIPFS(
2750
+ { metadata, encryptedFile, linkLock, ddocId: file.ddocId },
2751
+ authParams
2752
+ );
2753
+ const callData = prepareCallData({
2754
+ metadataHash,
2755
+ contentHash,
2756
+ gateHash,
2757
+ appFileId: file.ddocId,
2758
+ fileId: file.onChainFileId
2759
+ });
2760
+ const userOpHash = await this.sendFileOperation(callData);
2761
+ logger.debug(`Submitted update user op for file ${file.ddocId}`);
2762
+ return { userOpHash, metadata };
2763
+ }
2764
+ async submitDeleteFile(file) {
2765
+ logger.debug(`Submitting delete for file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
2766
+ const callData = prepareDeleteFileCallData({
2767
+ onChainFileId: file.onChainFileId
2768
+ });
2769
+ const userOpHash = await this.sendFileOperation(callData);
2770
+ logger.debug(`Submitted delete user op for file ${file.ddocId}`);
2771
+ return { userOpHash };
2772
+ }
2773
+ async updateFile(file) {
2774
+ logger.debug(`Updating file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
2775
+ const encryptedSecretKey = file.linkKey;
2776
+ const nonce = toUint8Array2(file.linkKeyNonce);
2777
+ const secretKey = toUint8Array2(file.secretKey);
2736
2778
  logger.debug(`Generating encrypted content file for file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
2737
2779
  const yjsContent = markdownToYjs(file.content);
2738
2780
  const { encryptedFile, key } = await createEncryptedContentFile(yjsContent);
@@ -2829,6 +2871,7 @@ var init_publish = __esm({
2829
2871
  init_smart_agent();
2830
2872
  init_file_manager();
2831
2873
  init_config();
2874
+ init_pimlico_utils();
2832
2875
  createFileManager = async (portalSeed, portalAddress, ucanSecret, privateAccountKey) => {
2833
2876
  const keyPair = ucans2.EdKeypair.fromSecretKey(fromUint8Array3(ucanSecret), {
2834
2877
  exportable: true
@@ -3390,7 +3433,9 @@ CREATE TABLE IF NOT EXISTS files (
3390
3433
  commentKey TEXT,
3391
3434
  linkKey TEXT,
3392
3435
  linkKeyNonce TEXT,
3393
- link TEXT
3436
+ link TEXT,
3437
+ derivedKey TEXT,
3438
+ secretKey TEXT
3394
3439
  );
3395
3440
  CREATE INDEX IF NOT EXISTS idx_files_createdAt ON files(createdAt);
3396
3441
  CREATE INDEX IF NOT EXISTS idx_files_syncStatus ON files(syncStatus);
@@ -3421,7 +3466,7 @@ CREATE TABLE IF NOT EXISTS events (
3421
3466
  type TEXT NOT NULL CHECK (type IN ('create', 'update', 'delete')),
3422
3467
  timestamp BIGINT NOT NULL,
3423
3468
  fileId TEXT NOT NULL,
3424
- status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'processed', 'failed')),
3469
+ status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'submitted', 'processed', 'failed')),
3425
3470
  retryCount INTEGER NOT NULL DEFAULT 0,
3426
3471
  lastError TEXT,
3427
3472
  lockedAt BIGINT,