@ckbfs/api 1.5.1 → 2.0.1

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.
Files changed (45) hide show
  1. package/README.md +31 -6
  2. package/RFC.v3.md +210 -0
  3. package/dist/index.d.ts +72 -7
  4. package/dist/index.js +437 -75
  5. package/dist/utils/checksum.d.ts +16 -0
  6. package/dist/utils/checksum.js +74 -8
  7. package/dist/utils/constants.d.ts +2 -1
  8. package/dist/utils/constants.js +12 -2
  9. package/dist/utils/file.d.ts +44 -0
  10. package/dist/utils/file.js +303 -30
  11. package/dist/utils/molecule.d.ts +13 -1
  12. package/dist/utils/molecule.js +32 -5
  13. package/dist/utils/transaction-backup.d.ts +117 -0
  14. package/dist/utils/transaction-backup.js +624 -0
  15. package/dist/utils/transaction.d.ts +7 -115
  16. package/dist/utils/transaction.js +45 -622
  17. package/dist/utils/transactions/index.d.ts +8 -0
  18. package/dist/utils/transactions/index.js +31 -0
  19. package/dist/utils/transactions/shared.d.ts +57 -0
  20. package/dist/utils/transactions/shared.js +17 -0
  21. package/dist/utils/transactions/v1v2.d.ts +80 -0
  22. package/dist/utils/transactions/v1v2.js +592 -0
  23. package/dist/utils/transactions/v3.d.ts +124 -0
  24. package/dist/utils/transactions/v3.js +369 -0
  25. package/dist/utils/witness.d.ts +45 -0
  26. package/dist/utils/witness.js +145 -3
  27. package/examples/append-v3.ts +310 -0
  28. package/examples/chunked-publish.ts +307 -0
  29. package/examples/publish-v3.ts +152 -0
  30. package/examples/publish.ts +4 -4
  31. package/examples/retrieve-v3.ts +222 -0
  32. package/package.json +6 -2
  33. package/small-example.txt +1 -0
  34. package/src/index.ts +568 -87
  35. package/src/utils/checksum.ts +90 -9
  36. package/src/utils/constants.ts +19 -2
  37. package/src/utils/file.ts +386 -35
  38. package/src/utils/molecule.ts +43 -6
  39. package/src/utils/transaction-backup.ts +849 -0
  40. package/src/utils/transaction.ts +39 -848
  41. package/src/utils/transactions/index.ts +16 -0
  42. package/src/utils/transactions/shared.ts +64 -0
  43. package/src/utils/transactions/v1v2.ts +791 -0
  44. package/src/utils/transactions/v3.ts +564 -0
  45. package/src/utils/witness.ts +193 -0
package/dist/index.js CHANGED
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CKBFS_CODE_HASH = exports.DEFAULT_VERSION = exports.DEFAULT_NETWORK = exports.ProtocolVersion = exports.NetworkType = exports.CKBFS_HEADER_STRING = exports.CKBFS_HEADER = exports.BackLinkV2 = exports.BackLinkV1 = exports.CKBFSData = exports.createChunkedCKBFSWitnesses = exports.isCKBFSWitness = exports.extractCKBFSWitnessContent = exports.createTextCKBFSWitness = exports.createCKBFSWitness = exports.saveFileFromWitnessData = exports.decodeFileFromWitnessData = exports.extractFileFromWitnesses = exports.decodeMultipleWitnessContents = exports.decodeWitnessContent = exports.IdentifierType = exports.parseIdentifier = exports.decodeFileFromChainByIdentifier = exports.saveFileFromChainByIdentifier = exports.getFileContentFromChainByIdentifier = exports.decodeFileFromChainByTypeId = exports.saveFileFromChainByTypeId = exports.getFileContentFromChainByTypeId = exports.saveFileFromChain = exports.getFileContentFromChain = exports.combineChunksToFile = exports.splitFileIntoChunks = exports.getContentType = exports.writeFile = exports.readFileAsUint8Array = exports.readFileAsText = exports.readFile = exports.createAppendTransactionDry = exports.appendCKBFS = exports.publishCKBFS = exports.prepareAppendTransaction = exports.createAppendTransaction = exports.preparePublishTransaction = exports.createPublishTransaction = exports.createCKBFSCell = exports.verifyWitnessChecksum = exports.updateChecksum = exports.verifyChecksum = exports.calculateChecksum = exports.CKBFS = void 0;
4
- exports.getCKBFSScriptConfig = exports.DEPLOY_TX_HASH = exports.DEP_GROUP_TX_HASH = exports.ADLER32_TYPE_ID = exports.ADLER32_CODE_HASH = exports.CKBFS_TYPE_ID = void 0;
3
+ exports.CKBFSData = exports.isCKBFSV3Witness = exports.extractCKBFSV3WitnessContent = exports.createChunkedCKBFSV3Witnesses = exports.createCKBFSV3Witness = exports.createChunkedCKBFSWitnesses = exports.isCKBFSWitness = exports.extractCKBFSWitnessContent = exports.createTextCKBFSWitness = exports.createCKBFSWitness = exports.saveFileFromChainByIdentifierV3 = exports.getFileContentFromChainByIdentifierV3 = exports.getFileContentFromChainV3 = exports.saveFileFromWitnessData = exports.decodeFileFromWitnessData = exports.extractFileFromWitnesses = exports.decodeMultipleWitnessContents = exports.decodeWitnessContent = exports.IdentifierType = exports.parseIdentifier = exports.decodeFileFromChainByIdentifier = exports.saveFileFromChainByIdentifier = exports.getFileContentFromChainByIdentifier = exports.decodeFileFromChainByTypeId = exports.saveFileFromChainByTypeId = exports.getFileContentFromChainByTypeId = exports.saveFileFromChain = exports.getFileContentFromChain = exports.combineChunksToFile = exports.splitFileIntoChunks = exports.getContentType = exports.writeFile = exports.readFileAsUint8Array = exports.readFileAsText = exports.readFile = exports.createAppendTransactionDry = exports.appendCKBFS = exports.publishCKBFS = exports.prepareAppendTransaction = exports.createAppendTransaction = exports.preparePublishTransaction = exports.createPublishTransaction = exports.createCKBFSCell = exports.verifyV3WitnessChain = exports.verifyV3WitnessChecksum = exports.verifyWitnessChecksum = exports.updateChecksum = exports.verifyChecksum = exports.calculateChecksum = exports.CKBFS = void 0;
4
+ exports.getCKBFSScriptConfig = exports.DEPLOY_TX_HASH = exports.DEP_GROUP_TX_HASH = exports.ADLER32_TYPE_ID = exports.ADLER32_CODE_HASH = exports.CKBFS_TYPE_ID = exports.CKBFS_CODE_HASH = exports.DEFAULT_VERSION = exports.DEFAULT_NETWORK = exports.ProtocolVersion = exports.NetworkType = exports.CKBFS_HEADER_STRING = exports.CKBFS_HEADER = exports.BackLinkV2 = exports.BackLinkV1 = void 0;
5
5
  const core_1 = require("@ckb-ccc/core");
6
6
  const checksum_1 = require("./utils/checksum");
7
7
  Object.defineProperty(exports, "calculateChecksum", { enumerable: true, get: function () { return checksum_1.calculateChecksum; } });
8
8
  Object.defineProperty(exports, "verifyChecksum", { enumerable: true, get: function () { return checksum_1.verifyChecksum; } });
9
9
  Object.defineProperty(exports, "updateChecksum", { enumerable: true, get: function () { return checksum_1.updateChecksum; } });
10
10
  Object.defineProperty(exports, "verifyWitnessChecksum", { enumerable: true, get: function () { return checksum_1.verifyWitnessChecksum; } });
11
+ Object.defineProperty(exports, "verifyV3WitnessChecksum", { enumerable: true, get: function () { return checksum_1.verifyV3WitnessChecksum; } });
12
+ Object.defineProperty(exports, "verifyV3WitnessChain", { enumerable: true, get: function () { return checksum_1.verifyV3WitnessChain; } });
11
13
  const transaction_1 = require("./utils/transaction");
12
14
  Object.defineProperty(exports, "createCKBFSCell", { enumerable: true, get: function () { return transaction_1.createCKBFSCell; } });
13
15
  Object.defineProperty(exports, "createPublishTransaction", { enumerable: true, get: function () { return transaction_1.createPublishTransaction; } });
@@ -40,12 +42,21 @@ Object.defineProperty(exports, "decodeMultipleWitnessContents", { enumerable: tr
40
42
  Object.defineProperty(exports, "extractFileFromWitnesses", { enumerable: true, get: function () { return file_1.extractFileFromWitnesses; } });
41
43
  Object.defineProperty(exports, "decodeFileFromWitnessData", { enumerable: true, get: function () { return file_1.decodeFileFromWitnessData; } });
42
44
  Object.defineProperty(exports, "saveFileFromWitnessData", { enumerable: true, get: function () { return file_1.saveFileFromWitnessData; } });
45
+ Object.defineProperty(exports, "getFileContentFromChainV3", { enumerable: true, get: function () { return
46
+ // V3 file retrieval functions
47
+ file_1.getFileContentFromChainV3; } });
48
+ Object.defineProperty(exports, "getFileContentFromChainByIdentifierV3", { enumerable: true, get: function () { return file_1.getFileContentFromChainByIdentifierV3; } });
49
+ Object.defineProperty(exports, "saveFileFromChainByIdentifierV3", { enumerable: true, get: function () { return file_1.saveFileFromChainByIdentifierV3; } });
43
50
  const witness_1 = require("./utils/witness");
44
51
  Object.defineProperty(exports, "createCKBFSWitness", { enumerable: true, get: function () { return witness_1.createCKBFSWitness; } });
45
52
  Object.defineProperty(exports, "createTextCKBFSWitness", { enumerable: true, get: function () { return witness_1.createTextCKBFSWitness; } });
46
53
  Object.defineProperty(exports, "extractCKBFSWitnessContent", { enumerable: true, get: function () { return witness_1.extractCKBFSWitnessContent; } });
47
54
  Object.defineProperty(exports, "isCKBFSWitness", { enumerable: true, get: function () { return witness_1.isCKBFSWitness; } });
48
55
  Object.defineProperty(exports, "createChunkedCKBFSWitnesses", { enumerable: true, get: function () { return witness_1.createChunkedCKBFSWitnesses; } });
56
+ Object.defineProperty(exports, "createCKBFSV3Witness", { enumerable: true, get: function () { return witness_1.createCKBFSV3Witness; } });
57
+ Object.defineProperty(exports, "createChunkedCKBFSV3Witnesses", { enumerable: true, get: function () { return witness_1.createChunkedCKBFSV3Witnesses; } });
58
+ Object.defineProperty(exports, "extractCKBFSV3WitnessContent", { enumerable: true, get: function () { return witness_1.extractCKBFSV3WitnessContent; } });
59
+ Object.defineProperty(exports, "isCKBFSV3Witness", { enumerable: true, get: function () { return witness_1.isCKBFSV3Witness; } });
49
60
  const molecule_1 = require("./utils/molecule");
50
61
  Object.defineProperty(exports, "CKBFSData", { enumerable: true, get: function () { return molecule_1.CKBFSData; } });
51
62
  Object.defineProperty(exports, "BackLinkV1", { enumerable: true, get: function () { return molecule_1.BackLinkV1; } });
@@ -154,22 +165,44 @@ class CKBFS {
154
165
  // Use the filename from the path if not provided
155
166
  const pathParts = filePath.split(/[\\\/]/);
156
167
  const filename = options.filename || pathParts[pathParts.length - 1];
157
- // Create and sign the transaction using the utility function
158
- const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
159
- contentChunks,
160
- contentType,
161
- filename,
162
- lock,
163
- capacity: options.capacity,
164
- feeRate: options.feeRate,
165
- network: options.network || this.network,
166
- version: options.version || this.version,
167
- useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
168
- });
169
- console.log("Publish file tx:", tx.stringify());
170
- // Send the transaction
171
- const txHash = await this.signer.sendTransaction(tx);
172
- return (0, transaction_2.ensureHexPrefix)(txHash);
168
+ // Determine version - default to V3, allow override
169
+ const version = options.version || this.version;
170
+ // Use V3 by default, fallback to legacy for older versions
171
+ if (version === constants_1.ProtocolVersion.V3) {
172
+ const tx = await (0, transaction_1.publishCKBFSV3)(this.signer, {
173
+ contentChunks,
174
+ contentType,
175
+ filename,
176
+ lock,
177
+ capacity: options.capacity,
178
+ feeRate: options.feeRate,
179
+ network: options.network || this.network,
180
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
181
+ version: constants_1.ProtocolVersion.V3,
182
+ });
183
+ console.log("Publish file tx:", tx.stringify());
184
+ // Send the transaction
185
+ const txHash = await this.signer.sendTransaction(tx);
186
+ return (0, transaction_2.ensureHexPrefix)(txHash);
187
+ }
188
+ else {
189
+ // Legacy V1/V2 behavior
190
+ const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
191
+ contentChunks,
192
+ contentType,
193
+ filename,
194
+ lock,
195
+ capacity: options.capacity,
196
+ feeRate: options.feeRate,
197
+ network: options.network || this.network,
198
+ version,
199
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
200
+ });
201
+ console.log("Publish file tx:", tx.stringify());
202
+ // Send the transaction
203
+ const txHash = await this.signer.sendTransaction(tx);
204
+ return (0, transaction_2.ensureHexPrefix)(txHash);
205
+ }
173
206
  }
174
207
  /**
175
208
  * Publishes content (string or Uint8Array) directly to CKBFS
@@ -186,20 +219,40 @@ class CKBFS {
186
219
  const lock = await this.getLock();
187
220
  // Use provided contentType and filename (required)
188
221
  const { contentType, filename } = options;
189
- const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
190
- contentChunks,
191
- contentType,
192
- filename,
193
- lock,
194
- capacity: options.capacity,
195
- feeRate: options.feeRate,
196
- network: options.network || this.network,
197
- version: options.version || this.version,
198
- useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
199
- });
200
- console.log("Publish content tx:", tx.stringify());
201
- const txHash = await this.signer.sendTransaction(tx);
202
- return (0, transaction_2.ensureHexPrefix)(txHash);
222
+ // Determine version - default to V3, allow override
223
+ const version = options.version || this.version;
224
+ // Use V3 by default, fallback to legacy for older versions
225
+ if (version === constants_1.ProtocolVersion.V3) {
226
+ const tx = await (0, transaction_1.publishCKBFSV3)(this.signer, {
227
+ contentChunks,
228
+ contentType,
229
+ filename,
230
+ lock,
231
+ capacity: options.capacity,
232
+ feeRate: options.feeRate,
233
+ network: options.network || this.network,
234
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
235
+ version: constants_1.ProtocolVersion.V3,
236
+ });
237
+ const txHash = await this.signer.sendTransaction(tx);
238
+ return (0, transaction_2.ensureHexPrefix)(txHash);
239
+ }
240
+ else {
241
+ // Legacy V1/V2 behavior
242
+ const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
243
+ contentChunks,
244
+ contentType,
245
+ filename,
246
+ lock,
247
+ capacity: options.capacity,
248
+ feeRate: options.feeRate,
249
+ network: options.network || this.network,
250
+ version,
251
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
252
+ });
253
+ const txHash = await this.signer.sendTransaction(tx);
254
+ return (0, transaction_2.ensureHexPrefix)(txHash);
255
+ }
203
256
  }
204
257
  /**
205
258
  * Appends content from a file to an existing CKBFS file
@@ -215,18 +268,40 @@ class CKBFS {
215
268
  for (let i = 0; i < fileContent.length; i += this.chunkSize) {
216
269
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
217
270
  }
218
- // Create and sign the transaction using the utility function
219
- const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
220
- ckbfsCell,
221
- contentChunks,
222
- feeRate: options.feeRate,
223
- network: options.network || this.network,
224
- version: options.version || this.version,
225
- });
226
- console.log("Append file tx:", tx.stringify());
227
- // Send the transaction
228
- const txHash = await this.signer.sendTransaction(tx);
229
- return (0, transaction_2.ensureHexPrefix)(txHash);
271
+ // Determine version - default to V3, allow override
272
+ const version = options.version || this.version;
273
+ // Use V3 when backlink parameters are provided or version is V3
274
+ if (version === constants_1.ProtocolVersion.V3 &&
275
+ options.previousTxHash &&
276
+ options.previousWitnessIndex !== undefined &&
277
+ options.previousChecksum !== undefined) {
278
+ const tx = await (0, transaction_1.appendCKBFSV3)(this.signer, {
279
+ ckbfsCell,
280
+ contentChunks,
281
+ feeRate: options.feeRate,
282
+ network: options.network || this.network,
283
+ version: constants_1.ProtocolVersion.V3,
284
+ previousTxHash: options.previousTxHash,
285
+ previousWitnessIndex: options.previousWitnessIndex,
286
+ previousChecksum: options.previousChecksum,
287
+ });
288
+ console.log("Append file v3 tx:", tx.stringify());
289
+ const txHash = await this.signer.sendTransaction(tx);
290
+ return (0, transaction_2.ensureHexPrefix)(txHash);
291
+ }
292
+ else {
293
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
294
+ const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
295
+ ckbfsCell,
296
+ contentChunks,
297
+ feeRate: options.feeRate,
298
+ network: options.network || this.network,
299
+ version: version === constants_1.ProtocolVersion.V3 ? constants_1.ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
300
+ });
301
+ console.log("Append file tx:", tx.stringify());
302
+ const txHash = await this.signer.sendTransaction(tx);
303
+ return (0, transaction_2.ensureHexPrefix)(txHash);
304
+ }
230
305
  }
231
306
  /**
232
307
  * Appends content (string or Uint8Array) directly to an existing CKBFS file
@@ -241,17 +316,39 @@ class CKBFS {
241
316
  for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
242
317
  contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
243
318
  }
244
- const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
245
- ckbfsCell,
246
- contentChunks,
247
- feeRate: options.feeRate,
248
- network: options.network || this.network,
249
- version: options.version || this.version,
250
- // No useTypeID option for append
251
- });
252
- console.log("Append content tx:", tx.stringify());
253
- const txHash = await this.signer.sendTransaction(tx);
254
- return (0, transaction_2.ensureHexPrefix)(txHash);
319
+ // Determine version - default to V3, allow override
320
+ const version = options.version || this.version;
321
+ // Use V3 when backlink parameters are provided or version is V3
322
+ if (version === constants_1.ProtocolVersion.V3 &&
323
+ options.previousTxHash &&
324
+ options.previousWitnessIndex !== undefined &&
325
+ options.previousChecksum !== undefined) {
326
+ const tx = await (0, transaction_1.appendCKBFSV3)(this.signer, {
327
+ ckbfsCell,
328
+ contentChunks,
329
+ feeRate: options.feeRate,
330
+ network: options.network || this.network,
331
+ version: constants_1.ProtocolVersion.V3,
332
+ previousTxHash: options.previousTxHash,
333
+ previousWitnessIndex: options.previousWitnessIndex,
334
+ previousChecksum: options.previousChecksum,
335
+ });
336
+ const txHash = await this.signer.sendTransaction(tx);
337
+ return (0, transaction_2.ensureHexPrefix)(txHash);
338
+ }
339
+ else {
340
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
341
+ const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
342
+ ckbfsCell,
343
+ contentChunks,
344
+ feeRate: options.feeRate,
345
+ network: options.network || this.network,
346
+ version: version === constants_1.ProtocolVersion.V3 ? constants_1.ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
347
+ // No useTypeID option for append
348
+ });
349
+ const txHash = await this.signer.sendTransaction(tx);
350
+ return (0, transaction_2.ensureHexPrefix)(txHash);
351
+ }
255
352
  }
256
353
  /**
257
354
  * Creates a new transaction for publishing a file but doesn't sign or send it
@@ -273,8 +370,192 @@ class CKBFS {
273
370
  // Use the filename from the path if not provided
274
371
  const pathParts = filePath.split(/[\\\/]/);
275
372
  const filename = options.filename || pathParts[pathParts.length - 1];
276
- // Create the transaction using the utility function
277
- return (0, transaction_1.createPublishTransaction)(this.signer, {
373
+ // Determine version - default to V3, allow override
374
+ const version = options.version || this.version;
375
+ // Use V3 by default, fallback to legacy for older versions
376
+ if (version === constants_1.ProtocolVersion.V3) {
377
+ return (0, transaction_1.createPublishV3Transaction)(this.signer, {
378
+ contentChunks,
379
+ contentType,
380
+ filename,
381
+ lock,
382
+ capacity: options.capacity,
383
+ feeRate: options.feeRate,
384
+ network: options.network || this.network,
385
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
386
+ version: constants_1.ProtocolVersion.V3,
387
+ });
388
+ }
389
+ else {
390
+ // Legacy V1/V2 behavior
391
+ return (0, transaction_1.createPublishTransaction)(this.signer, {
392
+ contentChunks,
393
+ contentType,
394
+ filename,
395
+ lock,
396
+ capacity: options.capacity,
397
+ feeRate: options.feeRate,
398
+ network: options.network || this.network,
399
+ version,
400
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
401
+ });
402
+ }
403
+ }
404
+ /**
405
+ * Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
406
+ * @param content The content string or byte array to publish
407
+ * @param options Options for publishing the content (contentType and filename are required)
408
+ * @returns Promise resolving to the unsigned transaction
409
+ */
410
+ async createPublishContentTransaction(content, options) {
411
+ const contentBytes = typeof content === "string" ? textEncoder.encode(content) : content;
412
+ const contentChunks = [];
413
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
414
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
415
+ }
416
+ const lock = await this.getLock();
417
+ // Use provided contentType and filename (required)
418
+ const { contentType, filename } = options;
419
+ // Determine version - default to V3, allow override
420
+ const version = options.version || this.version;
421
+ // Use V3 by default, fallback to legacy for older versions
422
+ if (version === constants_1.ProtocolVersion.V3) {
423
+ return (0, transaction_1.createPublishV3Transaction)(this.signer, {
424
+ contentChunks,
425
+ contentType,
426
+ filename,
427
+ lock,
428
+ capacity: options.capacity,
429
+ feeRate: options.feeRate,
430
+ network: options.network || this.network,
431
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
432
+ version: constants_1.ProtocolVersion.V3,
433
+ });
434
+ }
435
+ else {
436
+ // Legacy V1/V2 behavior
437
+ return (0, transaction_1.createPublishTransaction)(this.signer, {
438
+ contentChunks,
439
+ contentType,
440
+ filename,
441
+ lock,
442
+ capacity: options.capacity,
443
+ feeRate: options.feeRate,
444
+ network: options.network || this.network,
445
+ version,
446
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
447
+ });
448
+ }
449
+ }
450
+ /**
451
+ * Creates a new transaction for appending content from a file but doesn't sign or send it
452
+ * @param filePath The path to the file containing the content to append
453
+ * @param ckbfsCell The CKBFS cell to append to
454
+ * @param options Additional options for the append operation
455
+ * @returns Promise resolving to the unsigned transaction
456
+ */
457
+ async createAppendTransaction(filePath, ckbfsCell, options = {}) {
458
+ // Read the file and split into chunks
459
+ const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
460
+ const contentChunks = [];
461
+ for (let i = 0; i < fileContent.length; i += this.chunkSize) {
462
+ contentChunks.push(fileContent.slice(i, i + this.chunkSize));
463
+ }
464
+ // Determine version - default to V3, allow override
465
+ const version = options.version || this.version;
466
+ // Use V3 when backlink parameters are provided or version is V3
467
+ if (version === constants_1.ProtocolVersion.V3 &&
468
+ options.previousTxHash &&
469
+ options.previousWitnessIndex !== undefined &&
470
+ options.previousChecksum !== undefined) {
471
+ return (0, transaction_1.createAppendV3Transaction)(this.signer, {
472
+ ckbfsCell,
473
+ contentChunks,
474
+ feeRate: options.feeRate,
475
+ network: options.network || this.network,
476
+ version: constants_1.ProtocolVersion.V3,
477
+ previousTxHash: options.previousTxHash,
478
+ previousWitnessIndex: options.previousWitnessIndex,
479
+ previousChecksum: options.previousChecksum,
480
+ });
481
+ }
482
+ else {
483
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
484
+ return (0, transaction_1.createAppendTransaction)(this.signer, {
485
+ ckbfsCell,
486
+ contentChunks,
487
+ feeRate: options.feeRate,
488
+ network: options.network || this.network,
489
+ version: version === constants_1.ProtocolVersion.V3 ? constants_1.ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
490
+ });
491
+ }
492
+ }
493
+ /**
494
+ * Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
495
+ * @param content The content string or byte array to append
496
+ * @param ckbfsCell The CKBFS cell to append to
497
+ * @param options Additional options for the append operation
498
+ * @returns Promise resolving to the unsigned transaction
499
+ */
500
+ async createAppendContentTransaction(content, ckbfsCell, options = {}) {
501
+ const contentBytes = typeof content === "string" ? textEncoder.encode(content) : content;
502
+ const contentChunks = [];
503
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
504
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
505
+ }
506
+ // Determine version - default to V3, allow override
507
+ const version = options.version || this.version;
508
+ // Use V3 when backlink parameters are provided or version is V3
509
+ if (version === constants_1.ProtocolVersion.V3 &&
510
+ options.previousTxHash &&
511
+ options.previousWitnessIndex !== undefined &&
512
+ options.previousChecksum !== undefined) {
513
+ return (0, transaction_1.createAppendV3Transaction)(this.signer, {
514
+ ckbfsCell,
515
+ contentChunks,
516
+ feeRate: options.feeRate,
517
+ network: options.network || this.network,
518
+ version: constants_1.ProtocolVersion.V3,
519
+ previousTxHash: options.previousTxHash,
520
+ previousWitnessIndex: options.previousWitnessIndex,
521
+ previousChecksum: options.previousChecksum,
522
+ });
523
+ }
524
+ else {
525
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
526
+ return (0, transaction_1.createAppendTransaction)(this.signer, {
527
+ ckbfsCell,
528
+ contentChunks,
529
+ feeRate: options.feeRate,
530
+ network: options.network || this.network,
531
+ version: version === constants_1.ProtocolVersion.V3 ? constants_1.ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
532
+ // No useTypeID option for append
533
+ });
534
+ }
535
+ }
536
+ // V3 Methods
537
+ /**
538
+ * Publishes a file to CKBFS v3
539
+ * @param filePath The path to the file to publish
540
+ * @param options Options for publishing the file
541
+ * @returns Promise resolving to the transaction hash
542
+ */
543
+ async publishFileV3(filePath, options = {}) {
544
+ // Read the file and split into chunks
545
+ const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
546
+ const contentChunks = [];
547
+ for (let i = 0; i < fileContent.length; i += this.chunkSize) {
548
+ contentChunks.push(fileContent.slice(i, i + this.chunkSize));
549
+ }
550
+ // Get the lock script
551
+ const lock = await this.getLock();
552
+ // Determine content type if not provided
553
+ const contentType = options.contentType || (0, file_1.getContentType)(filePath);
554
+ // Use the filename from the path if not provided
555
+ const pathParts = filePath.split(/[\\\/]/);
556
+ const filename = options.filename || pathParts[pathParts.length - 1];
557
+ // Create and sign the transaction using the v3 utility function
558
+ const tx = await (0, transaction_1.publishCKBFSV3)(this.signer, {
278
559
  contentChunks,
279
560
  contentType,
280
561
  filename,
@@ -282,17 +563,21 @@ class CKBFS {
282
563
  capacity: options.capacity,
283
564
  feeRate: options.feeRate,
284
565
  network: options.network || this.network,
285
- version: options.version || this.version,
286
566
  useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
567
+ version: constants_1.ProtocolVersion.V3,
287
568
  });
569
+ console.log("Publish file v3 tx:", tx.stringify());
570
+ // Send the transaction
571
+ const txHash = await this.signer.sendTransaction(tx);
572
+ return (0, transaction_2.ensureHexPrefix)(txHash);
288
573
  }
289
574
  /**
290
- * Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
575
+ * Publishes content (string or Uint8Array) directly to CKBFS v3
291
576
  * @param content The content string or byte array to publish
292
577
  * @param options Options for publishing the content (contentType and filename are required)
293
- * @returns Promise resolving to the unsigned transaction
578
+ * @returns Promise resolving to the transaction hash
294
579
  */
295
- async createPublishContentTransaction(content, options) {
580
+ async publishContentV3(content, options) {
296
581
  const contentBytes = typeof content === "string" ? textEncoder.encode(content) : content;
297
582
  const contentChunks = [];
298
583
  for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
@@ -301,7 +586,7 @@ class CKBFS {
301
586
  const lock = await this.getLock();
302
587
  // Use provided contentType and filename (required)
303
588
  const { contentType, filename } = options;
304
- return (0, transaction_1.createPublishTransaction)(this.signer, {
589
+ const tx = await (0, transaction_1.publishCKBFSV3)(this.signer, {
305
590
  contentChunks,
306
591
  contentType,
307
592
  filename,
@@ -309,53 +594,130 @@ class CKBFS {
309
594
  capacity: options.capacity,
310
595
  feeRate: options.feeRate,
311
596
  network: options.network || this.network,
312
- version: options.version || this.version,
313
597
  useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
598
+ version: constants_1.ProtocolVersion.V3,
314
599
  });
600
+ const txHash = await this.signer.sendTransaction(tx);
601
+ return (0, transaction_2.ensureHexPrefix)(txHash);
315
602
  }
316
603
  /**
317
- * Creates a new transaction for appending content from a file but doesn't sign or send it
604
+ * Appends content from a file to an existing CKBFS v3 file
318
605
  * @param filePath The path to the file containing the content to append
319
606
  * @param ckbfsCell The CKBFS cell to append to
607
+ * @param previousTxHash The previous transaction hash for backlink
608
+ * @param previousWitnessIndex The previous witness index for backlink
609
+ * @param previousChecksum The previous checksum for backlink
320
610
  * @param options Additional options for the append operation
321
- * @returns Promise resolving to the unsigned transaction
611
+ * @returns Promise resolving to the transaction hash
322
612
  */
323
- async createAppendTransaction(filePath, ckbfsCell, options = {}) {
613
+ async appendFileV3(filePath, ckbfsCell, previousTxHash, previousWitnessIndex, previousChecksum, options = {}) {
324
614
  // Read the file and split into chunks
325
615
  const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
326
616
  const contentChunks = [];
327
617
  for (let i = 0; i < fileContent.length; i += this.chunkSize) {
328
618
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
329
619
  }
330
- // Create the transaction using the utility function
331
- return (0, transaction_1.createAppendTransaction)(this.signer, {
620
+ // Create and sign the transaction using the v3 utility function
621
+ const tx = await (0, transaction_1.appendCKBFSV3)(this.signer, {
332
622
  ckbfsCell,
333
623
  contentChunks,
334
624
  feeRate: options.feeRate,
335
625
  network: options.network || this.network,
336
- version: options.version || this.version,
626
+ version: constants_1.ProtocolVersion.V3,
627
+ previousTxHash,
628
+ previousWitnessIndex,
629
+ previousChecksum,
337
630
  });
631
+ console.log("Append file v3 tx:", tx.stringify());
632
+ // Send the transaction
633
+ const txHash = await this.signer.sendTransaction(tx);
634
+ return (0, transaction_2.ensureHexPrefix)(txHash);
338
635
  }
339
636
  /**
340
- * Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
637
+ * Appends content (string or Uint8Array) directly to an existing CKBFS v3 file
341
638
  * @param content The content string or byte array to append
342
639
  * @param ckbfsCell The CKBFS cell to append to
640
+ * @param previousTxHash The previous transaction hash for backlink
641
+ * @param previousWitnessIndex The previous witness index for backlink
642
+ * @param previousChecksum The previous checksum for backlink
343
643
  * @param options Additional options for the append operation
344
- * @returns Promise resolving to the unsigned transaction
644
+ * @returns Promise resolving to the transaction hash
345
645
  */
346
- async createAppendContentTransaction(content, ckbfsCell, options = {}) {
646
+ async appendContentV3(content, ckbfsCell, previousTxHash, previousWitnessIndex, previousChecksum, options = {}) {
347
647
  const contentBytes = typeof content === "string" ? textEncoder.encode(content) : content;
348
648
  const contentChunks = [];
349
649
  for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
350
650
  contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
351
651
  }
352
- return (0, transaction_1.createAppendTransaction)(this.signer, {
652
+ const tx = await (0, transaction_1.appendCKBFSV3)(this.signer, {
353
653
  ckbfsCell,
354
654
  contentChunks,
355
655
  feeRate: options.feeRate,
356
656
  network: options.network || this.network,
357
- version: options.version || this.version,
358
- // No useTypeID option for append
657
+ version: constants_1.ProtocolVersion.V3,
658
+ previousTxHash,
659
+ previousWitnessIndex,
660
+ previousChecksum,
661
+ });
662
+ const txHash = await this.signer.sendTransaction(tx);
663
+ return (0, transaction_2.ensureHexPrefix)(txHash);
664
+ }
665
+ /**
666
+ * Transfers ownership of a CKBFS v3 file to a new lock script
667
+ * @param ckbfsCell The CKBFS cell to transfer
668
+ * @param newLock The new lock script for the transferred file
669
+ * @param previousTxHash The previous transaction hash for backlink
670
+ * @param previousWitnessIndex The previous witness index for backlink
671
+ * @param previousChecksum The previous checksum for backlink
672
+ * @param options Additional options for the transfer operation
673
+ * @returns Promise resolving to the transaction hash
674
+ */
675
+ async transferFileV3(ckbfsCell, newLock, previousTxHash, previousWitnessIndex, previousChecksum, options = {}) {
676
+ const tx = await (0, transaction_1.transferCKBFSV3)(this.signer, {
677
+ ckbfsCell,
678
+ newLock,
679
+ feeRate: options.feeRate,
680
+ network: options.network || this.network,
681
+ version: constants_1.ProtocolVersion.V3,
682
+ previousTxHash,
683
+ previousWitnessIndex,
684
+ previousChecksum,
685
+ });
686
+ console.log("Transfer file v3 tx:", tx.stringify());
687
+ const txHash = await this.signer.sendTransaction(tx);
688
+ return (0, transaction_2.ensureHexPrefix)(txHash);
689
+ }
690
+ /**
691
+ * Creates a new transaction for publishing a file to CKBFS v3 but doesn't sign or send it
692
+ * @param filePath The path to the file to publish
693
+ * @param options Options for publishing the file
694
+ * @returns Promise resolving to the unsigned transaction
695
+ */
696
+ async createPublishV3Transaction(filePath, options = {}) {
697
+ // Read the file and split into chunks
698
+ const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
699
+ const contentChunks = [];
700
+ for (let i = 0; i < fileContent.length; i += this.chunkSize) {
701
+ contentChunks.push(fileContent.slice(i, i + this.chunkSize));
702
+ }
703
+ // Get the lock script
704
+ const lock = await this.getLock();
705
+ // Determine content type if not provided
706
+ const contentType = options.contentType || (0, file_1.getContentType)(filePath);
707
+ // Use the filename from the path if not provided
708
+ const pathParts = filePath.split(/[\\\/]/);
709
+ const filename = options.filename || pathParts[pathParts.length - 1];
710
+ // Create the transaction using the utility function
711
+ return (0, transaction_1.createPublishV3Transaction)(this.signer, {
712
+ contentChunks,
713
+ contentType,
714
+ filename,
715
+ lock,
716
+ capacity: options.capacity,
717
+ feeRate: options.feeRate,
718
+ network: options.network || this.network,
719
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
720
+ version: constants_1.ProtocolVersion.V3,
359
721
  });
360
722
  }
361
723
  }
@@ -31,3 +31,19 @@ export declare function verifyChecksum(data: Uint8Array, expectedChecksum: numbe
31
31
  export declare function verifyWitnessChecksum(witness: Uint8Array, expectedChecksum: number, backlinks?: {
32
32
  checksum: number;
33
33
  }[]): Promise<boolean>;
34
+ /**
35
+ * Verifies the checksum of a CKBFS v3 witness
36
+ * @param witness The v3 witness bytes
37
+ * @param expectedChecksum The expected checksum
38
+ * @param previousChecksum Optional previous checksum for chained verification
39
+ * @returns Promise resolving to a boolean indicating whether the checksum is valid
40
+ */
41
+ export declare function verifyV3WitnessChecksum(witness: Uint8Array, expectedChecksum: number, previousChecksum?: number): Promise<boolean>;
42
+ /**
43
+ * Verifies the checksum chain for multiple v3 witnesses
44
+ * @param witnesses Array of v3 witness bytes
45
+ * @param finalExpectedChecksum The expected final checksum
46
+ * @param initialChecksum Optional initial checksum (for append operations)
47
+ * @returns Promise resolving to a boolean indicating whether the checksum chain is valid
48
+ */
49
+ export declare function verifyV3WitnessChain(witnesses: Uint8Array[], finalExpectedChecksum: number, initialChecksum?: number): Promise<boolean>;