@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.
- package/README.md +31 -6
- package/RFC.v3.md +210 -0
- package/dist/index.d.ts +72 -7
- package/dist/index.js +440 -75
- package/dist/utils/checksum.d.ts +16 -0
- package/dist/utils/checksum.js +74 -8
- package/dist/utils/constants.d.ts +2 -1
- package/dist/utils/constants.js +12 -2
- package/dist/utils/file.d.ts +44 -0
- package/dist/utils/file.js +303 -30
- package/dist/utils/molecule.d.ts +13 -1
- package/dist/utils/molecule.js +32 -5
- package/dist/utils/transaction-backup.d.ts +117 -0
- package/dist/utils/transaction-backup.js +624 -0
- package/dist/utils/transaction.d.ts +7 -105
- package/dist/utils/transaction.js +45 -565
- package/dist/utils/transactions/index.d.ts +8 -0
- package/dist/utils/transactions/index.js +31 -0
- package/dist/utils/transactions/shared.d.ts +57 -0
- package/dist/utils/transactions/shared.js +17 -0
- package/dist/utils/transactions/v1v2.d.ts +80 -0
- package/dist/utils/transactions/v1v2.js +592 -0
- package/dist/utils/transactions/v3.d.ts +124 -0
- package/dist/utils/transactions/v3.js +369 -0
- package/dist/utils/witness.d.ts +45 -0
- package/dist/utils/witness.js +145 -3
- package/examples/append-v3.ts +310 -0
- package/examples/chunked-publish.ts +307 -0
- package/examples/publish-v3.ts +152 -0
- package/examples/publish.ts +4 -4
- package/examples/retrieve-v3.ts +222 -0
- package/package.json +6 -2
- package/small-example.txt +1 -0
- package/src/index.ts +568 -87
- package/src/utils/checksum.ts +90 -9
- package/src/utils/constants.ts +19 -2
- package/src/utils/file.ts +386 -35
- package/src/utils/molecule.ts +43 -6
- package/src/utils/transaction-backup.ts +849 -0
- package/src/utils/transaction.ts +39 -848
- package/src/utils/transactions/index.ts +16 -0
- package/src/utils/transactions/shared.ts +64 -0
- package/src/utils/transactions/v1v2.ts +791 -0
- package/src/utils/transactions/v3.ts +564 -0
- 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
|
-
> & {
|
|
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
|
-
//
|
|
246
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
262
|
-
const txHash = await this.signer.sendTransaction(tx);
|
|
290
|
+
console.log("Publish file tx:", tx.stringify());
|
|
263
291
|
|
|
264
|
-
|
|
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
|
-
|
|
291
|
-
|
|
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
|
-
|
|
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
|
-
|
|
306
|
-
|
|
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
|
-
//
|
|
330
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
341
|
-
const txHash = await this.signer.sendTransaction(tx);
|
|
428
|
+
console.log("Append file v3 tx:", tx.stringify());
|
|
342
429
|
|
|
343
|
-
|
|
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
|
-
|
|
367
|
-
|
|
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
|
-
|
|
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
|
-
|
|
378
|
-
|
|
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
|
-
//
|
|
410
|
-
|
|
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
|
-
|
|
419
|
-
|
|
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
|
-
*
|
|
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
|
|
789
|
+
* @returns Promise resolving to the transaction hash
|
|
429
790
|
*/
|
|
430
|
-
async
|
|
791
|
+
async publishContentV3(
|
|
431
792
|
content: string | Uint8Array,
|
|
432
793
|
options: PublishContentOptions,
|
|
433
|
-
): Promise<
|
|
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
|
-
|
|
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
|
-
|
|
456
|
-
|
|
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
|
-
*
|
|
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
|
|
832
|
+
* @returns Promise resolving to the transaction hash
|
|
467
833
|
*/
|
|
468
|
-
async
|
|
834
|
+
async appendFileV3(
|
|
469
835
|
filePath: string,
|
|
470
|
-
ckbfsCell:
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
*
|
|
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
|
|
878
|
+
* @returns Promise resolving to the transaction hash
|
|
497
879
|
*/
|
|
498
|
-
async
|
|
880
|
+
async appendContentV3(
|
|
499
881
|
content: string | Uint8Array,
|
|
500
|
-
ckbfsCell:
|
|
882
|
+
ckbfsCell: AppendV3Options["ckbfsCell"],
|
|
883
|
+
previousTxHash: string,
|
|
884
|
+
previousWitnessIndex: number,
|
|
885
|
+
previousChecksum: number,
|
|
501
886
|
options: AppendContentOptions = {},
|
|
502
|
-
): Promise<
|
|
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
|
-
|
|
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:
|
|
517
|
-
|
|
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,
|