Javascript SDK

CESS SDK implementation for TypeScript.

Installation

npm install @cessnetwork/api @cessnetwork/util @cessnetwork/types

Overview

Complete Workflow with All Three Packages

This workflow demonstrates how all three packages work together:

  • @cessnetwork/api provides the main client and gateway operations

  • @cessnetwork/util provides essential utility functions like signing

  • @cessnetwork/types provides all the type definitions needed for type safety

This section explains how to use all three CESS packages (@cessnetwork/api, @cessnetwork/util, and @cessnetwork/types) together to perform a complete gateway workflow for file storage operations on the CESS network.

Step 1: Initialize CESS Client

import { CESS, CESSConfig, downloadFile, ExtendedDownloadOptions, GenGatewayAccessToken, isKeyringReady, SDKError, uploadFile } from '@cessnetwork/api';
import { safeSignUnixTime, } from '@cessnetwork/util';
import { GatewayConfig, OssAuthorityList, OssDetail, UploadResponse } from "@cessnetwork/types";
import { u8aToHex } from "@polkadot/util";

const config: CESSConfig = {
    rpcs: ["wss://pm-rpc.cess.network/ws/"],
    privateKey: process.env.CESS_PRIVATE_KEY || "",
}
const cess = await CESS.newClient(config);

console.log('Connected to network:', cess.getNetworkEnv());
console.log('Chain Metadata:', cess.getMetadata());
if (isKeyringReady(cess.keyring)) {
    console.log('Account address:', cess.getSignatureAcc());
    console.log('Account balance:', cess.getBalances());
} else {
    throw new SDKError('Keyring Pair is required', 'INVALID_KEYRING');
}

Step 2: Sign Message for Gateway Authentication

Using @cessnetwork/util's signing utilities to authenticate with the gateway:

const sign_message = Date.now().toString();
const signature = safeSignUnixTime(sign_message, getMnemonic());
console.log("signature:", signature);

Step 3: Create Storage Territory (if needed)

// Check if territory exists, if not create one
let territoryToken
const myTerritory = "default"
const territory = await cess.queryTerritory(accountAddress, myTerritory) as Territory;
const curBlockHeight = await cess.queryBlockNumberByHash()
console.log('Current Block Height:', curBlockHeight);

if (!territory) {
    try {
        const result = await cess.mintTerritory(
            1, // gibCount
            myTerritory,
            30, // days
        );

        if (result.success) {
            console.log('✅ Mint successful!', {txHash: result.txHash, blockHash: result.blockHash});

            // Wait and query the minted territory
            console.log('Waiting 6 seconds before querying territory...');
            await new Promise(resolve => setTimeout(resolve, 6000));

            const territory = await cess.queryTerritory(accountAddress, myTerritory) as Territory;
            territoryToken = territory?.token
            console.log('Territory details:', territory);
            console.log('Territory Token:', territoryToken);
        } else {
            console.error('❌ Territory minting failed:', result.error);
        }
    } catch (error) {
        console.error('❌ Error during territory minting:', error);
    }
} else if (territory.deadline - curBlockHeight <= 100800) {
    // 100800 block means 7 days
    const renewalRes = await cess.renewalTerritory(myTerritory, 10)
    console.log('renew territory successfully:', renewalRes.blockHash);
} else if (territory.state != "Active" || curBlockHeight >= territory.deadline) {
    // data will be reset when re-activate territory
    const reactivateRes = await cess.reactivateTerritory(myTerritory, 30)
    console.log('reactivate territory successfully:', reactivateRes.blockHash);
} else if (territory.remainingSpace <= 1024 * 1024 * 1024) {
    // remaining space <= 1GiB
    const expandRes = await cess.expandingTerritory(myTerritory, 1)
    console.log('expand territory successfully:', expandRes.blockHash);
} else {
    console.log("territory exist: ", territory)
}

Step 4: Authorize Gateway Access

let gatewayAcc = ""
// get oss public acc by domain name
const ossAccList = await cess.queryOssByAccountId() as unknown as OssDetail[]
for (let i = 0; i < ossAccList.length; i++) {
    if (ossAccList[i].ossInfo.domain == gatewayUrl) {
        gatewayAcc = ossAccList[i].account
        break;
    }
}
if (!gatewayAcc) {
    console.error("gateway not found.");
    return;
}

// auth my territory to gateway acc
const authList = await cess.queryAuthorityListByAccountId(gatewayAcc) as unknown as OssAuthorityList[]
const authorizedAccounts: string[] = authList.map(item => item.authorizedAcc);
if (!authorizedAccounts.indexOf(accountAddress)) {
    try {
        console.log("start to auth")
        const result = await cess.authorize(gatewayAcc);
        if (result.success) {
            console.log('✅ Authorization successful!', {txHash: result.txHash, blockHash: result.blockHash});
        } else {
            console.error('❌ Authorization failed:', result.error);
        }
    } catch (error) {
        console.error('❌ Error during authorization:', error);
    }
} else {
    console.log("already auth")
}

Step 5: Obtain Gateway Token

const token = await GenGatewayAccessToken(gatewayUrl, {
    account: cess.getSignatureAcc(),
    message: sign_message,
    sign: u8aToHex(signature), // Convert signature to hex format
    expire: 1 // Token expiration in hours
});

Step 6: Upload File to Gateway

// Configure gateway connection
const gatewayConfig: GatewayConfigType = {
    baseUrl: gatewayUrl,
    token: token
};

// Upload file to the gateway
let uploadResult: UploadResponse;
uploadResult = await upload(gatewayConfig, "./path/to/your/file.txt", {
    territory: myTerritory,
    uploadFileWithProgress: (progress) => {
        console.log(`\rUpload progress: ${progress.percentage}% (${progress.loaded}/${progress.total} bytes) - ${progress.file}`);
    }
});
if (uploadResult.code == 200) {
    const fid = uploadResult.data; // File ID returned by the gateway
    console.log("File ID (FID): ", fid);
} else {
    throw new Error("Failed to upload file: " + uploadResult.error);
}

Step 7: Download File from Gateway

// Define download options
const downloadOptions: ExtendedDownloadOptions = {
    fid: fid, // The file ID from the upload step
    savePath: "./path/to/downloaded/file.txt",
    overwrite: true,
    createDirectories: true,
};

// Download the file from the gateway
const downloadResult = await downloadFile(gatewayConfig, downloadOptions);
if (downloadResult.success) {
    console.log("Download result: ", downloadResult.data);
} else {
    throw new Error("Failed to download file: " + (downloadResult.error || "Unknown error"));
}
console.log("Download result:", downloadResult);

Step 8: Query File Status on the Blockchain

// Check if the file is being processed by storage miners or already stored
const dealMap = await cess.queryDealMap(fid);
if (dealMap) {
    console.log("Storage order details: ", dealMap);
    console.log("File is being distributed to storage miners");
} else {
    console.log("File has been stored on storage nodes");
    const fileMeta = await cess.queryFileByFid(fid);
    console.log("File metadata: ", fileMeta);
}

await cess.close()

Last updated

Was this helpful?