@fileverse/api 0.0.21 → 0.0.22
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/cli/index.js +30 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/index.js +16 -126
- package/dist/commands/index.js.map +1 -1
- package/dist/index.js +112 -330
- package/dist/index.js.map +1 -1
- package/dist/worker.js +85 -258
- package/dist/worker.js.map +1 -1
- package/package.json +6 -5
- package/dist/cloudflare.js +0 -18259
- package/dist/cloudflare.js.map +0 -1
package/dist/worker.js
CHANGED
|
@@ -111,12 +111,7 @@ var init_config = __esm({
|
|
|
111
111
|
init_constants();
|
|
112
112
|
projectEnvPath = path2.join(process.cwd(), "config", ".env");
|
|
113
113
|
userEnvPath = path2.join(os.homedir(), ".fileverse", ".env");
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
loadConfig(false);
|
|
117
|
-
} catch {
|
|
118
|
-
}
|
|
119
|
-
}
|
|
114
|
+
loadConfig(false);
|
|
120
115
|
config = {
|
|
121
116
|
...STATIC_CONFIG,
|
|
122
117
|
get SERVICE_NAME() {
|
|
@@ -649,9 +644,7 @@ var init_files_model = __esm({
|
|
|
649
644
|
linkKey: fileRaw.linkKey,
|
|
650
645
|
linkKeyNonce: fileRaw.linkKeyNonce,
|
|
651
646
|
commentKey: fileRaw.commentKey,
|
|
652
|
-
link: fileRaw.link
|
|
653
|
-
derivedKey: fileRaw.derivedKey,
|
|
654
|
-
secretKey: fileRaw.secretKey
|
|
647
|
+
link: fileRaw.link
|
|
655
648
|
};
|
|
656
649
|
}
|
|
657
650
|
static async findAll(portalAddress, limit, skip) {
|
|
@@ -735,20 +728,10 @@ var init_files_model = __esm({
|
|
|
735
728
|
const _id = uuidv7();
|
|
736
729
|
const sql = `
|
|
737
730
|
INSERT INTO ${this.TABLE}
|
|
738
|
-
(_id, title, content, ddocId, portalAddress
|
|
739
|
-
VALUES (?, ?, ?, ?,
|
|
731
|
+
(_id, title, content, ddocId, portalAddress)
|
|
732
|
+
VALUES (?, ?, ?, ?, ?)
|
|
740
733
|
`;
|
|
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
|
-
]);
|
|
734
|
+
await QueryBuilder.execute(sql, [_id, input.title, input.content, input.ddocId, input.portalAddress]);
|
|
752
735
|
const created = await this.findById(_id, input.portalAddress);
|
|
753
736
|
if (!created) {
|
|
754
737
|
throw new Error("Failed to create file");
|
|
@@ -981,29 +964,6 @@ var init_events_model = __esm({
|
|
|
981
964
|
`;
|
|
982
965
|
await QueryBuilder.execute(sql, [Date.now(), _id]);
|
|
983
966
|
}
|
|
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
|
-
}
|
|
1007
967
|
static async markProcessed(_id) {
|
|
1008
968
|
const sql = `
|
|
1009
969
|
UPDATE ${this.TABLE}
|
|
@@ -1206,114 +1166,13 @@ var init_key_store = __esm({
|
|
|
1206
1166
|
}
|
|
1207
1167
|
});
|
|
1208
1168
|
|
|
1209
|
-
// src/sdk/ucan.ts
|
|
1210
|
-
import { sign, extractPublicKeyFromSecretKey } from "@stablelib/ed25519";
|
|
1211
|
-
import { toUint8Array } from "js-base64";
|
|
1212
|
-
function base58btcEncode(bytes) {
|
|
1213
|
-
const digits = [0];
|
|
1214
|
-
for (const byte of bytes) {
|
|
1215
|
-
let carry = byte;
|
|
1216
|
-
for (let j = 0; j < digits.length; j++) {
|
|
1217
|
-
carry += digits[j] << 8;
|
|
1218
|
-
digits[j] = carry % 58;
|
|
1219
|
-
carry = carry / 58 | 0;
|
|
1220
|
-
}
|
|
1221
|
-
while (carry > 0) {
|
|
1222
|
-
digits.push(carry % 58);
|
|
1223
|
-
carry = carry / 58 | 0;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
let result = "";
|
|
1227
|
-
for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
|
|
1228
|
-
result += BASE58_ALPHABET[0];
|
|
1229
|
-
}
|
|
1230
|
-
for (let i = digits.length - 1; i >= 0; i--) {
|
|
1231
|
-
result += BASE58_ALPHABET[digits[i]];
|
|
1232
|
-
}
|
|
1233
|
-
return result;
|
|
1234
|
-
}
|
|
1235
|
-
function base64urlEncode(data) {
|
|
1236
|
-
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
1237
|
-
let binary = "";
|
|
1238
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
1239
|
-
binary += String.fromCharCode(bytes[i]);
|
|
1240
|
-
}
|
|
1241
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1242
|
-
}
|
|
1243
|
-
async function buildAndEncode(params) {
|
|
1244
|
-
const {
|
|
1245
|
-
issuer,
|
|
1246
|
-
audience,
|
|
1247
|
-
capabilities = [],
|
|
1248
|
-
lifetimeInSeconds = 30,
|
|
1249
|
-
expiration,
|
|
1250
|
-
notBefore,
|
|
1251
|
-
facts,
|
|
1252
|
-
proofs = []
|
|
1253
|
-
} = params;
|
|
1254
|
-
const currentTime = Math.floor(Date.now() / 1e3);
|
|
1255
|
-
const exp = expiration ?? currentTime + lifetimeInSeconds;
|
|
1256
|
-
const header = { alg: issuer.jwtAlg, typ: "JWT", ucv: "0.8.1" };
|
|
1257
|
-
const att = capabilities.map((cap) => ({
|
|
1258
|
-
with: `${cap.with.scheme}:${cap.with.hierPart}`,
|
|
1259
|
-
can: [cap.can.namespace, ...cap.can.segments].join("/")
|
|
1260
|
-
}));
|
|
1261
|
-
const payload = {
|
|
1262
|
-
iss: issuer.did(),
|
|
1263
|
-
aud: audience,
|
|
1264
|
-
exp,
|
|
1265
|
-
att,
|
|
1266
|
-
prf: proofs
|
|
1267
|
-
};
|
|
1268
|
-
if (notBefore !== void 0) payload.nbf = notBefore;
|
|
1269
|
-
if (facts !== void 0) payload.fct = facts;
|
|
1270
|
-
const encodedHeader = base64urlEncode(JSON.stringify(header));
|
|
1271
|
-
const encodedPayload = base64urlEncode(JSON.stringify(payload));
|
|
1272
|
-
const signedData = `${encodedHeader}.${encodedPayload}`;
|
|
1273
|
-
const sig = await issuer.sign(new TextEncoder().encode(signedData));
|
|
1274
|
-
const signature = base64urlEncode(sig);
|
|
1275
|
-
return `${signedData}.${signature}`;
|
|
1276
|
-
}
|
|
1277
|
-
var BASE58_ALPHABET, EDWARDS_DID_PREFIX, EdKeypair;
|
|
1278
|
-
var init_ucan = __esm({
|
|
1279
|
-
"src/sdk/ucan.ts"() {
|
|
1280
|
-
"use strict";
|
|
1281
|
-
init_esm_shims();
|
|
1282
|
-
BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
1283
|
-
EDWARDS_DID_PREFIX = new Uint8Array([237, 1]);
|
|
1284
|
-
EdKeypair = class _EdKeypair {
|
|
1285
|
-
jwtAlg = "EdDSA";
|
|
1286
|
-
secretKey;
|
|
1287
|
-
publicKey;
|
|
1288
|
-
constructor(secretKey, publicKey) {
|
|
1289
|
-
this.secretKey = secretKey;
|
|
1290
|
-
this.publicKey = publicKey;
|
|
1291
|
-
}
|
|
1292
|
-
static fromSecretKey(key) {
|
|
1293
|
-
const secretKey = toUint8Array(key);
|
|
1294
|
-
const publicKey = extractPublicKeyFromSecretKey(secretKey);
|
|
1295
|
-
return new _EdKeypair(secretKey, publicKey);
|
|
1296
|
-
}
|
|
1297
|
-
did() {
|
|
1298
|
-
const bytes = new Uint8Array(EDWARDS_DID_PREFIX.length + this.publicKey.length);
|
|
1299
|
-
bytes.set(EDWARDS_DID_PREFIX);
|
|
1300
|
-
bytes.set(this.publicKey, EDWARDS_DID_PREFIX.length);
|
|
1301
|
-
return "did:key:z" + base58btcEncode(bytes);
|
|
1302
|
-
}
|
|
1303
|
-
async sign(msg) {
|
|
1304
|
-
return sign(this.secretKey, msg);
|
|
1305
|
-
}
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
});
|
|
1309
|
-
|
|
1310
1169
|
// src/sdk/auth-token-provider.ts
|
|
1170
|
+
import * as ucans from "@ucans/ucans";
|
|
1311
1171
|
var AuthTokenProvider;
|
|
1312
1172
|
var init_auth_token_provider = __esm({
|
|
1313
1173
|
"src/sdk/auth-token-provider.ts"() {
|
|
1314
1174
|
"use strict";
|
|
1315
1175
|
init_esm_shims();
|
|
1316
|
-
init_ucan();
|
|
1317
1176
|
AuthTokenProvider = class {
|
|
1318
1177
|
DEFAULT_OPTIONS = {
|
|
1319
1178
|
namespace: "file",
|
|
@@ -1327,7 +1186,7 @@ var init_auth_token_provider = __esm({
|
|
|
1327
1186
|
this.portalAddress = portalAddress;
|
|
1328
1187
|
}
|
|
1329
1188
|
async getAuthToken(audienceDid, options = this.DEFAULT_OPTIONS) {
|
|
1330
|
-
|
|
1189
|
+
const ucan = await ucans.build({
|
|
1331
1190
|
audience: audienceDid,
|
|
1332
1191
|
issuer: this.keyPair,
|
|
1333
1192
|
lifetimeInSeconds: 7 * 86400,
|
|
@@ -1341,6 +1200,7 @@ var init_auth_token_provider = __esm({
|
|
|
1341
1200
|
}
|
|
1342
1201
|
]
|
|
1343
1202
|
});
|
|
1203
|
+
return ucans.encode(ucan);
|
|
1344
1204
|
}
|
|
1345
1205
|
};
|
|
1346
1206
|
}
|
|
@@ -2508,20 +2368,60 @@ var init_file_encryption = __esm({
|
|
|
2508
2368
|
});
|
|
2509
2369
|
|
|
2510
2370
|
// src/sdk/file-utils.ts
|
|
2371
|
+
import { getArgon2idHash } from "@fileverse/crypto/argon";
|
|
2511
2372
|
import { bytesToBase64, generateRandomBytes as generateRandomBytes2 } from "@fileverse/crypto/utils";
|
|
2512
2373
|
import { derivePBKDF2Key, encryptAesCBC } from "@fileverse/crypto/kdf";
|
|
2513
2374
|
import { secretBoxEncrypt } from "@fileverse/crypto/nacl";
|
|
2375
|
+
import hkdf from "futoin-hkdf";
|
|
2514
2376
|
import tweetnacl from "tweetnacl";
|
|
2515
|
-
import { fromUint8Array, toUint8Array
|
|
2377
|
+
import { fromUint8Array, toUint8Array } from "js-base64";
|
|
2516
2378
|
import { toAESKey, aesEncrypt } from "@fileverse/crypto/webcrypto";
|
|
2379
|
+
import axios from "axios";
|
|
2517
2380
|
import { encodeFunctionData, parseEventLogs } from "viem";
|
|
2518
|
-
var jsonToFile, appendAuthTagIvToBlob, encryptFile, getNonceAppendedCipherText, jsonToBytes, buildLinklock, encryptTitleWithFileKey, uploadFileToIPFS, getEditFileTrxCalldata, getAddFileTrxCalldata, prepareCallData, prepareDeleteFileCallData, createEncryptedContentFile, buildFileMetadata, parseFileEventLog, uploadAllFilesToIPFS;
|
|
2381
|
+
var deriveKeyFromAg2Hash, decryptSecretKey, getExistingEncryptionMaterial, getNaclSecretKey, generateLinkKeyMaterial, jsonToFile, appendAuthTagIvToBlob, encryptFile, getNonceAppendedCipherText, jsonToBytes, buildLinklock, encryptTitleWithFileKey, uploadFileToIPFS, getEditFileTrxCalldata, getAddFileTrxCalldata, prepareCallData, prepareDeleteFileCallData, createEncryptedContentFile, buildFileMetadata, parseFileEventLog, uploadAllFilesToIPFS;
|
|
2519
2382
|
var init_file_utils = __esm({
|
|
2520
2383
|
"src/sdk/file-utils.ts"() {
|
|
2521
2384
|
"use strict";
|
|
2522
2385
|
init_esm_shims();
|
|
2523
2386
|
init_file_encryption();
|
|
2524
2387
|
init_constants3();
|
|
2388
|
+
deriveKeyFromAg2Hash = async (pass, salt) => {
|
|
2389
|
+
const key = await getArgon2idHash(pass, salt);
|
|
2390
|
+
return hkdf(Buffer.from(key), tweetnacl.secretbox.keyLength, {
|
|
2391
|
+
info: Buffer.from("encryptionKey")
|
|
2392
|
+
});
|
|
2393
|
+
};
|
|
2394
|
+
decryptSecretKey = async (docId, nonce, encryptedSecretKey) => {
|
|
2395
|
+
const derivedKey = await deriveKeyFromAg2Hash(docId, toUint8Array(nonce));
|
|
2396
|
+
return tweetnacl.secretbox.open(toUint8Array(encryptedSecretKey), toUint8Array(nonce), derivedKey);
|
|
2397
|
+
};
|
|
2398
|
+
getExistingEncryptionMaterial = async (existingEncryptedSecretKey, existingNonce, docId) => {
|
|
2399
|
+
const secretKey = await decryptSecretKey(docId, existingNonce, existingEncryptedSecretKey);
|
|
2400
|
+
return {
|
|
2401
|
+
encryptedSecretKey: existingEncryptedSecretKey,
|
|
2402
|
+
nonce: toUint8Array(existingNonce),
|
|
2403
|
+
secretKey
|
|
2404
|
+
};
|
|
2405
|
+
};
|
|
2406
|
+
getNaclSecretKey = async (ddocId) => {
|
|
2407
|
+
const { secretKey } = tweetnacl.box.keyPair();
|
|
2408
|
+
const nonce = tweetnacl.randomBytes(tweetnacl.secretbox.nonceLength);
|
|
2409
|
+
const derivedKey = await deriveKeyFromAg2Hash(ddocId, nonce);
|
|
2410
|
+
const encryptedSecretKey = fromUint8Array(tweetnacl.secretbox(secretKey, nonce, derivedKey), true);
|
|
2411
|
+
return { nonce, encryptedSecretKey, secretKey };
|
|
2412
|
+
};
|
|
2413
|
+
generateLinkKeyMaterial = async (params) => {
|
|
2414
|
+
if (params.linkKeyNonce && params.linkKey) {
|
|
2415
|
+
const { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2 } = await getExistingEncryptionMaterial(
|
|
2416
|
+
params.linkKey,
|
|
2417
|
+
params.linkKeyNonce,
|
|
2418
|
+
params.ddocId
|
|
2419
|
+
);
|
|
2420
|
+
if (secretKey2) return { encryptedSecretKey: encryptedSecretKey2, nonce: nonce2, secretKey: secretKey2 };
|
|
2421
|
+
}
|
|
2422
|
+
const { secretKey, nonce, encryptedSecretKey } = await getNaclSecretKey(params.ddocId);
|
|
2423
|
+
return { secretKey, nonce, encryptedSecretKey };
|
|
2424
|
+
};
|
|
2525
2425
|
jsonToFile = (json, fileName) => {
|
|
2526
2426
|
const blob = new Blob([JSON.stringify(json)], {
|
|
2527
2427
|
type: "application/json"
|
|
@@ -2551,8 +2451,8 @@ var init_file_utils = __esm({
|
|
|
2551
2451
|
const encryptedBlob = new Blob([ciphertext], { type: file.type });
|
|
2552
2452
|
const encryptedBlobWithAuthTagIv = await appendAuthTagIvToBlob(
|
|
2553
2453
|
encryptedBlob,
|
|
2554
|
-
|
|
2555
|
-
|
|
2454
|
+
toUint8Array(authTag),
|
|
2455
|
+
toUint8Array(iv)
|
|
2556
2456
|
);
|
|
2557
2457
|
return {
|
|
2558
2458
|
encryptedFile: new File([encryptedBlobWithAuthTagIv], file.name),
|
|
@@ -2598,7 +2498,7 @@ var init_file_utils = __esm({
|
|
|
2598
2498
|
};
|
|
2599
2499
|
};
|
|
2600
2500
|
encryptTitleWithFileKey = async (args) => {
|
|
2601
|
-
const key = await toAESKey(
|
|
2501
|
+
const key = await toAESKey(toUint8Array(args.key));
|
|
2602
2502
|
if (!key) throw new Error("Key is undefined");
|
|
2603
2503
|
const titleBytes = new TextEncoder().encode(args.title);
|
|
2604
2504
|
const encryptedTitle = await aesEncrypt(key, titleBytes, "base64");
|
|
@@ -2612,21 +2512,16 @@ var init_file_utils = __esm({
|
|
|
2612
2512
|
body.append("ipfsType", ipfsType);
|
|
2613
2513
|
body.append("appFileId", appFileId);
|
|
2614
2514
|
body.append("sourceApp", "ddoc");
|
|
2615
|
-
const
|
|
2616
|
-
|
|
2515
|
+
const uploadEndpoint = UPLOAD_SERVER_URL + "upload";
|
|
2516
|
+
const response = await axios.post(uploadEndpoint, body, {
|
|
2617
2517
|
headers: {
|
|
2618
2518
|
Authorization: `Bearer ${token}`,
|
|
2619
2519
|
contract: contractAddress,
|
|
2620
2520
|
invoker,
|
|
2621
|
-
chain:
|
|
2622
|
-
}
|
|
2623
|
-
body
|
|
2521
|
+
chain: process.env.chainId
|
|
2522
|
+
}
|
|
2624
2523
|
});
|
|
2625
|
-
|
|
2626
|
-
throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
|
|
2627
|
-
}
|
|
2628
|
-
const data = await response.json();
|
|
2629
|
-
return data.ipfsHash;
|
|
2524
|
+
return response.data.ipfsHash;
|
|
2630
2525
|
};
|
|
2631
2526
|
getEditFileTrxCalldata = (args) => {
|
|
2632
2527
|
return encodeFunctionData({
|
|
@@ -2721,7 +2616,7 @@ var init_file_utils = __esm({
|
|
|
2721
2616
|
});
|
|
2722
2617
|
|
|
2723
2618
|
// src/sdk/file-manager.ts
|
|
2724
|
-
import { fromUint8Array as fromUint8Array2, toUint8Array as
|
|
2619
|
+
import { fromUint8Array as fromUint8Array2, toUint8Array as toUint8Array2 } from "js-base64";
|
|
2725
2620
|
import { generateAESKey, exportAESKey } from "@fileverse/crypto/webcrypto";
|
|
2726
2621
|
import { markdownToYjs } from "@fileverse/content-processor";
|
|
2727
2622
|
var FileManager;
|
|
@@ -2742,8 +2637,8 @@ var init_file_manager = __esm({
|
|
|
2742
2637
|
}
|
|
2743
2638
|
createLocks(key, encryptedSecretKey, commentKey) {
|
|
2744
2639
|
const appLock = {
|
|
2745
|
-
lockedFileKey: this.keyStore.encryptData(
|
|
2746
|
-
lockedLinkKey: this.keyStore.encryptData(
|
|
2640
|
+
lockedFileKey: this.keyStore.encryptData(toUint8Array2(key)),
|
|
2641
|
+
lockedLinkKey: this.keyStore.encryptData(toUint8Array2(encryptedSecretKey)),
|
|
2747
2642
|
lockedChatKey: this.keyStore.encryptData(commentKey)
|
|
2748
2643
|
};
|
|
2749
2644
|
return { appLock, ownerLock: { ...appLock } };
|
|
@@ -2777,28 +2672,22 @@ var init_file_manager = __esm({
|
|
|
2777
2672
|
return this.agentClient.getAuthParams();
|
|
2778
2673
|
}
|
|
2779
2674
|
async submitAddFileTrx(file) {
|
|
2780
|
-
console.log("Submitting add file trx");
|
|
2781
2675
|
logger.debug(`Preparing to add file ${file.ddocId}`);
|
|
2782
|
-
const encryptedSecretKey =
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2676
|
+
const { encryptedSecretKey, nonce, secretKey } = await generateLinkKeyMaterial({
|
|
2677
|
+
ddocId: file.ddocId,
|
|
2678
|
+
linkKey: file.linkKey,
|
|
2679
|
+
linkKeyNonce: file.linkKeyNonce
|
|
2680
|
+
});
|
|
2786
2681
|
const yJSContent = markdownToYjs(file.content);
|
|
2787
|
-
console.log("Generated yjs content");
|
|
2788
2682
|
const { encryptedFile, key } = await createEncryptedContentFile(yJSContent);
|
|
2789
|
-
console.log("Generated encrypted content file");
|
|
2790
2683
|
logger.debug(`Generated encrypted content file for file ${file.ddocId}`);
|
|
2791
2684
|
const commentKey = await exportAESKey(await generateAESKey(128));
|
|
2792
|
-
console.log("Generated comment key");
|
|
2793
2685
|
const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
|
|
2794
|
-
|
|
2795
|
-
const linkLock = buildLinklock(secretKey, toUint8Array3(key), commentKey);
|
|
2796
|
-
console.log("Built link lock");
|
|
2686
|
+
const linkLock = buildLinklock(secretKey, toUint8Array2(key), commentKey);
|
|
2797
2687
|
const encryptedTitle = await encryptTitleWithFileKey({
|
|
2798
2688
|
title: file.title || "Untitled",
|
|
2799
2689
|
key
|
|
2800
2690
|
});
|
|
2801
|
-
console.log("Built encrypted title");
|
|
2802
2691
|
const metadata = buildFileMetadata({
|
|
2803
2692
|
encryptedTitle,
|
|
2804
2693
|
encryptedFileSize: encryptedFile.size,
|
|
@@ -2808,15 +2697,11 @@ var init_file_manager = __esm({
|
|
|
2808
2697
|
nonce: fromUint8Array2(nonce),
|
|
2809
2698
|
owner: this.agentClient.getAgentAddress()
|
|
2810
2699
|
});
|
|
2811
|
-
console.log("Built metadata");
|
|
2812
2700
|
const authParams = await this.getAuthParams();
|
|
2813
|
-
console.log("Got auth params");
|
|
2814
|
-
console.log("Uploading files to IPFS");
|
|
2815
2701
|
const { metadataHash, contentHash, gateHash } = await uploadAllFilesToIPFS(
|
|
2816
2702
|
{ metadata, encryptedFile, linkLock, ddocId: file.ddocId },
|
|
2817
2703
|
authParams
|
|
2818
2704
|
);
|
|
2819
|
-
console.log("Uploaded files to IPFS");
|
|
2820
2705
|
logger.debug(`Uploaded files to IPFS for file ${file.ddocId}`);
|
|
2821
2706
|
const callData = prepareCallData({
|
|
2822
2707
|
metadataHash,
|
|
@@ -2825,10 +2710,8 @@ var init_file_manager = __esm({
|
|
|
2825
2710
|
appFileId: file.ddocId,
|
|
2826
2711
|
fileId: file.fileId
|
|
2827
2712
|
});
|
|
2828
|
-
console.log("Prepared call data");
|
|
2829
2713
|
logger.debug(`Prepared call data for file ${file.ddocId}`);
|
|
2830
2714
|
const userOpHash = await this.sendFileOperation(callData);
|
|
2831
|
-
console.log("Submitted user op");
|
|
2832
2715
|
logger.debug(`Submitted user op for file ${file.ddocId}`);
|
|
2833
2716
|
return {
|
|
2834
2717
|
userOpHash,
|
|
@@ -2838,65 +2721,19 @@ var init_file_manager = __esm({
|
|
|
2838
2721
|
metadata
|
|
2839
2722
|
};
|
|
2840
2723
|
}
|
|
2841
|
-
async submitUpdateFile(file) {
|
|
2842
|
-
logger.debug(`Submitting update for file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
|
|
2843
|
-
const encryptedSecretKey = file.linkKey;
|
|
2844
|
-
const nonce = toUint8Array3(file.linkKeyNonce);
|
|
2845
|
-
const secretKey = toUint8Array3(file.secretKey);
|
|
2846
|
-
const yjsContent = markdownToYjs(file.content);
|
|
2847
|
-
const { encryptedFile, key } = await createEncryptedContentFile(yjsContent);
|
|
2848
|
-
const commentKey = toUint8Array3(file.commentKey);
|
|
2849
|
-
const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
|
|
2850
|
-
const linkLock = buildLinklock(secretKey, toUint8Array3(key), commentKey);
|
|
2851
|
-
const encryptedTitle = await encryptTitleWithFileKey({
|
|
2852
|
-
title: file.title || "Untitled",
|
|
2853
|
-
key
|
|
2854
|
-
});
|
|
2855
|
-
const metadata = buildFileMetadata({
|
|
2856
|
-
encryptedTitle,
|
|
2857
|
-
encryptedFileSize: encryptedFile.size,
|
|
2858
|
-
appLock,
|
|
2859
|
-
ownerLock,
|
|
2860
|
-
ddocId: file.ddocId,
|
|
2861
|
-
nonce: fromUint8Array2(nonce),
|
|
2862
|
-
owner: this.agentClient.getAgentAddress()
|
|
2863
|
-
});
|
|
2864
|
-
const authParams = await this.getAuthParams();
|
|
2865
|
-
const { metadataHash, contentHash, gateHash } = await uploadAllFilesToIPFS(
|
|
2866
|
-
{ metadata, encryptedFile, linkLock, ddocId: file.ddocId },
|
|
2867
|
-
authParams
|
|
2868
|
-
);
|
|
2869
|
-
const callData = prepareCallData({
|
|
2870
|
-
metadataHash,
|
|
2871
|
-
contentHash,
|
|
2872
|
-
gateHash,
|
|
2873
|
-
appFileId: file.ddocId,
|
|
2874
|
-
fileId: file.onChainFileId
|
|
2875
|
-
});
|
|
2876
|
-
const userOpHash = await this.sendFileOperation(callData);
|
|
2877
|
-
logger.debug(`Submitted update user op for file ${file.ddocId}`);
|
|
2878
|
-
return { userOpHash, metadata };
|
|
2879
|
-
}
|
|
2880
|
-
async submitDeleteFile(file) {
|
|
2881
|
-
logger.debug(`Submitting delete for file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
|
|
2882
|
-
const callData = prepareDeleteFileCallData({
|
|
2883
|
-
onChainFileId: file.onChainFileId
|
|
2884
|
-
});
|
|
2885
|
-
const userOpHash = await this.sendFileOperation(callData);
|
|
2886
|
-
logger.debug(`Submitted delete user op for file ${file.ddocId}`);
|
|
2887
|
-
return { userOpHash };
|
|
2888
|
-
}
|
|
2889
2724
|
async updateFile(file) {
|
|
2890
2725
|
logger.debug(`Updating file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
|
|
2891
|
-
const encryptedSecretKey =
|
|
2892
|
-
|
|
2893
|
-
|
|
2726
|
+
const { encryptedSecretKey, nonce, secretKey } = await generateLinkKeyMaterial({
|
|
2727
|
+
ddocId: file.ddocId,
|
|
2728
|
+
linkKey: file.linkKey,
|
|
2729
|
+
linkKeyNonce: file.linkKeyNonce
|
|
2730
|
+
});
|
|
2894
2731
|
logger.debug(`Generating encrypted content file for file ${file.ddocId} with onChainFileId ${file.onChainFileId}`);
|
|
2895
2732
|
const yjsContent = markdownToYjs(file.content);
|
|
2896
2733
|
const { encryptedFile, key } = await createEncryptedContentFile(yjsContent);
|
|
2897
|
-
const commentKey =
|
|
2734
|
+
const commentKey = toUint8Array2(file.commentKey);
|
|
2898
2735
|
const { appLock, ownerLock } = this.createLocks(key, encryptedSecretKey, commentKey);
|
|
2899
|
-
const linkLock = buildLinklock(secretKey,
|
|
2736
|
+
const linkLock = buildLinklock(secretKey, toUint8Array2(key), commentKey);
|
|
2900
2737
|
const encryptedTitle = await encryptTitleWithFileKey({
|
|
2901
2738
|
title: file.title || "Untitled",
|
|
2902
2739
|
key
|
|
@@ -2948,10 +2785,11 @@ var init_file_manager = __esm({
|
|
|
2948
2785
|
});
|
|
2949
2786
|
|
|
2950
2787
|
// src/domain/portal/publish.ts
|
|
2951
|
-
import { fromUint8Array as fromUint8Array3, toUint8Array as
|
|
2788
|
+
import { fromUint8Array as fromUint8Array3, toUint8Array as toUint8Array3 } from "js-base64";
|
|
2952
2789
|
import { stringToBytes } from "viem";
|
|
2953
2790
|
import { deriveHKDFKey } from "@fileverse/crypto/kdf";
|
|
2954
2791
|
import { generateKeyPairFromSeed } from "@stablelib/ed25519";
|
|
2792
|
+
import * as ucans2 from "@ucans/ucans";
|
|
2955
2793
|
async function getPortalData(fileId) {
|
|
2956
2794
|
const file = await FilesModel.findByIdIncludingDeleted(fileId);
|
|
2957
2795
|
if (!file) {
|
|
@@ -2983,23 +2821,17 @@ var init_publish = __esm({
|
|
|
2983
2821
|
init_infra();
|
|
2984
2822
|
init_key_store();
|
|
2985
2823
|
init_auth_token_provider();
|
|
2986
|
-
init_ucan();
|
|
2987
2824
|
init_smart_agent();
|
|
2988
2825
|
init_file_manager();
|
|
2989
2826
|
init_config();
|
|
2990
|
-
init_pimlico_utils();
|
|
2991
2827
|
createFileManager = async (portalSeed, portalAddress, ucanSecret, privateAccountKey) => {
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2828
|
+
const keyPair = ucans2.EdKeypair.fromSecretKey(fromUint8Array3(ucanSecret), {
|
|
2829
|
+
exportable: true
|
|
2830
|
+
});
|
|
2995
2831
|
const authTokenProvider = new AuthTokenProvider(keyPair, portalAddress);
|
|
2996
|
-
|
|
2997
|
-
const keyStore = new KeyStore(toUint8Array4(portalSeed), portalAddress, authTokenProvider);
|
|
2998
|
-
console.log("Created key store");
|
|
2832
|
+
const keyStore = new KeyStore(toUint8Array3(portalSeed), portalAddress, authTokenProvider);
|
|
2999
2833
|
const agentClient = new AgentClient(authTokenProvider);
|
|
3000
|
-
console.log("Created agent client");
|
|
3001
2834
|
await agentClient.initializeAgentClient(privateAccountKey);
|
|
3002
|
-
console.log("Initialized agent client");
|
|
3003
2835
|
return new FileManager(keyStore, agentClient);
|
|
3004
2836
|
};
|
|
3005
2837
|
executeOperation = async (fileManager, file, operation) => {
|
|
@@ -3016,7 +2848,7 @@ var init_publish = __esm({
|
|
|
3016
2848
|
handleExistingFileOp = async (fileId, operation) => {
|
|
3017
2849
|
try {
|
|
3018
2850
|
const { file, portalDetails, apiKey } = await getPortalData(fileId);
|
|
3019
|
-
const apiKeySeed =
|
|
2851
|
+
const apiKeySeed = toUint8Array3(apiKey);
|
|
3020
2852
|
const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
|
|
3021
2853
|
const fileManager = await createFileManager(
|
|
3022
2854
|
portalDetails.portalSeed,
|
|
@@ -3032,22 +2864,19 @@ var init_publish = __esm({
|
|
|
3032
2864
|
};
|
|
3033
2865
|
handleNewFileOp = async (fileId) => {
|
|
3034
2866
|
const { file, portalDetails, apiKey } = await getPortalData(fileId);
|
|
3035
|
-
|
|
3036
|
-
const apiKeySeed = toUint8Array4(apiKey);
|
|
2867
|
+
const apiKeySeed = toUint8Array3(apiKey);
|
|
3037
2868
|
const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
|
|
3038
|
-
console.log("Derived collaborator keys");
|
|
3039
2869
|
const fileManager = await createFileManager(
|
|
3040
2870
|
portalDetails.portalSeed,
|
|
3041
2871
|
portalDetails.portalAddress,
|
|
3042
2872
|
ucanSecret,
|
|
3043
2873
|
privateAccountKey
|
|
3044
2874
|
);
|
|
3045
|
-
console.log("Created file manager");
|
|
3046
2875
|
return fileManager.submitAddFileTrx(file);
|
|
3047
2876
|
};
|
|
3048
2877
|
getProxyAuthParams = async (fileId) => {
|
|
3049
2878
|
const { portalDetails, apiKey } = await getPortalData(fileId);
|
|
3050
|
-
const apiKeySeed =
|
|
2879
|
+
const apiKeySeed = toUint8Array3(apiKey);
|
|
3051
2880
|
const { privateAccountKey, ucanSecret } = deriveCollaboratorKeys(apiKeySeed);
|
|
3052
2881
|
const fileManager = await createFileManager(
|
|
3053
2882
|
portalDetails.portalSeed,
|
|
@@ -3556,9 +3385,7 @@ CREATE TABLE IF NOT EXISTS files (
|
|
|
3556
3385
|
commentKey TEXT,
|
|
3557
3386
|
linkKey TEXT,
|
|
3558
3387
|
linkKeyNonce TEXT,
|
|
3559
|
-
link TEXT
|
|
3560
|
-
derivedKey TEXT,
|
|
3561
|
-
secretKey TEXT
|
|
3388
|
+
link TEXT
|
|
3562
3389
|
);
|
|
3563
3390
|
CREATE INDEX IF NOT EXISTS idx_files_createdAt ON files(createdAt);
|
|
3564
3391
|
CREATE INDEX IF NOT EXISTS idx_files_syncStatus ON files(syncStatus);
|
|
@@ -3589,7 +3416,7 @@ CREATE TABLE IF NOT EXISTS events (
|
|
|
3589
3416
|
type TEXT NOT NULL CHECK (type IN ('create', 'update', 'delete')),
|
|
3590
3417
|
timestamp BIGINT NOT NULL,
|
|
3591
3418
|
fileId TEXT NOT NULL,
|
|
3592
|
-
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', '
|
|
3419
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'processed', 'failed')),
|
|
3593
3420
|
retryCount INTEGER NOT NULL DEFAULT 0,
|
|
3594
3421
|
lastError TEXT,
|
|
3595
3422
|
lockedAt BIGINT,
|