@ckbfs/api 1.5.1 → 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 +437 -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 -115
- package/dist/utils/transaction.js +45 -622
- 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
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ccc, Transaction, Script, Signer } from "@ckb-ccc/core";
|
|
2
|
+
import { CKBFSDataType } from "../molecule";
|
|
3
|
+
import { NetworkType, ProtocolVersion } from "../constants";
|
|
4
|
+
import { BaseCKBFSCellOptions } from "./shared";
|
|
5
|
+
/**
|
|
6
|
+
* V3 CKBFS transaction utilities - witnesses-based storage with backlinks
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* V3-specific Options for publishing a file to CKBFS
|
|
10
|
+
*/
|
|
11
|
+
export interface PublishV3Options extends Omit<BaseCKBFSCellOptions, 'version'> {
|
|
12
|
+
contentChunks: Uint8Array[];
|
|
13
|
+
feeRate?: number;
|
|
14
|
+
from?: Transaction;
|
|
15
|
+
version: typeof ProtocolVersion.V3;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* V3-specific Options for appending content to a CKBFS file
|
|
19
|
+
*/
|
|
20
|
+
export interface AppendV3Options {
|
|
21
|
+
ckbfsCell: {
|
|
22
|
+
outPoint: {
|
|
23
|
+
txHash: string;
|
|
24
|
+
index: number;
|
|
25
|
+
};
|
|
26
|
+
data: CKBFSDataType;
|
|
27
|
+
type: Script;
|
|
28
|
+
lock: Script;
|
|
29
|
+
capacity: bigint;
|
|
30
|
+
};
|
|
31
|
+
contentChunks: Uint8Array[];
|
|
32
|
+
feeRate?: number;
|
|
33
|
+
network?: NetworkType;
|
|
34
|
+
version: typeof ProtocolVersion.V3;
|
|
35
|
+
from?: Transaction;
|
|
36
|
+
previousTxHash: string;
|
|
37
|
+
previousWitnessIndex: number;
|
|
38
|
+
previousChecksum: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* V3-specific Options for transferring a CKBFS file
|
|
42
|
+
*/
|
|
43
|
+
export interface TransferV3Options {
|
|
44
|
+
ckbfsCell: {
|
|
45
|
+
outPoint: {
|
|
46
|
+
txHash: string;
|
|
47
|
+
index: number;
|
|
48
|
+
};
|
|
49
|
+
data: CKBFSDataType;
|
|
50
|
+
type: Script;
|
|
51
|
+
lock: Script;
|
|
52
|
+
capacity: bigint;
|
|
53
|
+
};
|
|
54
|
+
newLock: Script;
|
|
55
|
+
feeRate?: number;
|
|
56
|
+
network?: NetworkType;
|
|
57
|
+
version: typeof ProtocolVersion.V3;
|
|
58
|
+
from?: Transaction;
|
|
59
|
+
previousTxHash: string;
|
|
60
|
+
previousWitnessIndex: number;
|
|
61
|
+
previousChecksum: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Creates a CKBFS v3 cell
|
|
65
|
+
* @param options Options for creating the CKBFS cell
|
|
66
|
+
* @returns The created cell output
|
|
67
|
+
*/
|
|
68
|
+
export declare function createCKBFSV3Cell(options: BaseCKBFSCellOptions): {
|
|
69
|
+
lock: ccc.Script;
|
|
70
|
+
type: ccc.Script;
|
|
71
|
+
capacity: bigint;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Prepares a transaction for publishing a file to CKBFS v3 without fee and change handling
|
|
75
|
+
* @param options Options for publishing the file
|
|
76
|
+
* @returns Promise resolving to the prepared transaction and the output index of CKBFS Cell
|
|
77
|
+
*/
|
|
78
|
+
export declare function preparePublishV3Transaction(options: PublishV3Options): Promise<{
|
|
79
|
+
tx: Transaction;
|
|
80
|
+
outputIndex: number;
|
|
81
|
+
emptyTypeID: boolean;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Creates a transaction for publishing a file to CKBFS v3
|
|
85
|
+
* @param signer The signer to use for the transaction
|
|
86
|
+
* @param options Options for publishing the file
|
|
87
|
+
* @returns Promise resolving to the created transaction
|
|
88
|
+
*/
|
|
89
|
+
export declare function createPublishV3Transaction(signer: Signer, options: PublishV3Options): Promise<Transaction>;
|
|
90
|
+
/**
|
|
91
|
+
* Creates a transaction for appending content to a CKBFS v3 file
|
|
92
|
+
* @param signer The signer to use for the transaction
|
|
93
|
+
* @param options Options for appending content
|
|
94
|
+
* @returns Promise resolving to the created transaction
|
|
95
|
+
*/
|
|
96
|
+
export declare function createAppendV3Transaction(signer: Signer, options: AppendV3Options): Promise<Transaction>;
|
|
97
|
+
/**
|
|
98
|
+
* Creates a transaction for transferring ownership of a CKBFS v3 file
|
|
99
|
+
* @param signer The signer to use for the transaction
|
|
100
|
+
* @param options Options for transferring the file
|
|
101
|
+
* @returns Promise resolving to the created transaction
|
|
102
|
+
*/
|
|
103
|
+
export declare function createTransferV3Transaction(signer: Signer, options: TransferV3Options): Promise<Transaction>;
|
|
104
|
+
/**
|
|
105
|
+
* Creates a complete transaction for publishing a file to CKBFS v3
|
|
106
|
+
* @param signer The signer to use for the transaction
|
|
107
|
+
* @param options Options for publishing the file
|
|
108
|
+
* @returns Promise resolving to the signed transaction
|
|
109
|
+
*/
|
|
110
|
+
export declare function publishCKBFSV3(signer: Signer, options: PublishV3Options): Promise<Transaction>;
|
|
111
|
+
/**
|
|
112
|
+
* Creates a complete transaction for appending content to a CKBFS v3 file
|
|
113
|
+
* @param signer The signer to use for the transaction
|
|
114
|
+
* @param options Options for appending content
|
|
115
|
+
* @returns Promise resolving to the signed transaction
|
|
116
|
+
*/
|
|
117
|
+
export declare function appendCKBFSV3(signer: Signer, options: AppendV3Options): Promise<Transaction>;
|
|
118
|
+
/**
|
|
119
|
+
* Creates a complete transaction for transferring ownership of a CKBFS v3 file
|
|
120
|
+
* @param signer The signer to use for the transaction
|
|
121
|
+
* @param options Options for transferring the file
|
|
122
|
+
* @returns Promise resolving to the signed transaction
|
|
123
|
+
*/
|
|
124
|
+
export declare function transferCKBFSV3(signer: Signer, options: TransferV3Options): Promise<Transaction>;
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCKBFSV3Cell = createCKBFSV3Cell;
|
|
4
|
+
exports.preparePublishV3Transaction = preparePublishV3Transaction;
|
|
5
|
+
exports.createPublishV3Transaction = createPublishV3Transaction;
|
|
6
|
+
exports.createAppendV3Transaction = createAppendV3Transaction;
|
|
7
|
+
exports.createTransferV3Transaction = createTransferV3Transaction;
|
|
8
|
+
exports.publishCKBFSV3 = publishCKBFSV3;
|
|
9
|
+
exports.appendCKBFSV3 = appendCKBFSV3;
|
|
10
|
+
exports.transferCKBFSV3 = transferCKBFSV3;
|
|
11
|
+
const core_1 = require("@ckb-ccc/core");
|
|
12
|
+
const checksum_1 = require("../checksum");
|
|
13
|
+
const molecule_1 = require("../molecule");
|
|
14
|
+
const witness_1 = require("../witness");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
16
|
+
const shared_1 = require("./shared");
|
|
17
|
+
/**
|
|
18
|
+
* Creates a CKBFS v3 cell
|
|
19
|
+
* @param options Options for creating the CKBFS cell
|
|
20
|
+
* @returns The created cell output
|
|
21
|
+
*/
|
|
22
|
+
function createCKBFSV3Cell(options) {
|
|
23
|
+
const { contentType, filename, capacity, lock, network = constants_1.DEFAULT_NETWORK, useTypeID = false, } = options;
|
|
24
|
+
// Get CKBFS script config for v3
|
|
25
|
+
const config = (0, constants_1.getCKBFSScriptConfig)(network, constants_1.ProtocolVersion.V3, useTypeID);
|
|
26
|
+
// Create pre CKBFS type script
|
|
27
|
+
const preCkbfsTypeScript = new core_1.Script((0, shared_1.ensureHexPrefix)(config.codeHash), config.hashType, "0x0000000000000000000000000000000000000000000000000000000000000000");
|
|
28
|
+
// Return the cell output
|
|
29
|
+
return {
|
|
30
|
+
lock,
|
|
31
|
+
type: preCkbfsTypeScript,
|
|
32
|
+
capacity: capacity || 200n * 100000000n, // Default 200 CKB
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Prepares a transaction for publishing a file to CKBFS v3 without fee and change handling
|
|
37
|
+
* @param options Options for publishing the file
|
|
38
|
+
* @returns Promise resolving to the prepared transaction and the output index of CKBFS Cell
|
|
39
|
+
*/
|
|
40
|
+
async function preparePublishV3Transaction(options) {
|
|
41
|
+
const { from, contentChunks, contentType, filename, lock, capacity, network = constants_1.DEFAULT_NETWORK, useTypeID = false, } = options;
|
|
42
|
+
// Calculate checksum for the combined content
|
|
43
|
+
const combinedContent = Buffer.concat(contentChunks);
|
|
44
|
+
const checksum = await (0, checksum_1.calculateChecksum)(combinedContent);
|
|
45
|
+
// V3 format uses single index (first witness containing content)
|
|
46
|
+
const contentStartIndex = from?.witnesses.length || 1;
|
|
47
|
+
// Create CKBFS v3 witnesses (no backlinks for publish operation)
|
|
48
|
+
const ckbfsWitnesses = (0, witness_1.createChunkedCKBFSV3Witnesses)(contentChunks, {
|
|
49
|
+
// For publish operation, all previous fields are zero
|
|
50
|
+
previousTxHash: '0x' + '00'.repeat(32),
|
|
51
|
+
previousWitnessIndex: 0,
|
|
52
|
+
previousChecksum: 0,
|
|
53
|
+
startIndex: contentStartIndex,
|
|
54
|
+
});
|
|
55
|
+
// Create CKBFS v3 cell output data
|
|
56
|
+
const outputData = molecule_1.CKBFSData.pack({
|
|
57
|
+
index: contentStartIndex,
|
|
58
|
+
checksum,
|
|
59
|
+
contentType,
|
|
60
|
+
filename,
|
|
61
|
+
}, constants_1.ProtocolVersion.V3);
|
|
62
|
+
// Get CKBFS script config
|
|
63
|
+
const config = (0, constants_1.getCKBFSScriptConfig)(network, constants_1.ProtocolVersion.V3, useTypeID);
|
|
64
|
+
// Create pre CKBFS type script
|
|
65
|
+
const preCkbfsTypeScript = new core_1.Script((0, shared_1.ensureHexPrefix)(config.codeHash), config.hashType, "0x0000000000000000000000000000000000000000000000000000000000000000");
|
|
66
|
+
// Calculate the required capacity for the output cell
|
|
67
|
+
const ckbfsCellSize = BigInt(outputData.length +
|
|
68
|
+
preCkbfsTypeScript.occupiedSize +
|
|
69
|
+
lock.occupiedSize +
|
|
70
|
+
8) * 100000000n;
|
|
71
|
+
// Create pre transaction without cell deps initially
|
|
72
|
+
let preTx;
|
|
73
|
+
if (from) {
|
|
74
|
+
// If from is not empty, inject/merge the fields
|
|
75
|
+
preTx = core_1.Transaction.from({
|
|
76
|
+
...from,
|
|
77
|
+
outputs: from.outputs.length === 0
|
|
78
|
+
? [
|
|
79
|
+
createCKBFSV3Cell({
|
|
80
|
+
contentType,
|
|
81
|
+
filename,
|
|
82
|
+
lock,
|
|
83
|
+
network,
|
|
84
|
+
useTypeID,
|
|
85
|
+
capacity: ckbfsCellSize || capacity,
|
|
86
|
+
}),
|
|
87
|
+
]
|
|
88
|
+
: [
|
|
89
|
+
...from.outputs,
|
|
90
|
+
createCKBFSV3Cell({
|
|
91
|
+
contentType,
|
|
92
|
+
filename,
|
|
93
|
+
lock,
|
|
94
|
+
network,
|
|
95
|
+
useTypeID,
|
|
96
|
+
capacity: ckbfsCellSize || capacity,
|
|
97
|
+
}),
|
|
98
|
+
],
|
|
99
|
+
witnesses: from.witnesses.length === 0
|
|
100
|
+
? [
|
|
101
|
+
[], // Empty secp witness for signing if not provided
|
|
102
|
+
...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
|
|
103
|
+
]
|
|
104
|
+
: [
|
|
105
|
+
...from.witnesses,
|
|
106
|
+
...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
|
|
107
|
+
],
|
|
108
|
+
outputsData: from.outputsData.length === 0
|
|
109
|
+
? [outputData]
|
|
110
|
+
: [
|
|
111
|
+
...from.outputsData,
|
|
112
|
+
outputData,
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
preTx = core_1.Transaction.from({
|
|
118
|
+
outputs: [
|
|
119
|
+
createCKBFSV3Cell({
|
|
120
|
+
contentType,
|
|
121
|
+
filename,
|
|
122
|
+
lock,
|
|
123
|
+
network,
|
|
124
|
+
useTypeID,
|
|
125
|
+
capacity: ckbfsCellSize || capacity,
|
|
126
|
+
}),
|
|
127
|
+
],
|
|
128
|
+
witnesses: [
|
|
129
|
+
[], // Empty secp witness for signing
|
|
130
|
+
...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
|
|
131
|
+
],
|
|
132
|
+
outputsData: [outputData],
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// Add the CKBFS dep group cell dependency
|
|
136
|
+
preTx.addCellDeps({
|
|
137
|
+
outPoint: {
|
|
138
|
+
txHash: (0, shared_1.ensureHexPrefix)(config.depTxHash),
|
|
139
|
+
index: config.depIndex || 0,
|
|
140
|
+
},
|
|
141
|
+
depType: "depGroup",
|
|
142
|
+
});
|
|
143
|
+
// Create type ID args
|
|
144
|
+
const outputIndex = from ? from.outputs.length : 0;
|
|
145
|
+
const args = preTx.inputs.length > 0 ? core_1.ccc.hashTypeId(preTx.inputs[0], outputIndex) : "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
146
|
+
// Create CKBFS type script with type ID
|
|
147
|
+
const ckbfsTypeScript = new core_1.Script((0, shared_1.ensureHexPrefix)(config.codeHash), config.hashType, args);
|
|
148
|
+
// Create final transaction with same cell deps as preTx
|
|
149
|
+
const tx = core_1.Transaction.from({
|
|
150
|
+
cellDeps: preTx.cellDeps,
|
|
151
|
+
witnesses: preTx.witnesses,
|
|
152
|
+
outputsData: preTx.outputsData,
|
|
153
|
+
inputs: preTx.inputs,
|
|
154
|
+
outputs: outputIndex === 0
|
|
155
|
+
? [
|
|
156
|
+
{
|
|
157
|
+
lock,
|
|
158
|
+
type: ckbfsTypeScript,
|
|
159
|
+
capacity: preTx.outputs[outputIndex].capacity,
|
|
160
|
+
},
|
|
161
|
+
]
|
|
162
|
+
: [
|
|
163
|
+
...preTx.outputs.slice(0, outputIndex), // Include rest of outputs (e.g., change)
|
|
164
|
+
{
|
|
165
|
+
lock,
|
|
166
|
+
type: ckbfsTypeScript,
|
|
167
|
+
capacity: preTx.outputs[outputIndex].capacity,
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
return { tx, outputIndex, emptyTypeID: args === "0x0000000000000000000000000000000000000000000000000000000000000000" };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Creates a transaction for publishing a file to CKBFS v3
|
|
175
|
+
* @param signer The signer to use for the transaction
|
|
176
|
+
* @param options Options for publishing the file
|
|
177
|
+
* @returns Promise resolving to the created transaction
|
|
178
|
+
*/
|
|
179
|
+
async function createPublishV3Transaction(signer, options) {
|
|
180
|
+
const { feeRate, lock, } = options;
|
|
181
|
+
// Use preparePublishV3Transaction to create the base transaction
|
|
182
|
+
const { tx: preTx, outputIndex, emptyTypeID } = await preparePublishV3Transaction(options);
|
|
183
|
+
// Complete inputs by capacity
|
|
184
|
+
await preTx.completeInputsByCapacity(signer);
|
|
185
|
+
// Complete fee change to lock
|
|
186
|
+
await preTx.completeFeeChangeToLock(signer, lock, feeRate || 2000);
|
|
187
|
+
// If emptyTypeID is true, we need to create the proper type ID args
|
|
188
|
+
if (emptyTypeID) {
|
|
189
|
+
// Get CKBFS script config
|
|
190
|
+
const config = (0, constants_1.getCKBFSScriptConfig)(options.network || constants_1.DEFAULT_NETWORK, constants_1.ProtocolVersion.V3, options.useTypeID || false);
|
|
191
|
+
// Create type ID args
|
|
192
|
+
const args = core_1.ccc.hashTypeId(preTx.inputs[0], outputIndex);
|
|
193
|
+
// Create CKBFS type script with type ID
|
|
194
|
+
const ckbfsTypeScript = new core_1.Script((0, shared_1.ensureHexPrefix)(config.codeHash), config.hashType, args);
|
|
195
|
+
// Create final transaction with updated type script
|
|
196
|
+
const tx = core_1.Transaction.from({
|
|
197
|
+
cellDeps: preTx.cellDeps,
|
|
198
|
+
witnesses: preTx.witnesses,
|
|
199
|
+
outputsData: preTx.outputsData,
|
|
200
|
+
inputs: preTx.inputs,
|
|
201
|
+
outputs: preTx.outputs.map((output, index) => index === outputIndex
|
|
202
|
+
? {
|
|
203
|
+
...output,
|
|
204
|
+
type: ckbfsTypeScript,
|
|
205
|
+
}
|
|
206
|
+
: output),
|
|
207
|
+
});
|
|
208
|
+
return tx;
|
|
209
|
+
}
|
|
210
|
+
return preTx;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Creates a transaction for appending content to a CKBFS v3 file
|
|
214
|
+
* @param signer The signer to use for the transaction
|
|
215
|
+
* @param options Options for appending content
|
|
216
|
+
* @returns Promise resolving to the created transaction
|
|
217
|
+
*/
|
|
218
|
+
async function createAppendV3Transaction(signer, options) {
|
|
219
|
+
const { ckbfsCell, contentChunks, feeRate, network = constants_1.DEFAULT_NETWORK, previousTxHash, previousWitnessIndex, previousChecksum, } = options;
|
|
220
|
+
// Calculate new checksum by updating from previous checksum
|
|
221
|
+
const combinedContent = Buffer.concat(contentChunks);
|
|
222
|
+
const newChecksum = await (0, checksum_1.updateChecksum)(previousChecksum, combinedContent);
|
|
223
|
+
// Create CKBFS v3 witnesses with backlink info
|
|
224
|
+
const ckbfsWitnesses = (0, witness_1.createChunkedCKBFSV3Witnesses)(contentChunks, {
|
|
225
|
+
previousTxHash,
|
|
226
|
+
previousWitnessIndex,
|
|
227
|
+
previousChecksum,
|
|
228
|
+
});
|
|
229
|
+
// V3 format uses single index (first witness containing content)
|
|
230
|
+
const contentStartIndex = 1; // First witness is for signer, content starts at index 1
|
|
231
|
+
// Create updated CKBFS v3 cell output data
|
|
232
|
+
const outputData = molecule_1.CKBFSData.pack({
|
|
233
|
+
index: contentStartIndex,
|
|
234
|
+
checksum: newChecksum,
|
|
235
|
+
contentType: ckbfsCell.data.contentType,
|
|
236
|
+
filename: ckbfsCell.data.filename,
|
|
237
|
+
}, constants_1.ProtocolVersion.V3);
|
|
238
|
+
// Get CKBFS script config
|
|
239
|
+
const config = (0, constants_1.getCKBFSScriptConfig)(network, constants_1.ProtocolVersion.V3, false);
|
|
240
|
+
// Calculate the required capacity for the output cell
|
|
241
|
+
const ckbfsCellSize = BigInt(outputData.length + ckbfsCell.type.occupiedSize + ckbfsCell.lock.occupiedSize + 8) *
|
|
242
|
+
100000000n;
|
|
243
|
+
// Use the maximum value between calculated size and original capacity
|
|
244
|
+
const outputCapacity = ckbfsCellSize > ckbfsCell.capacity ? ckbfsCellSize : ckbfsCell.capacity;
|
|
245
|
+
// Create transaction
|
|
246
|
+
const tx = core_1.Transaction.from({
|
|
247
|
+
inputs: [
|
|
248
|
+
{
|
|
249
|
+
previousOutput: ckbfsCell.outPoint,
|
|
250
|
+
since: "0x0",
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
outputs: [
|
|
254
|
+
{
|
|
255
|
+
lock: ckbfsCell.lock,
|
|
256
|
+
type: ckbfsCell.type,
|
|
257
|
+
capacity: outputCapacity,
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
witnesses: [
|
|
261
|
+
[], // Empty secp witness for signing
|
|
262
|
+
...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
|
|
263
|
+
],
|
|
264
|
+
outputsData: [outputData],
|
|
265
|
+
});
|
|
266
|
+
// Add the CKBFS dep group cell dependency
|
|
267
|
+
tx.addCellDeps({
|
|
268
|
+
outPoint: {
|
|
269
|
+
txHash: (0, shared_1.ensureHexPrefix)(config.depTxHash),
|
|
270
|
+
index: config.depIndex || 0,
|
|
271
|
+
},
|
|
272
|
+
depType: "depGroup",
|
|
273
|
+
});
|
|
274
|
+
// Complete inputs by capacity for fees
|
|
275
|
+
await tx.completeInputsByCapacity(signer);
|
|
276
|
+
// Complete fee change to lock
|
|
277
|
+
await tx.completeFeeChangeToLock(signer, ckbfsCell.lock, feeRate || 2000);
|
|
278
|
+
return tx;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Creates a transaction for transferring ownership of a CKBFS v3 file
|
|
282
|
+
* @param signer The signer to use for the transaction
|
|
283
|
+
* @param options Options for transferring the file
|
|
284
|
+
* @returns Promise resolving to the created transaction
|
|
285
|
+
*/
|
|
286
|
+
async function createTransferV3Transaction(signer, options) {
|
|
287
|
+
const { ckbfsCell, newLock, feeRate, network = constants_1.DEFAULT_NETWORK, previousTxHash, previousWitnessIndex, previousChecksum, } = options;
|
|
288
|
+
// Create CKBFS v3 witness with backlink info but no content (transfer only)
|
|
289
|
+
const ckbfsWitnesses = (0, witness_1.createChunkedCKBFSV3Witnesses)([new Uint8Array(0)], {
|
|
290
|
+
previousTxHash,
|
|
291
|
+
previousWitnessIndex,
|
|
292
|
+
previousChecksum,
|
|
293
|
+
});
|
|
294
|
+
// V3 format uses single index (first witness containing backlink)
|
|
295
|
+
const contentStartIndex = 1; // First witness is for signer, backlink at index 1
|
|
296
|
+
// Create CKBFS v3 cell output data (unchanged for transfer)
|
|
297
|
+
const outputData = molecule_1.CKBFSData.pack({
|
|
298
|
+
index: contentStartIndex,
|
|
299
|
+
checksum: ckbfsCell.data.checksum, // Checksum unchanged in transfer
|
|
300
|
+
contentType: ckbfsCell.data.contentType,
|
|
301
|
+
filename: ckbfsCell.data.filename,
|
|
302
|
+
}, constants_1.ProtocolVersion.V3);
|
|
303
|
+
// Get CKBFS script config
|
|
304
|
+
const config = (0, constants_1.getCKBFSScriptConfig)(network, constants_1.ProtocolVersion.V3, false);
|
|
305
|
+
// Create transaction
|
|
306
|
+
const tx = core_1.Transaction.from({
|
|
307
|
+
inputs: [
|
|
308
|
+
{
|
|
309
|
+
previousOutput: ckbfsCell.outPoint,
|
|
310
|
+
since: "0x0",
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
outputs: [
|
|
314
|
+
{
|
|
315
|
+
lock: newLock,
|
|
316
|
+
type: ckbfsCell.type,
|
|
317
|
+
capacity: ckbfsCell.capacity,
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
witnesses: [
|
|
321
|
+
[], // Empty secp witness for signing
|
|
322
|
+
...ckbfsWitnesses.map((w) => `0x${Buffer.from(w).toString("hex")}`),
|
|
323
|
+
],
|
|
324
|
+
outputsData: [outputData],
|
|
325
|
+
});
|
|
326
|
+
// Add the CKBFS dep group cell dependency
|
|
327
|
+
tx.addCellDeps({
|
|
328
|
+
outPoint: {
|
|
329
|
+
txHash: (0, shared_1.ensureHexPrefix)(config.depTxHash),
|
|
330
|
+
index: config.depIndex || 0,
|
|
331
|
+
},
|
|
332
|
+
depType: "depGroup",
|
|
333
|
+
});
|
|
334
|
+
// Complete inputs by capacity for fees
|
|
335
|
+
await tx.completeInputsByCapacity(signer);
|
|
336
|
+
// Complete fee change to lock
|
|
337
|
+
await tx.completeFeeChangeToLock(signer, newLock, feeRate || 2000);
|
|
338
|
+
return tx;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Creates a complete transaction for publishing a file to CKBFS v3
|
|
342
|
+
* @param signer The signer to use for the transaction
|
|
343
|
+
* @param options Options for publishing the file
|
|
344
|
+
* @returns Promise resolving to the signed transaction
|
|
345
|
+
*/
|
|
346
|
+
async function publishCKBFSV3(signer, options) {
|
|
347
|
+
const tx = await createPublishV3Transaction(signer, options);
|
|
348
|
+
return signer.signTransaction(tx);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Creates a complete transaction for appending content to a CKBFS v3 file
|
|
352
|
+
* @param signer The signer to use for the transaction
|
|
353
|
+
* @param options Options for appending content
|
|
354
|
+
* @returns Promise resolving to the signed transaction
|
|
355
|
+
*/
|
|
356
|
+
async function appendCKBFSV3(signer, options) {
|
|
357
|
+
const tx = await createAppendV3Transaction(signer, options);
|
|
358
|
+
return signer.signTransaction(tx);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Creates a complete transaction for transferring ownership of a CKBFS v3 file
|
|
362
|
+
* @param signer The signer to use for the transaction
|
|
363
|
+
* @param options Options for transferring the file
|
|
364
|
+
* @returns Promise resolving to the signed transaction
|
|
365
|
+
*/
|
|
366
|
+
async function transferCKBFSV3(signer, options) {
|
|
367
|
+
const tx = await createTransferV3Transaction(signer, options);
|
|
368
|
+
return signer.signTransaction(tx);
|
|
369
|
+
}
|
package/dist/utils/witness.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for creating and handling CKBFS witnesses
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* V3 witness structure for backlinks and content chaining
|
|
6
|
+
*/
|
|
7
|
+
export interface CKBFSV3WitnessOptions {
|
|
8
|
+
previousTxHash?: string;
|
|
9
|
+
previousWitnessIndex?: number;
|
|
10
|
+
previousChecksum?: number;
|
|
11
|
+
nextIndex?: number;
|
|
12
|
+
content: Uint8Array;
|
|
13
|
+
}
|
|
4
14
|
/**
|
|
5
15
|
* Creates a CKBFS witness with content
|
|
6
16
|
* @param content The content to include in the witness
|
|
@@ -30,6 +40,41 @@ export declare function extractCKBFSWitnessContent(witness: Uint8Array): {
|
|
|
30
40
|
* @returns Boolean indicating whether the witness is a valid CKBFS witness
|
|
31
41
|
*/
|
|
32
42
|
export declare function isCKBFSWitness(witness: Uint8Array): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a CKBFS v3 witness with structured format
|
|
45
|
+
* @param options Witness options including backlink data and content
|
|
46
|
+
* @returns Uint8Array containing the v3 witness data
|
|
47
|
+
*/
|
|
48
|
+
export declare function createCKBFSV3Witness(options: CKBFSV3WitnessOptions): Uint8Array;
|
|
49
|
+
/**
|
|
50
|
+
* Creates an array of v3 witnesses for chunked content
|
|
51
|
+
* @param contentChunks Array of content chunks
|
|
52
|
+
* @param options Backlink options for head witness and start index
|
|
53
|
+
* @returns Array of Uint8Array witnesses
|
|
54
|
+
*/
|
|
55
|
+
export declare function createChunkedCKBFSV3Witnesses(contentChunks: Uint8Array[], options?: Omit<CKBFSV3WitnessOptions, 'content' | 'nextIndex'> & {
|
|
56
|
+
startIndex?: number;
|
|
57
|
+
}): Uint8Array[];
|
|
58
|
+
/**
|
|
59
|
+
* Extracts content from a CKBFS v3 witness
|
|
60
|
+
* @param witness The CKBFS v3 witness data
|
|
61
|
+
* @param isHeadWitness Whether this is the head witness or a continuation witness
|
|
62
|
+
* @returns Object containing the extracted data
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractCKBFSV3WitnessContent(witness: Uint8Array, isHeadWitness?: boolean): {
|
|
65
|
+
version?: number;
|
|
66
|
+
previousTxHash?: string;
|
|
67
|
+
previousWitnessIndex?: number;
|
|
68
|
+
previousChecksum?: number;
|
|
69
|
+
nextIndex: number;
|
|
70
|
+
content: Uint8Array;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Checks if a witness is a valid CKBFS v3 witness
|
|
74
|
+
* @param witness The witness data to check
|
|
75
|
+
* @returns Boolean indicating whether the witness is a valid CKBFS v3 witness
|
|
76
|
+
*/
|
|
77
|
+
export declare function isCKBFSV3Witness(witness: Uint8Array): boolean;
|
|
33
78
|
/**
|
|
34
79
|
* Creates an array of witnesses for a CKBFS transaction from content chunks
|
|
35
80
|
* @param contentChunks Array of content chunks
|