@ckbfs/api 2.0.18 → 2.0.19
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/utils/transactions/v3.js +1 -1
- package/examples/nervape.ts +503 -0
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/utils/transactions/v3.ts +1 -1
|
@@ -222,7 +222,7 @@ async function prepareAppendV3Transaction(options) {
|
|
|
222
222
|
const combinedContent = Buffer.concat(contentChunks);
|
|
223
223
|
const newChecksum = await (0, checksum_1.updateChecksum)(previousChecksum, combinedContent);
|
|
224
224
|
// Calculate the actual witness indices where our content is placed
|
|
225
|
-
const contentStartIndex = witnessStartIndex || from?.witnesses.length ||
|
|
225
|
+
const contentStartIndex = witnessStartIndex || from?.witnesses.length || 0;
|
|
226
226
|
// Create CKBFS v3 witnesses with backlink info
|
|
227
227
|
const ckbfsWitnesses = (0, witness_1.createChunkedCKBFSV3Witnesses)(contentChunks, {
|
|
228
228
|
previousTxHash,
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import fs from "fs"
|
|
2
|
+
import path, { parse } from 'path';
|
|
3
|
+
import {
|
|
4
|
+
CKBFS,
|
|
5
|
+
NetworkType,
|
|
6
|
+
CKBFSDataType,
|
|
7
|
+
ProtocolVersion,
|
|
8
|
+
CKBFSData,
|
|
9
|
+
getFileContentFromChain,
|
|
10
|
+
getCKBFSScriptConfig,
|
|
11
|
+
extractCKBFSV3WitnessContent,
|
|
12
|
+
isCKBFSV3Witness,
|
|
13
|
+
resolveCKBFSCell,
|
|
14
|
+
createAppendV3Transaction
|
|
15
|
+
} from '../src';
|
|
16
|
+
import {
|
|
17
|
+
Script,
|
|
18
|
+
Address,
|
|
19
|
+
ClientPublicTestnet,
|
|
20
|
+
ClientPublicMainnet,
|
|
21
|
+
Transaction,
|
|
22
|
+
ccc
|
|
23
|
+
} from "@ckb-ccc/core";
|
|
24
|
+
import {
|
|
25
|
+
transferSpore
|
|
26
|
+
} from "@ckb-ccc/spore";
|
|
27
|
+
//import { isMainnet, network, CKB_PRIVATE_KEY } from "../config"
|
|
28
|
+
|
|
29
|
+
const isMainnet = false
|
|
30
|
+
const CKB_PRIVATE_KEY = "0x1733e6f7825f99eb41ca26f8569fa90c2cb8c5ae199bbd38a97562291f784983"
|
|
31
|
+
|
|
32
|
+
const network = isMainnet ? NetworkType.Mainnet : NetworkType.Testnet
|
|
33
|
+
const client = isMainnet ? new ClientPublicMainnet() : new ClientPublicTestnet()
|
|
34
|
+
|
|
35
|
+
export const TestnetTraceLockDep = {
|
|
36
|
+
outPoint: {
|
|
37
|
+
// txHash: "0xb60c07715089877b238a60559ff4c15b46991ddcf1cfd2f9a40c32d6fff668ee",
|
|
38
|
+
txHash: "0x7a3e492188438ca4b260fed0f7a00d18ec9e4671a8c3b54fc2b3b49447ab2e2f",
|
|
39
|
+
index: 0x0,
|
|
40
|
+
},
|
|
41
|
+
depType: "code",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const MainnetTraceLockDep = {
|
|
45
|
+
outPoint: {
|
|
46
|
+
txHash: "0xd00a0222a12ae202d68fa4e90650ba560b325a3707c901395966a191372c47f7",
|
|
47
|
+
index: 0x0,
|
|
48
|
+
},
|
|
49
|
+
depType: "code",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const TestnetShadowDep = {
|
|
53
|
+
outPoint: {
|
|
54
|
+
txHash: "0x2d8a311a55e42d7d6810610149f6e125f0d292112f8ed4a21177aec05da2b905",
|
|
55
|
+
index: 0x0,
|
|
56
|
+
},
|
|
57
|
+
depType: "code",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const MainnetShadowDep = {
|
|
61
|
+
outPoint: {
|
|
62
|
+
txHash: "0x5b20ec7d7d5c6410ac4924c57d1eac1dd50129b6263be3dc93055397b5724dc2",
|
|
63
|
+
index: 0x0,
|
|
64
|
+
},
|
|
65
|
+
depType: "code",
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
const TraceLockDep = isMainnet ? MainnetTraceLockDep : TestnetTraceLockDep
|
|
70
|
+
const ShadowDep = isMainnet ? MainnetShadowDep : TestnetShadowDep
|
|
71
|
+
|
|
72
|
+
const TraceLogCodeHash = "0xbd7e56daaa4cc9ecf488a50d2f4db2a55a7c86eb2df2157d24a62be9be5b34ab"
|
|
73
|
+
const ShadowSporeCodeHash = "0x6361d4b20d845953d9c9431bbba08905573005a71e2a2432e7e0e7c685666f24"
|
|
74
|
+
|
|
75
|
+
const ckbfs = new CKBFS(
|
|
76
|
+
CKB_PRIVATE_KEY,
|
|
77
|
+
isMainnet ? NetworkType.Mainnet : NetworkType.Testnet,
|
|
78
|
+
{
|
|
79
|
+
version: ProtocolVersion.V3,
|
|
80
|
+
chunkSize: 30 * 1024, // 30KB chunks
|
|
81
|
+
useTypeID: false // Use code hash instead of type ID
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
async function getAddressScriptHash(addr: string | Address) {
|
|
86
|
+
if (typeof addr === 'string') {
|
|
87
|
+
addr = await Address.fromString(addr, client)
|
|
88
|
+
console.log("addr=", addr)
|
|
89
|
+
}
|
|
90
|
+
return `0x03${addr.script.hash().slice(2)}`
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function mint(physicalArtifactNo: string) {
|
|
94
|
+
// Get address info
|
|
95
|
+
const address = await ckbfs.getAddress();
|
|
96
|
+
const ownerHash = await getAddressScriptHash(address)
|
|
97
|
+
|
|
98
|
+
const content = `MINT,TO:${ownerHash}\n`
|
|
99
|
+
|
|
100
|
+
// You can provide additional options
|
|
101
|
+
const options = {
|
|
102
|
+
contentType: 'text/plain',
|
|
103
|
+
filename: `${physicalArtifactNo}.LOGS`,
|
|
104
|
+
};
|
|
105
|
+
const tx = await ckbfs.createPublishContentTransaction(content, options);
|
|
106
|
+
const signer = ckbfs['signer']
|
|
107
|
+
const txHash = await signer.sendTransaction(tx)
|
|
108
|
+
const ckbfsId = tx.outputs[0].type?.args.toString()
|
|
109
|
+
return { txHash, log: content, ckbfsId };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function claim(to: string, sporeId: string, ckbfsId: string) {
|
|
113
|
+
const from = await ckbfs.getAddress();
|
|
114
|
+
const ckbfsCell = await getCkbfsCellInfo(ckbfsId);
|
|
115
|
+
console.log("ckbfsCell=", ckbfsCell)
|
|
116
|
+
const fromHash = await getAddressScriptHash(from)
|
|
117
|
+
const toHash = await getAddressScriptHash(to)
|
|
118
|
+
|
|
119
|
+
const content = `TRANSFER,FROM:${fromHash},TO:${toHash}\n`
|
|
120
|
+
|
|
121
|
+
const tx = await ckbfs.createAppendContentTransaction(content, ckbfsCell);
|
|
122
|
+
|
|
123
|
+
tx.addCellDeps(TraceLockDep)
|
|
124
|
+
|
|
125
|
+
const sizeBefore = tx.outputs[0].lock.occupiedSize
|
|
126
|
+
const traceLogLock = Script.from({
|
|
127
|
+
codeHash: TraceLogCodeHash,
|
|
128
|
+
hashType: "type",
|
|
129
|
+
args: toHash
|
|
130
|
+
})
|
|
131
|
+
tx.outputs[0].lock = traceLogLock
|
|
132
|
+
const sizeAfter = traceLogLock.occupiedSize
|
|
133
|
+
|
|
134
|
+
const diffSize = BigInt(sizeAfter - sizeBefore) * BigInt(100000000)
|
|
135
|
+
tx.outputs[0].capacity = tx.outputs[0].capacity + diffSize
|
|
136
|
+
|
|
137
|
+
const sporeLockArgs = `0x01${ tx.outputs[0].type?.hash().slice(2) }`
|
|
138
|
+
const newSporeLock = Script.from({
|
|
139
|
+
codeHash: ShadowSporeCodeHash,
|
|
140
|
+
args: sporeLockArgs,
|
|
141
|
+
hashType: "data1",
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
tx.outputs = [
|
|
145
|
+
tx.outputs[0]
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
const signer = ckbfs['signer']
|
|
149
|
+
const sporeTx = await transferSpore({
|
|
150
|
+
signer: signer as any,
|
|
151
|
+
id: sporeId,
|
|
152
|
+
to: newSporeLock,
|
|
153
|
+
tx: tx,
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
tx.addCellDeps(ShadowDep)
|
|
157
|
+
|
|
158
|
+
const finalTx = sporeTx.tx
|
|
159
|
+
await finalTx.completeFeeBy(signer as any)
|
|
160
|
+
console.log("finalTx=", finalTx)
|
|
161
|
+
const txHash = await signer.sendTransaction(finalTx)
|
|
162
|
+
console.log(`File appended successfully! Transaction Hash: ${txHash}`);
|
|
163
|
+
return { txHash, log: content }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export async function giveName(name: string, ckbfsId: string) {
|
|
167
|
+
const ckbfsCell = await getCkbfsCellInfo(ckbfsId)
|
|
168
|
+
const content = `GIVE_NAME,NEW_NAME:${name}\n`
|
|
169
|
+
|
|
170
|
+
console.log("ckbfsCell=", ckbfsCell)
|
|
171
|
+
|
|
172
|
+
const signer = ckbfs['signer']
|
|
173
|
+
let tx = await ckbfs.createAppendContentTransaction(content, ckbfsCell);
|
|
174
|
+
tx.addCellDeps(TraceLockDep)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
parseCkbfsData(tx.outputsData[0])
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
//tx.witnesses = tx.witnesses.reverse()
|
|
181
|
+
// tx.witnesses[0] = '0x'
|
|
182
|
+
// tx.witnesses[0] = tx.witnesses[0]
|
|
183
|
+
|
|
184
|
+
console.log("tx=", tx)
|
|
185
|
+
|
|
186
|
+
tx = await signer.signTransaction(tx)
|
|
187
|
+
|
|
188
|
+
console.log("signed tx=", tx)
|
|
189
|
+
// await signer.sendTransaction(tx)
|
|
190
|
+
const txHash = await signer.sendTransaction(tx)
|
|
191
|
+
console.log(`File appended successfully! Transaction Hash: ${txHash}`);
|
|
192
|
+
return { txHash, log: content }
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export async function transfer(to: string, ckbfsId: string) {
|
|
196
|
+
const ckbfsCell = await getCkbfsCellInfo(ckbfsId)
|
|
197
|
+
const from = await ckbfs.getAddress();
|
|
198
|
+
const fromHash = await getAddressScriptHash(from)
|
|
199
|
+
const toHash = await getAddressScriptHash(to)
|
|
200
|
+
const content = `TRANSFER,FROM:${fromHash},TO:${toHash}\n`
|
|
201
|
+
|
|
202
|
+
const signer = ckbfs['signer']
|
|
203
|
+
let tx = await ckbfs.createAppendContentTransaction(content, ckbfsCell);
|
|
204
|
+
tx.outputs[0].lock.args = toHash as `0x{string}`;
|
|
205
|
+
// tx.addCellDeps(TestnetTraceLockDep)
|
|
206
|
+
const txHash = await signer.sendTransaction(tx)
|
|
207
|
+
console.log(`File appended successfully! Transaction Hash: ${txHash}`);
|
|
208
|
+
|
|
209
|
+
return { txHash, log: content };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// export async function release(from: string, ckbfsId: string) {
|
|
213
|
+
// const ckbfsCell = await await getCkbfsCellInfo(ckbfsId)
|
|
214
|
+
// const fromHash = await getAddressScriptHash(from)
|
|
215
|
+
// const content = `RELEASE,FROM:${fromHash}\n`
|
|
216
|
+
// const signer = ckbfs['signer']
|
|
217
|
+
// let tx = await ckbfs.createAppendContentTransaction(content, ckbfsCell);
|
|
218
|
+
|
|
219
|
+
// tx.addCellDeps(TestnetTraceLockDep)
|
|
220
|
+
// const txHash = await signer.sendTransaction(tx)
|
|
221
|
+
// console.log(`File appended successfully! Transaction Hash: ${txHash}`);
|
|
222
|
+
// return { txHash, log: content };
|
|
223
|
+
// }
|
|
224
|
+
|
|
225
|
+
// export async function retrieveLogsFromChain(ckbfsId: string) {
|
|
226
|
+
// const { outPoint, data } = await getCkbfsCellInfo(ckbfsId)
|
|
227
|
+
// const content = await getFileContentFromChain(client, outPoint, data)
|
|
228
|
+
// const logs = content.toString().trim().split("\n")
|
|
229
|
+
// return logs
|
|
230
|
+
// }
|
|
231
|
+
|
|
232
|
+
export async function getCkbfsCellInfo(ckbfsId: string) {
|
|
233
|
+
const { codeHash, hashType } = getCKBFSScriptConfig(isMainnet ? NetworkType.Mainnet : NetworkType.Testnet, ProtocolVersion.V3)
|
|
234
|
+
console.log("codeHash, hashType=", codeHash, hashType, ckbfsId)
|
|
235
|
+
const cell = await client.findSingletonCellByType({
|
|
236
|
+
codeHash,
|
|
237
|
+
hashType,
|
|
238
|
+
args: ckbfsId
|
|
239
|
+
}, true)
|
|
240
|
+
|
|
241
|
+
if (!cell || !cell.cellOutput.type) {
|
|
242
|
+
throw new Error('No CKBFS cell found');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const rawData = cell.outputData.startsWith('0x')
|
|
246
|
+
? Buffer.from(cell.outputData.slice(2), 'hex')
|
|
247
|
+
: Buffer.from(cell.outputData, 'hex');
|
|
248
|
+
|
|
249
|
+
const ckbfsData = CKBFSData.unpack(rawData, ProtocolVersion.V3)
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
outPoint: { txHash: cell.outPoint.txHash as string, index: Number(cell.outPoint.index) },
|
|
253
|
+
type: cell.cellOutput.type,
|
|
254
|
+
lock: cell.cellOutput.lock,
|
|
255
|
+
capacity: cell.cellOutput.capacity,
|
|
256
|
+
data: ckbfsData,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
export function getCkbfsList() {
|
|
262
|
+
const file = path.join(__dirname, `./data/${isMainnet ? 'mainnet' : 'testnet'}/ckbfs-list-x3.json`)
|
|
263
|
+
return JSON.parse(fs.readFileSync(file).toString())
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export async function mintAll() {
|
|
267
|
+
const ckbfsList = getCkbfsList()
|
|
268
|
+
for(const no of ckbfsList) {
|
|
269
|
+
const { txHash, ckbfsId } = await mint(no)
|
|
270
|
+
console.log(`minted ckbfs no=${no}, ckbfsId=${ckbfsId}, txHash=${txHash}`);
|
|
271
|
+
|
|
272
|
+
const interval = setInterval(async () => {
|
|
273
|
+
try {
|
|
274
|
+
const tx = await client.getTransaction(txHash)
|
|
275
|
+
if (tx && tx.status === 'committed') {
|
|
276
|
+
clearInterval(interval)
|
|
277
|
+
console.info(`tx confirmed, https://explorer.nervos.org/transaction/${txHash}`);
|
|
278
|
+
}
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.error(error)
|
|
281
|
+
}
|
|
282
|
+
}, 5 * 1000)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function getCellInfoFromV3Transaction(txHash: string): Promise<{
|
|
287
|
+
outPoint: { txHash: string; index: number };
|
|
288
|
+
type: Script;
|
|
289
|
+
data: CKBFSDataType;
|
|
290
|
+
lock: Script;
|
|
291
|
+
capacity: bigint;
|
|
292
|
+
previousTxHash: string;
|
|
293
|
+
previousWitnessIndex: number;
|
|
294
|
+
previousChecksum: number;
|
|
295
|
+
}> {
|
|
296
|
+
console.log(`Retrieving v3 transaction data for: ${txHash}`);
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
// Get transaction from RPC
|
|
300
|
+
const txWithStatus = await client.getTransaction(txHash);
|
|
301
|
+
if (!txWithStatus || !txWithStatus.transaction) {
|
|
302
|
+
throw new Error(`Transaction ${txHash} not found`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const tx = Transaction.from(txWithStatus.transaction);
|
|
306
|
+
console.log(`Transaction found with ${tx.outputs.length} outputs`);
|
|
307
|
+
|
|
308
|
+
// Find the CKBFS cell output (first output with type script)
|
|
309
|
+
let ckbfsCellIndex = 0;
|
|
310
|
+
const output = tx.outputs[ckbfsCellIndex];
|
|
311
|
+
if (!output || !output.type) {
|
|
312
|
+
throw new Error('No CKBFS cell found in the transaction');
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
console.log(`Found CKBFS v3 cell at index ${ckbfsCellIndex}`);
|
|
316
|
+
console.log(`Cell type script hash: ${output.type.hash()}`);
|
|
317
|
+
|
|
318
|
+
// Get output data
|
|
319
|
+
const outputData = tx.outputsData[ckbfsCellIndex];
|
|
320
|
+
if (!outputData) {
|
|
321
|
+
throw new Error('Output data not found');
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Parse the output data as CKBFS v3 data
|
|
325
|
+
const rawData = outputData.startsWith('0x')
|
|
326
|
+
? ccc.bytesFrom(outputData.slice(2), 'hex')
|
|
327
|
+
: Buffer.from(outputData, 'hex');
|
|
328
|
+
|
|
329
|
+
// Unpack the raw data using v3 format
|
|
330
|
+
const version = ProtocolVersion.V3;
|
|
331
|
+
console.log(`Using protocol version ${version} for unpacking v3 cell data`);
|
|
332
|
+
|
|
333
|
+
let ckbfsData: CKBFSDataType;
|
|
334
|
+
try {
|
|
335
|
+
ckbfsData = CKBFSData.unpack(rawData, version);
|
|
336
|
+
|
|
337
|
+
console.log('Successfully unpacked CKBFS v3 cell data:');
|
|
338
|
+
console.log(`- Checksum: ${ckbfsData.checksum}`);
|
|
339
|
+
console.log(`- File: ${ckbfsData.filename}`);
|
|
340
|
+
console.log(`- Content Type: ${ckbfsData.contentType}`);
|
|
341
|
+
console.log(`- Index: ${ckbfsData.index}`);
|
|
342
|
+
} catch (error) {
|
|
343
|
+
console.error('Error unpacking CKBFS v3 data:', error);
|
|
344
|
+
throw new Error(`Failed to unpack CKBFS v3 data: ${error}`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Extract backlink information from v3 witness
|
|
348
|
+
let previousTxHash = '0x' + '00'.repeat(32);
|
|
349
|
+
let previousWitnessIndex = 0;
|
|
350
|
+
let previousChecksum = 0;
|
|
351
|
+
|
|
352
|
+
if (ckbfsData.index !== undefined && ckbfsData.index < tx.witnesses.length) {
|
|
353
|
+
const witnessHex = tx.witnesses[ckbfsData.index];
|
|
354
|
+
const witness = Buffer.from(witnessHex.slice(2), 'hex');
|
|
355
|
+
|
|
356
|
+
if (isCKBFSV3Witness(witness)) {
|
|
357
|
+
try {
|
|
358
|
+
const witnessData = extractCKBFSV3WitnessContent(witness, true);
|
|
359
|
+
previousTxHash = witnessData.previousTxHash || previousTxHash;
|
|
360
|
+
previousWitnessIndex = witnessData.previousWitnessIndex || 0;
|
|
361
|
+
previousChecksum = witnessData.previousChecksum || 0;
|
|
362
|
+
|
|
363
|
+
console.log('Extracted v3 backlink information:');
|
|
364
|
+
console.log(`- Previous TX Hash: ${previousTxHash}`);
|
|
365
|
+
console.log(`- Previous Witness Index: ${previousWitnessIndex}`);
|
|
366
|
+
console.log(`- Previous Checksum: ${previousChecksum}`);
|
|
367
|
+
} catch (error) {
|
|
368
|
+
console.warn('Could not extract backlink info from witness:', error);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
outPoint: {
|
|
375
|
+
txHash,
|
|
376
|
+
index: ckbfsCellIndex
|
|
377
|
+
},
|
|
378
|
+
type: output.type,
|
|
379
|
+
lock: output.lock,
|
|
380
|
+
capacity: output.capacity,
|
|
381
|
+
data: ckbfsData,
|
|
382
|
+
previousTxHash,
|
|
383
|
+
previousWitnessIndex,
|
|
384
|
+
previousChecksum
|
|
385
|
+
};
|
|
386
|
+
} catch (error) {
|
|
387
|
+
console.error('Error retrieving v3 transaction data:', error);
|
|
388
|
+
throw new Error(`Failed to retrieve or parse v3 cell data: ${error}`);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export async function getCkbfsTxContent(txHash: string, index = 0) {
|
|
393
|
+
const tx = await client.getTransaction(txHash);
|
|
394
|
+
const {
|
|
395
|
+
transaction,
|
|
396
|
+
status: txStatus,
|
|
397
|
+
blockNumber,
|
|
398
|
+
} = tx!;
|
|
399
|
+
|
|
400
|
+
let timestamp: number = 0;
|
|
401
|
+
if (txStatus === 'committed') {
|
|
402
|
+
const header = await client.getHeaderByNumber(blockNumber!);
|
|
403
|
+
timestamp = Number(header?.timestamp);
|
|
404
|
+
}
|
|
405
|
+
const toAddress = Address.fromScript(
|
|
406
|
+
transaction.outputs[0].lock,
|
|
407
|
+
client,
|
|
408
|
+
).toString();
|
|
409
|
+
const outputData = transaction.outputsData[index];
|
|
410
|
+
|
|
411
|
+
const rawData = outputData.startsWith('0x')
|
|
412
|
+
? Buffer.from(outputData.slice(2), 'hex')
|
|
413
|
+
: Buffer.from(outputData, 'hex');
|
|
414
|
+
const ckbfsData = CKBFSData.unpack(rawData as any, ProtocolVersion.V3);
|
|
415
|
+
const contentChunks = [];
|
|
416
|
+
|
|
417
|
+
// const indexes =
|
|
418
|
+
// ckbfsData.indexes ||
|
|
419
|
+
// (ckbfsData.index !== undefined ? [ckbfsData.index] : []);
|
|
420
|
+
// if (indexes.length > 0) {
|
|
421
|
+
// // Get content from each witness index
|
|
422
|
+
// for (const idx of indexes) {
|
|
423
|
+
// if (idx >= transaction.witnesses.length) {
|
|
424
|
+
// console.warn(`Witness index ${idx} out of range`);
|
|
425
|
+
// continue;
|
|
426
|
+
// }
|
|
427
|
+
// const witnessHex = transaction.witnesses[idx];
|
|
428
|
+
// const witness = Buffer.from(witnessHex.slice(2), 'hex'); // Remove 0x prefix
|
|
429
|
+
// // Extract content (skip CKBFS header + version byte)
|
|
430
|
+
// if (witness.length >= 6 && witness.slice(0, 5).toString() === 'CKBFS') {
|
|
431
|
+
// const content = witness.slice(6);
|
|
432
|
+
// contentChunks.push(content); // Add to beginning of array (we're going backwards)
|
|
433
|
+
// } else {
|
|
434
|
+
// console.warn(`Witness at index ${idx} is not a valid CKBFS witness`);
|
|
435
|
+
// }
|
|
436
|
+
// }
|
|
437
|
+
// }
|
|
438
|
+
const witnessHex = transaction.witnesses[ckbfsData.index!];
|
|
439
|
+
const witness = Buffer.from(witnessHex.slice(2), 'hex');
|
|
440
|
+
const witnessData = extractCKBFSV3WitnessContent(new Uint8Array(witness), true);
|
|
441
|
+
|
|
442
|
+
// const witnessData = extractCKBFSV3WitnessContent(witness as any, true);
|
|
443
|
+
|
|
444
|
+
console.log("witnessData=", witnessData)
|
|
445
|
+
console.log("content=", Buffer.from(witnessData.content).toString())
|
|
446
|
+
|
|
447
|
+
const ckbfsId = transaction.outputs[0].type?.args.toString();
|
|
448
|
+
|
|
449
|
+
// const content = Buffer.concat(contentChunks).toString().trim();
|
|
450
|
+
return {
|
|
451
|
+
data: ckbfsData,
|
|
452
|
+
toAddress,
|
|
453
|
+
content: "",
|
|
454
|
+
ckbfsId,
|
|
455
|
+
txStatus,
|
|
456
|
+
committedAt: timestamp,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function parseCkbfsData(outputData: string){
|
|
461
|
+
// const outputData = "0x4500000014000000180000001c0000002a000000010000002614cb020a000000746578742f706c61696e170000003358303132354e4d4e5641503030303130312e4c4f4753"
|
|
462
|
+
// const outputData = "0x4500000014000000180000001c0000002a000000010000009443df5b0a000000746578742f706c61696e170000003358303132354e4d4e5641503030303130322e4c4f4753"
|
|
463
|
+
const rawData = outputData.startsWith('0x')
|
|
464
|
+
? Buffer.from(outputData.slice(2), 'hex')
|
|
465
|
+
: Buffer.from(outputData, 'hex');
|
|
466
|
+
const ckbfsData = CKBFSData.unpack(rawData as any, ProtocolVersion.V3);
|
|
467
|
+
console.log(ckbfsData)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
// mintAll()
|
|
472
|
+
|
|
473
|
+
// mint("3X0125NMNVAP000102").then(console.log)
|
|
474
|
+
|
|
475
|
+
// claim("ckt1qyqtaymen8quq9r3sf7x20uuq4pl5t8r4x8qqunj4q",
|
|
476
|
+
// "0x2b3cbd4c86a42e3ea1d092daab2f213e1600203906f33645f825159e1071d1e4", // sporeId
|
|
477
|
+
// "0x33fd0f19f411eec7cc84d32577a015612afc00cd008225a2ed34a8fda475e498" // ckbfsId
|
|
478
|
+
// );
|
|
479
|
+
|
|
480
|
+
// getCellInfoFromV3Transaction("0x54c86dbdc6bdafb4616221d54cfc0ff186a4a772eba509838684f8e1ea271b40").then(console.log)
|
|
481
|
+
|
|
482
|
+
// parseCkbfsData()
|
|
483
|
+
|
|
484
|
+
giveName(
|
|
485
|
+
"aaa",
|
|
486
|
+
"0x33fd0f19f411eec7cc84d32577a015612afc00cd008225a2ed34a8fda475e498" // ckbfsId
|
|
487
|
+
).then(console.log)
|
|
488
|
+
|
|
489
|
+
// transfer(
|
|
490
|
+
// "ckt1qyqtaymen8quq9r3sf7x20uuq4pl5t8r4x8qqunj4q",
|
|
491
|
+
// "0xe58baa82c4844add60911bb890487fea3c45436b9d7b203cc1065301d0a9c503"
|
|
492
|
+
// ).then(console.log)
|
|
493
|
+
|
|
494
|
+
// getCkbfsCellInfo("0x52315569e5ff0d6d6392f047fcbea97bae1b32b688c29aca5251a157157278d3").then((data) => {
|
|
495
|
+
// console.log("ckbfs data=", data)
|
|
496
|
+
// })
|
|
497
|
+
|
|
498
|
+
// getCkbfsTxContent("0xecc76092e301d15a808ee91570bc8c71ea448d17e9dc186c699db716878f116a").then(console.log)
|
|
499
|
+
// getCellInfoFromV3Transaction("0x8dc79a7630145e2a220e2363beca2781c6a4f0f79ef7a01ab73f17dc90571fb7").then(console.log)
|
|
500
|
+
|
|
501
|
+
// getCkbfsCellInfo("0x0084106b9bea08f512e35b725c4a710ebf09cb65c05601ebde8d911bc6c662bf").then(console.log)
|
|
502
|
+
|
|
503
|
+
// testReresolve("0x0084106b9bea08f512e35b725c4a710ebf09cb65c05601ebde8d911bc6c662bf").then(console.log)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckbfs/api",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.19",
|
|
4
4
|
"description": "SDK for CKBFS protocol on CKB",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Code Monad<code@lab-11.org>",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"sdk"
|
|
30
30
|
],
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@ckb-ccc/spore": "
|
|
32
|
+
"@ckb-ccc/spore": "1.5.5",
|
|
33
33
|
"@types/jest": "^29.5.12",
|
|
34
34
|
"@types/node": "^22.7.9",
|
|
35
35
|
"jest": "^29.7.0",
|
package/src/index.ts
CHANGED
|
@@ -366,7 +366,7 @@ export async function prepareAppendV3Transaction(
|
|
|
366
366
|
const newChecksum = await updateChecksum(previousChecksum, combinedContent);
|
|
367
367
|
|
|
368
368
|
// Calculate the actual witness indices where our content is placed
|
|
369
|
-
const contentStartIndex = witnessStartIndex || from?.witnesses.length ||
|
|
369
|
+
const contentStartIndex = witnessStartIndex || from?.witnesses.length || 0;
|
|
370
370
|
|
|
371
371
|
// Create CKBFS v3 witnesses with backlink info
|
|
372
372
|
const ckbfsWitnesses = createChunkedCKBFSV3Witnesses(contentChunks, {
|