@ckbfs/api 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +440 -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 -105
  16. package/dist/utils/transaction.js +45 -565
  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/src/index.ts CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  verifyChecksum,
12
12
  updateChecksum,
13
13
  verifyWitnessChecksum,
14
+ verifyV3WitnessChecksum,
15
+ verifyV3WitnessChain,
14
16
  } from "./utils/checksum";
15
17
  import {
16
18
  createCKBFSCell,
@@ -24,6 +26,16 @@ import {
24
26
  CKBFSCellOptions,
25
27
  PublishOptions,
26
28
  AppendOptions,
29
+ // V3 functions
30
+ PublishV3Options,
31
+ AppendV3Options,
32
+ TransferV3Options,
33
+ publishCKBFSV3,
34
+ appendCKBFSV3,
35
+ transferCKBFSV3,
36
+ createPublishV3Transaction,
37
+ createAppendV3Transaction,
38
+ createTransferV3Transaction,
27
39
  } from "./utils/transaction";
28
40
  import {
29
41
  readFile,
@@ -48,6 +60,10 @@ import {
48
60
  extractFileFromWitnesses,
49
61
  decodeFileFromWitnessData,
50
62
  saveFileFromWitnessData,
63
+ // V3 file retrieval functions
64
+ getFileContentFromChainV3,
65
+ getFileContentFromChainByIdentifierV3,
66
+ saveFileFromChainByIdentifierV3,
51
67
  } from "./utils/file";
52
68
  import {
53
69
  createCKBFSWitness,
@@ -55,6 +71,11 @@ import {
55
71
  extractCKBFSWitnessContent,
56
72
  isCKBFSWitness,
57
73
  createChunkedCKBFSWitnesses,
74
+ createCKBFSV3Witness,
75
+ createChunkedCKBFSV3Witnesses,
76
+ extractCKBFSV3WitnessContent,
77
+ isCKBFSV3Witness,
78
+ CKBFSV3WitnessOptions,
58
79
  } from "./utils/witness";
59
80
  import {
60
81
  CKBFSData,
@@ -115,7 +136,13 @@ export type PublishContentOptions = Omit<
115
136
  export type AppendContentOptions = Omit<
116
137
  FileOptions,
117
138
  "contentType" | "filename" | "capacity"
118
- > & { capacity?: bigint };
139
+ > & {
140
+ capacity?: bigint;
141
+ // V3 backlink parameters (optional for backward compatibility)
142
+ previousTxHash?: string;
143
+ previousWitnessIndex?: number;
144
+ previousChecksum?: number;
145
+ };
119
146
 
120
147
  /**
121
148
  * Configuration options for the CKBFS SDK
@@ -242,26 +269,52 @@ export class CKBFS {
242
269
  const pathParts = filePath.split(/[\\\/]/);
243
270
  const filename = options.filename || pathParts[pathParts.length - 1];
244
271
 
245
- // Create and sign the transaction using the utility function
246
- const tx = await utilPublishCKBFS(this.signer, {
247
- contentChunks,
248
- contentType,
249
- filename,
250
- lock,
251
- capacity: options.capacity,
252
- feeRate: options.feeRate,
253
- network: options.network || this.network,
254
- version: options.version || this.version,
255
- useTypeID:
256
- options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
257
- });
272
+ // Determine version - default to V3, allow override
273
+ const version = options.version || this.version;
258
274
 
259
- console.log("Publish file tx:", tx.stringify());
275
+ // Use V3 by default, fallback to legacy for older versions
276
+ if (version === ProtocolVersion.V3) {
277
+ const tx = await publishCKBFSV3(this.signer, {
278
+ contentChunks,
279
+ contentType,
280
+ filename,
281
+ lock,
282
+ capacity: options.capacity,
283
+ feeRate: options.feeRate,
284
+ network: options.network || this.network,
285
+ useTypeID:
286
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
287
+ version: ProtocolVersion.V3,
288
+ });
260
289
 
261
- // Send the transaction
262
- const txHash = await this.signer.sendTransaction(tx);
290
+ console.log("Publish file tx:", tx.stringify());
263
291
 
264
- return ensureHexPrefix(txHash);
292
+ // Send the transaction
293
+ const txHash = await this.signer.sendTransaction(tx);
294
+
295
+ return ensureHexPrefix(txHash);
296
+ } else {
297
+ // Legacy V1/V2 behavior
298
+ const tx = await utilPublishCKBFS(this.signer, {
299
+ contentChunks,
300
+ contentType,
301
+ filename,
302
+ lock,
303
+ capacity: options.capacity,
304
+ feeRate: options.feeRate,
305
+ network: options.network || this.network,
306
+ version,
307
+ useTypeID:
308
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
309
+ });
310
+
311
+ console.log("Publish file tx:", tx.stringify());
312
+
313
+ // Send the transaction
314
+ const txHash = await this.signer.sendTransaction(tx);
315
+
316
+ return ensureHexPrefix(txHash);
317
+ }
265
318
  }
266
319
 
267
320
  /**
@@ -287,23 +340,44 @@ export class CKBFS {
287
340
  // Use provided contentType and filename (required)
288
341
  const { contentType, filename } = options;
289
342
 
290
- const tx = await utilPublishCKBFS(this.signer, {
291
- contentChunks,
292
- contentType,
293
- filename,
294
- lock,
295
- capacity: options.capacity,
296
- feeRate: options.feeRate,
297
- network: options.network || this.network,
298
- version: options.version || this.version,
299
- useTypeID:
300
- options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
301
- });
343
+ // Determine version - default to V3, allow override
344
+ const version = options.version || this.version;
302
345
 
303
- console.log("Publish content tx:", tx.stringify());
346
+ // Use V3 by default, fallback to legacy for older versions
347
+ if (version === ProtocolVersion.V3) {
348
+ const tx = await publishCKBFSV3(this.signer, {
349
+ contentChunks,
350
+ contentType,
351
+ filename,
352
+ lock,
353
+ capacity: options.capacity,
354
+ feeRate: options.feeRate,
355
+ network: options.network || this.network,
356
+ useTypeID:
357
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
358
+ version: ProtocolVersion.V3,
359
+ });
304
360
 
305
- const txHash = await this.signer.sendTransaction(tx);
306
- return ensureHexPrefix(txHash);
361
+ const txHash = await this.signer.sendTransaction(tx);
362
+ return ensureHexPrefix(txHash);
363
+ } else {
364
+ // Legacy V1/V2 behavior
365
+ const tx = await utilPublishCKBFS(this.signer, {
366
+ contentChunks,
367
+ contentType,
368
+ filename,
369
+ lock,
370
+ capacity: options.capacity,
371
+ feeRate: options.feeRate,
372
+ network: options.network || this.network,
373
+ version,
374
+ useTypeID:
375
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
376
+ });
377
+
378
+ const txHash = await this.signer.sendTransaction(tx);
379
+ return ensureHexPrefix(txHash);
380
+ }
307
381
  }
308
382
 
309
383
  /**
@@ -316,7 +390,12 @@ export class CKBFS {
316
390
  async appendFile(
317
391
  filePath: string,
318
392
  ckbfsCell: AppendOptions["ckbfsCell"],
319
- options: Omit<FileOptions, "contentType" | "filename"> = {},
393
+ options: Omit<FileOptions, "contentType" | "filename"> & {
394
+ // V3 backlink parameters (optional for backward compatibility)
395
+ previousTxHash?: string;
396
+ previousWitnessIndex?: number;
397
+ previousChecksum?: number;
398
+ } = {},
320
399
  ): Promise<string> {
321
400
  // Read the file and split into chunks
322
401
  const fileContent = readFileAsUint8Array(filePath);
@@ -326,21 +405,45 @@ export class CKBFS {
326
405
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
327
406
  }
328
407
 
329
- // Create and sign the transaction using the utility function
330
- const tx = await utilAppendCKBFS(this.signer, {
331
- ckbfsCell,
332
- contentChunks,
333
- feeRate: options.feeRate,
334
- network: options.network || this.network,
335
- version: options.version || this.version,
336
- });
408
+ // Determine version - default to V3, allow override
409
+ const version = options.version || this.version;
337
410
 
338
- console.log("Append file tx:", tx.stringify());
411
+ // Use V3 when backlink parameters are provided or version is V3
412
+ if (version === ProtocolVersion.V3 &&
413
+ options.previousTxHash &&
414
+ options.previousWitnessIndex !== undefined &&
415
+ options.previousChecksum !== undefined) {
416
+
417
+ const tx = await appendCKBFSV3(this.signer, {
418
+ ckbfsCell,
419
+ contentChunks,
420
+ feeRate: options.feeRate,
421
+ network: options.network || this.network,
422
+ version: ProtocolVersion.V3,
423
+ previousTxHash: options.previousTxHash,
424
+ previousWitnessIndex: options.previousWitnessIndex,
425
+ previousChecksum: options.previousChecksum,
426
+ });
339
427
 
340
- // Send the transaction
341
- const txHash = await this.signer.sendTransaction(tx);
428
+ console.log("Append file v3 tx:", tx.stringify());
342
429
 
343
- return ensureHexPrefix(txHash);
430
+ const txHash = await this.signer.sendTransaction(tx);
431
+ return ensureHexPrefix(txHash);
432
+ } else {
433
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
434
+ const tx = await utilAppendCKBFS(this.signer, {
435
+ ckbfsCell,
436
+ contentChunks,
437
+ feeRate: options.feeRate,
438
+ network: options.network || this.network,
439
+ version: version === ProtocolVersion.V3 ? ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
440
+ });
441
+
442
+ console.log("Append file tx:", tx.stringify());
443
+
444
+ const txHash = await this.signer.sendTransaction(tx);
445
+ return ensureHexPrefix(txHash);
446
+ }
344
447
  }
345
448
 
346
449
  /**
@@ -363,19 +466,42 @@ export class CKBFS {
363
466
  contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
364
467
  }
365
468
 
366
- const tx = await utilAppendCKBFS(this.signer, {
367
- ckbfsCell,
368
- contentChunks,
369
- feeRate: options.feeRate,
370
- network: options.network || this.network,
371
- version: options.version || this.version,
372
- // No useTypeID option for append
373
- });
469
+ // Determine version - default to V3, allow override
470
+ const version = options.version || this.version;
374
471
 
375
- console.log("Append content tx:", tx.stringify());
472
+ // Use V3 when backlink parameters are provided or version is V3
473
+ if (version === ProtocolVersion.V3 &&
474
+ options.previousTxHash &&
475
+ options.previousWitnessIndex !== undefined &&
476
+ options.previousChecksum !== undefined) {
477
+
478
+ const tx = await appendCKBFSV3(this.signer, {
479
+ ckbfsCell,
480
+ contentChunks,
481
+ feeRate: options.feeRate,
482
+ network: options.network || this.network,
483
+ version: ProtocolVersion.V3,
484
+ previousTxHash: options.previousTxHash,
485
+ previousWitnessIndex: options.previousWitnessIndex,
486
+ previousChecksum: options.previousChecksum,
487
+ });
376
488
 
377
- const txHash = await this.signer.sendTransaction(tx);
378
- return ensureHexPrefix(txHash);
489
+ const txHash = await this.signer.sendTransaction(tx);
490
+ return ensureHexPrefix(txHash);
491
+ } else {
492
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
493
+ const tx = await utilAppendCKBFS(this.signer, {
494
+ ckbfsCell,
495
+ contentChunks,
496
+ feeRate: options.feeRate,
497
+ network: options.network || this.network,
498
+ version: version === ProtocolVersion.V3 ? ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
499
+ // No useTypeID option for append
500
+ });
501
+
502
+ const txHash = await this.signer.sendTransaction(tx);
503
+ return ensureHexPrefix(txHash);
504
+ }
379
505
  }
380
506
 
381
507
  /**
@@ -406,8 +532,237 @@ export class CKBFS {
406
532
  const pathParts = filePath.split(/[\\\/]/);
407
533
  const filename = options.filename || pathParts[pathParts.length - 1];
408
534
 
409
- // Create the transaction using the utility function
410
- return utilCreatePublishTransaction(this.signer, {
535
+ // Determine version - default to V3, allow override
536
+ const version = options.version || this.version;
537
+
538
+ // Use V3 by default, fallback to legacy for older versions
539
+ if (version === ProtocolVersion.V3) {
540
+ return createPublishV3Transaction(this.signer, {
541
+ contentChunks,
542
+ contentType,
543
+ filename,
544
+ lock,
545
+ capacity: options.capacity,
546
+ feeRate: options.feeRate,
547
+ network: options.network || this.network,
548
+ useTypeID:
549
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
550
+ version: ProtocolVersion.V3,
551
+ });
552
+ } else {
553
+ // Legacy V1/V2 behavior
554
+ return utilCreatePublishTransaction(this.signer, {
555
+ contentChunks,
556
+ contentType,
557
+ filename,
558
+ lock,
559
+ capacity: options.capacity,
560
+ feeRate: options.feeRate,
561
+ network: options.network || this.network,
562
+ version,
563
+ useTypeID:
564
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
565
+ });
566
+ }
567
+ }
568
+
569
+ /**
570
+ * Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
571
+ * @param content The content string or byte array to publish
572
+ * @param options Options for publishing the content (contentType and filename are required)
573
+ * @returns Promise resolving to the unsigned transaction
574
+ */
575
+ async createPublishContentTransaction(
576
+ content: string | Uint8Array,
577
+ options: PublishContentOptions,
578
+ ): Promise<Transaction> {
579
+ const contentBytes =
580
+ typeof content === "string" ? textEncoder.encode(content) : content;
581
+ const contentChunks = [];
582
+
583
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
584
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
585
+ }
586
+
587
+ const lock = await this.getLock();
588
+
589
+ // Use provided contentType and filename (required)
590
+ const { contentType, filename } = options;
591
+
592
+ // Determine version - default to V3, allow override
593
+ const version = options.version || this.version;
594
+
595
+ // Use V3 by default, fallback to legacy for older versions
596
+ if (version === ProtocolVersion.V3) {
597
+ return createPublishV3Transaction(this.signer, {
598
+ contentChunks,
599
+ contentType,
600
+ filename,
601
+ lock,
602
+ capacity: options.capacity,
603
+ feeRate: options.feeRate,
604
+ network: options.network || this.network,
605
+ useTypeID:
606
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
607
+ version: ProtocolVersion.V3,
608
+ });
609
+ } else {
610
+ // Legacy V1/V2 behavior
611
+ return utilCreatePublishTransaction(this.signer, {
612
+ contentChunks,
613
+ contentType,
614
+ filename,
615
+ lock,
616
+ capacity: options.capacity,
617
+ feeRate: options.feeRate,
618
+ network: options.network || this.network,
619
+ version,
620
+ useTypeID:
621
+ options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
622
+ });
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Creates a new transaction for appending content from a file but doesn't sign or send it
628
+ * @param filePath The path to the file containing the content to append
629
+ * @param ckbfsCell The CKBFS cell to append to
630
+ * @param options Additional options for the append operation
631
+ * @returns Promise resolving to the unsigned transaction
632
+ */
633
+ async createAppendTransaction(
634
+ filePath: string,
635
+ ckbfsCell: AppendOptions["ckbfsCell"],
636
+ options: Omit<FileOptions, "contentType" | "filename"> & {
637
+ // V3 backlink parameters (optional for backward compatibility)
638
+ previousTxHash?: string;
639
+ previousWitnessIndex?: number;
640
+ previousChecksum?: number;
641
+ } = {},
642
+ ): Promise<Transaction> {
643
+ // Read the file and split into chunks
644
+ const fileContent = readFileAsUint8Array(filePath);
645
+ const contentChunks = [];
646
+
647
+ for (let i = 0; i < fileContent.length; i += this.chunkSize) {
648
+ contentChunks.push(fileContent.slice(i, i + this.chunkSize));
649
+ }
650
+
651
+ // Determine version - default to V3, allow override
652
+ const version = options.version || this.version;
653
+
654
+ // Use V3 when backlink parameters are provided or version is V3
655
+ if (version === ProtocolVersion.V3 &&
656
+ options.previousTxHash &&
657
+ options.previousWitnessIndex !== undefined &&
658
+ options.previousChecksum !== undefined) {
659
+
660
+ return createAppendV3Transaction(this.signer, {
661
+ ckbfsCell,
662
+ contentChunks,
663
+ feeRate: options.feeRate,
664
+ network: options.network || this.network,
665
+ version: ProtocolVersion.V3,
666
+ previousTxHash: options.previousTxHash,
667
+ previousWitnessIndex: options.previousWitnessIndex,
668
+ previousChecksum: options.previousChecksum,
669
+ });
670
+ } else {
671
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
672
+ return utilCreateAppendTransaction(this.signer, {
673
+ ckbfsCell,
674
+ contentChunks,
675
+ feeRate: options.feeRate,
676
+ network: options.network || this.network,
677
+ version: version === ProtocolVersion.V3 ? ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
678
+ });
679
+ }
680
+ }
681
+
682
+ /**
683
+ * Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
684
+ * @param content The content string or byte array to append
685
+ * @param ckbfsCell The CKBFS cell to append to
686
+ * @param options Additional options for the append operation
687
+ * @returns Promise resolving to the unsigned transaction
688
+ */
689
+ async createAppendContentTransaction(
690
+ content: string | Uint8Array,
691
+ ckbfsCell: AppendOptions["ckbfsCell"],
692
+ options: AppendContentOptions = {},
693
+ ): Promise<Transaction> {
694
+ const contentBytes =
695
+ typeof content === "string" ? textEncoder.encode(content) : content;
696
+ const contentChunks = [];
697
+
698
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
699
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
700
+ }
701
+
702
+ // Determine version - default to V3, allow override
703
+ const version = options.version || this.version;
704
+
705
+ // Use V3 when backlink parameters are provided or version is V3
706
+ if (version === ProtocolVersion.V3 &&
707
+ options.previousTxHash &&
708
+ options.previousWitnessIndex !== undefined &&
709
+ options.previousChecksum !== undefined) {
710
+
711
+ return createAppendV3Transaction(this.signer, {
712
+ ckbfsCell,
713
+ contentChunks,
714
+ feeRate: options.feeRate,
715
+ network: options.network || this.network,
716
+ version: ProtocolVersion.V3,
717
+ previousTxHash: options.previousTxHash,
718
+ previousWitnessIndex: options.previousWitnessIndex,
719
+ previousChecksum: options.previousChecksum,
720
+ });
721
+ } else {
722
+ // Legacy V1/V2 behavior or when V3 backlink params are missing
723
+ return utilCreateAppendTransaction(this.signer, {
724
+ ckbfsCell,
725
+ contentChunks,
726
+ feeRate: options.feeRate,
727
+ network: options.network || this.network,
728
+ version: version === ProtocolVersion.V3 ? ProtocolVersion.V2 : version, // Fallback to V2 if V3 but missing backlink params
729
+ // No useTypeID option for append
730
+ });
731
+ }
732
+ }
733
+
734
+ // V3 Methods
735
+
736
+ /**
737
+ * Publishes a file to CKBFS v3
738
+ * @param filePath The path to the file to publish
739
+ * @param options Options for publishing the file
740
+ * @returns Promise resolving to the transaction hash
741
+ */
742
+ async publishFileV3(
743
+ filePath: string,
744
+ options: Omit<FileOptions, 'version'> = {},
745
+ ): Promise<string> {
746
+ // Read the file and split into chunks
747
+ const fileContent = readFileAsUint8Array(filePath);
748
+ const contentChunks = [];
749
+
750
+ for (let i = 0; i < fileContent.length; i += this.chunkSize) {
751
+ contentChunks.push(fileContent.slice(i, i + this.chunkSize));
752
+ }
753
+
754
+ // Get the lock script
755
+ const lock = await this.getLock();
756
+
757
+ // Determine content type if not provided
758
+ const contentType = options.contentType || getContentType(filePath);
759
+
760
+ // Use the filename from the path if not provided
761
+ const pathParts = filePath.split(/[\\\/]/);
762
+ const filename = options.filename || pathParts[pathParts.length - 1];
763
+
764
+ // Create and sign the transaction using the v3 utility function
765
+ const tx = await publishCKBFSV3(this.signer, {
411
766
  contentChunks,
412
767
  contentType,
413
768
  filename,
@@ -415,22 +770,28 @@ export class CKBFS {
415
770
  capacity: options.capacity,
416
771
  feeRate: options.feeRate,
417
772
  network: options.network || this.network,
418
- version: options.version || this.version,
419
- useTypeID:
420
- options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
773
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
774
+ version: ProtocolVersion.V3,
421
775
  });
776
+
777
+ console.log("Publish file v3 tx:", tx.stringify());
778
+
779
+ // Send the transaction
780
+ const txHash = await this.signer.sendTransaction(tx);
781
+
782
+ return ensureHexPrefix(txHash);
422
783
  }
423
784
 
424
785
  /**
425
- * Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
786
+ * Publishes content (string or Uint8Array) directly to CKBFS v3
426
787
  * @param content The content string or byte array to publish
427
788
  * @param options Options for publishing the content (contentType and filename are required)
428
- * @returns Promise resolving to the unsigned transaction
789
+ * @returns Promise resolving to the transaction hash
429
790
  */
430
- async createPublishContentTransaction(
791
+ async publishContentV3(
431
792
  content: string | Uint8Array,
432
793
  options: PublishContentOptions,
433
- ): Promise<Transaction> {
794
+ ): Promise<string> {
434
795
  const contentBytes =
435
796
  typeof content === "string" ? textEncoder.encode(content) : content;
436
797
  const contentChunks = [];
@@ -444,7 +805,7 @@ export class CKBFS {
444
805
  // Use provided contentType and filename (required)
445
806
  const { contentType, filename } = options;
446
807
 
447
- return utilCreatePublishTransaction(this.signer, {
808
+ const tx = await publishCKBFSV3(this.signer, {
448
809
  contentChunks,
449
810
  contentType,
450
811
  filename,
@@ -452,24 +813,32 @@ export class CKBFS {
452
813
  capacity: options.capacity,
453
814
  feeRate: options.feeRate,
454
815
  network: options.network || this.network,
455
- version: options.version || this.version,
456
- useTypeID:
457
- options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
816
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
817
+ version: ProtocolVersion.V3,
458
818
  });
819
+
820
+ const txHash = await this.signer.sendTransaction(tx);
821
+ return ensureHexPrefix(txHash);
459
822
  }
460
823
 
461
824
  /**
462
- * Creates a new transaction for appending content from a file but doesn't sign or send it
825
+ * Appends content from a file to an existing CKBFS v3 file
463
826
  * @param filePath The path to the file containing the content to append
464
827
  * @param ckbfsCell The CKBFS cell to append to
828
+ * @param previousTxHash The previous transaction hash for backlink
829
+ * @param previousWitnessIndex The previous witness index for backlink
830
+ * @param previousChecksum The previous checksum for backlink
465
831
  * @param options Additional options for the append operation
466
- * @returns Promise resolving to the unsigned transaction
832
+ * @returns Promise resolving to the transaction hash
467
833
  */
468
- async createAppendTransaction(
834
+ async appendFileV3(
469
835
  filePath: string,
470
- ckbfsCell: AppendOptions["ckbfsCell"],
471
- options: Omit<FileOptions, "contentType" | "filename"> = {},
472
- ): Promise<Transaction> {
836
+ ckbfsCell: AppendV3Options["ckbfsCell"],
837
+ previousTxHash: string,
838
+ previousWitnessIndex: number,
839
+ previousChecksum: number,
840
+ options: Omit<FileOptions, "contentType" | "filename" | "version"> = {},
841
+ ): Promise<string> {
473
842
  // Read the file and split into chunks
474
843
  const fileContent = readFileAsUint8Array(filePath);
475
844
  const contentChunks = [];
@@ -478,28 +847,44 @@ export class CKBFS {
478
847
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
479
848
  }
480
849
 
481
- // Create the transaction using the utility function
482
- return utilCreateAppendTransaction(this.signer, {
850
+ // Create and sign the transaction using the v3 utility function
851
+ const tx = await appendCKBFSV3(this.signer, {
483
852
  ckbfsCell,
484
853
  contentChunks,
485
854
  feeRate: options.feeRate,
486
855
  network: options.network || this.network,
487
- version: options.version || this.version,
856
+ version: ProtocolVersion.V3,
857
+ previousTxHash,
858
+ previousWitnessIndex,
859
+ previousChecksum,
488
860
  });
861
+
862
+ console.log("Append file v3 tx:", tx.stringify());
863
+
864
+ // Send the transaction
865
+ const txHash = await this.signer.sendTransaction(tx);
866
+
867
+ return ensureHexPrefix(txHash);
489
868
  }
490
869
 
491
870
  /**
492
- * Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
871
+ * Appends content (string or Uint8Array) directly to an existing CKBFS v3 file
493
872
  * @param content The content string or byte array to append
494
873
  * @param ckbfsCell The CKBFS cell to append to
874
+ * @param previousTxHash The previous transaction hash for backlink
875
+ * @param previousWitnessIndex The previous witness index for backlink
876
+ * @param previousChecksum The previous checksum for backlink
495
877
  * @param options Additional options for the append operation
496
- * @returns Promise resolving to the unsigned transaction
878
+ * @returns Promise resolving to the transaction hash
497
879
  */
498
- async createAppendContentTransaction(
880
+ async appendContentV3(
499
881
  content: string | Uint8Array,
500
- ckbfsCell: AppendOptions["ckbfsCell"],
882
+ ckbfsCell: AppendV3Options["ckbfsCell"],
883
+ previousTxHash: string,
884
+ previousWitnessIndex: number,
885
+ previousChecksum: number,
501
886
  options: AppendContentOptions = {},
502
- ): Promise<Transaction> {
887
+ ): Promise<string> {
503
888
  const contentBytes =
504
889
  typeof content === "string" ? textEncoder.encode(content) : content;
505
890
  const contentChunks = [];
@@ -508,13 +893,95 @@ export class CKBFS {
508
893
  contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
509
894
  }
510
895
 
511
- return utilCreateAppendTransaction(this.signer, {
896
+ const tx = await appendCKBFSV3(this.signer, {
512
897
  ckbfsCell,
513
898
  contentChunks,
514
899
  feeRate: options.feeRate,
515
900
  network: options.network || this.network,
516
- version: options.version || this.version,
517
- // No useTypeID option for append
901
+ version: ProtocolVersion.V3,
902
+ previousTxHash,
903
+ previousWitnessIndex,
904
+ previousChecksum,
905
+ });
906
+
907
+ const txHash = await this.signer.sendTransaction(tx);
908
+ return ensureHexPrefix(txHash);
909
+ }
910
+
911
+ /**
912
+ * Transfers ownership of a CKBFS v3 file to a new lock script
913
+ * @param ckbfsCell The CKBFS cell to transfer
914
+ * @param newLock The new lock script for the transferred file
915
+ * @param previousTxHash The previous transaction hash for backlink
916
+ * @param previousWitnessIndex The previous witness index for backlink
917
+ * @param previousChecksum The previous checksum for backlink
918
+ * @param options Additional options for the transfer operation
919
+ * @returns Promise resolving to the transaction hash
920
+ */
921
+ async transferFileV3(
922
+ ckbfsCell: TransferV3Options["ckbfsCell"],
923
+ newLock: Script,
924
+ previousTxHash: string,
925
+ previousWitnessIndex: number,
926
+ previousChecksum: number,
927
+ options: Omit<FileOptions, "contentType" | "filename" | "version"> = {},
928
+ ): Promise<string> {
929
+ const tx = await transferCKBFSV3(this.signer, {
930
+ ckbfsCell,
931
+ newLock,
932
+ feeRate: options.feeRate,
933
+ network: options.network || this.network,
934
+ version: ProtocolVersion.V3,
935
+ previousTxHash,
936
+ previousWitnessIndex,
937
+ previousChecksum,
938
+ });
939
+
940
+ console.log("Transfer file v3 tx:", tx.stringify());
941
+
942
+ const txHash = await this.signer.sendTransaction(tx);
943
+ return ensureHexPrefix(txHash);
944
+ }
945
+
946
+ /**
947
+ * Creates a new transaction for publishing a file to CKBFS v3 but doesn't sign or send it
948
+ * @param filePath The path to the file to publish
949
+ * @param options Options for publishing the file
950
+ * @returns Promise resolving to the unsigned transaction
951
+ */
952
+ async createPublishV3Transaction(
953
+ filePath: string,
954
+ options: Omit<FileOptions, 'version'> = {},
955
+ ): Promise<Transaction> {
956
+ // Read the file and split into chunks
957
+ const fileContent = readFileAsUint8Array(filePath);
958
+ const contentChunks = [];
959
+
960
+ for (let i = 0; i < fileContent.length; i += this.chunkSize) {
961
+ contentChunks.push(fileContent.slice(i, i + this.chunkSize));
962
+ }
963
+
964
+ // Get the lock script
965
+ const lock = await this.getLock();
966
+
967
+ // Determine content type if not provided
968
+ const contentType = options.contentType || getContentType(filePath);
969
+
970
+ // Use the filename from the path if not provided
971
+ const pathParts = filePath.split(/[\\\/]/);
972
+ const filename = options.filename || pathParts[pathParts.length - 1];
973
+
974
+ // Create the transaction using the utility function
975
+ return createPublishV3Transaction(this.signer, {
976
+ contentChunks,
977
+ contentType,
978
+ filename,
979
+ lock,
980
+ capacity: options.capacity,
981
+ feeRate: options.feeRate,
982
+ network: options.network || this.network,
983
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
984
+ version: ProtocolVersion.V3,
518
985
  });
519
986
  }
520
987
  }
@@ -526,6 +993,8 @@ export {
526
993
  verifyChecksum,
527
994
  updateChecksum,
528
995
  verifyWitnessChecksum,
996
+ verifyV3WitnessChecksum,
997
+ verifyV3WitnessChain,
529
998
 
530
999
  // Transaction utilities (Exporting original names from transaction.ts)
531
1000
  createCKBFSCell,
@@ -559,6 +1028,11 @@ export {
559
1028
  extractFileFromWitnesses,
560
1029
  decodeFileFromWitnessData,
561
1030
  saveFileFromWitnessData,
1031
+
1032
+ // V3 File utilities
1033
+ getFileContentFromChainV3,
1034
+ getFileContentFromChainByIdentifierV3,
1035
+ saveFileFromChainByIdentifierV3,
562
1036
 
563
1037
  // Witness utilities
564
1038
  createCKBFSWitness,
@@ -566,6 +1040,13 @@ export {
566
1040
  extractCKBFSWitnessContent,
567
1041
  isCKBFSWitness,
568
1042
  createChunkedCKBFSWitnesses,
1043
+
1044
+ // V3 Witness utilities
1045
+ createCKBFSV3Witness,
1046
+ createChunkedCKBFSV3Witnesses,
1047
+ extractCKBFSV3WitnessContent,
1048
+ isCKBFSV3Witness,
1049
+ CKBFSV3WitnessOptions,
569
1050
 
570
1051
  // Molecule definitions
571
1052
  CKBFSData,