@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/dist/index.js CHANGED
@@ -1,17 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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 = 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.appendCKBFS = exports.publishCKBFS = exports.createAppendTransaction = 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 = 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; } });
16
+ Object.defineProperty(exports, "preparePublishTransaction", { enumerable: true, get: function () { return transaction_1.preparePublishTransaction; } });
14
17
  Object.defineProperty(exports, "createAppendTransaction", { enumerable: true, get: function () { return transaction_1.createAppendTransaction; } });
18
+ Object.defineProperty(exports, "prepareAppendTransaction", { enumerable: true, get: function () { return transaction_1.prepareAppendTransaction; } });
19
+ Object.defineProperty(exports, "createAppendTransactionDry", { enumerable: true, get: function () { return transaction_1.createAppendTransactionDry; } });
15
20
  Object.defineProperty(exports, "publishCKBFS", { enumerable: true, get: function () { return transaction_1.publishCKBFS; } });
16
21
  Object.defineProperty(exports, "appendCKBFS", { enumerable: true, get: function () { return transaction_1.appendCKBFS; } });
17
22
  const file_1 = require("./utils/file");
@@ -37,12 +42,21 @@ Object.defineProperty(exports, "decodeMultipleWitnessContents", { enumerable: tr
37
42
  Object.defineProperty(exports, "extractFileFromWitnesses", { enumerable: true, get: function () { return file_1.extractFileFromWitnesses; } });
38
43
  Object.defineProperty(exports, "decodeFileFromWitnessData", { enumerable: true, get: function () { return file_1.decodeFileFromWitnessData; } });
39
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; } });
40
50
  const witness_1 = require("./utils/witness");
41
51
  Object.defineProperty(exports, "createCKBFSWitness", { enumerable: true, get: function () { return witness_1.createCKBFSWitness; } });
42
52
  Object.defineProperty(exports, "createTextCKBFSWitness", { enumerable: true, get: function () { return witness_1.createTextCKBFSWitness; } });
43
53
  Object.defineProperty(exports, "extractCKBFSWitnessContent", { enumerable: true, get: function () { return witness_1.extractCKBFSWitnessContent; } });
44
54
  Object.defineProperty(exports, "isCKBFSWitness", { enumerable: true, get: function () { return witness_1.isCKBFSWitness; } });
45
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; } });
46
60
  const molecule_1 = require("./utils/molecule");
47
61
  Object.defineProperty(exports, "CKBFSData", { enumerable: true, get: function () { return molecule_1.CKBFSData; } });
48
62
  Object.defineProperty(exports, "BackLinkV1", { enumerable: true, get: function () { return molecule_1.BackLinkV1; } });
@@ -151,22 +165,44 @@ class CKBFS {
151
165
  // Use the filename from the path if not provided
152
166
  const pathParts = filePath.split(/[\\\/]/);
153
167
  const filename = options.filename || pathParts[pathParts.length - 1];
154
- // Create and sign the transaction using the utility function
155
- const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
156
- contentChunks,
157
- contentType,
158
- filename,
159
- lock,
160
- capacity: options.capacity,
161
- feeRate: options.feeRate,
162
- network: options.network || this.network,
163
- version: options.version || this.version,
164
- useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
165
- });
166
- console.log("Publish file tx:", tx.stringify());
167
- // Send the transaction
168
- const txHash = await this.signer.sendTransaction(tx);
169
- 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
+ }
170
206
  }
171
207
  /**
172
208
  * Publishes content (string or Uint8Array) directly to CKBFS
@@ -183,20 +219,40 @@ class CKBFS {
183
219
  const lock = await this.getLock();
184
220
  // Use provided contentType and filename (required)
185
221
  const { contentType, filename } = options;
186
- const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
187
- contentChunks,
188
- contentType,
189
- filename,
190
- lock,
191
- capacity: options.capacity,
192
- feeRate: options.feeRate,
193
- network: options.network || this.network,
194
- version: options.version || this.version,
195
- useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
196
- });
197
- console.log("Publish content tx:", tx.stringify());
198
- const txHash = await this.signer.sendTransaction(tx);
199
- 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
+ }
200
256
  }
201
257
  /**
202
258
  * Appends content from a file to an existing CKBFS file
@@ -212,18 +268,40 @@ class CKBFS {
212
268
  for (let i = 0; i < fileContent.length; i += this.chunkSize) {
213
269
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
214
270
  }
215
- // Create and sign the transaction using the utility function
216
- const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
217
- ckbfsCell,
218
- contentChunks,
219
- feeRate: options.feeRate,
220
- network: options.network || this.network,
221
- version: options.version || this.version,
222
- });
223
- console.log("Append file tx:", tx.stringify());
224
- // Send the transaction
225
- const txHash = await this.signer.sendTransaction(tx);
226
- 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
+ }
227
305
  }
228
306
  /**
229
307
  * Appends content (string or Uint8Array) directly to an existing CKBFS file
@@ -238,17 +316,39 @@ class CKBFS {
238
316
  for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
239
317
  contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
240
318
  }
241
- const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
242
- ckbfsCell,
243
- contentChunks,
244
- feeRate: options.feeRate,
245
- network: options.network || this.network,
246
- version: options.version || this.version,
247
- // No useTypeID option for append
248
- });
249
- console.log("Append content tx:", tx.stringify());
250
- const txHash = await this.signer.sendTransaction(tx);
251
- 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
+ }
252
352
  }
253
353
  /**
254
354
  * Creates a new transaction for publishing a file but doesn't sign or send it
@@ -270,8 +370,192 @@ class CKBFS {
270
370
  // Use the filename from the path if not provided
271
371
  const pathParts = filePath.split(/[\\\/]/);
272
372
  const filename = options.filename || pathParts[pathParts.length - 1];
273
- // Create the transaction using the utility function
274
- 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, {
275
559
  contentChunks,
276
560
  contentType,
277
561
  filename,
@@ -279,17 +563,21 @@ class CKBFS {
279
563
  capacity: options.capacity,
280
564
  feeRate: options.feeRate,
281
565
  network: options.network || this.network,
282
- version: options.version || this.version,
283
566
  useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
567
+ version: constants_1.ProtocolVersion.V3,
284
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);
285
573
  }
286
574
  /**
287
- * 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
288
576
  * @param content The content string or byte array to publish
289
577
  * @param options Options for publishing the content (contentType and filename are required)
290
- * @returns Promise resolving to the unsigned transaction
578
+ * @returns Promise resolving to the transaction hash
291
579
  */
292
- async createPublishContentTransaction(content, options) {
580
+ async publishContentV3(content, options) {
293
581
  const contentBytes = typeof content === "string" ? textEncoder.encode(content) : content;
294
582
  const contentChunks = [];
295
583
  for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
@@ -298,7 +586,7 @@ class CKBFS {
298
586
  const lock = await this.getLock();
299
587
  // Use provided contentType and filename (required)
300
588
  const { contentType, filename } = options;
301
- return (0, transaction_1.createPublishTransaction)(this.signer, {
589
+ const tx = await (0, transaction_1.publishCKBFSV3)(this.signer, {
302
590
  contentChunks,
303
591
  contentType,
304
592
  filename,
@@ -306,53 +594,130 @@ class CKBFS {
306
594
  capacity: options.capacity,
307
595
  feeRate: options.feeRate,
308
596
  network: options.network || this.network,
309
- version: options.version || this.version,
310
597
  useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID,
598
+ version: constants_1.ProtocolVersion.V3,
311
599
  });
600
+ const txHash = await this.signer.sendTransaction(tx);
601
+ return (0, transaction_2.ensureHexPrefix)(txHash);
312
602
  }
313
603
  /**
314
- * 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
315
605
  * @param filePath The path to the file containing the content to append
316
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
317
610
  * @param options Additional options for the append operation
318
- * @returns Promise resolving to the unsigned transaction
611
+ * @returns Promise resolving to the transaction hash
319
612
  */
320
- async createAppendTransaction(filePath, ckbfsCell, options = {}) {
613
+ async appendFileV3(filePath, ckbfsCell, previousTxHash, previousWitnessIndex, previousChecksum, options = {}) {
321
614
  // Read the file and split into chunks
322
615
  const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
323
616
  const contentChunks = [];
324
617
  for (let i = 0; i < fileContent.length; i += this.chunkSize) {
325
618
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
326
619
  }
327
- // Create the transaction using the utility function
328
- 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, {
329
622
  ckbfsCell,
330
623
  contentChunks,
331
624
  feeRate: options.feeRate,
332
625
  network: options.network || this.network,
333
- version: options.version || this.version,
626
+ version: constants_1.ProtocolVersion.V3,
627
+ previousTxHash,
628
+ previousWitnessIndex,
629
+ previousChecksum,
334
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);
335
635
  }
336
636
  /**
337
- * 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
338
638
  * @param content The content string or byte array to append
339
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
340
643
  * @param options Additional options for the append operation
341
- * @returns Promise resolving to the unsigned transaction
644
+ * @returns Promise resolving to the transaction hash
342
645
  */
343
- async createAppendContentTransaction(content, ckbfsCell, options = {}) {
646
+ async appendContentV3(content, ckbfsCell, previousTxHash, previousWitnessIndex, previousChecksum, options = {}) {
344
647
  const contentBytes = typeof content === "string" ? textEncoder.encode(content) : content;
345
648
  const contentChunks = [];
346
649
  for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
347
650
  contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
348
651
  }
349
- return (0, transaction_1.createAppendTransaction)(this.signer, {
652
+ const tx = await (0, transaction_1.appendCKBFSV3)(this.signer, {
350
653
  ckbfsCell,
351
654
  contentChunks,
352
655
  feeRate: options.feeRate,
353
656
  network: options.network || this.network,
354
- version: options.version || this.version,
355
- // 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,
356
721
  });
357
722
  }
358
723
  }