@ckbfs/api 1.2.4 → 1.3.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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Script, Signer, Transaction } from "@ckb-ccc/core";
2
2
  import { calculateChecksum, verifyChecksum, updateChecksum, verifyWitnessChecksum } from './utils/checksum';
3
- import { createCKBFSCell, createPublishTransaction, createAppendTransaction, publishCKBFS, appendCKBFS, CKBFSCellOptions, PublishOptions, AppendOptions } from './utils/transaction';
3
+ import { createCKBFSCell, createPublishTransaction as utilCreatePublishTransaction, createAppendTransaction as utilCreateAppendTransaction, publishCKBFS as utilPublishCKBFS, appendCKBFS as utilAppendCKBFS, CKBFSCellOptions, PublishOptions, AppendOptions } from './utils/transaction';
4
4
  import { readFile, readFileAsText, readFileAsUint8Array, writeFile, getContentType, splitFileIntoChunks, combineChunksToFile, getFileContentFromChain, saveFileFromChain } from './utils/file';
5
5
  import { createCKBFSWitness, createTextCKBFSWitness, extractCKBFSWitnessContent, isCKBFSWitness, createChunkedCKBFSWitnesses } from './utils/witness';
6
6
  import { CKBFSData, BackLinkV1, BackLinkV2, CKBFSDataType, BackLinkType, CKBFS_HEADER, CKBFS_HEADER_STRING } from './utils/molecule';
@@ -17,6 +17,18 @@ export interface FileOptions {
17
17
  version?: string;
18
18
  useTypeID?: boolean;
19
19
  }
20
+ /**
21
+ * Options required when publishing content directly (string or Uint8Array)
22
+ */
23
+ export type PublishContentOptions = Omit<FileOptions, 'capacity' | 'contentType' | 'filename'> & Required<Pick<FileOptions, 'contentType' | 'filename'>> & {
24
+ capacity?: bigint;
25
+ };
26
+ /**
27
+ * Options required when appending content directly (string or Uint8Array)
28
+ */
29
+ export type AppendContentOptions = Omit<FileOptions, 'contentType' | 'filename' | 'capacity'> & {
30
+ capacity?: bigint;
31
+ };
20
32
  /**
21
33
  * Configuration options for the CKBFS SDK
22
34
  */
@@ -65,13 +77,28 @@ export declare class CKBFS {
65
77
  */
66
78
  publishFile(filePath: string, options?: FileOptions): Promise<string>;
67
79
  /**
68
- * Appends content to an existing CKBFS file
80
+ * Publishes content (string or Uint8Array) directly to CKBFS
81
+ * @param content The content string or byte array to publish
82
+ * @param options Options for publishing the content (contentType and filename are required)
83
+ * @returns Promise resolving to the transaction hash
84
+ */
85
+ publishContent(content: string | Uint8Array, options: PublishContentOptions): Promise<string>;
86
+ /**
87
+ * Appends content from a file to an existing CKBFS file
69
88
  * @param filePath The path to the file containing the content to append
70
89
  * @param ckbfsCell The CKBFS cell to append to
71
90
  * @param options Additional options for the append operation
72
91
  * @returns Promise resolving to the transaction hash
73
92
  */
74
93
  appendFile(filePath: string, ckbfsCell: AppendOptions['ckbfsCell'], options?: Omit<FileOptions, 'contentType' | 'filename'>): Promise<string>;
94
+ /**
95
+ * Appends content (string or Uint8Array) directly to an existing CKBFS file
96
+ * @param content The content string or byte array to append
97
+ * @param ckbfsCell The CKBFS cell to append to
98
+ * @param options Additional options for the append operation
99
+ * @returns Promise resolving to the transaction hash
100
+ */
101
+ appendContent(content: string | Uint8Array, ckbfsCell: AppendOptions['ckbfsCell'], options?: AppendContentOptions): Promise<string>;
75
102
  /**
76
103
  * Creates a new transaction for publishing a file but doesn't sign or send it
77
104
  * @param filePath The path to the file to publish
@@ -80,12 +107,27 @@ export declare class CKBFS {
80
107
  */
81
108
  createPublishTransaction(filePath: string, options?: FileOptions): Promise<Transaction>;
82
109
  /**
83
- * Creates a new transaction for appending content but doesn't sign or send it
110
+ * Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
111
+ * @param content The content string or byte array to publish
112
+ * @param options Options for publishing the content (contentType and filename are required)
113
+ * @returns Promise resolving to the unsigned transaction
114
+ */
115
+ createPublishContentTransaction(content: string | Uint8Array, options: PublishContentOptions): Promise<Transaction>;
116
+ /**
117
+ * Creates a new transaction for appending content from a file but doesn't sign or send it
84
118
  * @param filePath The path to the file containing the content to append
85
119
  * @param ckbfsCell The CKBFS cell to append to
86
120
  * @param options Additional options for the append operation
87
121
  * @returns Promise resolving to the unsigned transaction
88
122
  */
89
123
  createAppendTransaction(filePath: string, ckbfsCell: AppendOptions['ckbfsCell'], options?: Omit<FileOptions, 'contentType' | 'filename'>): Promise<Transaction>;
124
+ /**
125
+ * Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
126
+ * @param content The content string or byte array to append
127
+ * @param ckbfsCell The CKBFS cell to append to
128
+ * @param options Additional options for the append operation
129
+ * @returns Promise resolving to the unsigned transaction
130
+ */
131
+ createAppendContentTransaction(content: string | Uint8Array, ckbfsCell: AppendOptions['ckbfsCell'], options?: AppendContentOptions): Promise<Transaction>;
90
132
  }
91
- export { calculateChecksum, verifyChecksum, updateChecksum, verifyWitnessChecksum, createCKBFSCell, createPublishTransaction, createAppendTransaction, publishCKBFS, appendCKBFS, readFile, readFileAsText, readFileAsUint8Array, writeFile, getContentType, splitFileIntoChunks, combineChunksToFile, getFileContentFromChain, saveFileFromChain, createCKBFSWitness, createTextCKBFSWitness, extractCKBFSWitnessContent, isCKBFSWitness, createChunkedCKBFSWitnesses, CKBFSData, BackLinkV1, BackLinkV2, CKBFSDataType, BackLinkType, CKBFSCellOptions, PublishOptions, AppendOptions, CKBFS_HEADER, CKBFS_HEADER_STRING, NetworkType, ProtocolVersion, DEFAULT_NETWORK, DEFAULT_VERSION, CKBFS_CODE_HASH, CKBFS_TYPE_ID, ADLER32_CODE_HASH, ADLER32_TYPE_ID, DEP_GROUP_TX_HASH, DEPLOY_TX_HASH, getCKBFSScriptConfig, CKBFSScriptConfig };
133
+ export { calculateChecksum, verifyChecksum, updateChecksum, verifyWitnessChecksum, createCKBFSCell, utilCreatePublishTransaction as createPublishTransaction, utilCreateAppendTransaction as createAppendTransaction, utilPublishCKBFS as publishCKBFS, utilAppendCKBFS as appendCKBFS, readFile, readFileAsText, readFileAsUint8Array, writeFile, getContentType, splitFileIntoChunks, combineChunksToFile, getFileContentFromChain, saveFileFromChain, createCKBFSWitness, createTextCKBFSWitness, extractCKBFSWitnessContent, isCKBFSWitness, createChunkedCKBFSWitnesses, CKBFSData, BackLinkV1, BackLinkV2, CKBFSDataType, BackLinkType, CKBFSCellOptions, PublishOptions, AppendOptions, CKBFS_HEADER, CKBFS_HEADER_STRING, NetworkType, ProtocolVersion, DEFAULT_NETWORK, DEFAULT_VERSION, CKBFS_CODE_HASH, CKBFS_TYPE_ID, ADLER32_CODE_HASH, ADLER32_TYPE_ID, DEP_GROUP_TX_HASH, DEPLOY_TX_HASH, getCKBFSScriptConfig, CKBFSScriptConfig };
package/dist/index.js CHANGED
@@ -47,6 +47,9 @@ Object.defineProperty(exports, "ADLER32_TYPE_ID", { enumerable: true, get: funct
47
47
  Object.defineProperty(exports, "DEP_GROUP_TX_HASH", { enumerable: true, get: function () { return constants_1.DEP_GROUP_TX_HASH; } });
48
48
  Object.defineProperty(exports, "DEPLOY_TX_HASH", { enumerable: true, get: function () { return constants_1.DEPLOY_TX_HASH; } });
49
49
  Object.defineProperty(exports, "getCKBFSScriptConfig", { enumerable: true, get: function () { return constants_1.getCKBFSScriptConfig; } });
50
+ const transaction_2 = require("./utils/transaction");
51
+ // Helper to encode string to Uint8Array
52
+ const textEncoder = new TextEncoder();
50
53
  /**
51
54
  * Main CKBFS SDK class
52
55
  */
@@ -123,7 +126,7 @@ class CKBFS {
123
126
  // Use the filename from the path if not provided
124
127
  const pathParts = filePath.split(/[\\\/]/);
125
128
  const filename = options.filename || pathParts[pathParts.length - 1];
126
- // Create and sign the transaction
129
+ // Create and sign the transaction using the utility function
127
130
  const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
128
131
  contentChunks,
129
132
  contentType,
@@ -135,13 +138,43 @@ class CKBFS {
135
138
  version: options.version || this.version,
136
139
  useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
137
140
  });
138
- console.log('tx', tx.stringify());
141
+ console.log('Publish file tx:', tx.stringify());
139
142
  // Send the transaction
140
143
  const txHash = await this.signer.sendTransaction(tx);
141
- return txHash;
144
+ return (0, transaction_2.ensureHexPrefix)(txHash);
142
145
  }
143
146
  /**
144
- * Appends content to an existing CKBFS file
147
+ * Publishes content (string or Uint8Array) directly to CKBFS
148
+ * @param content The content string or byte array to publish
149
+ * @param options Options for publishing the content (contentType and filename are required)
150
+ * @returns Promise resolving to the transaction hash
151
+ */
152
+ async publishContent(content, options) {
153
+ const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
154
+ const contentChunks = [];
155
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
156
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
157
+ }
158
+ const lock = await this.getLock();
159
+ // Use provided contentType and filename (required)
160
+ const { contentType, filename } = options;
161
+ const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
162
+ contentChunks,
163
+ contentType,
164
+ filename,
165
+ lock,
166
+ capacity: options.capacity,
167
+ feeRate: options.feeRate,
168
+ network: options.network || this.network,
169
+ version: options.version || this.version,
170
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
171
+ });
172
+ console.log('Publish content tx:', tx.stringify());
173
+ const txHash = await this.signer.sendTransaction(tx);
174
+ return (0, transaction_2.ensureHexPrefix)(txHash);
175
+ }
176
+ /**
177
+ * Appends content from a file to an existing CKBFS file
145
178
  * @param filePath The path to the file containing the content to append
146
179
  * @param ckbfsCell The CKBFS cell to append to
147
180
  * @param options Additional options for the append operation
@@ -154,7 +187,7 @@ class CKBFS {
154
187
  for (let i = 0; i < fileContent.length; i += this.chunkSize) {
155
188
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
156
189
  }
157
- // Create and sign the transaction
190
+ // Create and sign the transaction using the utility function
158
191
  const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
159
192
  ckbfsCell,
160
193
  contentChunks,
@@ -162,9 +195,35 @@ class CKBFS {
162
195
  network: options.network || this.network,
163
196
  version: options.version || this.version
164
197
  });
198
+ console.log('Append file tx:', tx.stringify());
165
199
  // Send the transaction
166
200
  const txHash = await this.signer.sendTransaction(tx);
167
- return txHash;
201
+ return (0, transaction_2.ensureHexPrefix)(txHash);
202
+ }
203
+ /**
204
+ * Appends content (string or Uint8Array) directly to an existing CKBFS file
205
+ * @param content The content string or byte array to append
206
+ * @param ckbfsCell The CKBFS cell to append to
207
+ * @param options Additional options for the append operation
208
+ * @returns Promise resolving to the transaction hash
209
+ */
210
+ async appendContent(content, ckbfsCell, options = {}) {
211
+ const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
212
+ const contentChunks = [];
213
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
214
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
215
+ }
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
+ // No useTypeID option for append
223
+ });
224
+ console.log('Append content tx:', tx.stringify());
225
+ const txHash = await this.signer.sendTransaction(tx);
226
+ return (0, transaction_2.ensureHexPrefix)(txHash);
168
227
  }
169
228
  /**
170
229
  * Creates a new transaction for publishing a file but doesn't sign or send it
@@ -186,7 +245,34 @@ class CKBFS {
186
245
  // Use the filename from the path if not provided
187
246
  const pathParts = filePath.split(/[\\\/]/);
188
247
  const filename = options.filename || pathParts[pathParts.length - 1];
189
- // Create the transaction
248
+ // Create the transaction using the utility function
249
+ return (0, transaction_1.createPublishTransaction)(this.signer, {
250
+ contentChunks,
251
+ contentType,
252
+ filename,
253
+ lock,
254
+ capacity: options.capacity,
255
+ feeRate: options.feeRate,
256
+ network: options.network || this.network,
257
+ version: options.version || this.version,
258
+ useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
259
+ });
260
+ }
261
+ /**
262
+ * Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
263
+ * @param content The content string or byte array to publish
264
+ * @param options Options for publishing the content (contentType and filename are required)
265
+ * @returns Promise resolving to the unsigned transaction
266
+ */
267
+ async createPublishContentTransaction(content, options) {
268
+ const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
269
+ const contentChunks = [];
270
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
271
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
272
+ }
273
+ const lock = await this.getLock();
274
+ // Use provided contentType and filename (required)
275
+ const { contentType, filename } = options;
190
276
  return (0, transaction_1.createPublishTransaction)(this.signer, {
191
277
  contentChunks,
192
278
  contentType,
@@ -200,7 +286,7 @@ class CKBFS {
200
286
  });
201
287
  }
202
288
  /**
203
- * Creates a new transaction for appending content but doesn't sign or send it
289
+ * Creates a new transaction for appending content from a file but doesn't sign or send it
204
290
  * @param filePath The path to the file containing the content to append
205
291
  * @param ckbfsCell The CKBFS cell to append to
206
292
  * @param options Additional options for the append operation
@@ -213,13 +299,35 @@ class CKBFS {
213
299
  for (let i = 0; i < fileContent.length; i += this.chunkSize) {
214
300
  contentChunks.push(fileContent.slice(i, i + this.chunkSize));
215
301
  }
216
- // Create the transaction
302
+ // Create the transaction using the utility function
303
+ return (0, transaction_1.createAppendTransaction)(this.signer, {
304
+ ckbfsCell,
305
+ contentChunks,
306
+ feeRate: options.feeRate,
307
+ network: options.network || this.network,
308
+ version: options.version || this.version
309
+ });
310
+ }
311
+ /**
312
+ * Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
313
+ * @param content The content string or byte array to append
314
+ * @param ckbfsCell The CKBFS cell to append to
315
+ * @param options Additional options for the append operation
316
+ * @returns Promise resolving to the unsigned transaction
317
+ */
318
+ async createAppendContentTransaction(content, ckbfsCell, options = {}) {
319
+ const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
320
+ const contentChunks = [];
321
+ for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
322
+ contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
323
+ }
217
324
  return (0, transaction_1.createAppendTransaction)(this.signer, {
218
325
  ckbfsCell,
219
326
  contentChunks,
220
327
  feeRate: options.feeRate,
221
328
  network: options.network || this.network,
222
329
  version: options.version || this.version
330
+ // No useTypeID option for append
223
331
  });
224
332
  }
225
333
  }
@@ -42,6 +42,12 @@ export interface AppendOptions {
42
42
  network?: NetworkType;
43
43
  version?: string;
44
44
  }
45
+ /**
46
+ * Ensures a string is prefixed with '0x'
47
+ * @param value The string to ensure is hex prefixed
48
+ * @returns A hex prefixed string
49
+ */
50
+ export declare function ensureHexPrefix(value: string): `0x${string}`;
45
51
  /**
46
52
  * Creates a CKBFS cell
47
53
  * @param options Options for creating the CKBFS cell
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureHexPrefix = ensureHexPrefix;
3
4
  exports.createCKBFSCell = createCKBFSCell;
4
5
  exports.createPublishTransaction = createPublishTransaction;
5
6
  exports.createAppendTransaction = createAppendTransaction;
package/example.txt CHANGED
@@ -1 +1 @@
1
- Hello, CKBFS! This is a sample file published using 20240906.ce6724722cf6 protocol.
1
+ hello, world
@@ -1,4 +1,4 @@
1
- import { CKBFS, NetworkType, ProtocolVersion, CKBFSDataType, extractCKBFSWitnessContent, isCKBFSWitness, CKBFSData } from '../src/index';
1
+ import { CKBFS, NetworkType, ProtocolVersion, CKBFSDataType, extractCKBFSWitnessContent, isCKBFSWitness, CKBFSData, AppendContentOptions } from '../src/index';
2
2
  import { Script, ClientPublicTestnet, Transaction, ccc } from "@ckb-ccc/core";
3
3
 
4
4
  // Replace with your actual private key
@@ -169,6 +169,37 @@ async function appendExample() {
169
169
  }
170
170
  }
171
171
 
172
+ /**
173
+ * Example of appending content directly (string) to an existing CKBFS file
174
+ * @param previousAppendTxHash The transaction hash from the previous append operation
175
+ */
176
+ async function appendContentExample(previousAppendTxHash: string) {
177
+ try {
178
+ console.log(`Getting cell info from previous append transaction: ${previousAppendTxHash}`);
179
+ const ckbfsCell = await getCellInfoFromTransaction(previousAppendTxHash);
180
+
181
+ const contentToAppend = "\nAnd this is more content appended directly as a string!";
182
+ const options: AppendContentOptions = {
183
+ // You can optionally specify feeRate, network, version
184
+ // feeRate: 3000
185
+ };
186
+
187
+ console.log(`Appending direct content: "${contentToAppend}"`);
188
+
189
+ // Append the string content
190
+ const txHash = await ckbfs.appendContent(contentToAppend, ckbfsCell, options);
191
+
192
+ console.log(`Direct content appended successfully!`);
193
+ console.log(`Transaction Hash: ${txHash}`);
194
+ console.log(`View at: https://pudge.explorer.nervos.org/transaction/${txHash}`);
195
+
196
+ return txHash;
197
+ } catch (error) {
198
+ console.error('Error appending direct content:', error);
199
+ throw error;
200
+ }
201
+ }
202
+
172
203
  /**
173
204
  * Main function to run the example
174
205
  */
@@ -178,7 +209,13 @@ async function main() {
178
209
  console.log(`Using CKBFS protocol version: ${ProtocolVersion.V2}`);
179
210
 
180
211
  try {
181
- await appendExample();
212
+ // Run the file append first
213
+ const firstAppendTxHash = await appendExample();
214
+ console.log('-------------------------------');
215
+
216
+ // Now run the content append, using the output from the first append
217
+ await appendContentExample(firstAppendTxHash);
218
+
182
219
  console.log('Example completed successfully!');
183
220
  process.exit(0);
184
221
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import { CKBFS, NetworkType, ProtocolVersion } from '../src/index';
1
+ import { CKBFS, NetworkType, ProtocolVersion, PublishContentOptions } from '../src/index';
2
2
 
3
3
  // Replace with your actual private key
4
4
  const privateKey = process.env.CKB_PRIVATE_KEY || 'your-private-key-here';
@@ -52,6 +52,38 @@ async function publishExample() {
52
52
  }
53
53
  }
54
54
 
55
+ /**
56
+ * Example of publishing content directly (string) to CKBFS
57
+ */
58
+ async function publishContentExample() {
59
+ try {
60
+ // Get address info
61
+ const address = await ckbfs.getAddress();
62
+ console.log(`Using address for content publish: ${address.toString()}`);
63
+
64
+ // Define content and options (contentType and filename are required)
65
+ const content = "Hello CKBFS from direct content!";
66
+ const options: PublishContentOptions = {
67
+ contentType: 'text/plain',
68
+ filename: 'direct_content_example.txt',
69
+ // You can optionally specify feeRate, network, version, useTypeID
70
+ // feeRate: 3000
71
+ };
72
+
73
+ console.log(`Publishing direct content: "${content}"`);
74
+ const txHash = await ckbfs.publishContent(content, options);
75
+
76
+ console.log(`Direct content published successfully!`);
77
+ console.log(`Transaction Hash: ${txHash}`);
78
+ console.log(`View at: https://pudge.explorer.nervos.org/transaction/${txHash}`);
79
+
80
+ return txHash;
81
+ } catch (error) {
82
+ console.error('Error publishing direct content:', error);
83
+ throw error;
84
+ }
85
+ }
86
+
55
87
  /**
56
88
  * Main function to run the example
57
89
  */
@@ -62,6 +94,8 @@ async function main() {
62
94
 
63
95
  try {
64
96
  await publishExample();
97
+ console.log('----------------------------------');
98
+ await publishContentExample();
65
99
  console.log('Example completed successfully!');
66
100
  process.exit(0);
67
101
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckbfs/api",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "description": "SDK for CKBFS protocol on CKB",
5
5
  "license": "MIT",
6
6
  "author": "Code Monad<code@lab-11.org>",