@ckbfs/api
Version:
SDK for CKBFS protocol on CKB
335 lines (334 loc) • 19.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCKBFSScriptConfig = exports.DEPLOY_TX_HASH = exports.DEP_GROUP_TX_HASH = exports.ADLER32_TYPE_ID = exports.ADLER32_CODE_HASH = exports.CKBFS_TYPE_ID = exports.CKBFS_CODE_HASH = exports.DEFAULT_VERSION = exports.DEFAULT_NETWORK = exports.ProtocolVersion = exports.NetworkType = exports.CKBFS_HEADER_STRING = exports.CKBFS_HEADER = exports.BackLinkV2 = exports.BackLinkV1 = exports.CKBFSData = exports.createChunkedCKBFSWitnesses = exports.isCKBFSWitness = exports.extractCKBFSWitnessContent = exports.createTextCKBFSWitness = exports.createCKBFSWitness = exports.saveFileFromChain = exports.getFileContentFromChain = exports.combineChunksToFile = exports.splitFileIntoChunks = exports.getContentType = exports.writeFile = exports.readFileAsUint8Array = exports.readFileAsText = exports.readFile = exports.appendCKBFS = exports.publishCKBFS = exports.createAppendTransaction = exports.createPublishTransaction = exports.createCKBFSCell = exports.verifyWitnessChecksum = exports.updateChecksum = exports.verifyChecksum = exports.calculateChecksum = exports.CKBFS = void 0;
const core_1 = require("@ckb-ccc/core");
const checksum_1 = require("./utils/checksum");
Object.defineProperty(exports, "calculateChecksum", { enumerable: true, get: function () { return checksum_1.calculateChecksum; } });
Object.defineProperty(exports, "verifyChecksum", { enumerable: true, get: function () { return checksum_1.verifyChecksum; } });
Object.defineProperty(exports, "updateChecksum", { enumerable: true, get: function () { return checksum_1.updateChecksum; } });
Object.defineProperty(exports, "verifyWitnessChecksum", { enumerable: true, get: function () { return checksum_1.verifyWitnessChecksum; } });
const transaction_1 = require("./utils/transaction");
Object.defineProperty(exports, "createCKBFSCell", { enumerable: true, get: function () { return transaction_1.createCKBFSCell; } });
Object.defineProperty(exports, "createPublishTransaction", { enumerable: true, get: function () { return transaction_1.createPublishTransaction; } });
Object.defineProperty(exports, "createAppendTransaction", { enumerable: true, get: function () { return transaction_1.createAppendTransaction; } });
Object.defineProperty(exports, "publishCKBFS", { enumerable: true, get: function () { return transaction_1.publishCKBFS; } });
Object.defineProperty(exports, "appendCKBFS", { enumerable: true, get: function () { return transaction_1.appendCKBFS; } });
const file_1 = require("./utils/file");
Object.defineProperty(exports, "readFile", { enumerable: true, get: function () { return file_1.readFile; } });
Object.defineProperty(exports, "readFileAsText", { enumerable: true, get: function () { return file_1.readFileAsText; } });
Object.defineProperty(exports, "readFileAsUint8Array", { enumerable: true, get: function () { return file_1.readFileAsUint8Array; } });
Object.defineProperty(exports, "writeFile", { enumerable: true, get: function () { return file_1.writeFile; } });
Object.defineProperty(exports, "getContentType", { enumerable: true, get: function () { return file_1.getContentType; } });
Object.defineProperty(exports, "splitFileIntoChunks", { enumerable: true, get: function () { return file_1.splitFileIntoChunks; } });
Object.defineProperty(exports, "combineChunksToFile", { enumerable: true, get: function () { return file_1.combineChunksToFile; } });
Object.defineProperty(exports, "getFileContentFromChain", { enumerable: true, get: function () { return file_1.getFileContentFromChain; } });
Object.defineProperty(exports, "saveFileFromChain", { enumerable: true, get: function () { return file_1.saveFileFromChain; } });
const witness_1 = require("./utils/witness");
Object.defineProperty(exports, "createCKBFSWitness", { enumerable: true, get: function () { return witness_1.createCKBFSWitness; } });
Object.defineProperty(exports, "createTextCKBFSWitness", { enumerable: true, get: function () { return witness_1.createTextCKBFSWitness; } });
Object.defineProperty(exports, "extractCKBFSWitnessContent", { enumerable: true, get: function () { return witness_1.extractCKBFSWitnessContent; } });
Object.defineProperty(exports, "isCKBFSWitness", { enumerable: true, get: function () { return witness_1.isCKBFSWitness; } });
Object.defineProperty(exports, "createChunkedCKBFSWitnesses", { enumerable: true, get: function () { return witness_1.createChunkedCKBFSWitnesses; } });
const molecule_1 = require("./utils/molecule");
Object.defineProperty(exports, "CKBFSData", { enumerable: true, get: function () { return molecule_1.CKBFSData; } });
Object.defineProperty(exports, "BackLinkV1", { enumerable: true, get: function () { return molecule_1.BackLinkV1; } });
Object.defineProperty(exports, "BackLinkV2", { enumerable: true, get: function () { return molecule_1.BackLinkV2; } });
Object.defineProperty(exports, "CKBFS_HEADER", { enumerable: true, get: function () { return molecule_1.CKBFS_HEADER; } });
Object.defineProperty(exports, "CKBFS_HEADER_STRING", { enumerable: true, get: function () { return molecule_1.CKBFS_HEADER_STRING; } });
const constants_1 = require("./utils/constants");
Object.defineProperty(exports, "NetworkType", { enumerable: true, get: function () { return constants_1.NetworkType; } });
Object.defineProperty(exports, "ProtocolVersion", { enumerable: true, get: function () { return constants_1.ProtocolVersion; } });
Object.defineProperty(exports, "DEFAULT_NETWORK", { enumerable: true, get: function () { return constants_1.DEFAULT_NETWORK; } });
Object.defineProperty(exports, "DEFAULT_VERSION", { enumerable: true, get: function () { return constants_1.DEFAULT_VERSION; } });
Object.defineProperty(exports, "CKBFS_CODE_HASH", { enumerable: true, get: function () { return constants_1.CKBFS_CODE_HASH; } });
Object.defineProperty(exports, "CKBFS_TYPE_ID", { enumerable: true, get: function () { return constants_1.CKBFS_TYPE_ID; } });
Object.defineProperty(exports, "ADLER32_CODE_HASH", { enumerable: true, get: function () { return constants_1.ADLER32_CODE_HASH; } });
Object.defineProperty(exports, "ADLER32_TYPE_ID", { enumerable: true, get: function () { return constants_1.ADLER32_TYPE_ID; } });
Object.defineProperty(exports, "DEP_GROUP_TX_HASH", { enumerable: true, get: function () { return constants_1.DEP_GROUP_TX_HASH; } });
Object.defineProperty(exports, "DEPLOY_TX_HASH", { enumerable: true, get: function () { return constants_1.DEPLOY_TX_HASH; } });
Object.defineProperty(exports, "getCKBFSScriptConfig", { enumerable: true, get: function () { return constants_1.getCKBFSScriptConfig; } });
const transaction_2 = require("./utils/transaction");
// Helper to encode string to Uint8Array
const textEncoder = new TextEncoder();
/**
* Main CKBFS SDK class
*/
class CKBFS {
/**
* Creates a new CKBFS SDK instance
* @param signerOrPrivateKey The signer instance or CKB private key to use for signing transactions
* @param networkOrOptions The network type or configuration options
* @param options Additional configuration options when using privateKey
*/
constructor(signerOrPrivateKey, networkOrOptions = constants_1.DEFAULT_NETWORK, options) {
// Determine if first parameter is a Signer or privateKey
if (typeof signerOrPrivateKey === 'string') {
// Initialize with private key
const privateKey = signerOrPrivateKey;
const network = typeof networkOrOptions === 'string' ? networkOrOptions : constants_1.DEFAULT_NETWORK;
const opts = options || (typeof networkOrOptions === 'object' ? networkOrOptions : {});
const client = new core_1.ClientPublicTestnet();
this.signer = new core_1.SignerCkbPrivateKey(client, privateKey);
this.network = network;
this.chunkSize = opts.chunkSize || 30 * 1024;
this.version = opts.version || constants_1.DEFAULT_VERSION;
this.useTypeID = opts.useTypeID || false;
}
else {
// Initialize with signer
this.signer = signerOrPrivateKey;
const opts = typeof networkOrOptions === 'object' ? networkOrOptions : {};
this.network = opts.network || constants_1.DEFAULT_NETWORK;
this.chunkSize = opts.chunkSize || 30 * 1024;
this.version = opts.version || constants_1.DEFAULT_VERSION;
this.useTypeID = opts.useTypeID || false;
}
}
/**
* Gets the recommended address object for the signer
* @returns Promise resolving to the address object
*/
async getAddress() {
return this.signer.getRecommendedAddressObj();
}
/**
* Gets the lock script for the signer
* @returns Promise resolving to the lock script
*/
async getLock() {
const address = await this.getAddress();
return address.script;
}
/**
* Gets the CKBFS script configuration for the current settings
* @returns The CKBFS script configuration
*/
getCKBFSConfig() {
return (0, constants_1.getCKBFSScriptConfig)(this.network, this.version, this.useTypeID);
}
/**
* Publishes a file to CKBFS
* @param filePath The path to the file to publish
* @param options Options for publishing the file
* @returns Promise resolving to the transaction hash
*/
async publishFile(filePath, options = {}) {
// Read the file and split into chunks
const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
const contentChunks = [];
for (let i = 0; i < fileContent.length; i += this.chunkSize) {
contentChunks.push(fileContent.slice(i, i + this.chunkSize));
}
// Get the lock script
const lock = await this.getLock();
// Determine content type if not provided
const contentType = options.contentType || (0, file_1.getContentType)(filePath);
// Use the filename from the path if not provided
const pathParts = filePath.split(/[\\\/]/);
const filename = options.filename || pathParts[pathParts.length - 1];
// Create and sign the transaction using the utility function
const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
contentChunks,
contentType,
filename,
lock,
capacity: options.capacity,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version,
useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
});
console.log('Publish file tx:', tx.stringify());
// Send the transaction
const txHash = await this.signer.sendTransaction(tx);
return (0, transaction_2.ensureHexPrefix)(txHash);
}
/**
* Publishes content (string or Uint8Array) directly to CKBFS
* @param content The content string or byte array to publish
* @param options Options for publishing the content (contentType and filename are required)
* @returns Promise resolving to the transaction hash
*/
async publishContent(content, options) {
const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
const contentChunks = [];
for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
}
const lock = await this.getLock();
// Use provided contentType and filename (required)
const { contentType, filename } = options;
const tx = await (0, transaction_1.publishCKBFS)(this.signer, {
contentChunks,
contentType,
filename,
lock,
capacity: options.capacity,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version,
useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
});
console.log('Publish content tx:', tx.stringify());
const txHash = await this.signer.sendTransaction(tx);
return (0, transaction_2.ensureHexPrefix)(txHash);
}
/**
* Appends content from a file to an existing CKBFS file
* @param filePath The path to the file containing the content to append
* @param ckbfsCell The CKBFS cell to append to
* @param options Additional options for the append operation
* @returns Promise resolving to the transaction hash
*/
async appendFile(filePath, ckbfsCell, options = {}) {
// Read the file and split into chunks
const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
const contentChunks = [];
for (let i = 0; i < fileContent.length; i += this.chunkSize) {
contentChunks.push(fileContent.slice(i, i + this.chunkSize));
}
// Create and sign the transaction using the utility function
const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
ckbfsCell,
contentChunks,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version
});
console.log('Append file tx:', tx.stringify());
// Send the transaction
const txHash = await this.signer.sendTransaction(tx);
return (0, transaction_2.ensureHexPrefix)(txHash);
}
/**
* Appends content (string or Uint8Array) directly to an existing CKBFS file
* @param content The content string or byte array to append
* @param ckbfsCell The CKBFS cell to append to
* @param options Additional options for the append operation
* @returns Promise resolving to the transaction hash
*/
async appendContent(content, ckbfsCell, options = {}) {
const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
const contentChunks = [];
for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
}
const tx = await (0, transaction_1.appendCKBFS)(this.signer, {
ckbfsCell,
contentChunks,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version
// No useTypeID option for append
});
console.log('Append content tx:', tx.stringify());
const txHash = await this.signer.sendTransaction(tx);
return (0, transaction_2.ensureHexPrefix)(txHash);
}
/**
* Creates a new transaction for publishing a file but doesn't sign or send it
* @param filePath The path to the file to publish
* @param options Options for publishing the file
* @returns Promise resolving to the unsigned transaction
*/
async createPublishTransaction(filePath, options = {}) {
// Read the file and split into chunks
const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
const contentChunks = [];
for (let i = 0; i < fileContent.length; i += this.chunkSize) {
contentChunks.push(fileContent.slice(i, i + this.chunkSize));
}
// Get the lock script
const lock = await this.getLock();
// Determine content type if not provided
const contentType = options.contentType || (0, file_1.getContentType)(filePath);
// Use the filename from the path if not provided
const pathParts = filePath.split(/[\\\/]/);
const filename = options.filename || pathParts[pathParts.length - 1];
// Create the transaction using the utility function
return (0, transaction_1.createPublishTransaction)(this.signer, {
contentChunks,
contentType,
filename,
lock,
capacity: options.capacity,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version,
useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
});
}
/**
* Creates a new transaction for publishing content (string or Uint8Array) directly, but doesn't sign or send it
* @param content The content string or byte array to publish
* @param options Options for publishing the content (contentType and filename are required)
* @returns Promise resolving to the unsigned transaction
*/
async createPublishContentTransaction(content, options) {
const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
const contentChunks = [];
for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
}
const lock = await this.getLock();
// Use provided contentType and filename (required)
const { contentType, filename } = options;
return (0, transaction_1.createPublishTransaction)(this.signer, {
contentChunks,
contentType,
filename,
lock,
capacity: options.capacity,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version,
useTypeID: options.useTypeID !== undefined ? options.useTypeID : this.useTypeID
});
}
/**
* Creates a new transaction for appending content from a file but doesn't sign or send it
* @param filePath The path to the file containing the content to append
* @param ckbfsCell The CKBFS cell to append to
* @param options Additional options for the append operation
* @returns Promise resolving to the unsigned transaction
*/
async createAppendTransaction(filePath, ckbfsCell, options = {}) {
// Read the file and split into chunks
const fileContent = (0, file_1.readFileAsUint8Array)(filePath);
const contentChunks = [];
for (let i = 0; i < fileContent.length; i += this.chunkSize) {
contentChunks.push(fileContent.slice(i, i + this.chunkSize));
}
// Create the transaction using the utility function
return (0, transaction_1.createAppendTransaction)(this.signer, {
ckbfsCell,
contentChunks,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version
});
}
/**
* Creates a new transaction for appending content (string or Uint8Array) directly, but doesn't sign or send it
* @param content The content string or byte array to append
* @param ckbfsCell The CKBFS cell to append to
* @param options Additional options for the append operation
* @returns Promise resolving to the unsigned transaction
*/
async createAppendContentTransaction(content, ckbfsCell, options = {}) {
const contentBytes = typeof content === 'string' ? textEncoder.encode(content) : content;
const contentChunks = [];
for (let i = 0; i < contentBytes.length; i += this.chunkSize) {
contentChunks.push(contentBytes.slice(i, i + this.chunkSize));
}
return (0, transaction_1.createAppendTransaction)(this.signer, {
ckbfsCell,
contentChunks,
feeRate: options.feeRate,
network: options.network || this.network,
version: options.version || this.version
// No useTypeID option for append
});
}
}
exports.CKBFS = CKBFS;