@ckbfs/api 1.2.4 → 1.2.6

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.
@@ -1,14 +1,15 @@
1
1
  import { ccc, Transaction, Script, Signer } from "@ckb-ccc/core";
2
- import { calculateChecksum, updateChecksum } from './checksum';
3
- import { CKBFSData, BackLinkType, CKBFSDataType } from './molecule';
4
- import { createChunkedCKBFSWitnesses } from './witness';
5
- import {
6
- getCKBFSScriptConfig,
7
- NetworkType,
8
- ProtocolVersion,
9
- DEFAULT_NETWORK,
10
- DEFAULT_VERSION
11
- } from './constants';
2
+ import { calculateChecksum, updateChecksum } from "./checksum";
3
+ import { CKBFSData, BackLinkType, CKBFSDataType } from "./molecule";
4
+ import { createChunkedCKBFSWitnesses } from "./witness";
5
+ import {
6
+ getCKBFSScriptConfig,
7
+ NetworkType,
8
+ ProtocolVersion,
9
+ ProtocolVersionType,
10
+ DEFAULT_NETWORK,
11
+ DEFAULT_VERSION,
12
+ } from "./constants";
12
13
 
13
14
  /**
14
15
  * Utility functions for CKB transaction creation and handling
@@ -23,7 +24,7 @@ export interface CKBFSCellOptions {
23
24
  capacity?: bigint;
24
25
  lock: Script;
25
26
  network?: NetworkType;
26
- version?: string;
27
+ version?: ProtocolVersionType;
27
28
  useTypeID?: boolean;
28
29
  }
29
30
 
@@ -49,7 +50,7 @@ export interface AppendOptions {
49
50
  contentChunks: Uint8Array[];
50
51
  feeRate?: number;
51
52
  network?: NetworkType;
52
- version?: string;
53
+ version?: ProtocolVersionType;
53
54
  }
54
55
 
55
56
  /**
@@ -57,8 +58,8 @@ export interface AppendOptions {
57
58
  * @param value The string to ensure is hex prefixed
58
59
  * @returns A hex prefixed string
59
60
  */
60
- function ensureHexPrefix(value: string): `0x${string}` {
61
- if (value.startsWith('0x')) {
61
+ export function ensureHexPrefix(value: string): `0x${string}` {
62
+ if (value.startsWith("0x")) {
62
63
  return value as `0x${string}`;
63
64
  }
64
65
  return `0x${value}` as `0x${string}`;
@@ -70,26 +71,26 @@ function ensureHexPrefix(value: string): `0x${string}` {
70
71
  * @returns The created cell output
71
72
  */
72
73
  export function createCKBFSCell(options: CKBFSCellOptions) {
73
- const {
74
- contentType,
75
- filename,
76
- capacity,
77
- lock,
78
- network = DEFAULT_NETWORK,
74
+ const {
75
+ contentType,
76
+ filename,
77
+ capacity,
78
+ lock,
79
+ network = DEFAULT_NETWORK,
79
80
  version = DEFAULT_VERSION,
80
- useTypeID = false
81
+ useTypeID = false,
81
82
  } = options;
82
-
83
+
83
84
  // Get CKBFS script config
84
85
  const config = getCKBFSScriptConfig(network, version, useTypeID);
85
-
86
+
86
87
  // Create pre CKBFS type script
87
88
  const preCkbfsTypeScript = new Script(
88
89
  ensureHexPrefix(config.codeHash),
89
90
  config.hashType as any,
90
- "0x0000000000000000000000000000000000000000000000000000000000000000"
91
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
91
92
  );
92
-
93
+
93
94
  // Return the cell output
94
95
  return {
95
96
  lock,
@@ -105,130 +106,140 @@ export function createCKBFSCell(options: CKBFSCellOptions) {
105
106
  * @returns Promise resolving to the created transaction
106
107
  */
107
108
  export async function createPublishTransaction(
108
- signer: Signer,
109
- options: PublishOptions
109
+ signer: Signer,
110
+ options: PublishOptions,
110
111
  ): Promise<Transaction> {
111
- const {
112
- contentChunks,
113
- contentType,
114
- filename,
115
- lock,
112
+ const {
113
+ contentChunks,
114
+ contentType,
115
+ filename,
116
+ lock,
116
117
  capacity,
117
118
  feeRate,
118
119
  network = DEFAULT_NETWORK,
119
120
  version = DEFAULT_VERSION,
120
- useTypeID = false
121
+ useTypeID = false,
121
122
  } = options;
122
-
123
+
123
124
  // Calculate checksum for the combined content
124
125
  const textEncoder = new TextEncoder();
125
126
  const combinedContent = Buffer.concat(contentChunks);
126
127
  const checksum = await calculateChecksum(combinedContent);
127
-
128
+
128
129
  // Create CKBFS witnesses - each chunk already includes the CKBFS header
129
130
  // Pass 0 as version byte - this is the protocol version byte in the witness header
130
131
  // not to be confused with the Protocol Version (V1 vs V2)
131
132
  const ckbfsWitnesses = createChunkedCKBFSWitnesses(contentChunks);
132
-
133
+
133
134
  // Calculate the actual witness indices where our content is placed
134
135
  // Index 0 is reserved for the secp256k1 witness for signing
135
136
  // So our CKBFS data starts at index 1
136
137
  const contentStartIndex = 1;
137
138
  const witnessIndices = Array.from(
138
- { length: contentChunks.length },
139
- (_, i) => contentStartIndex + i
139
+ { length: contentChunks.length },
140
+ (_, i) => contentStartIndex + i,
140
141
  );
141
-
142
+
142
143
  // Create CKBFS cell output data based on version
143
144
  let outputData: Uint8Array;
144
-
145
+
145
146
  if (version === ProtocolVersion.V1) {
146
147
  // V1 format: Single index field (a single number, not an array)
147
148
  // For V1, use the first index where content is placed
148
- outputData = CKBFSData.pack({
149
- index: contentStartIndex,
150
- checksum,
151
- contentType: contentType,
152
- filename: filename,
153
- backLinks: [],
154
- }, version);
149
+ outputData = CKBFSData.pack(
150
+ {
151
+ index: contentStartIndex,
152
+ checksum,
153
+ contentType: contentType,
154
+ filename: filename,
155
+ backLinks: [],
156
+ },
157
+ version,
158
+ );
155
159
  } else {
156
160
  // V2 format: Multiple indexes (array of numbers)
157
161
  // For V2, use all the indices where content is placed
158
- outputData = CKBFSData.pack({
159
- indexes: witnessIndices,
160
- checksum,
161
- contentType,
162
- filename,
163
- backLinks: [],
164
- }, version);
162
+ outputData = CKBFSData.pack(
163
+ {
164
+ indexes: witnessIndices,
165
+ checksum,
166
+ contentType,
167
+ filename,
168
+ backLinks: [],
169
+ },
170
+ version,
171
+ );
165
172
  }
166
-
173
+
167
174
  // Get CKBFS script config
168
175
  const config = getCKBFSScriptConfig(network, version, useTypeID);
169
-
176
+
170
177
  const preCkbfsTypeScript = new Script(
171
178
  ensureHexPrefix(config.codeHash),
172
179
  config.hashType as any,
173
- "0x0000000000000000000000000000000000000000000000000000000000000000"
180
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
174
181
  );
175
- const ckbfsCellSize = BigInt(outputData.length + preCkbfsTypeScript.occupiedSize + lock.occupiedSize + 8) * 100000000n
182
+ const ckbfsCellSize =
183
+ BigInt(
184
+ outputData.length +
185
+ preCkbfsTypeScript.occupiedSize +
186
+ lock.occupiedSize +
187
+ 8,
188
+ ) * 100000000n;
176
189
  // Create pre transaction without cell deps initially
177
190
  const preTx = Transaction.from({
178
191
  outputs: [
179
- createCKBFSCell({
180
- contentType,
181
- filename,
182
- lock,
183
- network,
192
+ createCKBFSCell({
193
+ contentType,
194
+ filename,
195
+ lock,
196
+ network,
184
197
  version,
185
198
  useTypeID,
186
- capacity: ckbfsCellSize || capacity
187
- })
199
+ capacity: ckbfsCellSize || capacity,
200
+ }),
188
201
  ],
189
202
  witnesses: [
190
203
  [], // Empty secp witness for signing
191
- ...ckbfsWitnesses.map(w => `0x${Buffer.from(w).toString('hex')}`),
204
+ ...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
192
205
  ],
193
- outputsData: [
194
- outputData,
195
- ]
206
+ outputsData: [outputData],
196
207
  });
197
-
208
+
198
209
  // Add the CKBFS dep group cell dependency
199
210
  preTx.addCellDeps({
200
211
  outPoint: {
201
212
  txHash: ensureHexPrefix(config.depTxHash),
202
213
  index: config.depIndex || 0,
203
214
  },
204
- depType: "depGroup"
215
+ depType: "depGroup",
205
216
  });
206
-
217
+
207
218
  // Get the recommended address to ensure lock script cell deps are included
208
219
  const address = await signer.getRecommendedAddressObj();
209
-
220
+
210
221
  // Complete inputs by capacity
211
222
  await preTx.completeInputsByCapacity(signer);
212
-
223
+
213
224
  // Complete fee change to lock
214
225
  await preTx.completeFeeChangeToLock(signer, lock, feeRate || 2000);
215
-
226
+
216
227
  // Create type ID args
217
228
  const args = ccc.hashTypeId(preTx.inputs[0], 0x0);
218
-
229
+
219
230
  // Create CKBFS type script with type ID
220
231
  const ckbfsTypeScript = new Script(
221
232
  ensureHexPrefix(config.codeHash),
222
233
  config.hashType as any,
223
- args
234
+ args,
224
235
  );
225
-
236
+
226
237
  // Create final transaction with same cell deps as preTx
227
238
  const tx = Transaction.from({
228
239
  cellDeps: preTx.cellDeps,
229
240
  witnesses: [
230
241
  [], // Reset first witness for signing
231
- ...preTx.witnesses.slice(1)
242
+ ...preTx.witnesses.slice(1),
232
243
  ],
233
244
  outputsData: preTx.outputsData,
234
245
  inputs: preTx.inputs,
@@ -238,10 +249,10 @@ export async function createPublishTransaction(
238
249
  type: ckbfsTypeScript,
239
250
  capacity: preTx.outputs[0].capacity,
240
251
  },
241
- ...preTx.outputs.slice(1) // Include rest of outputs (e.g., change)
242
- ]
252
+ ...preTx.outputs.slice(1), // Include rest of outputs (e.g., change)
253
+ ],
243
254
  });
244
-
255
+
245
256
  return tx;
246
257
  }
247
258
 
@@ -252,34 +263,36 @@ export async function createPublishTransaction(
252
263
  * @returns Promise resolving to the created transaction
253
264
  */
254
265
  export async function createAppendTransaction(
255
- signer: Signer,
256
- options: AppendOptions
266
+ signer: Signer,
267
+ options: AppendOptions,
257
268
  ): Promise<Transaction> {
258
- const {
259
- ckbfsCell,
260
- contentChunks,
269
+ const {
270
+ ckbfsCell,
271
+ contentChunks,
261
272
  feeRate,
262
273
  network = DEFAULT_NETWORK,
263
- version = DEFAULT_VERSION
274
+ version = DEFAULT_VERSION,
264
275
  } = options;
265
276
  const { outPoint, data, type, lock, capacity } = ckbfsCell;
266
-
277
+
267
278
  // Get CKBFS script config early to use version info
268
279
  const config = getCKBFSScriptConfig(network, version);
269
-
280
+
270
281
  // Create CKBFS witnesses - each chunk already includes the CKBFS header
271
282
  // Pass 0 as version byte - this is the protocol version byte in the witness header
272
283
  // not to be confused with the Protocol Version (V1 vs V2)
273
284
  const ckbfsWitnesses = createChunkedCKBFSWitnesses(contentChunks);
274
-
285
+
275
286
  // Combine the new content chunks for checksum calculation
276
287
  const combinedContent = Buffer.concat(contentChunks);
277
-
288
+
278
289
  // Update the existing checksum with the new content - this matches Adler32's
279
290
  // cumulative nature as required by Rule 11 in the RFC
280
291
  const contentChecksum = await updateChecksum(data.checksum, combinedContent);
281
- console.log(`Updated checksum from ${data.checksum} to ${contentChecksum} for appended content`);
282
-
292
+ console.log(
293
+ `Updated checksum from ${data.checksum} to ${contentChecksum} for appended content`,
294
+ );
295
+
283
296
  // Get the recommended address to ensure lock script cell deps are included
284
297
  const address = await signer.getRecommendedAddressObj();
285
298
 
@@ -288,19 +301,21 @@ export async function createAppendTransaction(
288
301
  // else CKBFS data starts at index 0
289
302
  const contentStartIndex = address.script.hash() === lock.hash() ? 1 : 0;
290
303
  const witnessIndices = Array.from(
291
- { length: contentChunks.length },
292
- (_, i) => contentStartIndex + i
304
+ { length: contentChunks.length },
305
+ (_, i) => contentStartIndex + i,
293
306
  );
294
-
307
+
295
308
  // Create backlink for the current state based on version
296
309
  let newBackLink: any;
297
-
310
+
298
311
  if (version === ProtocolVersion.V1) {
299
312
  // V1 format: Use index field (single number)
300
313
  newBackLink = {
301
314
  // In V1, field order is index, checksum, txHash
302
315
  // and index is a single number value, not an array
303
- index: data.index || (data.indexes && data.indexes.length > 0 ? data.indexes[0] : 0),
316
+ index:
317
+ data.index ||
318
+ (data.indexes && data.indexes.length > 0 ? data.indexes[0] : 0),
304
319
  checksum: data.checksum,
305
320
  txHash: outPoint.txHash,
306
321
  };
@@ -314,51 +329,61 @@ export async function createAppendTransaction(
314
329
  txHash: outPoint.txHash,
315
330
  };
316
331
  }
317
-
332
+
318
333
  // Update backlinks - add the new one to the existing backlinks array
319
334
  const backLinks = [...(data.backLinks || []), newBackLink];
320
-
335
+
321
336
  // Define output data based on version
322
337
  let outputData: Uint8Array;
323
-
338
+
324
339
  if (version === ProtocolVersion.V1) {
325
340
  // In V1, index is a single number, not an array
326
341
  // The first witness index is used (V1 can only reference one witness)
327
- outputData = CKBFSData.pack({
328
- index: witnessIndices[0], // Use only the first index as a number
329
- checksum: contentChecksum,
330
- contentType: data.contentType,
331
- filename: data.filename,
332
- backLinks,
333
- }, ProtocolVersion.V1); // Explicitly use V1 for packing
342
+ outputData = CKBFSData.pack(
343
+ {
344
+ index: witnessIndices[0], // Use only the first index as a number
345
+ checksum: contentChecksum,
346
+ contentType: data.contentType,
347
+ filename: data.filename,
348
+ backLinks,
349
+ },
350
+ ProtocolVersion.V1,
351
+ ); // Explicitly use V1 for packing
334
352
  } else {
335
353
  // In V2, indexes is an array of witness indices
336
- outputData = CKBFSData.pack({
337
- indexes: witnessIndices,
338
- checksum: contentChecksum,
339
- contentType: data.contentType,
340
- filename: data.filename,
341
- backLinks,
342
- }, ProtocolVersion.V2); // Explicitly use V2 for packing
354
+ outputData = CKBFSData.pack(
355
+ {
356
+ indexes: witnessIndices,
357
+ checksum: contentChecksum,
358
+ contentType: data.contentType,
359
+ filename: data.filename,
360
+ backLinks,
361
+ },
362
+ ProtocolVersion.V2,
363
+ ); // Explicitly use V2 for packing
343
364
  }
344
-
365
+
345
366
  // Pack the original data to get its size - use the appropriate version
346
367
  const originalData = CKBFSData.pack(data, version);
347
368
  const originalDataSize = originalData.length;
348
-
369
+
349
370
  // Get sizes and calculate capacity requirements
350
371
  const newDataSize = outputData.length;
351
-
372
+
352
373
  // Calculate the required capacity for the output cell
353
- // This accounts for:
374
+ // This accounts for:
354
375
  // 1. The output data size
355
376
  // 2. The type script's occupied size
356
377
  // 3. The lock script's occupied size
357
378
  // 4. A constant of 8 bytes (for header overhead)
358
- const ckbfsCellSize = BigInt(outputData.length + type.occupiedSize + lock.occupiedSize + 8) * 100000000n;
359
-
360
- console.log(`Original capacity: ${capacity}, Calculated size: ${ckbfsCellSize}, Data size: ${outputData.length}`);
361
-
379
+ const ckbfsCellSize =
380
+ BigInt(outputData.length + type.occupiedSize + lock.occupiedSize + 8) *
381
+ 100000000n;
382
+
383
+ console.log(
384
+ `Original capacity: ${capacity}, Calculated size: ${ckbfsCellSize}, Data size: ${outputData.length}`,
385
+ );
386
+
362
387
  // Use the maximum value between calculated size and original capacity
363
388
  // to ensure we have enough capacity but don't decrease capacity unnecessarily
364
389
  const outputCapacity = ckbfsCellSize > capacity ? ckbfsCellSize : capacity;
@@ -372,56 +397,57 @@ export async function createAppendTransaction(
372
397
  index: outPoint.index,
373
398
  },
374
399
  since: "0x0",
375
- }
400
+ },
376
401
  ],
377
402
  outputs: [
378
403
  {
379
404
  lock,
380
405
  type,
381
406
  capacity: outputCapacity,
382
- }
407
+ },
383
408
  ],
384
- outputsData: [
385
- outputData,
386
- ]
409
+ outputsData: [outputData],
387
410
  });
388
411
 
389
-
390
412
  // Add the CKBFS dep group cell dependency
391
413
  tx.addCellDeps({
392
414
  outPoint: {
393
415
  txHash: ensureHexPrefix(config.depTxHash),
394
416
  index: config.depIndex || 0,
395
417
  },
396
- depType: "depGroup"
418
+ depType: "depGroup",
397
419
  });
398
-
420
+
399
421
  const inputsBefore = tx.inputs.length;
400
422
  // If we need more capacity than the original cell had, add additional inputs
401
423
  if (outputCapacity > capacity) {
402
- console.log(`Need additional capacity: ${outputCapacity - capacity} shannons`);
424
+ console.log(
425
+ `Need additional capacity: ${outputCapacity - capacity} shannons`,
426
+ );
403
427
  // Add more inputs to cover the increased capacity
404
428
  await tx.completeInputsByCapacity(signer);
405
429
  }
406
430
 
407
- const witnesses: any = []
431
+ const witnesses: any = [];
408
432
  // add empty witness for signer if ckbfs's lock is the same as signer's lock
409
- if(address.script.hash() === lock.hash()) {
410
- witnesses.push('0x')
433
+ if (address.script.hash() === lock.hash()) {
434
+ witnesses.push("0x");
411
435
  }
412
436
  // add ckbfs witnesses
413
- witnesses.push(...ckbfsWitnesses.map(w => `0x${Buffer.from(w).toString('hex')}`))
437
+ witnesses.push(
438
+ ...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
439
+ );
414
440
 
415
441
  // Add empty witnesses for signer's input
416
442
  // This is to ensure that the transaction is valid and can be signed
417
- for(let i = inputsBefore; i < tx.inputs.length; i++) {
418
- witnesses.push('0x')
443
+ for (let i = inputsBefore; i < tx.inputs.length; i++) {
444
+ witnesses.push("0x");
419
445
  }
420
- tx.witnesses = witnesses
446
+ tx.witnesses = witnesses;
421
447
 
422
448
  // Complete fee
423
449
  await tx.completeFeeChangeToLock(signer, address.script, feeRate || 2000);
424
-
450
+
425
451
  return tx;
426
452
  }
427
453
 
@@ -432,8 +458,8 @@ export async function createAppendTransaction(
432
458
  * @returns Promise resolving to the signed transaction
433
459
  */
434
460
  export async function publishCKBFS(
435
- signer: Signer,
436
- options: PublishOptions
461
+ signer: Signer,
462
+ options: PublishOptions,
437
463
  ): Promise<Transaction> {
438
464
  const tx = await createPublishTransaction(signer, options);
439
465
  return signer.signTransaction(tx);
@@ -446,9 +472,9 @@ export async function publishCKBFS(
446
472
  * @returns Promise resolving to the signed transaction
447
473
  */
448
474
  export async function appendCKBFS(
449
- signer: Signer,
450
- options: AppendOptions
475
+ signer: Signer,
476
+ options: AppendOptions,
451
477
  ): Promise<Transaction> {
452
478
  const tx = await createAppendTransaction(signer, options);
453
479
  return signer.signTransaction(tx);
454
- }
480
+ }
@@ -0,0 +1 @@
1
+ Hello CKBFS from direct content!
@@ -0,0 +1 @@
1
+ Hello CKBFS from direct content!
@@ -1,49 +0,0 @@
1
- ---
2
- description:
3
- globs:
4
- alwaysApply: true
5
- ---
6
-
7
- You are an expert in TypeScript, Node.js, Next.js App Router, React, Shadcn UI, Radix UI and Tailwind.
8
-
9
- Code Style and Structure
10
- - Write concise, technical TypeScript code with accurate examples.
11
- - Use functional and declarative programming patterns; avoid classes.
12
- - Prefer iteration and modularization over code duplication.
13
- - Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
14
- - Structure files: exported component, subcomponents, helpers, static content, types.
15
-
16
- Naming Conventions
17
- - Use lowercase with dashes for directories (e.g., components/auth-wizard).
18
- - Favor named exports for components.
19
-
20
- TypeScript Usage
21
- - Use TypeScript for all code; prefer interfaces over types.
22
- - Avoid enums; use maps instead.
23
- - Use functional components with TypeScript interfaces.
24
-
25
- Syntax and Formatting
26
- - Use the "function" keyword for pure functions.
27
- - Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
28
- - Use declarative JSX.
29
-
30
- UI and Styling
31
- - Use Shadcn UI, Radix, and Tailwind for components and styling.
32
- - Implement responsive design with Tailwind CSS; use a mobile-first approach.
33
-
34
- Performance Optimization
35
- - Minimize 'use client', 'useEffect', and 'setState'; favor React Server Components (RSC).
36
- - Wrap client components in Suspense with fallback.
37
- - Use dynamic loading for non-critical components.
38
- - Optimize images: use WebP format, include size data, implement lazy loading.
39
-
40
- Key Conventions
41
- - Use 'nuqs' for URL search parameter state management.
42
- - Optimize Web Vitals (LCP, CLS, FID).
43
- - Limit 'use client':
44
- - Favor server components and Next.js SSR.
45
- - Use only for Web API access in small components.
46
- - Avoid for data fetching or state management.
47
-
48
- Follow Next.js docs for Data Fetching, Rendering, and Routing.
49
-
package/ABC.LOGS DELETED
@@ -1 +0,0 @@
1
- MINT,TO:ckt1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqdpallzwnhe64rqnqmev7hf98yrmh4yzucgdw7qwGIVE_NAME,NEW_NAME:NERVAPE_COOKIE